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