GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / media / platform / mediatek / mdp3 / mtk-mdp3-m2m.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2022 MediaTek Inc.
4  * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
5  */
6
7 #include <linux/platform_device.h>
8 #include <media/v4l2-ioctl.h>
9 #include <media/v4l2-event.h>
10 #include <media/videobuf2-dma-contig.h>
11 #include "mtk-mdp3-m2m.h"
12
13 static inline struct mdp_m2m_ctx *fh_to_ctx(struct v4l2_fh *fh)
14 {
15         return container_of(fh, struct mdp_m2m_ctx, fh);
16 }
17
18 static inline struct mdp_m2m_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl)
19 {
20         return container_of(ctrl->handler, struct mdp_m2m_ctx, ctrl_handler);
21 }
22
23 static inline struct mdp_frame *ctx_get_frame(struct mdp_m2m_ctx *ctx,
24                                               enum v4l2_buf_type type)
25 {
26         if (V4L2_TYPE_IS_OUTPUT(type))
27                 return &ctx->curr_param.output;
28         else
29                 return &ctx->curr_param.captures[0];
30 }
31
32 static inline void mdp_m2m_ctx_set_state(struct mdp_m2m_ctx *ctx, u32 state)
33 {
34         atomic_or(state, &ctx->curr_param.state);
35 }
36
37 static inline bool mdp_m2m_ctx_is_state_set(struct mdp_m2m_ctx *ctx, u32 mask)
38 {
39         return ((atomic_read(&ctx->curr_param.state) & mask) == mask);
40 }
41
42 static void mdp_m2m_process_done(void *priv, int vb_state)
43 {
44         struct mdp_m2m_ctx *ctx = priv;
45         struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf;
46
47         src_vbuf = (struct vb2_v4l2_buffer *)
48                         v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
49         dst_vbuf = (struct vb2_v4l2_buffer *)
50                         v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
51         ctx->curr_param.frame_no = ctx->frame_count[MDP_M2M_SRC];
52         src_vbuf->sequence = ctx->frame_count[MDP_M2M_SRC]++;
53         dst_vbuf->sequence = ctx->frame_count[MDP_M2M_DST]++;
54         v4l2_m2m_buf_copy_metadata(src_vbuf, dst_vbuf, true);
55
56         v4l2_m2m_buf_done(src_vbuf, vb_state);
57         v4l2_m2m_buf_done(dst_vbuf, vb_state);
58         v4l2_m2m_job_finish(ctx->mdp_dev->m2m_dev, ctx->m2m_ctx);
59 }
60
61 static void mdp_m2m_device_run(void *priv)
62 {
63         struct mdp_m2m_ctx *ctx = priv;
64         struct mdp_frame *frame;
65         struct vb2_v4l2_buffer *src_vb, *dst_vb;
66         struct img_ipi_frameparam param = {};
67         struct mdp_cmdq_param task = {};
68         enum vb2_buffer_state vb_state = VB2_BUF_STATE_ERROR;
69         int ret;
70
71         if (mdp_m2m_ctx_is_state_set(ctx, MDP_M2M_CTX_ERROR)) {
72                 dev_err(&ctx->mdp_dev->pdev->dev,
73                         "mdp_m2m_ctx is in error state\n");
74                 goto worker_end;
75         }
76
77         param.frame_no = ctx->curr_param.frame_no;
78         param.type = ctx->curr_param.type;
79         param.num_inputs = 1;
80         param.num_outputs = 1;
81
82         frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
83         src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
84         mdp_set_src_config(&param.inputs[0], frame, &src_vb->vb2_buf);
85
86         frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
87         dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
88         mdp_set_dst_config(&param.outputs[0], frame, &dst_vb->vb2_buf);
89
90         ret = mdp_vpu_process(&ctx->mdp_dev->vpu, &param);
91         if (ret) {
92                 dev_err(&ctx->mdp_dev->pdev->dev,
93                         "VPU MDP process failed: %d\n", ret);
94                 goto worker_end;
95         }
96
97         task.config = ctx->mdp_dev->vpu.config;
98         task.param = &param;
99         task.composes[0] = &frame->compose;
100         task.cmdq_cb = NULL;
101         task.cb_data = NULL;
102         task.mdp_ctx = ctx;
103
104         ret = mdp_cmdq_send(ctx->mdp_dev, &task);
105         if (ret) {
106                 dev_err(&ctx->mdp_dev->pdev->dev,
107                         "CMDQ sendtask failed: %d\n", ret);
108                 goto worker_end;
109         }
110
111         return;
112
113 worker_end:
114         mdp_m2m_process_done(ctx, vb_state);
115 }
116
117 static int mdp_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
118 {
119         struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q);
120         struct mdp_frame *capture;
121         struct vb2_queue *vq;
122         int ret;
123         bool out_streaming, cap_streaming;
124
125         if (V4L2_TYPE_IS_OUTPUT(q->type))
126                 ctx->frame_count[MDP_M2M_SRC] = 0;
127
128         if (V4L2_TYPE_IS_CAPTURE(q->type))
129                 ctx->frame_count[MDP_M2M_DST] = 0;
130
131         capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
132         vq = v4l2_m2m_get_src_vq(ctx->m2m_ctx);
133         out_streaming = vb2_is_streaming(vq);
134         vq = v4l2_m2m_get_dst_vq(ctx->m2m_ctx);
135         cap_streaming = vb2_is_streaming(vq);
136
137         /* Check to see if scaling ratio is within supported range */
138         if ((V4L2_TYPE_IS_OUTPUT(q->type) && cap_streaming) ||
139             (V4L2_TYPE_IS_CAPTURE(q->type) && out_streaming)) {
140                 ret = mdp_check_scaling_ratio(&capture->crop.c,
141                                               &capture->compose,
142                                               capture->rotation,
143                                               ctx->curr_param.limit);
144                 if (ret) {
145                         dev_err(&ctx->mdp_dev->pdev->dev,
146                                 "Out of scaling range\n");
147                         return ret;
148                 }
149         }
150
151         if (!mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT)) {
152                 ret = mdp_vpu_get_locked(ctx->mdp_dev);
153                 if (ret) {
154                         dev_err(&ctx->mdp_dev->pdev->dev,
155                                 "VPU init failed %d\n", ret);
156                         return -EINVAL;
157                 }
158                 mdp_m2m_ctx_set_state(ctx, MDP_VPU_INIT);
159         }
160
161         return 0;
162 }
163
164 static struct vb2_v4l2_buffer *mdp_m2m_buf_remove(struct mdp_m2m_ctx *ctx,
165                                                   unsigned int type)
166 {
167         if (V4L2_TYPE_IS_OUTPUT(type))
168                 return (struct vb2_v4l2_buffer *)
169                         v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
170         else
171                 return (struct vb2_v4l2_buffer *)
172                         v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
173 }
174
175 static void mdp_m2m_stop_streaming(struct vb2_queue *q)
176 {
177         struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q);
178         struct vb2_v4l2_buffer *vb;
179
180         vb = mdp_m2m_buf_remove(ctx, q->type);
181         while (vb) {
182                 v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
183                 vb = mdp_m2m_buf_remove(ctx, q->type);
184         }
185 }
186
187 static int mdp_m2m_queue_setup(struct vb2_queue *q,
188                                unsigned int *num_buffers,
189                                unsigned int *num_planes, unsigned int sizes[],
190                                struct device *alloc_devs[])
191 {
192         struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(q);
193         struct v4l2_pix_format_mplane *pix_mp;
194         u32 i;
195
196         pix_mp = &ctx_get_frame(ctx, q->type)->format.fmt.pix_mp;
197
198         /* from VIDIOC_CREATE_BUFS */
199         if (*num_planes) {
200                 if (*num_planes != pix_mp->num_planes)
201                         return -EINVAL;
202                 for (i = 0; i < pix_mp->num_planes; ++i)
203                         if (sizes[i] < pix_mp->plane_fmt[i].sizeimage)
204                                 return -EINVAL;
205         } else {/* from VIDIOC_REQBUFS */
206                 *num_planes = pix_mp->num_planes;
207                 for (i = 0; i < pix_mp->num_planes; ++i)
208                         sizes[i] = pix_mp->plane_fmt[i].sizeimage;
209         }
210
211         return 0;
212 }
213
214 static int mdp_m2m_buf_prepare(struct vb2_buffer *vb)
215 {
216         struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
217         struct v4l2_pix_format_mplane *pix_mp;
218         struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb);
219         u32 i;
220
221         v4l2_buf->field = V4L2_FIELD_NONE;
222
223         if (V4L2_TYPE_IS_CAPTURE(vb->type)) {
224                 pix_mp = &ctx_get_frame(ctx, vb->type)->format.fmt.pix_mp;
225                 for (i = 0; i < pix_mp->num_planes; ++i) {
226                         vb2_set_plane_payload(vb, i,
227                                               pix_mp->plane_fmt[i].sizeimage);
228                 }
229         }
230         return 0;
231 }
232
233 static int mdp_m2m_buf_out_validate(struct vb2_buffer *vb)
234 {
235         struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb);
236
237         v4l2_buf->field = V4L2_FIELD_NONE;
238
239         return 0;
240 }
241
242 static void mdp_m2m_buf_queue(struct vb2_buffer *vb)
243 {
244         struct mdp_m2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
245         struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb);
246
247         v4l2_buf->field = V4L2_FIELD_NONE;
248
249         v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb));
250 }
251
252 static const struct vb2_ops mdp_m2m_qops = {
253         .queue_setup    = mdp_m2m_queue_setup,
254         .wait_prepare   = vb2_ops_wait_prepare,
255         .wait_finish    = vb2_ops_wait_finish,
256         .buf_prepare    = mdp_m2m_buf_prepare,
257         .start_streaming = mdp_m2m_start_streaming,
258         .stop_streaming = mdp_m2m_stop_streaming,
259         .buf_queue      = mdp_m2m_buf_queue,
260         .buf_out_validate = mdp_m2m_buf_out_validate,
261 };
262
263 static int mdp_m2m_querycap(struct file *file, void *fh,
264                             struct v4l2_capability *cap)
265 {
266         strscpy(cap->driver, MDP_MODULE_NAME, sizeof(cap->driver));
267         strscpy(cap->card, MDP_DEVICE_NAME, sizeof(cap->card));
268
269         return 0;
270 }
271
272 static int mdp_m2m_enum_fmt_mplane(struct file *file, void *fh,
273                                    struct v4l2_fmtdesc *f)
274 {
275         struct mdp_m2m_ctx *ctx = fh_to_ctx(fh);
276
277         return mdp_enum_fmt_mplane(ctx->mdp_dev, f);
278 }
279
280 static int mdp_m2m_g_fmt_mplane(struct file *file, void *fh,
281                                 struct v4l2_format *f)
282 {
283         struct mdp_m2m_ctx *ctx = fh_to_ctx(fh);
284         struct mdp_frame *frame;
285         struct v4l2_pix_format_mplane *pix_mp;
286
287         frame = ctx_get_frame(ctx, f->type);
288         *f = frame->format;
289         pix_mp = &f->fmt.pix_mp;
290         pix_mp->colorspace = ctx->curr_param.colorspace;
291         pix_mp->xfer_func = ctx->curr_param.xfer_func;
292         pix_mp->ycbcr_enc = ctx->curr_param.ycbcr_enc;
293         pix_mp->quantization = ctx->curr_param.quant;
294
295         return 0;
296 }
297
298 static int mdp_m2m_s_fmt_mplane(struct file *file, void *fh,
299                                 struct v4l2_format *f)
300 {
301         struct mdp_m2m_ctx *ctx = fh_to_ctx(fh);
302         struct mdp_frame *frame = ctx_get_frame(ctx, f->type);
303         struct mdp_frame *capture;
304         const struct mdp_format *fmt;
305         struct vb2_queue *vq;
306
307         fmt = mdp_try_fmt_mplane(ctx->mdp_dev, f, &ctx->curr_param, ctx->id);
308         if (!fmt)
309                 return -EINVAL;
310
311         vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
312         if (vb2_is_busy(vq))
313                 return -EBUSY;
314
315         frame->format = *f;
316         frame->mdp_fmt = fmt;
317         frame->ycbcr_prof = mdp_map_ycbcr_prof_mplane(f, fmt->mdp_color);
318         frame->usage = V4L2_TYPE_IS_OUTPUT(f->type) ?
319                 MDP_BUFFER_USAGE_HW_READ : MDP_BUFFER_USAGE_MDP;
320
321         capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
322         if (V4L2_TYPE_IS_OUTPUT(f->type)) {
323                 capture->crop.c.left = 0;
324                 capture->crop.c.top = 0;
325                 capture->crop.c.width = f->fmt.pix_mp.width;
326                 capture->crop.c.height = f->fmt.pix_mp.height;
327                 ctx->curr_param.colorspace = f->fmt.pix_mp.colorspace;
328                 ctx->curr_param.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
329                 ctx->curr_param.quant = f->fmt.pix_mp.quantization;
330                 ctx->curr_param.xfer_func = f->fmt.pix_mp.xfer_func;
331         } else {
332                 capture->compose.left = 0;
333                 capture->compose.top = 0;
334                 capture->compose.width = f->fmt.pix_mp.width;
335                 capture->compose.height = f->fmt.pix_mp.height;
336         }
337
338         return 0;
339 }
340
341 static int mdp_m2m_try_fmt_mplane(struct file *file, void *fh,
342                                   struct v4l2_format *f)
343 {
344         struct mdp_m2m_ctx *ctx = fh_to_ctx(fh);
345
346         if (!mdp_try_fmt_mplane(ctx->mdp_dev, f, &ctx->curr_param, ctx->id))
347                 return -EINVAL;
348
349         return 0;
350 }
351
352 static int mdp_m2m_g_selection(struct file *file, void *fh,
353                                struct v4l2_selection *s)
354 {
355         struct mdp_m2m_ctx *ctx = fh_to_ctx(fh);
356         struct mdp_frame *frame;
357         bool valid = false;
358
359         if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
360                 valid = mdp_target_is_crop(s->target);
361         else if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
362                 valid = mdp_target_is_compose(s->target);
363
364         if (!valid)
365                 return -EINVAL;
366
367         switch (s->target) {
368         case V4L2_SEL_TGT_CROP:
369                 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
370                         return -EINVAL;
371                 frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
372                 s->r = frame->crop.c;
373                 return 0;
374         case V4L2_SEL_TGT_COMPOSE:
375                 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
376                         return -EINVAL;
377                 frame = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
378                 s->r = frame->compose;
379                 return 0;
380         case V4L2_SEL_TGT_CROP_DEFAULT:
381         case V4L2_SEL_TGT_CROP_BOUNDS:
382                 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
383                         return -EINVAL;
384                 frame = ctx_get_frame(ctx, s->type);
385                 s->r.left = 0;
386                 s->r.top = 0;
387                 s->r.width = frame->format.fmt.pix_mp.width;
388                 s->r.height = frame->format.fmt.pix_mp.height;
389                 return 0;
390         case V4L2_SEL_TGT_COMPOSE_DEFAULT:
391         case V4L2_SEL_TGT_COMPOSE_BOUNDS:
392                 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
393                         return -EINVAL;
394                 frame = ctx_get_frame(ctx, s->type);
395                 s->r.left = 0;
396                 s->r.top = 0;
397                 s->r.width = frame->format.fmt.pix_mp.width;
398                 s->r.height = frame->format.fmt.pix_mp.height;
399                 return 0;
400         }
401         return -EINVAL;
402 }
403
404 static int mdp_m2m_s_selection(struct file *file, void *fh,
405                                struct v4l2_selection *s)
406 {
407         struct mdp_m2m_ctx *ctx = fh_to_ctx(fh);
408         struct mdp_frame *frame = ctx_get_frame(ctx, s->type);
409         struct mdp_frame *capture;
410         struct v4l2_rect r;
411         struct device *dev = &ctx->mdp_dev->pdev->dev;
412         bool valid = false;
413         int ret;
414
415         if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
416                 valid = (s->target == V4L2_SEL_TGT_CROP);
417         else if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
418                 valid = (s->target == V4L2_SEL_TGT_COMPOSE);
419
420         if (!valid) {
421                 dev_dbg(dev, "[%s:%d] invalid type:%u target:%u", __func__,
422                         ctx->id, s->type, s->target);
423                 return -EINVAL;
424         }
425
426         ret = mdp_try_crop(ctx, &r, s, frame);
427         if (ret)
428                 return ret;
429         capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
430
431         if (mdp_target_is_crop(s->target))
432                 capture->crop.c = r;
433         else
434                 capture->compose = r;
435
436         s->r = r;
437
438         return 0;
439 }
440
441 static const struct v4l2_ioctl_ops mdp_m2m_ioctl_ops = {
442         .vidioc_querycap                = mdp_m2m_querycap,
443         .vidioc_enum_fmt_vid_cap        = mdp_m2m_enum_fmt_mplane,
444         .vidioc_enum_fmt_vid_out        = mdp_m2m_enum_fmt_mplane,
445         .vidioc_g_fmt_vid_cap_mplane    = mdp_m2m_g_fmt_mplane,
446         .vidioc_g_fmt_vid_out_mplane    = mdp_m2m_g_fmt_mplane,
447         .vidioc_s_fmt_vid_cap_mplane    = mdp_m2m_s_fmt_mplane,
448         .vidioc_s_fmt_vid_out_mplane    = mdp_m2m_s_fmt_mplane,
449         .vidioc_try_fmt_vid_cap_mplane  = mdp_m2m_try_fmt_mplane,
450         .vidioc_try_fmt_vid_out_mplane  = mdp_m2m_try_fmt_mplane,
451         .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
452         .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
453         .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
454         .vidioc_expbuf                  = v4l2_m2m_ioctl_expbuf,
455         .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
456         .vidioc_create_bufs             = v4l2_m2m_ioctl_create_bufs,
457         .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
458         .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
459         .vidioc_g_selection             = mdp_m2m_g_selection,
460         .vidioc_s_selection             = mdp_m2m_s_selection,
461         .vidioc_subscribe_event         = v4l2_ctrl_subscribe_event,
462         .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
463 };
464
465 static int mdp_m2m_queue_init(void *priv,
466                               struct vb2_queue *src_vq,
467                               struct vb2_queue *dst_vq)
468 {
469         struct mdp_m2m_ctx *ctx = priv;
470         int ret;
471
472         src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
473         src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
474         src_vq->ops = &mdp_m2m_qops;
475         src_vq->mem_ops = &vb2_dma_contig_memops;
476         src_vq->drv_priv = ctx;
477         src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
478         src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
479         src_vq->dev = &ctx->mdp_dev->pdev->dev;
480         src_vq->lock = &ctx->ctx_lock;
481
482         ret = vb2_queue_init(src_vq);
483         if (ret)
484                 return ret;
485
486         dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
487         dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
488         dst_vq->ops = &mdp_m2m_qops;
489         dst_vq->mem_ops = &vb2_dma_contig_memops;
490         dst_vq->drv_priv = ctx;
491         dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
492         dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
493         dst_vq->dev = &ctx->mdp_dev->pdev->dev;
494         dst_vq->lock = &ctx->ctx_lock;
495
496         return vb2_queue_init(dst_vq);
497 }
498
499 static int mdp_m2m_s_ctrl(struct v4l2_ctrl *ctrl)
500 {
501         struct mdp_m2m_ctx *ctx = ctrl_to_ctx(ctrl);
502         struct mdp_frame *capture;
503
504         capture = ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
505         switch (ctrl->id) {
506         case V4L2_CID_HFLIP:
507                 capture->hflip = ctrl->val;
508                 break;
509         case V4L2_CID_VFLIP:
510                 capture->vflip = ctrl->val;
511                 break;
512         case V4L2_CID_ROTATE:
513                 capture->rotation = ctrl->val;
514                 break;
515         }
516
517         return 0;
518 }
519
520 static const struct v4l2_ctrl_ops mdp_m2m_ctrl_ops = {
521         .s_ctrl = mdp_m2m_s_ctrl,
522 };
523
524 static int mdp_m2m_ctrls_create(struct mdp_m2m_ctx *ctx)
525 {
526         v4l2_ctrl_handler_init(&ctx->ctrl_handler, MDP_MAX_CTRLS);
527         ctx->ctrls.hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler,
528                                              &mdp_m2m_ctrl_ops, V4L2_CID_HFLIP,
529                                              0, 1, 1, 0);
530         ctx->ctrls.vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler,
531                                              &mdp_m2m_ctrl_ops, V4L2_CID_VFLIP,
532                                              0, 1, 1, 0);
533         ctx->ctrls.rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler,
534                                               &mdp_m2m_ctrl_ops,
535                                               V4L2_CID_ROTATE, 0, 270, 90, 0);
536
537         if (ctx->ctrl_handler.error) {
538                 int err = ctx->ctrl_handler.error;
539
540                 v4l2_ctrl_handler_free(&ctx->ctrl_handler);
541                 dev_err(&ctx->mdp_dev->pdev->dev,
542                         "Failed to register controls\n");
543                 return err;
544         }
545         return 0;
546 }
547
548 static int mdp_m2m_open(struct file *file)
549 {
550         struct video_device *vdev = video_devdata(file);
551         struct mdp_dev *mdp = video_get_drvdata(vdev);
552         struct mdp_m2m_ctx *ctx;
553         struct device *dev = &mdp->pdev->dev;
554         int ret;
555         struct v4l2_format default_format = {};
556         const struct mdp_limit *limit = mdp->mdp_data->def_limit;
557
558         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
559         if (!ctx)
560                 return -ENOMEM;
561
562         if (mutex_lock_interruptible(&mdp->m2m_lock)) {
563                 ret = -ERESTARTSYS;
564                 goto err_free_ctx;
565         }
566
567         ret = ida_alloc(&mdp->mdp_ida, GFP_KERNEL);
568         if (ret < 0)
569                 goto err_unlock_mutex;
570         ctx->id = ret;
571
572         ctx->mdp_dev = mdp;
573
574         v4l2_fh_init(&ctx->fh, vdev);
575         file->private_data = &ctx->fh;
576         ret = mdp_m2m_ctrls_create(ctx);
577         if (ret)
578                 goto err_exit_fh;
579
580         /* Use separate control handler per file handle */
581         ctx->fh.ctrl_handler = &ctx->ctrl_handler;
582         v4l2_fh_add(&ctx->fh);
583
584         mutex_init(&ctx->ctx_lock);
585         ctx->m2m_ctx = v4l2_m2m_ctx_init(mdp->m2m_dev, ctx, mdp_m2m_queue_init);
586         if (IS_ERR(ctx->m2m_ctx)) {
587                 dev_err(dev, "Failed to initialize m2m context\n");
588                 ret = PTR_ERR(ctx->m2m_ctx);
589                 goto err_release_handler;
590         }
591         ctx->fh.m2m_ctx = ctx->m2m_ctx;
592
593         ctx->curr_param.ctx = ctx;
594         ret = mdp_frameparam_init(mdp, &ctx->curr_param);
595         if (ret) {
596                 dev_err(dev, "Failed to initialize mdp parameter\n");
597                 goto err_release_m2m_ctx;
598         }
599
600         mutex_unlock(&mdp->m2m_lock);
601
602         /* Default format */
603         default_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
604         default_format.fmt.pix_mp.width = limit->out_limit.wmin;
605         default_format.fmt.pix_mp.height = limit->out_limit.hmin;
606         default_format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M;
607         mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format);
608         default_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
609         mdp_m2m_s_fmt_mplane(file, &ctx->fh, &default_format);
610
611         dev_dbg(dev, "%s:[%d]", __func__, ctx->id);
612
613         return 0;
614
615 err_release_m2m_ctx:
616         v4l2_m2m_ctx_release(ctx->m2m_ctx);
617 err_release_handler:
618         v4l2_ctrl_handler_free(&ctx->ctrl_handler);
619         v4l2_fh_del(&ctx->fh);
620 err_exit_fh:
621         v4l2_fh_exit(&ctx->fh);
622         ida_free(&mdp->mdp_ida, ctx->id);
623 err_unlock_mutex:
624         mutex_unlock(&mdp->m2m_lock);
625 err_free_ctx:
626         kfree(ctx);
627
628         return ret;
629 }
630
631 static int mdp_m2m_release(struct file *file)
632 {
633         struct mdp_m2m_ctx *ctx = fh_to_ctx(file->private_data);
634         struct mdp_dev *mdp = video_drvdata(file);
635         struct device *dev = &mdp->pdev->dev;
636
637         mutex_lock(&mdp->m2m_lock);
638         v4l2_m2m_ctx_release(ctx->m2m_ctx);
639         if (mdp_m2m_ctx_is_state_set(ctx, MDP_VPU_INIT))
640                 mdp_vpu_put_locked(mdp);
641
642         v4l2_ctrl_handler_free(&ctx->ctrl_handler);
643         v4l2_fh_del(&ctx->fh);
644         v4l2_fh_exit(&ctx->fh);
645         ida_free(&mdp->mdp_ida, ctx->id);
646         mutex_unlock(&mdp->m2m_lock);
647
648         dev_dbg(dev, "%s:[%d]", __func__, ctx->id);
649         kfree(ctx);
650
651         return 0;
652 }
653
654 static const struct v4l2_file_operations mdp_m2m_fops = {
655         .owner          = THIS_MODULE,
656         .poll           = v4l2_m2m_fop_poll,
657         .unlocked_ioctl = video_ioctl2,
658         .mmap           = v4l2_m2m_fop_mmap,
659         .open           = mdp_m2m_open,
660         .release        = mdp_m2m_release,
661 };
662
663 static const struct v4l2_m2m_ops mdp_m2m_ops = {
664         .device_run     = mdp_m2m_device_run,
665 };
666
667 int mdp_m2m_device_register(struct mdp_dev *mdp)
668 {
669         struct device *dev = &mdp->pdev->dev;
670         int ret = 0;
671
672         mdp->m2m_vdev = video_device_alloc();
673         if (!mdp->m2m_vdev) {
674                 dev_err(dev, "Failed to allocate video device\n");
675                 ret = -ENOMEM;
676                 goto err_video_alloc;
677         }
678         mdp->m2m_vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE |
679                 V4L2_CAP_STREAMING;
680         mdp->m2m_vdev->fops = &mdp_m2m_fops;
681         mdp->m2m_vdev->ioctl_ops = &mdp_m2m_ioctl_ops;
682         mdp->m2m_vdev->release = mdp_video_device_release;
683         mdp->m2m_vdev->lock = &mdp->m2m_lock;
684         mdp->m2m_vdev->vfl_dir = VFL_DIR_M2M;
685         mdp->m2m_vdev->v4l2_dev = &mdp->v4l2_dev;
686         snprintf(mdp->m2m_vdev->name, sizeof(mdp->m2m_vdev->name), "%s:m2m",
687                  MDP_MODULE_NAME);
688         video_set_drvdata(mdp->m2m_vdev, mdp);
689
690         mdp->m2m_dev = v4l2_m2m_init(&mdp_m2m_ops);
691         if (IS_ERR(mdp->m2m_dev)) {
692                 dev_err(dev, "Failed to initialize v4l2-m2m device\n");
693                 ret = PTR_ERR(mdp->m2m_dev);
694                 goto err_m2m_init;
695         }
696
697         ret = video_register_device(mdp->m2m_vdev, VFL_TYPE_VIDEO, -1);
698         if (ret) {
699                 dev_err(dev, "Failed to register video device\n");
700                 goto err_video_register;
701         }
702
703         v4l2_info(&mdp->v4l2_dev, "Driver registered as /dev/video%d",
704                   mdp->m2m_vdev->num);
705         return 0;
706
707 err_video_register:
708         v4l2_m2m_release(mdp->m2m_dev);
709 err_m2m_init:
710         video_device_release(mdp->m2m_vdev);
711 err_video_alloc:
712
713         return ret;
714 }
715
716 void mdp_m2m_device_unregister(struct mdp_dev *mdp)
717 {
718         video_unregister_device(mdp->m2m_vdev);
719 }
720
721 void mdp_m2m_job_finish(struct mdp_m2m_ctx *ctx)
722 {
723         enum vb2_buffer_state vb_state = VB2_BUF_STATE_DONE;
724
725         mdp_m2m_process_done(ctx, vb_state);
726 }