Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fimc-m2m.c
Go to the documentation of this file.
1 /*
2  * Samsung S5P/EXYNOS4 SoC series FIMC (video postprocessor) driver
3  *
4  * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5  * Sylwester Nawrocki, <[email protected]>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published
9  * by the Free Software Foundation, either version 2 of the License,
10  * or (at your option) any later version.
11  */
12 
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <linux/errno.h>
17 #include <linux/bug.h>
18 #include <linux/interrupt.h>
19 #include <linux/device.h>
20 #include <linux/platform_device.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/list.h>
23 #include <linux/io.h>
24 #include <linux/slab.h>
25 #include <linux/clk.h>
26 #include <media/v4l2-ioctl.h>
27 #include <media/videobuf2-core.h>
29 
30 #include "fimc-core.h"
31 #include "fimc-reg.h"
32 #include "fimc-mdevice.h"
33 
34 
35 static unsigned int get_m2m_fmt_flags(unsigned int stream_type)
36 {
37  if (stream_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
38  return FMT_FLAGS_M2M_IN;
39  else
40  return FMT_FLAGS_M2M_OUT;
41 }
42 
43 void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state)
44 {
45  struct vb2_buffer *src_vb, *dst_vb;
46 
47  if (!ctx || !ctx->m2m_ctx)
48  return;
49 
50  src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
51  dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
52 
53  if (src_vb && dst_vb) {
54  v4l2_m2m_buf_done(src_vb, vb_state);
55  v4l2_m2m_buf_done(dst_vb, vb_state);
56  v4l2_m2m_job_finish(ctx->fimc_dev->m2m.m2m_dev,
57  ctx->m2m_ctx);
58  }
59 }
60 
61 /* Complete the transaction which has been scheduled for execution. */
62 static int fimc_m2m_shutdown(struct fimc_ctx *ctx)
63 {
64  struct fimc_dev *fimc = ctx->fimc_dev;
65  int ret;
66 
67  if (!fimc_m2m_pending(fimc))
68  return 0;
69 
70  fimc_ctx_state_set(FIMC_CTX_SHUT, ctx);
71 
72  ret = wait_event_timeout(fimc->irq_queue,
73  !fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx),
75 
76  return ret == 0 ? -ETIMEDOUT : ret;
77 }
78 
79 static int start_streaming(struct vb2_queue *q, unsigned int count)
80 {
81  struct fimc_ctx *ctx = q->drv_priv;
82  int ret;
83 
84  ret = pm_runtime_get_sync(&ctx->fimc_dev->pdev->dev);
85  return ret > 0 ? 0 : ret;
86 }
87 
88 static int stop_streaming(struct vb2_queue *q)
89 {
90  struct fimc_ctx *ctx = q->drv_priv;
91  int ret;
92 
93  ret = fimc_m2m_shutdown(ctx);
94  if (ret == -ETIMEDOUT)
96 
97  pm_runtime_put(&ctx->fimc_dev->pdev->dev);
98  return 0;
99 }
100 
101 static void fimc_device_run(void *priv)
102 {
103  struct vb2_buffer *vb = NULL;
104  struct fimc_ctx *ctx = priv;
105  struct fimc_frame *sf, *df;
106  struct fimc_dev *fimc;
107  unsigned long flags;
108  u32 ret;
109 
110  if (WARN(!ctx, "Null context\n"))
111  return;
112 
113  fimc = ctx->fimc_dev;
114  spin_lock_irqsave(&fimc->slock, flags);
115 
116  set_bit(ST_M2M_PEND, &fimc->state);
117  sf = &ctx->s_frame;
118  df = &ctx->d_frame;
119 
120  if (ctx->state & FIMC_PARAMS) {
121  /* Prepare the DMA offsets for scaler */
122  fimc_prepare_dma_offset(ctx, sf);
123  fimc_prepare_dma_offset(ctx, df);
124  }
125 
126  vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
127  ret = fimc_prepare_addr(ctx, vb, sf, &sf->paddr);
128  if (ret)
129  goto dma_unlock;
130 
131  vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
132  ret = fimc_prepare_addr(ctx, vb, df, &df->paddr);
133  if (ret)
134  goto dma_unlock;
135 
136  /* Reconfigure hardware if the context has changed. */
137  if (fimc->m2m.ctx != ctx) {
138  ctx->state |= FIMC_PARAMS;
139  fimc->m2m.ctx = ctx;
140  }
141 
142  if (ctx->state & FIMC_PARAMS) {
143  fimc_set_yuv_order(ctx);
145  fimc_hw_set_in_dma(ctx);
146  ret = fimc_set_scaler_info(ctx);
147  if (ret)
148  goto dma_unlock;
153  fimc_hw_set_effect(ctx);
154  fimc_hw_set_out_dma(ctx);
155  if (fimc->variant->has_alpha)
158  }
159  fimc_hw_set_input_addr(fimc, &sf->paddr);
160  fimc_hw_set_output_addr(fimc, &df->paddr, -1);
161 
163  ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP |
165  fimc_hw_activate_input_dma(fimc, true);
166 
167 dma_unlock:
168  spin_unlock_irqrestore(&fimc->slock, flags);
169 }
170 
171 static void fimc_job_abort(void *priv)
172 {
173  fimc_m2m_shutdown(priv);
174 }
175 
176 static int fimc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
177  unsigned int *num_buffers, unsigned int *num_planes,
178  unsigned int sizes[], void *allocators[])
179 {
180  struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
181  struct fimc_frame *f;
182  int i;
183 
184  f = ctx_get_frame(ctx, vq->type);
185  if (IS_ERR(f))
186  return PTR_ERR(f);
187  /*
188  * Return number of non-contigous planes (plane buffers)
189  * depending on the configured color format.
190  */
191  if (!f->fmt)
192  return -EINVAL;
193 
194  *num_planes = f->fmt->memplanes;
195  for (i = 0; i < f->fmt->memplanes; i++) {
196  sizes[i] = (f->f_width * f->f_height * f->fmt->depth[i]) / 8;
197  allocators[i] = ctx->fimc_dev->alloc_ctx;
198  }
199  return 0;
200 }
201 
202 static int fimc_buf_prepare(struct vb2_buffer *vb)
203 {
204  struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
205  struct fimc_frame *frame;
206  int i;
207 
208  frame = ctx_get_frame(ctx, vb->vb2_queue->type);
209  if (IS_ERR(frame))
210  return PTR_ERR(frame);
211 
212  for (i = 0; i < frame->fmt->memplanes; i++)
213  vb2_set_plane_payload(vb, i, frame->payload[i]);
214 
215  return 0;
216 }
217 
218 static void fimc_buf_queue(struct vb2_buffer *vb)
219 {
220  struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
221 
222  dbg("ctx: %p, ctx->state: 0x%x", ctx, ctx->state);
223 
224  if (ctx->m2m_ctx)
225  v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
226 }
227 
228 static void fimc_lock(struct vb2_queue *vq)
229 {
230  struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
231  mutex_lock(&ctx->fimc_dev->lock);
232 }
233 
234 static void fimc_unlock(struct vb2_queue *vq)
235 {
236  struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
237  mutex_unlock(&ctx->fimc_dev->lock);
238 }
239 
240 static struct vb2_ops fimc_qops = {
241  .queue_setup = fimc_queue_setup,
242  .buf_prepare = fimc_buf_prepare,
243  .buf_queue = fimc_buf_queue,
244  .wait_prepare = fimc_unlock,
245  .wait_finish = fimc_lock,
246  .stop_streaming = stop_streaming,
247  .start_streaming = start_streaming,
248 };
249 
250 /*
251  * V4L2 ioctl handlers
252  */
253 static int fimc_m2m_querycap(struct file *file, void *fh,
254  struct v4l2_capability *cap)
255 {
256  struct fimc_ctx *ctx = fh_to_ctx(fh);
257  struct fimc_dev *fimc = ctx->fimc_dev;
258 
259  strncpy(cap->driver, fimc->pdev->name, sizeof(cap->driver) - 1);
260  strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
261  cap->bus_info[0] = 0;
262  /*
263  * This is only a mem-to-mem video device. The capture and output
264  * device capability flags are left only for backward compatibility
265  * and are scheduled for removal.
266  */
269 
270  return 0;
271 }
272 
273 static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv,
274  struct v4l2_fmtdesc *f)
275 {
276  struct fimc_fmt *fmt;
277 
278  fmt = fimc_find_format(NULL, NULL, get_m2m_fmt_flags(f->type),
279  f->index);
280  if (!fmt)
281  return -EINVAL;
282 
283  strncpy(f->description, fmt->name, sizeof(f->description) - 1);
284  f->pixelformat = fmt->fourcc;
285  return 0;
286 }
287 
288 static int fimc_m2m_g_fmt_mplane(struct file *file, void *fh,
289  struct v4l2_format *f)
290 {
291  struct fimc_ctx *ctx = fh_to_ctx(fh);
292  struct fimc_frame *frame = ctx_get_frame(ctx, f->type);
293 
294  if (IS_ERR(frame))
295  return PTR_ERR(frame);
296 
297  return fimc_fill_format(frame, f);
298 }
299 
300 static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f)
301 {
302  struct fimc_dev *fimc = ctx->fimc_dev;
303  struct fimc_variant *variant = fimc->variant;
304  struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
305  struct fimc_fmt *fmt;
306  u32 max_w, mod_x, mod_y;
307 
308  if (!IS_M2M(f->type))
309  return -EINVAL;
310 
311  dbg("w: %d, h: %d", pix->width, pix->height);
312 
313  fmt = fimc_find_format(&pix->pixelformat, NULL,
314  get_m2m_fmt_flags(f->type), 0);
315  if (WARN(fmt == NULL, "Pixel format lookup failed"))
316  return -EINVAL;
317 
318  if (pix->field == V4L2_FIELD_ANY)
319  pix->field = V4L2_FIELD_NONE;
320  else if (pix->field != V4L2_FIELD_NONE)
321  return -EINVAL;
322 
324  max_w = variant->pix_limit->scaler_dis_w;
325  mod_x = ffs(variant->min_inp_pixsize) - 1;
326  } else {
327  max_w = variant->pix_limit->out_rot_dis_w;
328  mod_x = ffs(variant->min_out_pixsize) - 1;
329  }
330 
331  if (tiled_fmt(fmt)) {
332  mod_x = 6; /* 64 x 32 pixels tile */
333  mod_y = 5;
334  } else {
335  if (variant->min_vsize_align == 1)
336  mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1;
337  else
338  mod_y = ffs(variant->min_vsize_align) - 1;
339  }
340 
341  v4l_bound_align_image(&pix->width, 16, max_w, mod_x,
342  &pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0);
343 
344  fimc_adjust_mplane_format(fmt, pix->width, pix->height, &f->fmt.pix_mp);
345  return 0;
346 }
347 
348 static int fimc_m2m_try_fmt_mplane(struct file *file, void *fh,
349  struct v4l2_format *f)
350 {
351  struct fimc_ctx *ctx = fh_to_ctx(fh);
352 
353  return fimc_try_fmt_mplane(ctx, f);
354 }
355 
356 static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
357  struct v4l2_format *f)
358 {
359  struct fimc_ctx *ctx = fh_to_ctx(fh);
360  struct fimc_dev *fimc = ctx->fimc_dev;
361  struct vb2_queue *vq;
362  struct fimc_frame *frame;
363  struct v4l2_pix_format_mplane *pix;
364  int i, ret = 0;
365 
366  ret = fimc_try_fmt_mplane(ctx, f);
367  if (ret)
368  return ret;
369 
370  vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
371 
372  if (vb2_is_busy(vq)) {
373  v4l2_err(&fimc->m2m.vfd, "queue (%d) busy\n", f->type);
374  return -EBUSY;
375  }
376 
378  frame = &ctx->s_frame;
379  else
380  frame = &ctx->d_frame;
381 
382  pix = &f->fmt.pix_mp;
383  frame->fmt = fimc_find_format(&pix->pixelformat, NULL,
384  get_m2m_fmt_flags(f->type), 0);
385  if (!frame->fmt)
386  return -EINVAL;
387 
388  /* Update RGB Alpha control state and value range */
390 
391  for (i = 0; i < frame->fmt->colplanes; i++) {
392  frame->payload[i] =
393  (pix->width * pix->height * frame->fmt->depth[i]) / 8;
394  }
395 
396  fimc_fill_frame(frame, f);
397 
398  ctx->scaler.enabled = 1;
399 
401  fimc_ctx_state_set(FIMC_PARAMS | FIMC_DST_FMT, ctx);
402  else
403  fimc_ctx_state_set(FIMC_PARAMS | FIMC_SRC_FMT, ctx);
404 
405  dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height);
406 
407  return 0;
408 }
409 
410 static int fimc_m2m_reqbufs(struct file *file, void *fh,
411  struct v4l2_requestbuffers *reqbufs)
412 {
413  struct fimc_ctx *ctx = fh_to_ctx(fh);
414 
415  return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
416 }
417 
418 static int fimc_m2m_querybuf(struct file *file, void *fh,
419  struct v4l2_buffer *buf)
420 {
421  struct fimc_ctx *ctx = fh_to_ctx(fh);
422 
423  return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
424 }
425 
426 static int fimc_m2m_qbuf(struct file *file, void *fh,
427  struct v4l2_buffer *buf)
428 {
429  struct fimc_ctx *ctx = fh_to_ctx(fh);
430 
431  return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
432 }
433 
434 static int fimc_m2m_dqbuf(struct file *file, void *fh,
435  struct v4l2_buffer *buf)
436 {
437  struct fimc_ctx *ctx = fh_to_ctx(fh);
438 
439  return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
440 }
441 
442 static int fimc_m2m_streamon(struct file *file, void *fh,
443  enum v4l2_buf_type type)
444 {
445  struct fimc_ctx *ctx = fh_to_ctx(fh);
446 
447  /* The source and target color format need to be set */
448  if (V4L2_TYPE_IS_OUTPUT(type)) {
449  if (!fimc_ctx_state_is_set(FIMC_SRC_FMT, ctx))
450  return -EINVAL;
451  } else if (!fimc_ctx_state_is_set(FIMC_DST_FMT, ctx)) {
452  return -EINVAL;
453  }
454 
455  return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
456 }
457 
458 static int fimc_m2m_streamoff(struct file *file, void *fh,
459  enum v4l2_buf_type type)
460 {
461  struct fimc_ctx *ctx = fh_to_ctx(fh);
462 
463  return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
464 }
465 
466 static int fimc_m2m_cropcap(struct file *file, void *fh,
467  struct v4l2_cropcap *cr)
468 {
469  struct fimc_ctx *ctx = fh_to_ctx(fh);
470  struct fimc_frame *frame;
471 
472  frame = ctx_get_frame(ctx, cr->type);
473  if (IS_ERR(frame))
474  return PTR_ERR(frame);
475 
476  cr->bounds.left = 0;
477  cr->bounds.top = 0;
478  cr->bounds.width = frame->o_width;
479  cr->bounds.height = frame->o_height;
480  cr->defrect = cr->bounds;
481 
482  return 0;
483 }
484 
485 static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
486 {
487  struct fimc_ctx *ctx = fh_to_ctx(fh);
488  struct fimc_frame *frame;
489 
490  frame = ctx_get_frame(ctx, cr->type);
491  if (IS_ERR(frame))
492  return PTR_ERR(frame);
493 
494  cr->c.left = frame->offs_h;
495  cr->c.top = frame->offs_v;
496  cr->c.width = frame->width;
497  cr->c.height = frame->height;
498 
499  return 0;
500 }
501 
502 static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
503 {
504  struct fimc_dev *fimc = ctx->fimc_dev;
505  struct fimc_frame *f;
506  u32 min_size, halign, depth = 0;
507  int i;
508 
509  if (cr->c.top < 0 || cr->c.left < 0) {
510  v4l2_err(&fimc->m2m.vfd,
511  "doesn't support negative values for top & left\n");
512  return -EINVAL;
513  }
515  f = &ctx->d_frame;
516  else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
517  f = &ctx->s_frame;
518  else
519  return -EINVAL;
520 
521  min_size = (f == &ctx->s_frame) ?
522  fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
523 
524  /* Get pixel alignment constraints. */
525  if (fimc->variant->min_vsize_align == 1)
526  halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1;
527  else
528  halign = ffs(fimc->variant->min_vsize_align) - 1;
529 
530  for (i = 0; i < f->fmt->colplanes; i++)
531  depth += f->fmt->depth[i];
532 
533  v4l_bound_align_image(&cr->c.width, min_size, f->o_width,
534  ffs(min_size) - 1,
535  &cr->c.height, min_size, f->o_height,
536  halign, 64/(ALIGN(depth, 8)));
537 
538  /* adjust left/top if cropping rectangle is out of bounds */
539  if (cr->c.left + cr->c.width > f->o_width)
540  cr->c.left = f->o_width - cr->c.width;
541  if (cr->c.top + cr->c.height > f->o_height)
542  cr->c.top = f->o_height - cr->c.height;
543 
544  cr->c.left = round_down(cr->c.left, min_size);
545  cr->c.top = round_down(cr->c.top, fimc->variant->hor_offs_align);
546 
547  dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d",
548  cr->c.left, cr->c.top, cr->c.width, cr->c.height,
549  f->f_width, f->f_height);
550 
551  return 0;
552 }
553 
554 static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
555 {
556  struct fimc_ctx *ctx = fh_to_ctx(fh);
557  struct fimc_dev *fimc = ctx->fimc_dev;
558  struct v4l2_crop cr = *crop;
559  struct fimc_frame *f;
560  int ret;
561 
562  ret = fimc_m2m_try_crop(ctx, &cr);
563  if (ret)
564  return ret;
565 
567  &ctx->s_frame : &ctx->d_frame;
568 
569  /* Check to see if scaling ratio is within supported range */
570  if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
572  ret = fimc_check_scaler_ratio(ctx, cr.c.width,
573  cr.c.height, ctx->d_frame.width,
574  ctx->d_frame.height, ctx->rotation);
575  } else {
576  ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
577  ctx->s_frame.height, cr.c.width,
578  cr.c.height, ctx->rotation);
579  }
580  if (ret) {
581  v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n");
582  return -EINVAL;
583  }
584  }
585 
586  f->offs_h = cr.c.left;
587  f->offs_v = cr.c.top;
588  f->width = cr.c.width;
589  f->height = cr.c.height;
590 
591  fimc_ctx_state_set(FIMC_PARAMS, ctx);
592 
593  return 0;
594 }
595 
596 static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
597  .vidioc_querycap = fimc_m2m_querycap,
598  .vidioc_enum_fmt_vid_cap_mplane = fimc_m2m_enum_fmt_mplane,
599  .vidioc_enum_fmt_vid_out_mplane = fimc_m2m_enum_fmt_mplane,
600  .vidioc_g_fmt_vid_cap_mplane = fimc_m2m_g_fmt_mplane,
601  .vidioc_g_fmt_vid_out_mplane = fimc_m2m_g_fmt_mplane,
602  .vidioc_try_fmt_vid_cap_mplane = fimc_m2m_try_fmt_mplane,
603  .vidioc_try_fmt_vid_out_mplane = fimc_m2m_try_fmt_mplane,
604  .vidioc_s_fmt_vid_cap_mplane = fimc_m2m_s_fmt_mplane,
605  .vidioc_s_fmt_vid_out_mplane = fimc_m2m_s_fmt_mplane,
606  .vidioc_reqbufs = fimc_m2m_reqbufs,
607  .vidioc_querybuf = fimc_m2m_querybuf,
608  .vidioc_qbuf = fimc_m2m_qbuf,
609  .vidioc_dqbuf = fimc_m2m_dqbuf,
610  .vidioc_streamon = fimc_m2m_streamon,
611  .vidioc_streamoff = fimc_m2m_streamoff,
612  .vidioc_g_crop = fimc_m2m_g_crop,
613  .vidioc_s_crop = fimc_m2m_s_crop,
614  .vidioc_cropcap = fimc_m2m_cropcap
615 
616 };
617 
618 static int queue_init(void *priv, struct vb2_queue *src_vq,
619  struct vb2_queue *dst_vq)
620 {
621  struct fimc_ctx *ctx = priv;
622  int ret;
623 
625  src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
626  src_vq->drv_priv = ctx;
627  src_vq->ops = &fimc_qops;
628  src_vq->mem_ops = &vb2_dma_contig_memops;
629  src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
630 
631  ret = vb2_queue_init(src_vq);
632  if (ret)
633  return ret;
634 
636  dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
637  dst_vq->drv_priv = ctx;
638  dst_vq->ops = &fimc_qops;
639  dst_vq->mem_ops = &vb2_dma_contig_memops;
640  dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
641 
642  return vb2_queue_init(dst_vq);
643 }
644 
645 static int fimc_m2m_open(struct file *file)
646 {
647  struct fimc_dev *fimc = video_drvdata(file);
648  struct fimc_ctx *ctx;
649  int ret = -EBUSY;
650 
651  dbg("pid: %d, state: 0x%lx, refcnt: %d",
652  task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt);
653 
654  if (mutex_lock_interruptible(&fimc->lock))
655  return -ERESTARTSYS;
656  /*
657  * Return if the corresponding video capture node
658  * is already opened.
659  */
660  if (fimc->vid_cap.refcnt > 0)
661  goto unlock;
662 
663  ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
664  if (!ctx) {
665  ret = -ENOMEM;
666  goto unlock;
667  }
668  v4l2_fh_init(&ctx->fh, &fimc->m2m.vfd);
669  ctx->fimc_dev = fimc;
670 
671  /* Default color format */
672  ctx->s_frame.fmt = fimc_get_format(0);
673  ctx->d_frame.fmt = fimc_get_format(0);
674 
675  ret = fimc_ctrls_create(ctx);
676  if (ret)
677  goto error_fh;
678 
679  /* Use separate control handler per file handle */
680  ctx->fh.ctrl_handler = &ctx->ctrls.handler;
681  file->private_data = &ctx->fh;
682  v4l2_fh_add(&ctx->fh);
683 
684  /* Setup the device context for memory-to-memory mode */
685  ctx->state = FIMC_CTX_M2M;
686  ctx->flags = 0;
687  ctx->in_path = FIMC_IO_DMA;
688  ctx->out_path = FIMC_IO_DMA;
689 
690  ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init);
691  if (IS_ERR(ctx->m2m_ctx)) {
692  ret = PTR_ERR(ctx->m2m_ctx);
693  goto error_c;
694  }
695 
696  if (fimc->m2m.refcnt++ == 0)
697  set_bit(ST_M2M_RUN, &fimc->state);
698 
699  mutex_unlock(&fimc->lock);
700  return 0;
701 
702 error_c:
703  fimc_ctrls_delete(ctx);
704 error_fh:
705  v4l2_fh_del(&ctx->fh);
706  v4l2_fh_exit(&ctx->fh);
707  kfree(ctx);
708 unlock:
709  mutex_unlock(&fimc->lock);
710  return ret;
711 }
712 
713 static int fimc_m2m_release(struct file *file)
714 {
715  struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
716  struct fimc_dev *fimc = ctx->fimc_dev;
717 
718  dbg("pid: %d, state: 0x%lx, refcnt= %d",
719  task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
720 
721  mutex_lock(&fimc->lock);
722 
724  fimc_ctrls_delete(ctx);
725  v4l2_fh_del(&ctx->fh);
726  v4l2_fh_exit(&ctx->fh);
727 
728  if (--fimc->m2m.refcnt <= 0)
729  clear_bit(ST_M2M_RUN, &fimc->state);
730  kfree(ctx);
731 
732  mutex_unlock(&fimc->lock);
733  return 0;
734 }
735 
736 static unsigned int fimc_m2m_poll(struct file *file,
737  struct poll_table_struct *wait)
738 {
739  struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
740  struct fimc_dev *fimc = ctx->fimc_dev;
741  int ret;
742 
743  if (mutex_lock_interruptible(&fimc->lock))
744  return -ERESTARTSYS;
745 
746  ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
747  mutex_unlock(&fimc->lock);
748 
749  return ret;
750 }
751 
752 
753 static int fimc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
754 {
755  struct fimc_ctx *ctx = fh_to_ctx(file->private_data);
756  struct fimc_dev *fimc = ctx->fimc_dev;
757  int ret;
758 
759  if (mutex_lock_interruptible(&fimc->lock))
760  return -ERESTARTSYS;
761 
762  ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
763  mutex_unlock(&fimc->lock);
764 
765  return ret;
766 }
767 
768 static const struct v4l2_file_operations fimc_m2m_fops = {
769  .owner = THIS_MODULE,
770  .open = fimc_m2m_open,
771  .release = fimc_m2m_release,
772  .poll = fimc_m2m_poll,
773  .unlocked_ioctl = video_ioctl2,
774  .mmap = fimc_m2m_mmap,
775 };
776 
777 static struct v4l2_m2m_ops m2m_ops = {
778  .device_run = fimc_device_run,
779  .job_abort = fimc_job_abort,
780 };
781 
783  struct v4l2_device *v4l2_dev)
784 {
785  struct video_device *vfd = &fimc->m2m.vfd;
786  int ret;
787 
788  fimc->v4l2_dev = v4l2_dev;
789 
790  memset(vfd, 0, sizeof(*vfd));
791  vfd->fops = &fimc_m2m_fops;
792  vfd->ioctl_ops = &fimc_m2m_ioctl_ops;
793  vfd->v4l2_dev = v4l2_dev;
794  vfd->minor = -1;
796  vfd->lock = &fimc->lock;
797  vfd->vfl_dir = VFL_DIR_M2M;
798 
799  snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id);
800  video_set_drvdata(vfd, fimc);
801 
802  fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops);
803  if (IS_ERR(fimc->m2m.m2m_dev)) {
804  v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n");
805  return PTR_ERR(fimc->m2m.m2m_dev);
806  }
807 
808  ret = media_entity_init(&vfd->entity, 0, NULL, 0);
809  if (ret)
810  goto err_me;
811 
812  ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
813  if (ret)
814  goto err_vd;
815 
816  v4l2_info(v4l2_dev, "Registered %s as /dev/%s\n",
817  vfd->name, video_device_node_name(vfd));
818  return 0;
819 
820 err_vd:
821  media_entity_cleanup(&vfd->entity);
822 err_me:
823  v4l2_m2m_release(fimc->m2m.m2m_dev);
824  return ret;
825 }
826 
828 {
829  if (!fimc)
830  return;
831 
832  if (fimc->m2m.m2m_dev)
833  v4l2_m2m_release(fimc->m2m.m2m_dev);
834 
835  if (video_is_registered(&fimc->m2m.vfd)) {
836  video_unregister_device(&fimc->m2m.vfd);
837  media_entity_cleanup(&fimc->m2m.vfd.entity);
838  }
839 }