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