]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/media/video/mem2mem_testdev.c
V4L/DVB: media/mem2mem: dereferencing free memory
[net-next-2.6.git] / drivers / media / video / mem2mem_testdev.c
CommitLineData
96d8eab5
PO
1/*
2 * A virtual v4l2-mem2mem example device.
3 *
4 * This is a virtual device driver for testing mem-to-mem videobuf framework.
5 * It simulates a device that uses memory buffers for both source and
6 * destination, processes the data and issues an "irq" (simulated by a timer).
7 * The device is capable of multi-instance, multi-buffer-per-transaction
8 * operation (via the mem2mem framework).
9 *
10 * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
11 * Pawel Osciak, <p.osciak@samsung.com>
12 * Marek Szyprowski, <m.szyprowski@samsung.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version
18 */
19#include <linux/module.h>
20#include <linux/delay.h>
21#include <linux/fs.h>
22#include <linux/version.h>
23#include <linux/timer.h>
24#include <linux/sched.h>
25
26#include <linux/platform_device.h>
27#include <media/v4l2-mem2mem.h>
28#include <media/v4l2-device.h>
29#include <media/v4l2-ioctl.h>
30#include <media/videobuf-vmalloc.h>
31
32#define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev"
33
34MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
35MODULE_AUTHOR("Pawel Osciak, <p.osciak@samsung.com>");
36MODULE_LICENSE("GPL");
37
38
39#define MIN_W 32
40#define MIN_H 32
41#define MAX_W 640
42#define MAX_H 480
43#define DIM_ALIGN_MASK 0x08 /* 8-alignment for dimensions */
44
45/* Flags that indicate a format can be used for capture/output */
46#define MEM2MEM_CAPTURE (1 << 0)
47#define MEM2MEM_OUTPUT (1 << 1)
48
49#define MEM2MEM_NAME "m2m-testdev"
50
51/* Per queue */
52#define MEM2MEM_DEF_NUM_BUFS VIDEO_MAX_FRAME
53/* In bytes, per queue */
54#define MEM2MEM_VID_MEM_LIMIT (16 * 1024 * 1024)
55
56/* Default transaction time in msec */
57#define MEM2MEM_DEF_TRANSTIME 1000
58/* Default number of buffers per transaction */
59#define MEM2MEM_DEF_TRANSLEN 1
60#define MEM2MEM_COLOR_STEP (0xff >> 4)
61#define MEM2MEM_NUM_TILES 8
62
63#define dprintk(dev, fmt, arg...) \
64 v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
65
66
67void m2mtest_dev_release(struct device *dev)
68{}
69
70static struct platform_device m2mtest_pdev = {
71 .name = MEM2MEM_NAME,
72 .dev.release = m2mtest_dev_release,
73};
74
75struct m2mtest_fmt {
76 char *name;
77 u32 fourcc;
78 int depth;
79 /* Types the format can be used for */
80 u32 types;
81};
82
83static struct m2mtest_fmt formats[] = {
84 {
85 .name = "RGB565 (BE)",
86 .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
87 .depth = 16,
88 /* Both capture and output format */
89 .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
90 },
91 {
92 .name = "4:2:2, packed, YUYV",
93 .fourcc = V4L2_PIX_FMT_YUYV,
94 .depth = 16,
95 /* Output-only format */
96 .types = MEM2MEM_OUTPUT,
97 },
98};
99
100/* Per-queue, driver-specific private data */
101struct m2mtest_q_data {
102 unsigned int width;
103 unsigned int height;
104 unsigned int sizeimage;
105 struct m2mtest_fmt *fmt;
106};
107
108enum {
109 V4L2_M2M_SRC = 0,
110 V4L2_M2M_DST = 1,
111};
112
113/* Source and destination queue data */
114static struct m2mtest_q_data q_data[2];
115
116static struct m2mtest_q_data *get_q_data(enum v4l2_buf_type type)
117{
118 switch (type) {
119 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
120 return &q_data[V4L2_M2M_SRC];
121 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
122 return &q_data[V4L2_M2M_DST];
123 default:
124 BUG();
125 }
126 return NULL;
127}
128
129#define V4L2_CID_TRANS_TIME_MSEC V4L2_CID_PRIVATE_BASE
130#define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_PRIVATE_BASE + 1)
131
132static struct v4l2_queryctrl m2mtest_ctrls[] = {
133 {
134 .id = V4L2_CID_TRANS_TIME_MSEC,
135 .type = V4L2_CTRL_TYPE_INTEGER,
136 .name = "Transaction time (msec)",
137 .minimum = 1,
138 .maximum = 10000,
139 .step = 100,
140 .default_value = 1000,
141 .flags = 0,
142 }, {
143 .id = V4L2_CID_TRANS_NUM_BUFS,
144 .type = V4L2_CTRL_TYPE_INTEGER,
145 .name = "Buffers per transaction",
146 .minimum = 1,
147 .maximum = MEM2MEM_DEF_NUM_BUFS,
148 .step = 1,
149 .default_value = 1,
150 .flags = 0,
151 },
152};
153
154#define NUM_FORMATS ARRAY_SIZE(formats)
155
156static struct m2mtest_fmt *find_format(struct v4l2_format *f)
157{
158 struct m2mtest_fmt *fmt;
159 unsigned int k;
160
161 for (k = 0; k < NUM_FORMATS; k++) {
162 fmt = &formats[k];
163 if (fmt->fourcc == f->fmt.pix.pixelformat)
164 break;
165 }
166
167 if (k == NUM_FORMATS)
168 return NULL;
169
170 return &formats[k];
171}
172
173struct m2mtest_dev {
174 struct v4l2_device v4l2_dev;
175 struct video_device *vfd;
176
177 atomic_t num_inst;
178 struct mutex dev_mutex;
179 spinlock_t irqlock;
180
181 struct timer_list timer;
182
183 struct v4l2_m2m_dev *m2m_dev;
184};
185
186struct m2mtest_ctx {
187 struct m2mtest_dev *dev;
188
189 /* Processed buffers in this transaction */
190 u8 num_processed;
191
192 /* Transaction length (i.e. how many buffers per transaction) */
193 u32 translen;
194 /* Transaction time (i.e. simulated processing time) in milliseconds */
195 u32 transtime;
196
197 /* Abort requested by m2m */
198 int aborting;
199
200 struct v4l2_m2m_ctx *m2m_ctx;
201};
202
203struct m2mtest_buffer {
204 /* vb must be first! */
205 struct videobuf_buffer vb;
206};
207
208static struct v4l2_queryctrl *get_ctrl(int id)
209{
210 int i;
211
212 for (i = 0; i < ARRAY_SIZE(m2mtest_ctrls); ++i) {
213 if (id == m2mtest_ctrls[i].id)
214 return &m2mtest_ctrls[i];
215 }
216
217 return NULL;
218}
219
220static int device_process(struct m2mtest_ctx *ctx,
221 struct m2mtest_buffer *in_buf,
222 struct m2mtest_buffer *out_buf)
223{
224 struct m2mtest_dev *dev = ctx->dev;
225 u8 *p_in, *p_out;
226 int x, y, t, w;
227 int tile_w, bytes_left;
228 struct videobuf_queue *src_q;
229 struct videobuf_queue *dst_q;
230
231 src_q = v4l2_m2m_get_src_vq(ctx->m2m_ctx);
232 dst_q = v4l2_m2m_get_dst_vq(ctx->m2m_ctx);
233 p_in = videobuf_queue_to_vaddr(src_q, &in_buf->vb);
234 p_out = videobuf_queue_to_vaddr(dst_q, &out_buf->vb);
235 if (!p_in || !p_out) {
236 v4l2_err(&dev->v4l2_dev,
237 "Acquiring kernel pointers to buffers failed\n");
238 return -EFAULT;
239 }
240
241 if (in_buf->vb.size < out_buf->vb.size) {
242 v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n");
243 return -EINVAL;
244 }
245
246 tile_w = (in_buf->vb.width * (q_data[V4L2_M2M_DST].fmt->depth >> 3))
247 / MEM2MEM_NUM_TILES;
248 bytes_left = in_buf->vb.bytesperline - tile_w * MEM2MEM_NUM_TILES;
249 w = 0;
250
251 for (y = 0; y < in_buf->vb.height; ++y) {
252 for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
253 if (w & 0x1) {
254 for (x = 0; x < tile_w; ++x)
255 *p_out++ = *p_in++ + MEM2MEM_COLOR_STEP;
256 } else {
257 for (x = 0; x < tile_w; ++x)
258 *p_out++ = *p_in++ - MEM2MEM_COLOR_STEP;
259 }
260 ++w;
261 }
262 p_in += bytes_left;
263 p_out += bytes_left;
264 }
265
266 return 0;
267}
268
269static void schedule_irq(struct m2mtest_dev *dev, int msec_timeout)
270{
271 dprintk(dev, "Scheduling a simulated irq\n");
272 mod_timer(&dev->timer, jiffies + msecs_to_jiffies(msec_timeout));
273}
274
275/*
276 * mem2mem callbacks
277 */
278
279/**
280 * job_ready() - check whether an instance is ready to be scheduled to run
281 */
282static int job_ready(void *priv)
283{
284 struct m2mtest_ctx *ctx = priv;
285
286 if (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) < ctx->translen
287 || v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) < ctx->translen) {
288 dprintk(ctx->dev, "Not enough buffers available\n");
289 return 0;
290 }
291
292 return 1;
293}
294
295static void job_abort(void *priv)
296{
297 struct m2mtest_ctx *ctx = priv;
298
299 /* Will cancel the transaction in the next interrupt handler */
300 ctx->aborting = 1;
301}
302
303/* device_run() - prepares and starts the device
304 *
305 * This simulates all the immediate preparations required before starting
306 * a device. This will be called by the framework when it decides to schedule
307 * a particular instance.
308 */
309static void device_run(void *priv)
310{
311 struct m2mtest_ctx *ctx = priv;
312 struct m2mtest_dev *dev = ctx->dev;
313 struct m2mtest_buffer *src_buf, *dst_buf;
314
315 src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
316 dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
317
318 device_process(ctx, src_buf, dst_buf);
319
320 /* Run a timer, which simulates a hardware irq */
321 schedule_irq(dev, ctx->transtime);
322}
323
324
325static void device_isr(unsigned long priv)
326{
327 struct m2mtest_dev *m2mtest_dev = (struct m2mtest_dev *)priv;
328 struct m2mtest_ctx *curr_ctx;
329 struct m2mtest_buffer *src_buf, *dst_buf;
330 unsigned long flags;
331
332 curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev);
333
334 if (NULL == curr_ctx) {
335 printk(KERN_ERR
336 "Instance released before the end of transaction\n");
337 return;
338 }
339
340 src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
341 dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
342 curr_ctx->num_processed++;
343
344 if (curr_ctx->num_processed == curr_ctx->translen
345 || curr_ctx->aborting) {
346 dprintk(curr_ctx->dev, "Finishing transaction\n");
347 curr_ctx->num_processed = 0;
348 spin_lock_irqsave(&m2mtest_dev->irqlock, flags);
349 src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
350 wake_up(&src_buf->vb.done);
351 wake_up(&dst_buf->vb.done);
352 spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
353 v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->m2m_ctx);
354 } else {
355 spin_lock_irqsave(&m2mtest_dev->irqlock, flags);
356 src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
357 wake_up(&src_buf->vb.done);
358 wake_up(&dst_buf->vb.done);
359 spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
360 device_run(curr_ctx);
361 }
362}
363
364
365/*
366 * video ioctls
367 */
368static int vidioc_querycap(struct file *file, void *priv,
369 struct v4l2_capability *cap)
370{
371 strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
372 strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
373 cap->bus_info[0] = 0;
374 cap->version = KERNEL_VERSION(0, 1, 0);
375 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
376 | V4L2_CAP_STREAMING;
377
378 return 0;
379}
380
381static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
382{
383 int i, num;
384 struct m2mtest_fmt *fmt;
385
386 num = 0;
387
388 for (i = 0; i < NUM_FORMATS; ++i) {
389 if (formats[i].types & type) {
390 /* index-th format of type type found ? */
391 if (num == f->index)
392 break;
393 /* Correct type but haven't reached our index yet,
394 * just increment per-type index */
395 ++num;
396 }
397 }
398
399 if (i < NUM_FORMATS) {
400 /* Format found */
401 fmt = &formats[i];
402 strncpy(f->description, fmt->name, sizeof(f->description) - 1);
403 f->pixelformat = fmt->fourcc;
404 return 0;
405 }
406
407 /* Format not found */
408 return -EINVAL;
409}
410
411static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
412 struct v4l2_fmtdesc *f)
413{
414 return enum_fmt(f, MEM2MEM_CAPTURE);
415}
416
417static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
418 struct v4l2_fmtdesc *f)
419{
420 return enum_fmt(f, MEM2MEM_OUTPUT);
421}
422
423static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
424{
425 struct videobuf_queue *vq;
426 struct m2mtest_q_data *q_data;
427
428 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
429 if (!vq)
430 return -EINVAL;
431
432 q_data = get_q_data(f->type);
433
434 f->fmt.pix.width = q_data->width;
435 f->fmt.pix.height = q_data->height;
436 f->fmt.pix.field = vq->field;
437 f->fmt.pix.pixelformat = q_data->fmt->fourcc;
438 f->fmt.pix.bytesperline = (q_data->width * q_data->fmt->depth) >> 3;
439 f->fmt.pix.sizeimage = q_data->sizeimage;
440
441 return 0;
442}
443
444static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
445 struct v4l2_format *f)
446{
447 return vidioc_g_fmt(priv, f);
448}
449
450static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
451 struct v4l2_format *f)
452{
453 return vidioc_g_fmt(priv, f);
454}
455
456static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt)
457{
458 enum v4l2_field field;
459
460 field = f->fmt.pix.field;
461
462 if (field == V4L2_FIELD_ANY)
463 field = V4L2_FIELD_NONE;
464 else if (V4L2_FIELD_NONE != field)
465 return -EINVAL;
466
467 /* V4L2 specification suggests the driver corrects the format struct
468 * if any of the dimensions is unsupported */
469 f->fmt.pix.field = field;
470
471 if (f->fmt.pix.height < MIN_H)
472 f->fmt.pix.height = MIN_H;
473 else if (f->fmt.pix.height > MAX_H)
474 f->fmt.pix.height = MAX_H;
475
476 if (f->fmt.pix.width < MIN_W)
477 f->fmt.pix.width = MIN_W;
478 else if (f->fmt.pix.width > MAX_W)
479 f->fmt.pix.width = MAX_W;
480
481 f->fmt.pix.width &= ~DIM_ALIGN_MASK;
482 f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
483 f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
484
485 return 0;
486}
487
488static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
489 struct v4l2_format *f)
490{
491 struct m2mtest_fmt *fmt;
492 struct m2mtest_ctx *ctx = priv;
493
494 fmt = find_format(f);
495 if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) {
496 v4l2_err(&ctx->dev->v4l2_dev,
497 "Fourcc format (0x%08x) invalid.\n",
498 f->fmt.pix.pixelformat);
499 return -EINVAL;
500 }
501
502 return vidioc_try_fmt(f, fmt);
503}
504
505static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
506 struct v4l2_format *f)
507{
508 struct m2mtest_fmt *fmt;
509 struct m2mtest_ctx *ctx = priv;
510
511 fmt = find_format(f);
512 if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) {
513 v4l2_err(&ctx->dev->v4l2_dev,
514 "Fourcc format (0x%08x) invalid.\n",
515 f->fmt.pix.pixelformat);
516 return -EINVAL;
517 }
518
519 return vidioc_try_fmt(f, fmt);
520}
521
522static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
523{
524 struct m2mtest_q_data *q_data;
525 struct videobuf_queue *vq;
526 int ret = 0;
527
528 vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
529 if (!vq)
530 return -EINVAL;
531
532 q_data = get_q_data(f->type);
533 if (!q_data)
534 return -EINVAL;
535
536 mutex_lock(&vq->vb_lock);
537
538 if (videobuf_queue_is_busy(vq)) {
539 v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
540 ret = -EBUSY;
541 goto out;
542 }
543
544 q_data->fmt = find_format(f);
545 q_data->width = f->fmt.pix.width;
546 q_data->height = f->fmt.pix.height;
547 q_data->sizeimage = q_data->width * q_data->height
548 * q_data->fmt->depth >> 3;
549 vq->field = f->fmt.pix.field;
550
551 dprintk(ctx->dev,
552 "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
553 f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
554
555out:
556 mutex_unlock(&vq->vb_lock);
557 return ret;
558}
559
560static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
561 struct v4l2_format *f)
562{
563 int ret;
564
565 ret = vidioc_try_fmt_vid_cap(file, priv, f);
566 if (ret)
567 return ret;
568
569 return vidioc_s_fmt(priv, f);
570}
571
572static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
573 struct v4l2_format *f)
574{
575 int ret;
576
577 ret = vidioc_try_fmt_vid_out(file, priv, f);
578 if (ret)
579 return ret;
580
581 return vidioc_s_fmt(priv, f);
582}
583
584static int vidioc_reqbufs(struct file *file, void *priv,
585 struct v4l2_requestbuffers *reqbufs)
586{
587 struct m2mtest_ctx *ctx = priv;
588
589 return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
590}
591
592static int vidioc_querybuf(struct file *file, void *priv,
593 struct v4l2_buffer *buf)
594{
595 struct m2mtest_ctx *ctx = priv;
596
597 return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
598}
599
600static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
601{
602 struct m2mtest_ctx *ctx = priv;
603
604 return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
605}
606
607static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
608{
609 struct m2mtest_ctx *ctx = priv;
610
611 return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
612}
613
614static int vidioc_streamon(struct file *file, void *priv,
615 enum v4l2_buf_type type)
616{
617 struct m2mtest_ctx *ctx = priv;
618
619 return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
620}
621
622static int vidioc_streamoff(struct file *file, void *priv,
623 enum v4l2_buf_type type)
624{
625 struct m2mtest_ctx *ctx = priv;
626
627 return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
628}
629
630static int vidioc_queryctrl(struct file *file, void *priv,
631 struct v4l2_queryctrl *qc)
632{
633 struct v4l2_queryctrl *c;
634
635 c = get_ctrl(qc->id);
636 if (!c)
637 return -EINVAL;
638
639 *qc = *c;
640 return 0;
641}
642
643static int vidioc_g_ctrl(struct file *file, void *priv,
644 struct v4l2_control *ctrl)
645{
646 struct m2mtest_ctx *ctx = priv;
647
648 switch (ctrl->id) {
649 case V4L2_CID_TRANS_TIME_MSEC:
650 ctrl->value = ctx->transtime;
651 break;
652
653 case V4L2_CID_TRANS_NUM_BUFS:
654 ctrl->value = ctx->translen;
655 break;
656
657 default:
658 v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
659 return -EINVAL;
660 }
661
662 return 0;
663}
664
665static int check_ctrl_val(struct m2mtest_ctx *ctx, struct v4l2_control *ctrl)
666{
667 struct v4l2_queryctrl *c;
668
669 c = get_ctrl(ctrl->id);
670 if (!c)
671 return -EINVAL;
672
673 if (ctrl->value < c->minimum || ctrl->value > c->maximum) {
674 v4l2_err(&ctx->dev->v4l2_dev, "Value out of range\n");
675 return -ERANGE;
676 }
677
678 return 0;
679}
680
681static int vidioc_s_ctrl(struct file *file, void *priv,
682 struct v4l2_control *ctrl)
683{
684 struct m2mtest_ctx *ctx = priv;
685 int ret = 0;
686
687 ret = check_ctrl_val(ctx, ctrl);
688 if (ret != 0)
689 return ret;
690
691 switch (ctrl->id) {
692 case V4L2_CID_TRANS_TIME_MSEC:
693 ctx->transtime = ctrl->value;
694 break;
695
696 case V4L2_CID_TRANS_NUM_BUFS:
697 ctx->translen = ctrl->value;
698 break;
699
700 default:
701 v4l2_err(&ctx->dev->v4l2_dev, "Invalid control\n");
702 return -EINVAL;
703 }
704
705 return 0;
706}
707
708
709static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = {
710 .vidioc_querycap = vidioc_querycap,
711
712 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
713 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
714 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
715 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
716
717 .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
718 .vidioc_g_fmt_vid_out = vidioc_g_fmt_vid_out,
719 .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
720 .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out,
721
722 .vidioc_reqbufs = vidioc_reqbufs,
723 .vidioc_querybuf = vidioc_querybuf,
724
725 .vidioc_qbuf = vidioc_qbuf,
726 .vidioc_dqbuf = vidioc_dqbuf,
727
728 .vidioc_streamon = vidioc_streamon,
729 .vidioc_streamoff = vidioc_streamoff,
730
731 .vidioc_queryctrl = vidioc_queryctrl,
732 .vidioc_g_ctrl = vidioc_g_ctrl,
733 .vidioc_s_ctrl = vidioc_s_ctrl,
734};
735
736
737/*
738 * Queue operations
739 */
740
741static void m2mtest_buf_release(struct videobuf_queue *vq,
742 struct videobuf_buffer *vb)
743{
744 struct m2mtest_ctx *ctx = vq->priv_data;
745
746 dprintk(ctx->dev, "type: %d, index: %d, state: %d\n",
747 vq->type, vb->i, vb->state);
748
749 videobuf_vmalloc_free(vb);
750 vb->state = VIDEOBUF_NEEDS_INIT;
751}
752
753static int m2mtest_buf_setup(struct videobuf_queue *vq, unsigned int *count,
754 unsigned int *size)
755{
756 struct m2mtest_ctx *ctx = vq->priv_data;
757 struct m2mtest_q_data *q_data;
758
759 q_data = get_q_data(vq->type);
760
761 *size = q_data->width * q_data->height * q_data->fmt->depth >> 3;
762 dprintk(ctx->dev, "size:%d, w/h %d/%d, depth: %d\n",
763 *size, q_data->width, q_data->height, q_data->fmt->depth);
764
765 if (0 == *count)
766 *count = MEM2MEM_DEF_NUM_BUFS;
767
768 while (*size * *count > MEM2MEM_VID_MEM_LIMIT)
769 (*count)--;
770
771 v4l2_info(&ctx->dev->v4l2_dev,
772 "%d buffers of size %d set up.\n", *count, *size);
773
774 return 0;
775}
776
777static int m2mtest_buf_prepare(struct videobuf_queue *vq,
778 struct videobuf_buffer *vb,
779 enum v4l2_field field)
780{
781 struct m2mtest_ctx *ctx = vq->priv_data;
782 struct m2mtest_q_data *q_data;
783 int ret;
784
785 dprintk(ctx->dev, "type: %d, index: %d, state: %d\n",
786 vq->type, vb->i, vb->state);
787
788 q_data = get_q_data(vq->type);
789
790 if (vb->baddr) {
791 /* User-provided buffer */
792 if (vb->bsize < q_data->sizeimage) {
793 /* Buffer too small to fit a frame */
794 v4l2_err(&ctx->dev->v4l2_dev,
795 "User-provided buffer too small\n");
796 return -EINVAL;
797 }
798 } else if (vb->state != VIDEOBUF_NEEDS_INIT
799 && vb->bsize < q_data->sizeimage) {
800 /* We provide the buffer, but it's already been initialized
801 * and is too small */
802 return -EINVAL;
803 }
804
805 vb->width = q_data->width;
806 vb->height = q_data->height;
807 vb->bytesperline = (q_data->width * q_data->fmt->depth) >> 3;
808 vb->size = q_data->sizeimage;
809 vb->field = field;
810
811 if (VIDEOBUF_NEEDS_INIT == vb->state) {
812 ret = videobuf_iolock(vq, vb, NULL);
813 if (ret) {
814 v4l2_err(&ctx->dev->v4l2_dev,
815 "Iolock failed\n");
816 goto fail;
817 }
818 }
819
820 vb->state = VIDEOBUF_PREPARED;
821
822 return 0;
823fail:
824 m2mtest_buf_release(vq, vb);
825 return ret;
826}
827
828static void m2mtest_buf_queue(struct videobuf_queue *vq,
829 struct videobuf_buffer *vb)
830{
831 struct m2mtest_ctx *ctx = vq->priv_data;
832
833 v4l2_m2m_buf_queue(ctx->m2m_ctx, vq, vb);
834}
835
836static struct videobuf_queue_ops m2mtest_qops = {
837 .buf_setup = m2mtest_buf_setup,
838 .buf_prepare = m2mtest_buf_prepare,
839 .buf_queue = m2mtest_buf_queue,
840 .buf_release = m2mtest_buf_release,
841};
842
843static void queue_init(void *priv, struct videobuf_queue *vq,
844 enum v4l2_buf_type type)
845{
846 struct m2mtest_ctx *ctx = priv;
847
848 videobuf_queue_vmalloc_init(vq, &m2mtest_qops, ctx->dev->v4l2_dev.dev,
849 &ctx->dev->irqlock, type, V4L2_FIELD_NONE,
850 sizeof(struct m2mtest_buffer), priv);
851}
852
853
854/*
855 * File operations
856 */
857static int m2mtest_open(struct file *file)
858{
859 struct m2mtest_dev *dev = video_drvdata(file);
860 struct m2mtest_ctx *ctx = NULL;
861
862 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
863 if (!ctx)
864 return -ENOMEM;
865
866 file->private_data = ctx;
867 ctx->dev = dev;
868 ctx->translen = MEM2MEM_DEF_TRANSLEN;
869 ctx->transtime = MEM2MEM_DEF_TRANSTIME;
870 ctx->num_processed = 0;
871
872 ctx->m2m_ctx = v4l2_m2m_ctx_init(ctx, dev->m2m_dev, queue_init);
873 if (IS_ERR(ctx->m2m_ctx)) {
16ee9bb1
DC
874 int ret = PTR_ERR(ctx->m2m_ctx);
875
96d8eab5 876 kfree(ctx);
16ee9bb1 877 return ret;
96d8eab5
PO
878 }
879
880 atomic_inc(&dev->num_inst);
881
882 dprintk(dev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
883
884 return 0;
885}
886
887static int m2mtest_release(struct file *file)
888{
889 struct m2mtest_dev *dev = video_drvdata(file);
890 struct m2mtest_ctx *ctx = file->private_data;
891
892 dprintk(dev, "Releasing instance %p\n", ctx);
893
894 v4l2_m2m_ctx_release(ctx->m2m_ctx);
895 kfree(ctx);
896
897 atomic_dec(&dev->num_inst);
898
899 return 0;
900}
901
902static unsigned int m2mtest_poll(struct file *file,
903 struct poll_table_struct *wait)
904{
905 struct m2mtest_ctx *ctx = (struct m2mtest_ctx *)file->private_data;
906
907 return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
908}
909
910static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma)
911{
912 struct m2mtest_ctx *ctx = (struct m2mtest_ctx *)file->private_data;
913
914 return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
915}
916
917static const struct v4l2_file_operations m2mtest_fops = {
918 .owner = THIS_MODULE,
919 .open = m2mtest_open,
920 .release = m2mtest_release,
921 .poll = m2mtest_poll,
922 .ioctl = video_ioctl2,
923 .mmap = m2mtest_mmap,
924};
925
926static struct video_device m2mtest_videodev = {
927 .name = MEM2MEM_NAME,
928 .fops = &m2mtest_fops,
929 .ioctl_ops = &m2mtest_ioctl_ops,
930 .minor = -1,
931 .release = video_device_release,
932};
933
934static struct v4l2_m2m_ops m2m_ops = {
935 .device_run = device_run,
936 .job_ready = job_ready,
937 .job_abort = job_abort,
938};
939
940static int m2mtest_probe(struct platform_device *pdev)
941{
942 struct m2mtest_dev *dev;
943 struct video_device *vfd;
944 int ret;
945
946 dev = kzalloc(sizeof *dev, GFP_KERNEL);
947 if (!dev)
948 return -ENOMEM;
949
950 spin_lock_init(&dev->irqlock);
951
952 ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
953 if (ret)
954 goto free_dev;
955
956 atomic_set(&dev->num_inst, 0);
957 mutex_init(&dev->dev_mutex);
958
959 vfd = video_device_alloc();
960 if (!vfd) {
961 v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
962 ret = -ENOMEM;
963 goto unreg_dev;
964 }
965
966 *vfd = m2mtest_videodev;
967
968 ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
969 if (ret) {
970 v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
971 goto rel_vdev;
972 }
973
974 video_set_drvdata(vfd, dev);
975 snprintf(vfd->name, sizeof(vfd->name), "%s", m2mtest_videodev.name);
976 dev->vfd = vfd;
977 v4l2_info(&dev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME
978 "Device registered as /dev/video%d\n", vfd->num);
979
980 setup_timer(&dev->timer, device_isr, (long)dev);
981 platform_set_drvdata(pdev, dev);
982
983 dev->m2m_dev = v4l2_m2m_init(&m2m_ops);
984 if (IS_ERR(dev->m2m_dev)) {
985 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
986 ret = PTR_ERR(dev->m2m_dev);
987 goto err_m2m;
988 }
989
990 return 0;
991
992err_m2m:
993 video_unregister_device(dev->vfd);
994rel_vdev:
995 video_device_release(vfd);
996unreg_dev:
997 v4l2_device_unregister(&dev->v4l2_dev);
998free_dev:
999 kfree(dev);
1000
1001 return ret;
1002}
1003
1004static int m2mtest_remove(struct platform_device *pdev)
1005{
1006 struct m2mtest_dev *dev =
1007 (struct m2mtest_dev *)platform_get_drvdata(pdev);
1008
1009 v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
1010 v4l2_m2m_release(dev->m2m_dev);
1011 del_timer_sync(&dev->timer);
1012 video_unregister_device(dev->vfd);
1013 v4l2_device_unregister(&dev->v4l2_dev);
1014 kfree(dev);
1015
1016 return 0;
1017}
1018
1019static struct platform_driver m2mtest_pdrv = {
1020 .probe = m2mtest_probe,
1021 .remove = m2mtest_remove,
1022 .driver = {
1023 .name = MEM2MEM_NAME,
1024 .owner = THIS_MODULE,
1025 },
1026};
1027
1028static void __exit m2mtest_exit(void)
1029{
1030 platform_driver_unregister(&m2mtest_pdrv);
1031 platform_device_unregister(&m2mtest_pdev);
1032}
1033
1034static int __init m2mtest_init(void)
1035{
1036 int ret;
1037
1038 ret = platform_device_register(&m2mtest_pdev);
1039 if (ret)
1040 return ret;
1041
1042 ret = platform_driver_register(&m2mtest_pdrv);
1043 if (ret)
1044 platform_device_unregister(&m2mtest_pdev);
1045
1046 return 0;
1047}
1048
1049module_init(m2mtest_init);
1050module_exit(m2mtest_exit);
1051