flexfiles: use per-mirror specified stateid for IO
[sfrench/cifs-2.6.git] / drivers / media / platform / vicodec / vicodec-core.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * A virtual codec example device.
4  *
5  * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6  *
7  * This is a virtual codec device driver for testing the codec framework.
8  * It simulates a device that uses memory buffers for both source and
9  * destination and encodes or decodes the data.
10  */
11
12 #include <linux/module.h>
13 #include <linux/delay.h>
14 #include <linux/fs.h>
15 #include <linux/sched.h>
16 #include <linux/slab.h>
17
18 #include <linux/platform_device.h>
19 #include <media/v4l2-mem2mem.h>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-ioctl.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-event.h>
24 #include <media/videobuf2-vmalloc.h>
25
26 #include "codec-v4l2-fwht.h"
27
28 MODULE_DESCRIPTION("Virtual codec device");
29 MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
30 MODULE_LICENSE("GPL v2");
31
32 static bool multiplanar;
33 module_param(multiplanar, bool, 0444);
34 MODULE_PARM_DESC(multiplanar,
35                  " use multi-planar API instead of single-planar API");
36
37 static unsigned int debug;
38 module_param(debug, uint, 0644);
39 MODULE_PARM_DESC(debug, " activates debug info");
40
41 #define VICODEC_NAME            "vicodec"
42 #define MAX_WIDTH               4096U
43 #define MIN_WIDTH               640U
44 #define MAX_HEIGHT              2160U
45 #define MIN_HEIGHT              480U
46
47 #define dprintk(dev, fmt, arg...) \
48         v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
49
50
51 struct pixfmt_info {
52         u32 id;
53         unsigned int bytesperline_mult;
54         unsigned int sizeimage_mult;
55         unsigned int sizeimage_div;
56         unsigned int luma_step;
57         unsigned int chroma_step;
58         /* Chroma plane subsampling */
59         unsigned int width_div;
60         unsigned int height_div;
61 };
62
63 static const struct v4l2_fwht_pixfmt_info pixfmt_fwht = {
64         V4L2_PIX_FMT_FWHT, 0, 3, 1, 1, 1, 1, 1
65 };
66
67 static void vicodec_dev_release(struct device *dev)
68 {
69 }
70
71 static struct platform_device vicodec_pdev = {
72         .name           = VICODEC_NAME,
73         .dev.release    = vicodec_dev_release,
74 };
75
76 /* Per-queue, driver-specific private data */
77 struct vicodec_q_data {
78         unsigned int            width;
79         unsigned int            height;
80         unsigned int            sizeimage;
81         unsigned int            sequence;
82         const struct v4l2_fwht_pixfmt_info *info;
83 };
84
85 enum {
86         V4L2_M2M_SRC = 0,
87         V4L2_M2M_DST = 1,
88 };
89
90 struct vicodec_dev {
91         struct v4l2_device      v4l2_dev;
92         struct video_device     enc_vfd;
93         struct video_device     dec_vfd;
94 #ifdef CONFIG_MEDIA_CONTROLLER
95         struct media_device     mdev;
96 #endif
97
98         struct mutex            enc_mutex;
99         struct mutex            dec_mutex;
100         spinlock_t              enc_lock;
101         spinlock_t              dec_lock;
102
103         struct v4l2_m2m_dev     *enc_dev;
104         struct v4l2_m2m_dev     *dec_dev;
105 };
106
107 struct vicodec_ctx {
108         struct v4l2_fh          fh;
109         struct vicodec_dev      *dev;
110         bool                    is_enc;
111         spinlock_t              *lock;
112
113         struct v4l2_ctrl_handler hdl;
114
115         struct vb2_v4l2_buffer *last_src_buf;
116         struct vb2_v4l2_buffer *last_dst_buf;
117
118         /* Source and destination queue data */
119         struct vicodec_q_data   q_data[2];
120         struct v4l2_fwht_state  state;
121
122         u32                     cur_buf_offset;
123         u32                     comp_max_size;
124         u32                     comp_size;
125         u32                     comp_magic_cnt;
126         u32                     comp_frame_size;
127         bool                    comp_has_frame;
128         bool                    comp_has_next_frame;
129 };
130
131 static inline struct vicodec_ctx *file2ctx(struct file *file)
132 {
133         return container_of(file->private_data, struct vicodec_ctx, fh);
134 }
135
136 static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx,
137                                          enum v4l2_buf_type type)
138 {
139         switch (type) {
140         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
141         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
142                 return &ctx->q_data[V4L2_M2M_SRC];
143         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
144         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
145                 return &ctx->q_data[V4L2_M2M_DST];
146         default:
147                 WARN_ON(1);
148                 break;
149         }
150         return NULL;
151 }
152
153 static int device_process(struct vicodec_ctx *ctx,
154                           struct vb2_v4l2_buffer *in_vb,
155                           struct vb2_v4l2_buffer *out_vb)
156 {
157         struct vicodec_dev *dev = ctx->dev;
158         struct vicodec_q_data *q_cap;
159         struct v4l2_fwht_state *state = &ctx->state;
160         u8 *p_in, *p_out;
161         int ret;
162
163         q_cap = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
164         if (ctx->is_enc)
165                 p_in = vb2_plane_vaddr(&in_vb->vb2_buf, 0);
166         else
167                 p_in = state->compressed_frame;
168         p_out = vb2_plane_vaddr(&out_vb->vb2_buf, 0);
169         if (!p_in || !p_out) {
170                 v4l2_err(&dev->v4l2_dev,
171                          "Acquiring kernel pointers to buffers failed\n");
172                 return -EFAULT;
173         }
174
175         if (ctx->is_enc) {
176                 struct vicodec_q_data *q_out;
177
178                 q_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
179                 state->info = q_out->info;
180                 ret = v4l2_fwht_encode(state, p_in, p_out);
181                 if (ret < 0)
182                         return ret;
183                 vb2_set_plane_payload(&out_vb->vb2_buf, 0, ret);
184         } else {
185                 state->info = q_cap->info;
186                 ret = v4l2_fwht_decode(state, p_in, p_out);
187                 if (ret < 0)
188                         return ret;
189                 vb2_set_plane_payload(&out_vb->vb2_buf, 0, q_cap->sizeimage);
190         }
191
192         out_vb->sequence = q_cap->sequence++;
193         out_vb->vb2_buf.timestamp = in_vb->vb2_buf.timestamp;
194
195         if (in_vb->flags & V4L2_BUF_FLAG_TIMECODE)
196                 out_vb->timecode = in_vb->timecode;
197         out_vb->field = in_vb->field;
198         out_vb->flags &= ~V4L2_BUF_FLAG_LAST;
199         out_vb->flags |= in_vb->flags &
200                 (V4L2_BUF_FLAG_TIMECODE |
201                  V4L2_BUF_FLAG_KEYFRAME |
202                  V4L2_BUF_FLAG_PFRAME |
203                  V4L2_BUF_FLAG_BFRAME |
204                  V4L2_BUF_FLAG_TSTAMP_SRC_MASK);
205
206         return 0;
207 }
208
209 /*
210  * mem2mem callbacks
211  */
212
213 /* device_run() - prepares and starts the device */
214 static void device_run(void *priv)
215 {
216         static const struct v4l2_event eos_event = {
217                 .type = V4L2_EVENT_EOS
218         };
219         struct vicodec_ctx *ctx = priv;
220         struct vicodec_dev *dev = ctx->dev;
221         struct vb2_v4l2_buffer *src_buf, *dst_buf;
222         struct vicodec_q_data *q_out;
223         u32 state;
224
225         src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
226         dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
227         q_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
228
229         state = VB2_BUF_STATE_DONE;
230         if (device_process(ctx, src_buf, dst_buf))
231                 state = VB2_BUF_STATE_ERROR;
232         ctx->last_dst_buf = dst_buf;
233
234         spin_lock(ctx->lock);
235         if (!ctx->comp_has_next_frame && src_buf == ctx->last_src_buf) {
236                 dst_buf->flags |= V4L2_BUF_FLAG_LAST;
237                 v4l2_event_queue_fh(&ctx->fh, &eos_event);
238         }
239         if (ctx->is_enc) {
240                 src_buf->sequence = q_out->sequence++;
241                 src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
242                 v4l2_m2m_buf_done(src_buf, state);
243         } else if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == ctx->cur_buf_offset) {
244                 src_buf->sequence = q_out->sequence++;
245                 src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
246                 v4l2_m2m_buf_done(src_buf, state);
247                 ctx->cur_buf_offset = 0;
248                 ctx->comp_has_next_frame = false;
249         }
250         v4l2_m2m_buf_done(dst_buf, state);
251         ctx->comp_size = 0;
252         ctx->comp_magic_cnt = 0;
253         ctx->comp_has_frame = false;
254         spin_unlock(ctx->lock);
255
256         if (ctx->is_enc)
257                 v4l2_m2m_job_finish(dev->enc_dev, ctx->fh.m2m_ctx);
258         else
259                 v4l2_m2m_job_finish(dev->dec_dev, ctx->fh.m2m_ctx);
260 }
261
262 static void job_remove_out_buf(struct vicodec_ctx *ctx, u32 state)
263 {
264         struct vb2_v4l2_buffer *src_buf;
265         struct vicodec_q_data *q_out;
266
267         q_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
268         spin_lock(ctx->lock);
269         src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
270         src_buf->sequence = q_out->sequence++;
271         v4l2_m2m_buf_done(src_buf, state);
272         ctx->cur_buf_offset = 0;
273         spin_unlock(ctx->lock);
274 }
275
276 static int job_ready(void *priv)
277 {
278         static const u8 magic[] = {
279                 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
280         };
281         struct vicodec_ctx *ctx = priv;
282         struct vb2_v4l2_buffer *src_buf;
283         u8 *p_out;
284         u8 *p;
285         u32 sz;
286         u32 state;
287
288         if (ctx->is_enc || ctx->comp_has_frame)
289                 return 1;
290
291 restart:
292         ctx->comp_has_next_frame = false;
293         src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
294         if (!src_buf)
295                 return 0;
296         p_out = vb2_plane_vaddr(&src_buf->vb2_buf, 0);
297         sz = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
298         p = p_out + ctx->cur_buf_offset;
299
300         state = VB2_BUF_STATE_DONE;
301
302         if (!ctx->comp_size) {
303                 state = VB2_BUF_STATE_ERROR;
304                 for (; p < p_out + sz; p++) {
305                         u32 copy;
306
307                         p = memchr(p, magic[ctx->comp_magic_cnt], sz);
308                         if (!p) {
309                                 ctx->comp_magic_cnt = 0;
310                                 break;
311                         }
312                         copy = sizeof(magic) - ctx->comp_magic_cnt;
313                         if (p_out + sz - p < copy)
314                                 copy = p_out + sz - p;
315                         memcpy(ctx->state.compressed_frame + ctx->comp_magic_cnt,
316                                p, copy);
317                         ctx->comp_magic_cnt += copy;
318                         if (!memcmp(ctx->state.compressed_frame, magic,
319                                     ctx->comp_magic_cnt)) {
320                                 p += copy;
321                                 state = VB2_BUF_STATE_DONE;
322                                 break;
323                         }
324                         ctx->comp_magic_cnt = 0;
325                 }
326                 if (ctx->comp_magic_cnt < sizeof(magic)) {
327                         job_remove_out_buf(ctx, state);
328                         goto restart;
329                 }
330                 ctx->comp_size = sizeof(magic);
331         }
332         if (ctx->comp_size < sizeof(struct fwht_cframe_hdr)) {
333                 struct fwht_cframe_hdr *p_hdr =
334                         (struct fwht_cframe_hdr *)ctx->state.compressed_frame;
335                 u32 copy = sizeof(struct fwht_cframe_hdr) - ctx->comp_size;
336
337                 if (copy > p_out + sz - p)
338                         copy = p_out + sz - p;
339                 memcpy(ctx->state.compressed_frame + ctx->comp_size,
340                        p, copy);
341                 p += copy;
342                 ctx->comp_size += copy;
343                 if (ctx->comp_size < sizeof(struct fwht_cframe_hdr)) {
344                         job_remove_out_buf(ctx, state);
345                         goto restart;
346                 }
347                 ctx->comp_frame_size = ntohl(p_hdr->size) + sizeof(*p_hdr);
348                 if (ctx->comp_frame_size > ctx->comp_max_size)
349                         ctx->comp_frame_size = ctx->comp_max_size;
350         }
351         if (ctx->comp_size < ctx->comp_frame_size) {
352                 u32 copy = ctx->comp_frame_size - ctx->comp_size;
353
354                 if (copy > p_out + sz - p)
355                         copy = p_out + sz - p;
356                 memcpy(ctx->state.compressed_frame + ctx->comp_size,
357                        p, copy);
358                 p += copy;
359                 ctx->comp_size += copy;
360                 if (ctx->comp_size < ctx->comp_frame_size) {
361                         job_remove_out_buf(ctx, state);
362                         goto restart;
363                 }
364         }
365         ctx->cur_buf_offset = p - p_out;
366         ctx->comp_has_frame = true;
367         ctx->comp_has_next_frame = false;
368         if (sz - ctx->cur_buf_offset >= sizeof(struct fwht_cframe_hdr)) {
369                 struct fwht_cframe_hdr *p_hdr = (struct fwht_cframe_hdr *)p;
370                 u32 frame_size = ntohl(p_hdr->size);
371                 u32 remaining = sz - ctx->cur_buf_offset - sizeof(*p_hdr);
372
373                 if (!memcmp(p, magic, sizeof(magic)))
374                         ctx->comp_has_next_frame = remaining >= frame_size;
375         }
376         return 1;
377 }
378
379 /*
380  * video ioctls
381  */
382
383 static const struct v4l2_fwht_pixfmt_info *find_fmt(u32 fmt)
384 {
385         const struct v4l2_fwht_pixfmt_info *info =
386                 v4l2_fwht_find_pixfmt(fmt);
387
388         if (!info)
389                 info = v4l2_fwht_get_pixfmt(0);
390         return info;
391 }
392
393 static int vidioc_querycap(struct file *file, void *priv,
394                            struct v4l2_capability *cap)
395 {
396         strncpy(cap->driver, VICODEC_NAME, sizeof(cap->driver) - 1);
397         strncpy(cap->card, VICODEC_NAME, sizeof(cap->card) - 1);
398         snprintf(cap->bus_info, sizeof(cap->bus_info),
399                         "platform:%s", VICODEC_NAME);
400         cap->device_caps =  V4L2_CAP_STREAMING |
401                             (multiplanar ?
402                              V4L2_CAP_VIDEO_M2M_MPLANE :
403                              V4L2_CAP_VIDEO_M2M);
404         cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
405         return 0;
406 }
407
408 static int enum_fmt(struct v4l2_fmtdesc *f, bool is_enc, bool is_out)
409 {
410         bool is_uncomp = (is_enc && is_out) || (!is_enc && !is_out);
411
412         if (V4L2_TYPE_IS_MULTIPLANAR(f->type) && !multiplanar)
413                 return -EINVAL;
414         if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && multiplanar)
415                 return -EINVAL;
416
417         if (is_uncomp) {
418                 const struct v4l2_fwht_pixfmt_info *info =
419                         v4l2_fwht_get_pixfmt(f->index);
420
421                 if (!info)
422                         return -EINVAL;
423                 f->pixelformat = info->id;
424         } else {
425                 if (f->index)
426                         return -EINVAL;
427                 f->pixelformat = V4L2_PIX_FMT_FWHT;
428         }
429         return 0;
430 }
431
432 static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
433                                    struct v4l2_fmtdesc *f)
434 {
435         struct vicodec_ctx *ctx = file2ctx(file);
436
437         return enum_fmt(f, ctx->is_enc, false);
438 }
439
440 static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
441                                    struct v4l2_fmtdesc *f)
442 {
443         struct vicodec_ctx *ctx = file2ctx(file);
444
445         return enum_fmt(f, ctx->is_enc, true);
446 }
447
448 static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
449 {
450         struct vb2_queue *vq;
451         struct vicodec_q_data *q_data;
452         struct v4l2_pix_format_mplane *pix_mp;
453         struct v4l2_pix_format *pix;
454         const struct v4l2_fwht_pixfmt_info *info;
455
456         vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
457         if (!vq)
458                 return -EINVAL;
459
460         q_data = get_q_data(ctx, f->type);
461         info = q_data->info;
462
463         switch (f->type) {
464         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
465         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
466                 if (multiplanar)
467                         return -EINVAL;
468                 pix = &f->fmt.pix;
469                 pix->width = q_data->width;
470                 pix->height = q_data->height;
471                 pix->field = V4L2_FIELD_NONE;
472                 pix->pixelformat = info->id;
473                 pix->bytesperline = q_data->width * info->bytesperline_mult;
474                 pix->sizeimage = q_data->sizeimage;
475                 pix->colorspace = ctx->state.colorspace;
476                 pix->xfer_func = ctx->state.xfer_func;
477                 pix->ycbcr_enc = ctx->state.ycbcr_enc;
478                 pix->quantization = ctx->state.quantization;
479                 break;
480
481         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
482         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
483                 if (!multiplanar)
484                         return -EINVAL;
485                 pix_mp = &f->fmt.pix_mp;
486                 pix_mp->width = q_data->width;
487                 pix_mp->height = q_data->height;
488                 pix_mp->field = V4L2_FIELD_NONE;
489                 pix_mp->pixelformat = info->id;
490                 pix_mp->num_planes = 1;
491                 pix_mp->plane_fmt[0].bytesperline =
492                                 q_data->width * info->bytesperline_mult;
493                 pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage;
494                 pix_mp->colorspace = ctx->state.colorspace;
495                 pix_mp->xfer_func = ctx->state.xfer_func;
496                 pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
497                 pix_mp->quantization = ctx->state.quantization;
498                 memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
499                 memset(pix_mp->plane_fmt[0].reserved, 0,
500                        sizeof(pix_mp->plane_fmt[0].reserved));
501                 break;
502         default:
503                 return -EINVAL;
504         }
505         return 0;
506 }
507
508 static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
509                                 struct v4l2_format *f)
510 {
511         return vidioc_g_fmt(file2ctx(file), f);
512 }
513
514 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
515                                 struct v4l2_format *f)
516 {
517         return vidioc_g_fmt(file2ctx(file), f);
518 }
519
520 static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
521 {
522         struct v4l2_pix_format_mplane *pix_mp;
523         struct v4l2_pix_format *pix;
524         struct v4l2_plane_pix_format *plane;
525         const struct v4l2_fwht_pixfmt_info *info = &pixfmt_fwht;
526
527         switch (f->type) {
528         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
529         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
530                 pix = &f->fmt.pix;
531                 if (pix->pixelformat != V4L2_PIX_FMT_FWHT)
532                         info = find_fmt(pix->pixelformat);
533                 pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH) & ~7;
534                 pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT) & ~7;
535                 pix->field = V4L2_FIELD_NONE;
536                 pix->bytesperline =
537                         pix->width * info->bytesperline_mult;
538                 pix->sizeimage = pix->width * pix->height *
539                         info->sizeimage_mult / info->sizeimage_div;
540                 if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
541                         pix->sizeimage += sizeof(struct fwht_cframe_hdr);
542                 break;
543         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
544         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
545                 pix_mp = &f->fmt.pix_mp;
546                 plane = pix_mp->plane_fmt;
547                 if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT)
548                         info = find_fmt(pix_mp->pixelformat);
549                 pix_mp->num_planes = 1;
550                 pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH) & ~7;
551                 pix_mp->height =
552                         clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT) & ~7;
553                 pix_mp->field = V4L2_FIELD_NONE;
554                 plane->bytesperline =
555                         pix_mp->width * info->bytesperline_mult;
556                 plane->sizeimage = pix_mp->width * pix_mp->height *
557                         info->sizeimage_mult / info->sizeimage_div;
558                 if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
559                         plane->sizeimage += sizeof(struct fwht_cframe_hdr);
560                 memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
561                 memset(plane->reserved, 0, sizeof(plane->reserved));
562                 break;
563         default:
564                 return -EINVAL;
565         }
566
567         return 0;
568 }
569
570 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
571                                   struct v4l2_format *f)
572 {
573         struct vicodec_ctx *ctx = file2ctx(file);
574         struct v4l2_pix_format_mplane *pix_mp;
575         struct v4l2_pix_format *pix;
576
577         switch (f->type) {
578         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
579                 if (multiplanar)
580                         return -EINVAL;
581                 pix = &f->fmt.pix;
582                 pix->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
583                                    find_fmt(f->fmt.pix.pixelformat)->id;
584                 pix->colorspace = ctx->state.colorspace;
585                 pix->xfer_func = ctx->state.xfer_func;
586                 pix->ycbcr_enc = ctx->state.ycbcr_enc;
587                 pix->quantization = ctx->state.quantization;
588                 break;
589         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
590                 if (!multiplanar)
591                         return -EINVAL;
592                 pix_mp = &f->fmt.pix_mp;
593                 pix_mp->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
594                                       find_fmt(pix_mp->pixelformat)->id;
595                 pix_mp->colorspace = ctx->state.colorspace;
596                 pix_mp->xfer_func = ctx->state.xfer_func;
597                 pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
598                 pix_mp->quantization = ctx->state.quantization;
599                 break;
600         default:
601                 return -EINVAL;
602         }
603
604         return vidioc_try_fmt(ctx, f);
605 }
606
607 static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
608                                   struct v4l2_format *f)
609 {
610         struct vicodec_ctx *ctx = file2ctx(file);
611         struct v4l2_pix_format_mplane *pix_mp;
612         struct v4l2_pix_format *pix;
613
614         switch (f->type) {
615         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
616                 if (multiplanar)
617                         return -EINVAL;
618                 pix = &f->fmt.pix;
619                 pix->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT :
620                                    find_fmt(pix->pixelformat)->id;
621                 if (!pix->colorspace)
622                         pix->colorspace = V4L2_COLORSPACE_REC709;
623                 break;
624         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
625                 if (!multiplanar)
626                         return -EINVAL;
627                 pix_mp = &f->fmt.pix_mp;
628                 pix_mp->pixelformat = !ctx->is_enc ? V4L2_PIX_FMT_FWHT :
629                                       find_fmt(pix_mp->pixelformat)->id;
630                 if (!pix_mp->colorspace)
631                         pix_mp->colorspace = V4L2_COLORSPACE_REC709;
632                 break;
633         default:
634                 return -EINVAL;
635         }
636
637         return vidioc_try_fmt(ctx, f);
638 }
639
640 static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
641 {
642         struct vicodec_q_data *q_data;
643         struct vb2_queue *vq;
644         bool fmt_changed = true;
645         struct v4l2_pix_format_mplane *pix_mp;
646         struct v4l2_pix_format *pix;
647
648         vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
649         if (!vq)
650                 return -EINVAL;
651
652         q_data = get_q_data(ctx, f->type);
653         if (!q_data)
654                 return -EINVAL;
655
656         switch (f->type) {
657         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
658         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
659                 pix = &f->fmt.pix;
660                 if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
661                         fmt_changed =
662                                 q_data->info->id != pix->pixelformat ||
663                                 q_data->width != pix->width ||
664                                 q_data->height != pix->height;
665
666                 if (vb2_is_busy(vq) && fmt_changed)
667                         return -EBUSY;
668
669                 if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
670                         q_data->info = &pixfmt_fwht;
671                 else
672                         q_data->info = find_fmt(pix->pixelformat);
673                 q_data->width = pix->width;
674                 q_data->height = pix->height;
675                 q_data->sizeimage = pix->sizeimage;
676                 break;
677         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
678         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
679                 pix_mp = &f->fmt.pix_mp;
680                 if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
681                         fmt_changed =
682                                 q_data->info->id != pix_mp->pixelformat ||
683                                 q_data->width != pix_mp->width ||
684                                 q_data->height != pix_mp->height;
685
686                 if (vb2_is_busy(vq) && fmt_changed)
687                         return -EBUSY;
688
689                 if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
690                         q_data->info = &pixfmt_fwht;
691                 else
692                         q_data->info = find_fmt(pix_mp->pixelformat);
693                 q_data->width = pix_mp->width;
694                 q_data->height = pix_mp->height;
695                 q_data->sizeimage = pix_mp->plane_fmt[0].sizeimage;
696                 break;
697         default:
698                 return -EINVAL;
699         }
700
701         dprintk(ctx->dev,
702                 "Setting format for type %d, wxh: %dx%d, fourcc: %08x\n",
703                 f->type, q_data->width, q_data->height, q_data->info->id);
704
705         return 0;
706 }
707
708 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
709                                 struct v4l2_format *f)
710 {
711         int ret;
712
713         ret = vidioc_try_fmt_vid_cap(file, priv, f);
714         if (ret)
715                 return ret;
716
717         return vidioc_s_fmt(file2ctx(file), f);
718 }
719
720 static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
721                                 struct v4l2_format *f)
722 {
723         struct vicodec_ctx *ctx = file2ctx(file);
724         struct v4l2_pix_format_mplane *pix_mp;
725         struct v4l2_pix_format *pix;
726         int ret;
727
728         ret = vidioc_try_fmt_vid_out(file, priv, f);
729         if (ret)
730                 return ret;
731
732         ret = vidioc_s_fmt(file2ctx(file), f);
733         if (!ret) {
734                 switch (f->type) {
735                 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
736                 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
737                         pix = &f->fmt.pix;
738                         ctx->state.colorspace = pix->colorspace;
739                         ctx->state.xfer_func = pix->xfer_func;
740                         ctx->state.ycbcr_enc = pix->ycbcr_enc;
741                         ctx->state.quantization = pix->quantization;
742                         break;
743                 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
744                 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
745                         pix_mp = &f->fmt.pix_mp;
746                         ctx->state.colorspace = pix_mp->colorspace;
747                         ctx->state.xfer_func = pix_mp->xfer_func;
748                         ctx->state.ycbcr_enc = pix_mp->ycbcr_enc;
749                         ctx->state.quantization = pix_mp->quantization;
750                         break;
751                 default:
752                         break;
753                 }
754         }
755         return ret;
756 }
757
758 static void vicodec_mark_last_buf(struct vicodec_ctx *ctx)
759 {
760         static const struct v4l2_event eos_event = {
761                 .type = V4L2_EVENT_EOS
762         };
763
764         spin_lock(ctx->lock);
765         ctx->last_src_buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
766         if (!ctx->last_src_buf && ctx->last_dst_buf) {
767                 ctx->last_dst_buf->flags |= V4L2_BUF_FLAG_LAST;
768                 v4l2_event_queue_fh(&ctx->fh, &eos_event);
769         }
770         spin_unlock(ctx->lock);
771 }
772
773 static int vicodec_try_encoder_cmd(struct file *file, void *fh,
774                                 struct v4l2_encoder_cmd *ec)
775 {
776         if (ec->cmd != V4L2_ENC_CMD_STOP)
777                 return -EINVAL;
778
779         if (ec->flags & V4L2_ENC_CMD_STOP_AT_GOP_END)
780                 return -EINVAL;
781
782         return 0;
783 }
784
785 static int vicodec_encoder_cmd(struct file *file, void *fh,
786                             struct v4l2_encoder_cmd *ec)
787 {
788         struct vicodec_ctx *ctx = file2ctx(file);
789         int ret;
790
791         ret = vicodec_try_encoder_cmd(file, fh, ec);
792         if (ret < 0)
793                 return ret;
794
795         vicodec_mark_last_buf(ctx);
796         return 0;
797 }
798
799 static int vicodec_try_decoder_cmd(struct file *file, void *fh,
800                                 struct v4l2_decoder_cmd *dc)
801 {
802         if (dc->cmd != V4L2_DEC_CMD_STOP)
803                 return -EINVAL;
804
805         if (dc->flags & V4L2_DEC_CMD_STOP_TO_BLACK)
806                 return -EINVAL;
807
808         if (!(dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) && (dc->stop.pts != 0))
809                 return -EINVAL;
810
811         return 0;
812 }
813
814 static int vicodec_decoder_cmd(struct file *file, void *fh,
815                             struct v4l2_decoder_cmd *dc)
816 {
817         struct vicodec_ctx *ctx = file2ctx(file);
818         int ret;
819
820         ret = vicodec_try_decoder_cmd(file, fh, dc);
821         if (ret < 0)
822                 return ret;
823
824         vicodec_mark_last_buf(ctx);
825         return 0;
826 }
827
828 static int vicodec_enum_framesizes(struct file *file, void *fh,
829                                    struct v4l2_frmsizeenum *fsize)
830 {
831         switch (fsize->pixel_format) {
832         case V4L2_PIX_FMT_FWHT:
833                 break;
834         default:
835                 if (find_fmt(fsize->pixel_format)->id == fsize->pixel_format)
836                         break;
837                 return -EINVAL;
838         }
839
840         if (fsize->index)
841                 return -EINVAL;
842
843         fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
844
845         fsize->stepwise.min_width = MIN_WIDTH;
846         fsize->stepwise.max_width = MAX_WIDTH;
847         fsize->stepwise.step_width = 8;
848         fsize->stepwise.min_height = MIN_HEIGHT;
849         fsize->stepwise.max_height = MAX_HEIGHT;
850         fsize->stepwise.step_height = 8;
851
852         return 0;
853 }
854
855 static int vicodec_subscribe_event(struct v4l2_fh *fh,
856                                 const struct v4l2_event_subscription *sub)
857 {
858         switch (sub->type) {
859         case V4L2_EVENT_EOS:
860                 return v4l2_event_subscribe(fh, sub, 0, NULL);
861         default:
862                 return v4l2_ctrl_subscribe_event(fh, sub);
863         }
864 }
865
866 static const struct v4l2_ioctl_ops vicodec_ioctl_ops = {
867         .vidioc_querycap        = vidioc_querycap,
868
869         .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
870         .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
871         .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
872         .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
873
874         .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap,
875         .vidioc_g_fmt_vid_cap_mplane    = vidioc_g_fmt_vid_cap,
876         .vidioc_try_fmt_vid_cap_mplane  = vidioc_try_fmt_vid_cap,
877         .vidioc_s_fmt_vid_cap_mplane    = vidioc_s_fmt_vid_cap,
878
879         .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
880         .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
881         .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
882         .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
883
884         .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out,
885         .vidioc_g_fmt_vid_out_mplane    = vidioc_g_fmt_vid_out,
886         .vidioc_try_fmt_vid_out_mplane  = vidioc_try_fmt_vid_out,
887         .vidioc_s_fmt_vid_out_mplane    = vidioc_s_fmt_vid_out,
888
889         .vidioc_reqbufs         = v4l2_m2m_ioctl_reqbufs,
890         .vidioc_querybuf        = v4l2_m2m_ioctl_querybuf,
891         .vidioc_qbuf            = v4l2_m2m_ioctl_qbuf,
892         .vidioc_dqbuf           = v4l2_m2m_ioctl_dqbuf,
893         .vidioc_prepare_buf     = v4l2_m2m_ioctl_prepare_buf,
894         .vidioc_create_bufs     = v4l2_m2m_ioctl_create_bufs,
895         .vidioc_expbuf          = v4l2_m2m_ioctl_expbuf,
896
897         .vidioc_streamon        = v4l2_m2m_ioctl_streamon,
898         .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
899
900         .vidioc_try_encoder_cmd = vicodec_try_encoder_cmd,
901         .vidioc_encoder_cmd     = vicodec_encoder_cmd,
902         .vidioc_try_decoder_cmd = vicodec_try_decoder_cmd,
903         .vidioc_decoder_cmd     = vicodec_decoder_cmd,
904         .vidioc_enum_framesizes = vicodec_enum_framesizes,
905
906         .vidioc_subscribe_event = vicodec_subscribe_event,
907         .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
908 };
909
910
911 /*
912  * Queue operations
913  */
914
915 static int vicodec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
916                                unsigned int *nplanes, unsigned int sizes[],
917                                struct device *alloc_devs[])
918 {
919         struct vicodec_ctx *ctx = vb2_get_drv_priv(vq);
920         struct vicodec_q_data *q_data = get_q_data(ctx, vq->type);
921         unsigned int size = q_data->sizeimage;
922
923         if (*nplanes)
924                 return sizes[0] < size ? -EINVAL : 0;
925
926         *nplanes = 1;
927         sizes[0] = size;
928         return 0;
929 }
930
931 static int vicodec_buf_prepare(struct vb2_buffer *vb)
932 {
933         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
934         struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
935         struct vicodec_q_data *q_data;
936
937         dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
938
939         q_data = get_q_data(ctx, vb->vb2_queue->type);
940         if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
941                 if (vbuf->field == V4L2_FIELD_ANY)
942                         vbuf->field = V4L2_FIELD_NONE;
943                 if (vbuf->field != V4L2_FIELD_NONE) {
944                         dprintk(ctx->dev, "%s field isn't supported\n",
945                                         __func__);
946                         return -EINVAL;
947                 }
948         }
949
950         if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
951                 dprintk(ctx->dev,
952                         "%s data will not fit into plane (%lu < %lu)\n",
953                         __func__, vb2_plane_size(vb, 0),
954                         (long)q_data->sizeimage);
955                 return -EINVAL;
956         }
957
958         return 0;
959 }
960
961 static void vicodec_buf_queue(struct vb2_buffer *vb)
962 {
963         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
964         struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
965
966         v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
967 }
968
969 static void vicodec_return_bufs(struct vb2_queue *q, u32 state)
970 {
971         struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
972         struct vb2_v4l2_buffer *vbuf;
973
974         for (;;) {
975                 if (V4L2_TYPE_IS_OUTPUT(q->type))
976                         vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
977                 else
978                         vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
979                 if (vbuf == NULL)
980                         return;
981                 spin_lock(ctx->lock);
982                 v4l2_m2m_buf_done(vbuf, state);
983                 spin_unlock(ctx->lock);
984         }
985 }
986
987 static int vicodec_start_streaming(struct vb2_queue *q,
988                                    unsigned int count)
989 {
990         struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
991         struct vicodec_q_data *q_data = get_q_data(ctx, q->type);
992         struct v4l2_fwht_state *state = &ctx->state;
993         unsigned int size = q_data->width * q_data->height;
994         const struct v4l2_fwht_pixfmt_info *info = q_data->info;
995         unsigned int chroma_div = info->width_div * info->height_div;
996
997         q_data->sequence = 0;
998
999         if (!V4L2_TYPE_IS_OUTPUT(q->type))
1000                 return 0;
1001
1002         state->width = q_data->width;
1003         state->height = q_data->height;
1004         state->ref_frame.width = state->ref_frame.height = 0;
1005         state->ref_frame.luma = kvmalloc(size + 2 * size / chroma_div,
1006                                          GFP_KERNEL);
1007         ctx->comp_max_size = size + 2 * size / chroma_div +
1008                              sizeof(struct fwht_cframe_hdr);
1009         state->compressed_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
1010         if (!state->ref_frame.luma || !state->compressed_frame) {
1011                 kvfree(state->ref_frame.luma);
1012                 kvfree(state->compressed_frame);
1013                 vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
1014                 return -ENOMEM;
1015         }
1016         state->ref_frame.cb = state->ref_frame.luma + size;
1017         state->ref_frame.cr = state->ref_frame.cb + size / chroma_div;
1018         ctx->last_src_buf = NULL;
1019         ctx->last_dst_buf = NULL;
1020         state->gop_cnt = 0;
1021         ctx->cur_buf_offset = 0;
1022         ctx->comp_size = 0;
1023         ctx->comp_magic_cnt = 0;
1024         ctx->comp_has_frame = false;
1025
1026         return 0;
1027 }
1028
1029 static void vicodec_stop_streaming(struct vb2_queue *q)
1030 {
1031         struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
1032
1033         vicodec_return_bufs(q, VB2_BUF_STATE_ERROR);
1034
1035         if (!V4L2_TYPE_IS_OUTPUT(q->type))
1036                 return;
1037
1038         kvfree(ctx->state.ref_frame.luma);
1039         kvfree(ctx->state.compressed_frame);
1040 }
1041
1042 static const struct vb2_ops vicodec_qops = {
1043         .queue_setup     = vicodec_queue_setup,
1044         .buf_prepare     = vicodec_buf_prepare,
1045         .buf_queue       = vicodec_buf_queue,
1046         .start_streaming = vicodec_start_streaming,
1047         .stop_streaming  = vicodec_stop_streaming,
1048         .wait_prepare    = vb2_ops_wait_prepare,
1049         .wait_finish     = vb2_ops_wait_finish,
1050 };
1051
1052 static int queue_init(void *priv, struct vb2_queue *src_vq,
1053                       struct vb2_queue *dst_vq)
1054 {
1055         struct vicodec_ctx *ctx = priv;
1056         int ret;
1057
1058         src_vq->type = (multiplanar ?
1059                         V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
1060                         V4L2_BUF_TYPE_VIDEO_OUTPUT);
1061         src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1062         src_vq->drv_priv = ctx;
1063         src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1064         src_vq->ops = &vicodec_qops;
1065         src_vq->mem_ops = &vb2_vmalloc_memops;
1066         src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1067         src_vq->lock = ctx->is_enc ? &ctx->dev->enc_mutex :
1068                 &ctx->dev->dec_mutex;
1069
1070         ret = vb2_queue_init(src_vq);
1071         if (ret)
1072                 return ret;
1073
1074         dst_vq->type = (multiplanar ?
1075                         V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
1076                         V4L2_BUF_TYPE_VIDEO_CAPTURE);
1077         dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1078         dst_vq->drv_priv = ctx;
1079         dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1080         dst_vq->ops = &vicodec_qops;
1081         dst_vq->mem_ops = &vb2_vmalloc_memops;
1082         dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1083         dst_vq->lock = src_vq->lock;
1084
1085         return vb2_queue_init(dst_vq);
1086 }
1087
1088 #define VICODEC_CID_CUSTOM_BASE         (V4L2_CID_MPEG_BASE | 0xf000)
1089 #define VICODEC_CID_I_FRAME_QP          (VICODEC_CID_CUSTOM_BASE + 0)
1090 #define VICODEC_CID_P_FRAME_QP          (VICODEC_CID_CUSTOM_BASE + 1)
1091
1092 static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
1093 {
1094         struct vicodec_ctx *ctx = container_of(ctrl->handler,
1095                                                struct vicodec_ctx, hdl);
1096
1097         switch (ctrl->id) {
1098         case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1099                 ctx->state.gop_size = ctrl->val;
1100                 return 0;
1101         case VICODEC_CID_I_FRAME_QP:
1102                 ctx->state.i_frame_qp = ctrl->val;
1103                 return 0;
1104         case VICODEC_CID_P_FRAME_QP:
1105                 ctx->state.p_frame_qp = ctrl->val;
1106                 return 0;
1107         }
1108         return -EINVAL;
1109 }
1110
1111 static struct v4l2_ctrl_ops vicodec_ctrl_ops = {
1112         .s_ctrl = vicodec_s_ctrl,
1113 };
1114
1115 static const struct v4l2_ctrl_config vicodec_ctrl_i_frame = {
1116         .ops = &vicodec_ctrl_ops,
1117         .id = VICODEC_CID_I_FRAME_QP,
1118         .name = "FWHT I-Frame QP Value",
1119         .type = V4L2_CTRL_TYPE_INTEGER,
1120         .min = 1,
1121         .max = 31,
1122         .def = 20,
1123         .step = 1,
1124 };
1125
1126 static const struct v4l2_ctrl_config vicodec_ctrl_p_frame = {
1127         .ops = &vicodec_ctrl_ops,
1128         .id = VICODEC_CID_P_FRAME_QP,
1129         .name = "FWHT P-Frame QP Value",
1130         .type = V4L2_CTRL_TYPE_INTEGER,
1131         .min = 1,
1132         .max = 31,
1133         .def = 20,
1134         .step = 1,
1135 };
1136
1137 /*
1138  * File operations
1139  */
1140 static int vicodec_open(struct file *file)
1141 {
1142         struct video_device *vfd = video_devdata(file);
1143         struct vicodec_dev *dev = video_drvdata(file);
1144         struct vicodec_ctx *ctx = NULL;
1145         struct v4l2_ctrl_handler *hdl;
1146         unsigned int size;
1147         int rc = 0;
1148
1149         if (mutex_lock_interruptible(vfd->lock))
1150                 return -ERESTARTSYS;
1151         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1152         if (!ctx) {
1153                 rc = -ENOMEM;
1154                 goto open_unlock;
1155         }
1156
1157         if (vfd == &dev->enc_vfd)
1158                 ctx->is_enc = true;
1159
1160         v4l2_fh_init(&ctx->fh, video_devdata(file));
1161         file->private_data = &ctx->fh;
1162         ctx->dev = dev;
1163         hdl = &ctx->hdl;
1164         v4l2_ctrl_handler_init(hdl, 4);
1165         v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE,
1166                           1, 16, 1, 10);
1167         v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_i_frame, NULL);
1168         v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_p_frame, NULL);
1169         if (hdl->error) {
1170                 rc = hdl->error;
1171                 v4l2_ctrl_handler_free(hdl);
1172                 kfree(ctx);
1173                 goto open_unlock;
1174         }
1175         ctx->fh.ctrl_handler = hdl;
1176         v4l2_ctrl_handler_setup(hdl);
1177
1178         ctx->q_data[V4L2_M2M_SRC].info =
1179                 ctx->is_enc ? v4l2_fwht_get_pixfmt(0) : &pixfmt_fwht;
1180         ctx->q_data[V4L2_M2M_SRC].width = 1280;
1181         ctx->q_data[V4L2_M2M_SRC].height = 720;
1182         size = 1280 * 720 * ctx->q_data[V4L2_M2M_SRC].info->sizeimage_mult /
1183                 ctx->q_data[V4L2_M2M_SRC].info->sizeimage_div;
1184         if (ctx->is_enc)
1185                 ctx->q_data[V4L2_M2M_SRC].sizeimage = size;
1186         else
1187                 ctx->q_data[V4L2_M2M_SRC].sizeimage =
1188                         size + sizeof(struct fwht_cframe_hdr);
1189         ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
1190         ctx->q_data[V4L2_M2M_DST].info =
1191                 ctx->is_enc ? &pixfmt_fwht : v4l2_fwht_get_pixfmt(0);
1192         size = 1280 * 720 * ctx->q_data[V4L2_M2M_DST].info->sizeimage_mult /
1193                 ctx->q_data[V4L2_M2M_DST].info->sizeimage_div;
1194         if (ctx->is_enc)
1195                 ctx->q_data[V4L2_M2M_DST].sizeimage =
1196                         size + sizeof(struct fwht_cframe_hdr);
1197         else
1198                 ctx->q_data[V4L2_M2M_DST].sizeimage = size;
1199         ctx->state.colorspace = V4L2_COLORSPACE_REC709;
1200
1201         if (ctx->is_enc) {
1202                 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->enc_dev, ctx,
1203                                                     &queue_init);
1204                 ctx->lock = &dev->enc_lock;
1205         } else {
1206                 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->dec_dev, ctx,
1207                                                     &queue_init);
1208                 ctx->lock = &dev->dec_lock;
1209         }
1210
1211         if (IS_ERR(ctx->fh.m2m_ctx)) {
1212                 rc = PTR_ERR(ctx->fh.m2m_ctx);
1213
1214                 v4l2_ctrl_handler_free(hdl);
1215                 v4l2_fh_exit(&ctx->fh);
1216                 kfree(ctx);
1217                 goto open_unlock;
1218         }
1219
1220         v4l2_fh_add(&ctx->fh);
1221
1222 open_unlock:
1223         mutex_unlock(vfd->lock);
1224         return rc;
1225 }
1226
1227 static int vicodec_release(struct file *file)
1228 {
1229         struct video_device *vfd = video_devdata(file);
1230         struct vicodec_ctx *ctx = file2ctx(file);
1231
1232         v4l2_fh_del(&ctx->fh);
1233         v4l2_fh_exit(&ctx->fh);
1234         v4l2_ctrl_handler_free(&ctx->hdl);
1235         mutex_lock(vfd->lock);
1236         v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
1237         mutex_unlock(vfd->lock);
1238         kfree(ctx);
1239
1240         return 0;
1241 }
1242
1243 static const struct v4l2_file_operations vicodec_fops = {
1244         .owner          = THIS_MODULE,
1245         .open           = vicodec_open,
1246         .release        = vicodec_release,
1247         .poll           = v4l2_m2m_fop_poll,
1248         .unlocked_ioctl = video_ioctl2,
1249         .mmap           = v4l2_m2m_fop_mmap,
1250 };
1251
1252 static const struct video_device vicodec_videodev = {
1253         .name           = VICODEC_NAME,
1254         .vfl_dir        = VFL_DIR_M2M,
1255         .fops           = &vicodec_fops,
1256         .ioctl_ops      = &vicodec_ioctl_ops,
1257         .minor          = -1,
1258         .release        = video_device_release_empty,
1259 };
1260
1261 static const struct v4l2_m2m_ops m2m_ops = {
1262         .device_run     = device_run,
1263         .job_ready      = job_ready,
1264 };
1265
1266 static int vicodec_probe(struct platform_device *pdev)
1267 {
1268         struct vicodec_dev *dev;
1269         struct video_device *vfd;
1270         int ret;
1271
1272         dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
1273         if (!dev)
1274                 return -ENOMEM;
1275
1276         spin_lock_init(&dev->enc_lock);
1277         spin_lock_init(&dev->dec_lock);
1278
1279         ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
1280         if (ret)
1281                 return ret;
1282
1283 #ifdef CONFIG_MEDIA_CONTROLLER
1284         dev->mdev.dev = &pdev->dev;
1285         strscpy(dev->mdev.model, "vicodec", sizeof(dev->mdev.model));
1286         media_device_init(&dev->mdev);
1287         dev->v4l2_dev.mdev = &dev->mdev;
1288 #endif
1289
1290         mutex_init(&dev->enc_mutex);
1291         mutex_init(&dev->dec_mutex);
1292
1293         platform_set_drvdata(pdev, dev);
1294
1295         dev->enc_dev = v4l2_m2m_init(&m2m_ops);
1296         if (IS_ERR(dev->enc_dev)) {
1297                 v4l2_err(&dev->v4l2_dev, "Failed to init vicodec device\n");
1298                 ret = PTR_ERR(dev->enc_dev);
1299                 goto unreg_dev;
1300         }
1301
1302         dev->dec_dev = v4l2_m2m_init(&m2m_ops);
1303         if (IS_ERR(dev->dec_dev)) {
1304                 v4l2_err(&dev->v4l2_dev, "Failed to init vicodec device\n");
1305                 ret = PTR_ERR(dev->dec_dev);
1306                 goto err_enc_m2m;
1307         }
1308
1309         dev->enc_vfd = vicodec_videodev;
1310         vfd = &dev->enc_vfd;
1311         vfd->lock = &dev->enc_mutex;
1312         vfd->v4l2_dev = &dev->v4l2_dev;
1313         strscpy(vfd->name, "vicodec-enc", sizeof(vfd->name));
1314         v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
1315         v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
1316         video_set_drvdata(vfd, dev);
1317
1318         ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
1319         if (ret) {
1320                 v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
1321                 goto err_dec_m2m;
1322         }
1323         v4l2_info(&dev->v4l2_dev,
1324                         "Device registered as /dev/video%d\n", vfd->num);
1325
1326         dev->dec_vfd = vicodec_videodev;
1327         vfd = &dev->dec_vfd;
1328         vfd->lock = &dev->dec_mutex;
1329         vfd->v4l2_dev = &dev->v4l2_dev;
1330         strscpy(vfd->name, "vicodec-dec", sizeof(vfd->name));
1331         v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
1332         v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
1333         video_set_drvdata(vfd, dev);
1334
1335         ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
1336         if (ret) {
1337                 v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
1338                 goto unreg_enc;
1339         }
1340         v4l2_info(&dev->v4l2_dev,
1341                         "Device registered as /dev/video%d\n", vfd->num);
1342
1343 #ifdef CONFIG_MEDIA_CONTROLLER
1344         ret = v4l2_m2m_register_media_controller(dev->enc_dev,
1345                         &dev->enc_vfd, MEDIA_ENT_F_PROC_VIDEO_ENCODER);
1346         if (ret) {
1347                 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
1348                 goto unreg_m2m;
1349         }
1350
1351         ret = v4l2_m2m_register_media_controller(dev->dec_dev,
1352                         &dev->dec_vfd, MEDIA_ENT_F_PROC_VIDEO_DECODER);
1353         if (ret) {
1354                 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
1355                 goto unreg_m2m_enc_mc;
1356         }
1357
1358         ret = media_device_register(&dev->mdev);
1359         if (ret) {
1360                 v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n");
1361                 goto unreg_m2m_dec_mc;
1362         }
1363 #endif
1364         return 0;
1365
1366 #ifdef CONFIG_MEDIA_CONTROLLER
1367 unreg_m2m_dec_mc:
1368         v4l2_m2m_unregister_media_controller(dev->dec_dev);
1369 unreg_m2m_enc_mc:
1370         v4l2_m2m_unregister_media_controller(dev->enc_dev);
1371 unreg_m2m:
1372         video_unregister_device(&dev->dec_vfd);
1373 #endif
1374 unreg_enc:
1375         video_unregister_device(&dev->enc_vfd);
1376 err_dec_m2m:
1377         v4l2_m2m_release(dev->dec_dev);
1378 err_enc_m2m:
1379         v4l2_m2m_release(dev->enc_dev);
1380 unreg_dev:
1381         v4l2_device_unregister(&dev->v4l2_dev);
1382
1383         return ret;
1384 }
1385
1386 static int vicodec_remove(struct platform_device *pdev)
1387 {
1388         struct vicodec_dev *dev = platform_get_drvdata(pdev);
1389
1390         v4l2_info(&dev->v4l2_dev, "Removing " VICODEC_NAME);
1391
1392 #ifdef CONFIG_MEDIA_CONTROLLER
1393         media_device_unregister(&dev->mdev);
1394         v4l2_m2m_unregister_media_controller(dev->enc_dev);
1395         v4l2_m2m_unregister_media_controller(dev->dec_dev);
1396         media_device_cleanup(&dev->mdev);
1397 #endif
1398
1399         v4l2_m2m_release(dev->enc_dev);
1400         v4l2_m2m_release(dev->dec_dev);
1401         video_unregister_device(&dev->enc_vfd);
1402         video_unregister_device(&dev->dec_vfd);
1403         v4l2_device_unregister(&dev->v4l2_dev);
1404
1405         return 0;
1406 }
1407
1408 static struct platform_driver vicodec_pdrv = {
1409         .probe          = vicodec_probe,
1410         .remove         = vicodec_remove,
1411         .driver         = {
1412                 .name   = VICODEC_NAME,
1413         },
1414 };
1415
1416 static void __exit vicodec_exit(void)
1417 {
1418         platform_driver_unregister(&vicodec_pdrv);
1419         platform_device_unregister(&vicodec_pdev);
1420 }
1421
1422 static int __init vicodec_init(void)
1423 {
1424         int ret;
1425
1426         ret = platform_device_register(&vicodec_pdev);
1427         if (ret)
1428                 return ret;
1429
1430         ret = platform_driver_register(&vicodec_pdrv);
1431         if (ret)
1432                 platform_device_unregister(&vicodec_pdev);
1433
1434         return ret;
1435 }
1436
1437 module_init(vicodec_init);
1438 module_exit(vicodec_exit);