root/drivers/media/platform/vicodec/vicodec-core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vicodec_dev_release
  2. file2ctx
  3. get_q_data
  4. copy_cap_to_ref
  5. validate_by_version
  6. validate_stateless_params_flags
  7. update_state_from_header
  8. device_process
  9. get_next_header
  10. device_run
  11. job_remove_src_buf
  12. info_from_header
  13. is_header_valid
  14. update_capture_data_from_header
  15. set_last_buffer
  16. job_ready
  17. find_fmt
  18. vidioc_querycap
  19. enum_fmt
  20. vidioc_enum_fmt_vid_cap
  21. vidioc_enum_fmt_vid_out
  22. vidioc_g_fmt
  23. vidioc_g_fmt_vid_out
  24. vidioc_g_fmt_vid_cap
  25. vidioc_try_fmt
  26. vidioc_try_fmt_vid_cap
  27. vidioc_try_fmt_vid_out
  28. vidioc_s_fmt
  29. vidioc_s_fmt_vid_cap
  30. vidioc_s_fmt_vid_out
  31. vidioc_g_selection
  32. vidioc_s_selection
  33. vicodec_mark_last_buf
  34. vicodec_encoder_cmd
  35. vicodec_decoder_cmd
  36. vicodec_enum_framesizes
  37. vicodec_subscribe_event
  38. vicodec_queue_setup
  39. vicodec_buf_out_validate
  40. vicodec_buf_prepare
  41. vicodec_buf_queue
  42. vicodec_return_bufs
  43. total_frame_size
  44. vicodec_start_streaming
  45. vicodec_stop_streaming
  46. vicodec_buf_request_complete
  47. queue_init
  48. vicodec_try_ctrl
  49. update_header_from_stateless_params
  50. vicodec_s_ctrl
  51. vicodec_open
  52. vicodec_release
  53. vicodec_request_validate
  54. register_instance
  55. vicodec_v4l2_dev_release
  56. vicodec_probe
  57. vicodec_remove
  58. vicodec_exit
  59. vicodec_init

   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              360U
  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, 0, 1
  65 };
  66 
  67 static const struct v4l2_fwht_pixfmt_info pixfmt_stateless_fwht = {
  68         V4L2_PIX_FMT_FWHT_STATELESS, 0, 3, 1, 1, 1, 1, 1, 0, 1
  69 };
  70 
  71 static void vicodec_dev_release(struct device *dev)
  72 {
  73 }
  74 
  75 static struct platform_device vicodec_pdev = {
  76         .name           = VICODEC_NAME,
  77         .dev.release    = vicodec_dev_release,
  78 };
  79 
  80 /* Per-queue, driver-specific private data */
  81 struct vicodec_q_data {
  82         unsigned int            coded_width;
  83         unsigned int            coded_height;
  84         unsigned int            visible_width;
  85         unsigned int            visible_height;
  86         unsigned int            sizeimage;
  87         unsigned int            vb2_sizeimage;
  88         unsigned int            sequence;
  89         const struct v4l2_fwht_pixfmt_info *info;
  90 };
  91 
  92 enum {
  93         V4L2_M2M_SRC = 0,
  94         V4L2_M2M_DST = 1,
  95 };
  96 
  97 struct vicodec_dev_instance {
  98         struct video_device     vfd;
  99         struct mutex            mutex;
 100         spinlock_t              lock;
 101         struct v4l2_m2m_dev     *m2m_dev;
 102 };
 103 
 104 struct vicodec_dev {
 105         struct v4l2_device      v4l2_dev;
 106         struct vicodec_dev_instance stateful_enc;
 107         struct vicodec_dev_instance stateful_dec;
 108         struct vicodec_dev_instance stateless_dec;
 109 #ifdef CONFIG_MEDIA_CONTROLLER
 110         struct media_device     mdev;
 111 #endif
 112 
 113 };
 114 
 115 struct vicodec_ctx {
 116         struct v4l2_fh          fh;
 117         struct vicodec_dev      *dev;
 118         bool                    is_enc;
 119         bool                    is_stateless;
 120         bool                    is_draining;
 121         bool                    next_is_last;
 122         bool                    has_stopped;
 123         spinlock_t              *lock;
 124 
 125         struct v4l2_ctrl_handler hdl;
 126 
 127         struct vb2_v4l2_buffer *last_src_buf;
 128 
 129         /* Source and destination queue data */
 130         struct vicodec_q_data   q_data[2];
 131         struct v4l2_fwht_state  state;
 132 
 133         u32                     cur_buf_offset;
 134         u32                     comp_max_size;
 135         u32                     comp_size;
 136         u32                     header_size;
 137         u32                     comp_magic_cnt;
 138         bool                    comp_has_frame;
 139         bool                    comp_has_next_frame;
 140         bool                    first_source_change_sent;
 141         bool                    source_changed;
 142 };
 143 
 144 static const struct v4l2_event vicodec_eos_event = {
 145         .type = V4L2_EVENT_EOS
 146 };
 147 
 148 static inline struct vicodec_ctx *file2ctx(struct file *file)
 149 {
 150         return container_of(file->private_data, struct vicodec_ctx, fh);
 151 }
 152 
 153 static struct vicodec_q_data *get_q_data(struct vicodec_ctx *ctx,
 154                                          enum v4l2_buf_type type)
 155 {
 156         switch (type) {
 157         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 158         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 159                 return &ctx->q_data[V4L2_M2M_SRC];
 160         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 161         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 162                 return &ctx->q_data[V4L2_M2M_DST];
 163         default:
 164                 break;
 165         }
 166         return NULL;
 167 }
 168 
 169 static void copy_cap_to_ref(const u8 *cap, const struct v4l2_fwht_pixfmt_info *info,
 170                 struct v4l2_fwht_state *state)
 171 {
 172         int plane_idx;
 173         u8 *p_ref = state->ref_frame.buf;
 174         unsigned int cap_stride = state->stride;
 175         unsigned int ref_stride = state->ref_stride;
 176 
 177         for (plane_idx = 0; plane_idx < info->planes_num; plane_idx++) {
 178                 int i;
 179                 unsigned int h_div = (plane_idx == 1 || plane_idx == 2) ?
 180                         info->height_div : 1;
 181                 const u8 *row_cap = cap;
 182                 u8 *row_ref = p_ref;
 183 
 184                 if (info->planes_num == 3 && plane_idx == 1) {
 185                         cap_stride /= 2;
 186                         ref_stride /= 2;
 187                 }
 188 
 189                 if (plane_idx == 1 &&
 190                     (info->id == V4L2_PIX_FMT_NV24 ||
 191                      info->id == V4L2_PIX_FMT_NV42)) {
 192                         cap_stride *= 2;
 193                         ref_stride *= 2;
 194                 }
 195 
 196                 for (i = 0; i < state->visible_height / h_div; i++) {
 197                         memcpy(row_ref, row_cap, ref_stride);
 198                         row_ref += ref_stride;
 199                         row_cap += cap_stride;
 200                 }
 201                 cap += cap_stride * (state->coded_height / h_div);
 202                 p_ref += ref_stride * (state->coded_height / h_div);
 203         }
 204 }
 205 
 206 static bool validate_by_version(unsigned int flags, unsigned int version)
 207 {
 208         if (!version || version > FWHT_VERSION)
 209                 return false;
 210 
 211         if (version >= 2) {
 212                 unsigned int components_num = 1 +
 213                         ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
 214                          FWHT_FL_COMPONENTS_NUM_OFFSET);
 215                 unsigned int pixenc = flags & FWHT_FL_PIXENC_MSK;
 216 
 217                 if (components_num == 0 || components_num > 4 || !pixenc)
 218                         return false;
 219         }
 220         return true;
 221 }
 222 
 223 static bool validate_stateless_params_flags(const struct v4l2_ctrl_fwht_params *params,
 224                                             const struct v4l2_fwht_pixfmt_info *cur_info)
 225 {
 226         unsigned int width_div =
 227                 (params->flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
 228         unsigned int height_div =
 229                 (params->flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
 230         unsigned int components_num = 3;
 231         unsigned int pixenc = 0;
 232 
 233         if (params->version < 3)
 234                 return false;
 235 
 236         components_num = 1 + ((params->flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
 237                               FWHT_FL_COMPONENTS_NUM_OFFSET);
 238         pixenc = (params->flags & FWHT_FL_PIXENC_MSK);
 239         if (v4l2_fwht_validate_fmt(cur_info, width_div, height_div,
 240                                     components_num, pixenc))
 241                 return true;
 242         return false;
 243 }
 244 
 245 
 246 static void update_state_from_header(struct vicodec_ctx *ctx)
 247 {
 248         const struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
 249 
 250         ctx->state.visible_width = ntohl(p_hdr->width);
 251         ctx->state.visible_height = ntohl(p_hdr->height);
 252         ctx->state.colorspace = ntohl(p_hdr->colorspace);
 253         ctx->state.xfer_func = ntohl(p_hdr->xfer_func);
 254         ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
 255         ctx->state.quantization = ntohl(p_hdr->quantization);
 256 }
 257 
 258 static int device_process(struct vicodec_ctx *ctx,
 259                           struct vb2_v4l2_buffer *src_vb,
 260                           struct vb2_v4l2_buffer *dst_vb)
 261 {
 262         struct vicodec_dev *dev = ctx->dev;
 263         struct v4l2_fwht_state *state = &ctx->state;
 264         u8 *p_src, *p_dst;
 265         int ret = 0;
 266 
 267         if (ctx->is_enc || ctx->is_stateless)
 268                 p_src = vb2_plane_vaddr(&src_vb->vb2_buf, 0);
 269         else
 270                 p_src = state->compressed_frame;
 271 
 272         if (ctx->is_stateless) {
 273                 struct media_request *src_req = src_vb->vb2_buf.req_obj.req;
 274 
 275                 ret = v4l2_ctrl_request_setup(src_req, &ctx->hdl);
 276                 if (ret)
 277                         return ret;
 278                 update_state_from_header(ctx);
 279 
 280                 ctx->state.header.size =
 281                         htonl(vb2_get_plane_payload(&src_vb->vb2_buf, 0));
 282                 /*
 283                  * set the reference buffer from the reference timestamp
 284                  * only if this is a P-frame
 285                  */
 286                 if (!(ntohl(ctx->state.header.flags) & FWHT_FL_I_FRAME)) {
 287                         struct vb2_buffer *ref_vb2_buf;
 288                         int ref_buf_idx;
 289                         struct vb2_queue *vq_cap =
 290                                 v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
 291                                                 V4L2_BUF_TYPE_VIDEO_CAPTURE);
 292 
 293                         ref_buf_idx = vb2_find_timestamp(vq_cap,
 294                                                          ctx->state.ref_frame_ts, 0);
 295                         if (ref_buf_idx < 0)
 296                                 return -EINVAL;
 297 
 298                         ref_vb2_buf = vq_cap->bufs[ref_buf_idx];
 299                         if (ref_vb2_buf->state == VB2_BUF_STATE_ERROR)
 300                                 ret = -EINVAL;
 301                         ctx->state.ref_frame.buf =
 302                                 vb2_plane_vaddr(ref_vb2_buf, 0);
 303                 } else {
 304                         ctx->state.ref_frame.buf = NULL;
 305                 }
 306         }
 307         p_dst = vb2_plane_vaddr(&dst_vb->vb2_buf, 0);
 308         if (!p_src || !p_dst) {
 309                 v4l2_err(&dev->v4l2_dev,
 310                          "Acquiring kernel pointers to buffers failed\n");
 311                 return -EFAULT;
 312         }
 313 
 314         if (ctx->is_enc) {
 315                 struct vicodec_q_data *q_src;
 316                 int comp_sz_or_errcode;
 317 
 318                 q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 319                 state->info = q_src->info;
 320                 comp_sz_or_errcode = v4l2_fwht_encode(state, p_src, p_dst);
 321                 if (comp_sz_or_errcode < 0)
 322                         return comp_sz_or_errcode;
 323                 vb2_set_plane_payload(&dst_vb->vb2_buf, 0, comp_sz_or_errcode);
 324         } else {
 325                 struct vicodec_q_data *q_dst;
 326                 unsigned int comp_frame_size = ntohl(ctx->state.header.size);
 327 
 328                 q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 329                 if (comp_frame_size > ctx->comp_max_size)
 330                         return -EINVAL;
 331                 state->info = q_dst->info;
 332                 ret = v4l2_fwht_decode(state, p_src, p_dst);
 333                 if (ret < 0)
 334                         return ret;
 335                 if (!ctx->is_stateless)
 336                         copy_cap_to_ref(p_dst, ctx->state.info, &ctx->state);
 337 
 338                 vb2_set_plane_payload(&dst_vb->vb2_buf, 0, q_dst->sizeimage);
 339                 if (ntohl(ctx->state.header.flags) & FWHT_FL_I_FRAME)
 340                         dst_vb->flags |= V4L2_BUF_FLAG_KEYFRAME;
 341                 else
 342                         dst_vb->flags |= V4L2_BUF_FLAG_PFRAME;
 343         }
 344         return ret;
 345 }
 346 
 347 /*
 348  * mem2mem callbacks
 349  */
 350 static enum vb2_buffer_state get_next_header(struct vicodec_ctx *ctx,
 351                                              u8 **pp, u32 sz)
 352 {
 353         static const u8 magic[] = {
 354                 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
 355         };
 356         u8 *p = *pp;
 357         u32 state;
 358         u8 *header = (u8 *)&ctx->state.header;
 359 
 360         state = VB2_BUF_STATE_DONE;
 361 
 362         if (!ctx->header_size) {
 363                 state = VB2_BUF_STATE_ERROR;
 364                 for (; p < *pp + sz; p++) {
 365                         u32 copy;
 366 
 367                         p = memchr(p, magic[ctx->comp_magic_cnt],
 368                                    *pp + sz - p);
 369                         if (!p) {
 370                                 ctx->comp_magic_cnt = 0;
 371                                 p = *pp + sz;
 372                                 break;
 373                         }
 374                         copy = sizeof(magic) - ctx->comp_magic_cnt;
 375                         if (*pp + sz - p < copy)
 376                                 copy = *pp + sz - p;
 377 
 378                         memcpy(header + ctx->comp_magic_cnt, p, copy);
 379                         ctx->comp_magic_cnt += copy;
 380                         if (!memcmp(header, magic, ctx->comp_magic_cnt)) {
 381                                 p += copy;
 382                                 state = VB2_BUF_STATE_DONE;
 383                                 break;
 384                         }
 385                         ctx->comp_magic_cnt = 0;
 386                 }
 387                 if (ctx->comp_magic_cnt < sizeof(magic)) {
 388                         *pp = p;
 389                         return state;
 390                 }
 391                 ctx->header_size = sizeof(magic);
 392         }
 393 
 394         if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
 395                 u32 copy = sizeof(struct fwht_cframe_hdr) - ctx->header_size;
 396 
 397                 if (*pp + sz - p < copy)
 398                         copy = *pp + sz - p;
 399 
 400                 memcpy(header + ctx->header_size, p, copy);
 401                 p += copy;
 402                 ctx->header_size += copy;
 403         }
 404         *pp = p;
 405         return state;
 406 }
 407 
 408 /* device_run() - prepares and starts the device */
 409 static void device_run(void *priv)
 410 {
 411         struct vicodec_ctx *ctx = priv;
 412         struct vicodec_dev *dev = ctx->dev;
 413         struct vb2_v4l2_buffer *src_buf, *dst_buf;
 414         struct vicodec_q_data *q_src, *q_dst;
 415         u32 state;
 416         struct media_request *src_req;
 417 
 418         src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
 419         dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 420         src_req = src_buf->vb2_buf.req_obj.req;
 421 
 422         q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 423         q_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 424 
 425         state = VB2_BUF_STATE_DONE;
 426         if (device_process(ctx, src_buf, dst_buf))
 427                 state = VB2_BUF_STATE_ERROR;
 428         else
 429                 dst_buf->sequence = q_dst->sequence++;
 430         dst_buf->flags &= ~V4L2_BUF_FLAG_LAST;
 431         v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
 432 
 433         spin_lock(ctx->lock);
 434         if (!ctx->comp_has_next_frame && src_buf == ctx->last_src_buf) {
 435                 dst_buf->flags |= V4L2_BUF_FLAG_LAST;
 436                 v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
 437                 ctx->is_draining = false;
 438                 ctx->has_stopped = true;
 439         }
 440         if (ctx->is_enc || ctx->is_stateless) {
 441                 src_buf->sequence = q_src->sequence++;
 442                 src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 443                 v4l2_m2m_buf_done(src_buf, state);
 444         } else if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == ctx->cur_buf_offset) {
 445                 src_buf->sequence = q_src->sequence++;
 446                 src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 447                 v4l2_m2m_buf_done(src_buf, state);
 448                 ctx->cur_buf_offset = 0;
 449                 ctx->comp_has_next_frame = false;
 450         }
 451         v4l2_m2m_buf_done(dst_buf, state);
 452 
 453         ctx->comp_size = 0;
 454         ctx->header_size = 0;
 455         ctx->comp_magic_cnt = 0;
 456         ctx->comp_has_frame = false;
 457         spin_unlock(ctx->lock);
 458         if (ctx->is_stateless && src_req)
 459                 v4l2_ctrl_request_complete(src_req, &ctx->hdl);
 460 
 461         if (ctx->is_enc)
 462                 v4l2_m2m_job_finish(dev->stateful_enc.m2m_dev, ctx->fh.m2m_ctx);
 463         else if (ctx->is_stateless)
 464                 v4l2_m2m_job_finish(dev->stateless_dec.m2m_dev,
 465                                     ctx->fh.m2m_ctx);
 466         else
 467                 v4l2_m2m_job_finish(dev->stateful_dec.m2m_dev, ctx->fh.m2m_ctx);
 468 }
 469 
 470 static void job_remove_src_buf(struct vicodec_ctx *ctx, u32 state)
 471 {
 472         struct vb2_v4l2_buffer *src_buf;
 473         struct vicodec_q_data *q_src;
 474 
 475         q_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 476         spin_lock(ctx->lock);
 477         src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
 478         src_buf->sequence = q_src->sequence++;
 479         v4l2_m2m_buf_done(src_buf, state);
 480         ctx->cur_buf_offset = 0;
 481         spin_unlock(ctx->lock);
 482 }
 483 
 484 static const struct v4l2_fwht_pixfmt_info *
 485 info_from_header(const struct fwht_cframe_hdr *p_hdr)
 486 {
 487         unsigned int flags = ntohl(p_hdr->flags);
 488         unsigned int width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
 489         unsigned int height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
 490         unsigned int components_num = 3;
 491         unsigned int pixenc = 0;
 492         unsigned int version = ntohl(p_hdr->version);
 493 
 494         if (version >= 2) {
 495                 components_num = 1 + ((flags & FWHT_FL_COMPONENTS_NUM_MSK) >>
 496                                 FWHT_FL_COMPONENTS_NUM_OFFSET);
 497                 pixenc = (flags & FWHT_FL_PIXENC_MSK);
 498         }
 499         return v4l2_fwht_find_nth_fmt(width_div, height_div,
 500                                      components_num, pixenc, 0);
 501 }
 502 
 503 static bool is_header_valid(const struct fwht_cframe_hdr *p_hdr)
 504 {
 505         const struct v4l2_fwht_pixfmt_info *info;
 506         unsigned int w = ntohl(p_hdr->width);
 507         unsigned int h = ntohl(p_hdr->height);
 508         unsigned int version = ntohl(p_hdr->version);
 509         unsigned int flags = ntohl(p_hdr->flags);
 510 
 511         if (w < MIN_WIDTH || w > MAX_WIDTH || h < MIN_HEIGHT || h > MAX_HEIGHT)
 512                 return false;
 513 
 514         if (!validate_by_version(flags, version))
 515                 return false;
 516 
 517         info = info_from_header(p_hdr);
 518         if (!info)
 519                 return false;
 520         return true;
 521 }
 522 
 523 static void update_capture_data_from_header(struct vicodec_ctx *ctx)
 524 {
 525         struct vicodec_q_data *q_dst = get_q_data(ctx,
 526                                                   V4L2_BUF_TYPE_VIDEO_CAPTURE);
 527         const struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
 528         const struct v4l2_fwht_pixfmt_info *info = info_from_header(p_hdr);
 529         unsigned int flags = ntohl(p_hdr->flags);
 530         unsigned int hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
 531         unsigned int hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
 532 
 533         /*
 534          * This function should not be used by a stateless codec since
 535          * it changes values in q_data that are not request specific
 536          */
 537         WARN_ON(ctx->is_stateless);
 538 
 539         q_dst->info = info;
 540         q_dst->visible_width = ntohl(p_hdr->width);
 541         q_dst->visible_height = ntohl(p_hdr->height);
 542         q_dst->coded_width = vic_round_dim(q_dst->visible_width, hdr_width_div);
 543         q_dst->coded_height = vic_round_dim(q_dst->visible_height,
 544                                             hdr_height_div);
 545 
 546         q_dst->sizeimage = q_dst->coded_width * q_dst->coded_height *
 547                 q_dst->info->sizeimage_mult / q_dst->info->sizeimage_div;
 548         ctx->state.colorspace = ntohl(p_hdr->colorspace);
 549 
 550         ctx->state.xfer_func = ntohl(p_hdr->xfer_func);
 551         ctx->state.ycbcr_enc = ntohl(p_hdr->ycbcr_enc);
 552         ctx->state.quantization = ntohl(p_hdr->quantization);
 553 }
 554 
 555 static void set_last_buffer(struct vb2_v4l2_buffer *dst_buf,
 556                             const struct vb2_v4l2_buffer *src_buf,
 557                             struct vicodec_ctx *ctx)
 558 {
 559         struct vicodec_q_data *q_dst = get_q_data(ctx,
 560                                                   V4L2_BUF_TYPE_VIDEO_CAPTURE);
 561 
 562         vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0);
 563         dst_buf->sequence = q_dst->sequence++;
 564 
 565         v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, !ctx->is_enc);
 566         dst_buf->flags |= V4L2_BUF_FLAG_LAST;
 567         v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
 568 }
 569 
 570 static int job_ready(void *priv)
 571 {
 572         static const u8 magic[] = {
 573                 0x4f, 0x4f, 0x4f, 0x4f, 0xff, 0xff, 0xff, 0xff
 574         };
 575         struct vicodec_ctx *ctx = priv;
 576         struct vb2_v4l2_buffer *src_buf;
 577         u8 *p_src;
 578         u8 *p;
 579         u32 sz;
 580         u32 state;
 581         struct vicodec_q_data *q_dst = get_q_data(ctx,
 582                                                   V4L2_BUF_TYPE_VIDEO_CAPTURE);
 583         unsigned int flags;
 584         unsigned int hdr_width_div;
 585         unsigned int hdr_height_div;
 586         unsigned int max_to_copy;
 587         unsigned int comp_frame_size;
 588 
 589         if (ctx->has_stopped)
 590                 return 0;
 591         if (ctx->source_changed)
 592                 return 0;
 593         if (ctx->is_stateless || ctx->is_enc || ctx->comp_has_frame)
 594                 return 1;
 595 
 596 restart:
 597         ctx->comp_has_next_frame = false;
 598         src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
 599         if (!src_buf)
 600                 return 0;
 601         p_src = vb2_plane_vaddr(&src_buf->vb2_buf, 0);
 602         sz = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
 603         p = p_src + ctx->cur_buf_offset;
 604 
 605         state = VB2_BUF_STATE_DONE;
 606 
 607         if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
 608                 state = get_next_header(ctx, &p, p_src + sz - p);
 609                 if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
 610                         if (ctx->is_draining && src_buf == ctx->last_src_buf)
 611                                 return 1;
 612                         job_remove_src_buf(ctx, state);
 613                         goto restart;
 614                 }
 615         }
 616 
 617         comp_frame_size = ntohl(ctx->state.header.size);
 618 
 619         /*
 620          * The current scanned frame might be the first frame of a new
 621          * resolution so its size might be larger than ctx->comp_max_size.
 622          * In that case it is copied up to the current buffer capacity and
 623          * the copy will continue after allocating new large enough buffer
 624          * when restreaming
 625          */
 626         max_to_copy = min(comp_frame_size, ctx->comp_max_size);
 627 
 628         if (ctx->comp_size < max_to_copy) {
 629                 u32 copy = max_to_copy - ctx->comp_size;
 630 
 631                 if (copy > p_src + sz - p)
 632                         copy = p_src + sz - p;
 633 
 634                 memcpy(ctx->state.compressed_frame + ctx->comp_size,
 635                        p, copy);
 636                 p += copy;
 637                 ctx->comp_size += copy;
 638                 if (ctx->comp_size < max_to_copy) {
 639                         if (ctx->is_draining && src_buf == ctx->last_src_buf)
 640                                 return 1;
 641                         job_remove_src_buf(ctx, state);
 642                         goto restart;
 643                 }
 644         }
 645         ctx->cur_buf_offset = p - p_src;
 646         if (ctx->comp_size == comp_frame_size)
 647                 ctx->comp_has_frame = true;
 648         ctx->comp_has_next_frame = false;
 649         if (ctx->comp_has_frame && sz - ctx->cur_buf_offset >=
 650                         sizeof(struct fwht_cframe_hdr)) {
 651                 struct fwht_cframe_hdr *p_hdr = (struct fwht_cframe_hdr *)p;
 652                 u32 frame_size = ntohl(p_hdr->size);
 653                 u32 remaining = sz - ctx->cur_buf_offset - sizeof(*p_hdr);
 654 
 655                 if (!memcmp(p, magic, sizeof(magic)))
 656                         ctx->comp_has_next_frame = remaining >= frame_size;
 657         }
 658         /*
 659          * if the header is invalid the device_run will just drop the frame
 660          * with an error
 661          */
 662         if (!is_header_valid(&ctx->state.header) && ctx->comp_has_frame)
 663                 return 1;
 664         flags = ntohl(ctx->state.header.flags);
 665         hdr_width_div = (flags & FWHT_FL_CHROMA_FULL_WIDTH) ? 1 : 2;
 666         hdr_height_div = (flags & FWHT_FL_CHROMA_FULL_HEIGHT) ? 1 : 2;
 667 
 668         if (ntohl(ctx->state.header.width) != q_dst->visible_width ||
 669             ntohl(ctx->state.header.height) != q_dst->visible_height ||
 670             !q_dst->info ||
 671             hdr_width_div != q_dst->info->width_div ||
 672             hdr_height_div != q_dst->info->height_div) {
 673                 static const struct v4l2_event rs_event = {
 674                         .type = V4L2_EVENT_SOURCE_CHANGE,
 675                         .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
 676                 };
 677 
 678                 struct vb2_v4l2_buffer *dst_buf =
 679                         v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 680 
 681                 update_capture_data_from_header(ctx);
 682                 v4l2_event_queue_fh(&ctx->fh, &rs_event);
 683                 set_last_buffer(dst_buf, src_buf, ctx);
 684                 ctx->source_changed = true;
 685                 return 0;
 686         }
 687         return 1;
 688 }
 689 
 690 /*
 691  * video ioctls
 692  */
 693 
 694 static const struct v4l2_fwht_pixfmt_info *find_fmt(u32 fmt)
 695 {
 696         const struct v4l2_fwht_pixfmt_info *info =
 697                 v4l2_fwht_find_pixfmt(fmt);
 698 
 699         if (!info)
 700                 info = v4l2_fwht_get_pixfmt(0);
 701         return info;
 702 }
 703 
 704 static int vidioc_querycap(struct file *file, void *priv,
 705                            struct v4l2_capability *cap)
 706 {
 707         strscpy(cap->driver, VICODEC_NAME, sizeof(cap->driver));
 708         strscpy(cap->card, VICODEC_NAME, sizeof(cap->card));
 709         snprintf(cap->bus_info, sizeof(cap->bus_info),
 710                         "platform:%s", VICODEC_NAME);
 711         return 0;
 712 }
 713 
 714 static int enum_fmt(struct v4l2_fmtdesc *f, struct vicodec_ctx *ctx,
 715                     bool is_out)
 716 {
 717         bool is_uncomp = (ctx->is_enc && is_out) || (!ctx->is_enc && !is_out);
 718 
 719         if (V4L2_TYPE_IS_MULTIPLANAR(f->type) && !multiplanar)
 720                 return -EINVAL;
 721         if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && multiplanar)
 722                 return -EINVAL;
 723 
 724         if (is_uncomp) {
 725                 const struct v4l2_fwht_pixfmt_info *info =
 726                                         get_q_data(ctx, f->type)->info;
 727 
 728                 if (ctx->is_enc ||
 729                     !vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q))
 730                         info = v4l2_fwht_get_pixfmt(f->index);
 731                 else
 732                         info = v4l2_fwht_find_nth_fmt(info->width_div,
 733                                                      info->height_div,
 734                                                      info->components_num,
 735                                                      info->pixenc,
 736                                                      f->index);
 737                 if (!info)
 738                         return -EINVAL;
 739                 f->pixelformat = info->id;
 740         } else {
 741                 if (f->index)
 742                         return -EINVAL;
 743                 f->pixelformat = ctx->is_stateless ?
 744                         V4L2_PIX_FMT_FWHT_STATELESS : V4L2_PIX_FMT_FWHT;
 745                 if (!ctx->is_enc && !ctx->is_stateless)
 746                         f->flags = V4L2_FMT_FLAG_DYN_RESOLUTION |
 747                                    V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM;
 748         }
 749         return 0;
 750 }
 751 
 752 static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 753                                    struct v4l2_fmtdesc *f)
 754 {
 755         struct vicodec_ctx *ctx = file2ctx(file);
 756 
 757         return enum_fmt(f, ctx, false);
 758 }
 759 
 760 static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
 761                                    struct v4l2_fmtdesc *f)
 762 {
 763         struct vicodec_ctx *ctx = file2ctx(file);
 764 
 765         return enum_fmt(f, ctx, true);
 766 }
 767 
 768 static int vidioc_g_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
 769 {
 770         struct vb2_queue *vq;
 771         struct vicodec_q_data *q_data;
 772         struct v4l2_pix_format_mplane *pix_mp;
 773         struct v4l2_pix_format *pix;
 774         const struct v4l2_fwht_pixfmt_info *info;
 775 
 776         vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 777         if (!vq)
 778                 return -EINVAL;
 779 
 780         q_data = get_q_data(ctx, f->type);
 781         info = q_data->info;
 782 
 783         switch (f->type) {
 784         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 785         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 786                 if (multiplanar)
 787                         return -EINVAL;
 788                 pix = &f->fmt.pix;
 789                 pix->width = q_data->coded_width;
 790                 pix->height = q_data->coded_height;
 791                 pix->field = V4L2_FIELD_NONE;
 792                 pix->pixelformat = info->id;
 793                 pix->bytesperline = q_data->coded_width *
 794                                         info->bytesperline_mult;
 795                 pix->sizeimage = q_data->sizeimage;
 796                 pix->colorspace = ctx->state.colorspace;
 797                 pix->xfer_func = ctx->state.xfer_func;
 798                 pix->ycbcr_enc = ctx->state.ycbcr_enc;
 799                 pix->quantization = ctx->state.quantization;
 800                 break;
 801 
 802         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 803         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 804                 if (!multiplanar)
 805                         return -EINVAL;
 806                 pix_mp = &f->fmt.pix_mp;
 807                 pix_mp->width = q_data->coded_width;
 808                 pix_mp->height = q_data->coded_height;
 809                 pix_mp->field = V4L2_FIELD_NONE;
 810                 pix_mp->pixelformat = info->id;
 811                 pix_mp->num_planes = 1;
 812                 pix_mp->plane_fmt[0].bytesperline =
 813                                 q_data->coded_width * info->bytesperline_mult;
 814                 pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage;
 815                 pix_mp->colorspace = ctx->state.colorspace;
 816                 pix_mp->xfer_func = ctx->state.xfer_func;
 817                 pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
 818                 pix_mp->quantization = ctx->state.quantization;
 819                 memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
 820                 memset(pix_mp->plane_fmt[0].reserved, 0,
 821                        sizeof(pix_mp->plane_fmt[0].reserved));
 822                 break;
 823         default:
 824                 return -EINVAL;
 825         }
 826         return 0;
 827 }
 828 
 829 static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
 830                                 struct v4l2_format *f)
 831 {
 832         return vidioc_g_fmt(file2ctx(file), f);
 833 }
 834 
 835 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 836                                 struct v4l2_format *f)
 837 {
 838         return vidioc_g_fmt(file2ctx(file), f);
 839 }
 840 
 841 static int vidioc_try_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
 842 {
 843         struct v4l2_pix_format_mplane *pix_mp;
 844         struct v4l2_pix_format *pix;
 845         struct v4l2_plane_pix_format *plane;
 846         const struct v4l2_fwht_pixfmt_info *info = ctx->is_stateless ?
 847                 &pixfmt_stateless_fwht : &pixfmt_fwht;
 848 
 849         switch (f->type) {
 850         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 851         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 852                 pix = &f->fmt.pix;
 853                 if (pix->pixelformat != V4L2_PIX_FMT_FWHT &&
 854                     pix->pixelformat != V4L2_PIX_FMT_FWHT_STATELESS)
 855                         info = find_fmt(pix->pixelformat);
 856 
 857                 pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH);
 858                 pix->width = vic_round_dim(pix->width, info->width_div);
 859 
 860                 pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT);
 861                 pix->height = vic_round_dim(pix->height, info->height_div);
 862 
 863                 pix->field = V4L2_FIELD_NONE;
 864                 pix->bytesperline =
 865                         pix->width * info->bytesperline_mult;
 866                 pix->sizeimage = pix->width * pix->height *
 867                         info->sizeimage_mult / info->sizeimage_div;
 868                 if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
 869                         pix->sizeimage += sizeof(struct fwht_cframe_hdr);
 870                 break;
 871         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 872         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 873                 pix_mp = &f->fmt.pix_mp;
 874                 plane = pix_mp->plane_fmt;
 875                 if (pix_mp->pixelformat != V4L2_PIX_FMT_FWHT &&
 876                     pix_mp->pixelformat != V4L2_PIX_FMT_FWHT_STATELESS)
 877                         info = find_fmt(pix_mp->pixelformat);
 878                 pix_mp->num_planes = 1;
 879 
 880                 pix_mp->width = clamp(pix_mp->width, MIN_WIDTH, MAX_WIDTH);
 881                 pix_mp->width = vic_round_dim(pix_mp->width, info->width_div);
 882 
 883                 pix_mp->height = clamp(pix_mp->height, MIN_HEIGHT, MAX_HEIGHT);
 884                 pix_mp->height = vic_round_dim(pix_mp->height,
 885                                                info->height_div);
 886 
 887                 pix_mp->field = V4L2_FIELD_NONE;
 888                 plane->bytesperline =
 889                         pix_mp->width * info->bytesperline_mult;
 890                 plane->sizeimage = pix_mp->width * pix_mp->height *
 891                         info->sizeimage_mult / info->sizeimage_div;
 892                 if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
 893                         plane->sizeimage += sizeof(struct fwht_cframe_hdr);
 894                 memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
 895                 memset(plane->reserved, 0, sizeof(plane->reserved));
 896                 break;
 897         default:
 898                 return -EINVAL;
 899         }
 900 
 901         return 0;
 902 }
 903 
 904 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 905                                   struct v4l2_format *f)
 906 {
 907         struct vicodec_ctx *ctx = file2ctx(file);
 908         struct v4l2_pix_format_mplane *pix_mp;
 909         struct v4l2_pix_format *pix;
 910 
 911         switch (f->type) {
 912         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 913                 if (multiplanar)
 914                         return -EINVAL;
 915                 pix = &f->fmt.pix;
 916                 pix->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
 917                                    find_fmt(f->fmt.pix.pixelformat)->id;
 918                 pix->colorspace = ctx->state.colorspace;
 919                 pix->xfer_func = ctx->state.xfer_func;
 920                 pix->ycbcr_enc = ctx->state.ycbcr_enc;
 921                 pix->quantization = ctx->state.quantization;
 922                 break;
 923         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 924                 if (!multiplanar)
 925                         return -EINVAL;
 926                 pix_mp = &f->fmt.pix_mp;
 927                 pix_mp->pixelformat = ctx->is_enc ? V4L2_PIX_FMT_FWHT :
 928                                       find_fmt(pix_mp->pixelformat)->id;
 929                 pix_mp->colorspace = ctx->state.colorspace;
 930                 pix_mp->xfer_func = ctx->state.xfer_func;
 931                 pix_mp->ycbcr_enc = ctx->state.ycbcr_enc;
 932                 pix_mp->quantization = ctx->state.quantization;
 933                 break;
 934         default:
 935                 return -EINVAL;
 936         }
 937 
 938         return vidioc_try_fmt(ctx, f);
 939 }
 940 
 941 static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
 942                                   struct v4l2_format *f)
 943 {
 944         struct vicodec_ctx *ctx = file2ctx(file);
 945         struct v4l2_pix_format_mplane *pix_mp;
 946         struct v4l2_pix_format *pix;
 947 
 948         switch (f->type) {
 949         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 950                 if (multiplanar)
 951                         return -EINVAL;
 952                 pix = &f->fmt.pix;
 953                 if (ctx->is_enc)
 954                         pix->pixelformat = find_fmt(pix->pixelformat)->id;
 955                 else if (ctx->is_stateless)
 956                         pix->pixelformat = V4L2_PIX_FMT_FWHT_STATELESS;
 957                 else
 958                         pix->pixelformat = V4L2_PIX_FMT_FWHT;
 959                 if (!pix->colorspace)
 960                         pix->colorspace = V4L2_COLORSPACE_REC709;
 961                 break;
 962         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 963                 if (!multiplanar)
 964                         return -EINVAL;
 965                 pix_mp = &f->fmt.pix_mp;
 966                 if (ctx->is_enc)
 967                         pix_mp->pixelformat = find_fmt(pix_mp->pixelformat)->id;
 968                 else if (ctx->is_stateless)
 969                         pix_mp->pixelformat = V4L2_PIX_FMT_FWHT_STATELESS;
 970                 else
 971                         pix_mp->pixelformat = V4L2_PIX_FMT_FWHT;
 972                 if (!pix_mp->colorspace)
 973                         pix_mp->colorspace = V4L2_COLORSPACE_REC709;
 974                 break;
 975         default:
 976                 return -EINVAL;
 977         }
 978 
 979         return vidioc_try_fmt(ctx, f);
 980 }
 981 
 982 static int vidioc_s_fmt(struct vicodec_ctx *ctx, struct v4l2_format *f)
 983 {
 984         struct vicodec_q_data *q_data;
 985         struct vb2_queue *vq;
 986         bool fmt_changed = true;
 987         struct v4l2_pix_format_mplane *pix_mp;
 988         struct v4l2_pix_format *pix;
 989 
 990         vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
 991         if (!vq)
 992                 return -EINVAL;
 993 
 994         q_data = get_q_data(ctx, f->type);
 995         if (!q_data)
 996                 return -EINVAL;
 997 
 998         switch (f->type) {
 999         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1000         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1001                 pix = &f->fmt.pix;
1002                 if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
1003                         fmt_changed =
1004                                 !q_data->info ||
1005                                 q_data->info->id != pix->pixelformat ||
1006                                 q_data->coded_width != pix->width ||
1007                                 q_data->coded_height != pix->height;
1008 
1009                 if (vb2_is_busy(vq) && fmt_changed)
1010                         return -EBUSY;
1011 
1012                 if (pix->pixelformat == V4L2_PIX_FMT_FWHT)
1013                         q_data->info = &pixfmt_fwht;
1014                 else if (pix->pixelformat == V4L2_PIX_FMT_FWHT_STATELESS)
1015                         q_data->info = &pixfmt_stateless_fwht;
1016                 else
1017                         q_data->info = find_fmt(pix->pixelformat);
1018                 q_data->coded_width = pix->width;
1019                 q_data->coded_height = pix->height;
1020                 q_data->sizeimage = pix->sizeimage;
1021                 break;
1022         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1023         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1024                 pix_mp = &f->fmt.pix_mp;
1025                 if (ctx->is_enc && V4L2_TYPE_IS_OUTPUT(f->type))
1026                         fmt_changed =
1027                                 !q_data->info ||
1028                                 q_data->info->id != pix_mp->pixelformat ||
1029                                 q_data->coded_width != pix_mp->width ||
1030                                 q_data->coded_height != pix_mp->height;
1031 
1032                 if (vb2_is_busy(vq) && fmt_changed)
1033                         return -EBUSY;
1034 
1035                 if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT)
1036                         q_data->info = &pixfmt_fwht;
1037                 else if (pix_mp->pixelformat == V4L2_PIX_FMT_FWHT_STATELESS)
1038                         q_data->info = &pixfmt_stateless_fwht;
1039                 else
1040                         q_data->info = find_fmt(pix_mp->pixelformat);
1041                 q_data->coded_width = pix_mp->width;
1042                 q_data->coded_height = pix_mp->height;
1043                 q_data->sizeimage = pix_mp->plane_fmt[0].sizeimage;
1044                 break;
1045         default:
1046                 return -EINVAL;
1047         }
1048 
1049         dprintk(ctx->dev,
1050                 "Setting format for type %d, coded wxh: %dx%d, fourcc: 0x%08x\n",
1051                 f->type, q_data->coded_width, q_data->coded_height,
1052                 q_data->info->id);
1053 
1054         return 0;
1055 }
1056 
1057 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1058                                 struct v4l2_format *f)
1059 {
1060         int ret;
1061 
1062         ret = vidioc_try_fmt_vid_cap(file, priv, f);
1063         if (ret)
1064                 return ret;
1065 
1066         return vidioc_s_fmt(file2ctx(file), f);
1067 }
1068 
1069 static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
1070                                 struct v4l2_format *f)
1071 {
1072         struct vicodec_ctx *ctx = file2ctx(file);
1073         struct vicodec_q_data *q_data;
1074         struct vicodec_q_data *q_data_cap;
1075         struct v4l2_pix_format *pix;
1076         struct v4l2_pix_format_mplane *pix_mp;
1077         u32 coded_w = 0, coded_h = 0;
1078         unsigned int size = 0;
1079         int ret;
1080 
1081         q_data = get_q_data(ctx, f->type);
1082         q_data_cap = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
1083 
1084         ret = vidioc_try_fmt_vid_out(file, priv, f);
1085         if (ret)
1086                 return ret;
1087 
1088         if (ctx->is_enc) {
1089                 struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
1090                 struct vb2_queue *vq_cap = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
1091                                                            V4L2_BUF_TYPE_VIDEO_CAPTURE);
1092                 const struct v4l2_fwht_pixfmt_info *info = ctx->is_stateless ?
1093                         &pixfmt_stateless_fwht : &pixfmt_fwht;
1094 
1095                 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1096                         coded_w = f->fmt.pix.width;
1097                         coded_h = f->fmt.pix.height;
1098                 } else {
1099                         coded_w = f->fmt.pix_mp.width;
1100                         coded_h = f->fmt.pix_mp.height;
1101                 }
1102                 if (vb2_is_busy(vq) && (coded_w != q_data->coded_width ||
1103                                         coded_h != q_data->coded_height))
1104                         return -EBUSY;
1105                 size = coded_w * coded_h *
1106                         info->sizeimage_mult / info->sizeimage_div;
1107                 if (!ctx->is_stateless)
1108                         size += sizeof(struct fwht_cframe_hdr);
1109 
1110                 if (vb2_is_busy(vq_cap) && size > q_data_cap->sizeimage)
1111                         return -EBUSY;
1112         }
1113 
1114         ret = vidioc_s_fmt(file2ctx(file), f);
1115         if (!ret) {
1116                 if (ctx->is_enc) {
1117                         q_data->visible_width = coded_w;
1118                         q_data->visible_height = coded_h;
1119                         q_data_cap->coded_width = coded_w;
1120                         q_data_cap->coded_height = coded_h;
1121                         q_data_cap->sizeimage = size;
1122                 }
1123 
1124                 switch (f->type) {
1125                 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1126                         pix = &f->fmt.pix;
1127                         ctx->state.colorspace = pix->colorspace;
1128                         ctx->state.xfer_func = pix->xfer_func;
1129                         ctx->state.ycbcr_enc = pix->ycbcr_enc;
1130                         ctx->state.quantization = pix->quantization;
1131                         break;
1132                 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1133                         pix_mp = &f->fmt.pix_mp;
1134                         ctx->state.colorspace = pix_mp->colorspace;
1135                         ctx->state.xfer_func = pix_mp->xfer_func;
1136                         ctx->state.ycbcr_enc = pix_mp->ycbcr_enc;
1137                         ctx->state.quantization = pix_mp->quantization;
1138                         break;
1139                 default:
1140                         break;
1141                 }
1142         }
1143         return ret;
1144 }
1145 
1146 static int vidioc_g_selection(struct file *file, void *priv,
1147                               struct v4l2_selection *s)
1148 {
1149         struct vicodec_ctx *ctx = file2ctx(file);
1150         struct vicodec_q_data *q_data;
1151 
1152         q_data = get_q_data(ctx, s->type);
1153         if (!q_data)
1154                 return -EINVAL;
1155         /*
1156          * encoder supports only cropping on the OUTPUT buffer
1157          * decoder supports only composing on the CAPTURE buffer
1158          */
1159         if (ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1160                 switch (s->target) {
1161                 case V4L2_SEL_TGT_CROP:
1162                         s->r.left = 0;
1163                         s->r.top = 0;
1164                         s->r.width = q_data->visible_width;
1165                         s->r.height = q_data->visible_height;
1166                         return 0;
1167                 case V4L2_SEL_TGT_CROP_DEFAULT:
1168                 case V4L2_SEL_TGT_CROP_BOUNDS:
1169                         s->r.left = 0;
1170                         s->r.top = 0;
1171                         s->r.width = q_data->coded_width;
1172                         s->r.height = q_data->coded_height;
1173                         return 0;
1174                 }
1175         } else if (!ctx->is_enc && s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1176                 switch (s->target) {
1177                 case V4L2_SEL_TGT_COMPOSE:
1178                         s->r.left = 0;
1179                         s->r.top = 0;
1180                         s->r.width = q_data->visible_width;
1181                         s->r.height = q_data->visible_height;
1182                         return 0;
1183                 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
1184                 case V4L2_SEL_TGT_COMPOSE_BOUNDS:
1185                         s->r.left = 0;
1186                         s->r.top = 0;
1187                         s->r.width = q_data->coded_width;
1188                         s->r.height = q_data->coded_height;
1189                         return 0;
1190                 }
1191         }
1192         return -EINVAL;
1193 }
1194 
1195 static int vidioc_s_selection(struct file *file, void *priv,
1196                               struct v4l2_selection *s)
1197 {
1198         struct vicodec_ctx *ctx = file2ctx(file);
1199         struct vicodec_q_data *q_data;
1200 
1201         if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
1202                 return -EINVAL;
1203 
1204         q_data = get_q_data(ctx, s->type);
1205         if (!q_data)
1206                 return -EINVAL;
1207 
1208         if (!ctx->is_enc || s->target != V4L2_SEL_TGT_CROP)
1209                 return -EINVAL;
1210 
1211         s->r.left = 0;
1212         s->r.top = 0;
1213         q_data->visible_width = clamp(s->r.width, MIN_WIDTH,
1214                                       q_data->coded_width);
1215         s->r.width = q_data->visible_width;
1216         q_data->visible_height = clamp(s->r.height, MIN_HEIGHT,
1217                                        q_data->coded_height);
1218         s->r.height = q_data->visible_height;
1219         return 0;
1220 }
1221 
1222 static int vicodec_mark_last_buf(struct vicodec_ctx *ctx)
1223 {
1224         struct vb2_v4l2_buffer *next_dst_buf;
1225         int ret = 0;
1226 
1227         spin_lock(ctx->lock);
1228         if (ctx->is_draining) {
1229                 ret = -EBUSY;
1230                 goto unlock;
1231         }
1232         if (ctx->has_stopped)
1233                 goto unlock;
1234 
1235         ctx->last_src_buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
1236         ctx->is_draining = true;
1237         if (ctx->last_src_buf)
1238                 goto unlock;
1239 
1240         next_dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
1241         if (!next_dst_buf) {
1242                 ctx->next_is_last = true;
1243                 goto unlock;
1244         }
1245 
1246         next_dst_buf->flags |= V4L2_BUF_FLAG_LAST;
1247         vb2_buffer_done(&next_dst_buf->vb2_buf, VB2_BUF_STATE_DONE);
1248         ctx->is_draining = false;
1249         ctx->has_stopped = true;
1250         v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
1251 
1252 unlock:
1253         spin_unlock(ctx->lock);
1254         return ret;
1255 }
1256 
1257 static int vicodec_encoder_cmd(struct file *file, void *fh,
1258                             struct v4l2_encoder_cmd *ec)
1259 {
1260         struct vicodec_ctx *ctx = file2ctx(file);
1261         int ret;
1262 
1263         ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec);
1264         if (ret < 0)
1265                 return ret;
1266 
1267         if (!vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q) ||
1268             !vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))
1269                 return 0;
1270 
1271         if (ec->cmd == V4L2_ENC_CMD_STOP)
1272                 return vicodec_mark_last_buf(ctx);
1273         ret = 0;
1274         spin_lock(ctx->lock);
1275         if (ctx->is_draining) {
1276                 ret = -EBUSY;
1277         } else if (ctx->has_stopped) {
1278                 ctx->has_stopped = false;
1279                 vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);
1280         }
1281         spin_unlock(ctx->lock);
1282         return ret;
1283 }
1284 
1285 static int vicodec_decoder_cmd(struct file *file, void *fh,
1286                             struct v4l2_decoder_cmd *dc)
1287 {
1288         struct vicodec_ctx *ctx = file2ctx(file);
1289         int ret;
1290 
1291         ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc);
1292         if (ret < 0)
1293                 return ret;
1294 
1295         if (!vb2_is_streaming(&ctx->fh.m2m_ctx->cap_q_ctx.q) ||
1296             !vb2_is_streaming(&ctx->fh.m2m_ctx->out_q_ctx.q))
1297                 return 0;
1298 
1299         if (dc->cmd == V4L2_DEC_CMD_STOP)
1300                 return vicodec_mark_last_buf(ctx);
1301         ret = 0;
1302         spin_lock(ctx->lock);
1303         if (ctx->is_draining) {
1304                 ret = -EBUSY;
1305         } else if (ctx->has_stopped) {
1306                 ctx->has_stopped = false;
1307                 vb2_clear_last_buffer_dequeued(&ctx->fh.m2m_ctx->cap_q_ctx.q);
1308         }
1309         spin_unlock(ctx->lock);
1310         return ret;
1311 }
1312 
1313 static int vicodec_enum_framesizes(struct file *file, void *fh,
1314                                    struct v4l2_frmsizeenum *fsize)
1315 {
1316         switch (fsize->pixel_format) {
1317         case V4L2_PIX_FMT_FWHT_STATELESS:
1318                 break;
1319         case V4L2_PIX_FMT_FWHT:
1320                 break;
1321         default:
1322                 if (find_fmt(fsize->pixel_format)->id == fsize->pixel_format)
1323                         break;
1324                 return -EINVAL;
1325         }
1326 
1327         if (fsize->index)
1328                 return -EINVAL;
1329 
1330         fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1331 
1332         fsize->stepwise.min_width = MIN_WIDTH;
1333         fsize->stepwise.max_width = MAX_WIDTH;
1334         fsize->stepwise.step_width = 8;
1335         fsize->stepwise.min_height = MIN_HEIGHT;
1336         fsize->stepwise.max_height = MAX_HEIGHT;
1337         fsize->stepwise.step_height = 8;
1338 
1339         return 0;
1340 }
1341 
1342 static int vicodec_subscribe_event(struct v4l2_fh *fh,
1343                                 const struct v4l2_event_subscription *sub)
1344 {
1345         struct vicodec_ctx *ctx = container_of(fh, struct vicodec_ctx, fh);
1346 
1347         switch (sub->type) {
1348         case V4L2_EVENT_SOURCE_CHANGE:
1349                 if (ctx->is_enc)
1350                         return -EINVAL;
1351                 /* fall through */
1352         case V4L2_EVENT_EOS:
1353                 if (ctx->is_stateless)
1354                         return -EINVAL;
1355                 return v4l2_event_subscribe(fh, sub, 0, NULL);
1356         default:
1357                 return v4l2_ctrl_subscribe_event(fh, sub);
1358         }
1359 }
1360 
1361 static const struct v4l2_ioctl_ops vicodec_ioctl_ops = {
1362         .vidioc_querycap        = vidioc_querycap,
1363 
1364         .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1365         .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
1366         .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1367         .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
1368 
1369         .vidioc_g_fmt_vid_cap_mplane    = vidioc_g_fmt_vid_cap,
1370         .vidioc_try_fmt_vid_cap_mplane  = vidioc_try_fmt_vid_cap,
1371         .vidioc_s_fmt_vid_cap_mplane    = vidioc_s_fmt_vid_cap,
1372 
1373         .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
1374         .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
1375         .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
1376         .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
1377 
1378         .vidioc_g_fmt_vid_out_mplane    = vidioc_g_fmt_vid_out,
1379         .vidioc_try_fmt_vid_out_mplane  = vidioc_try_fmt_vid_out,
1380         .vidioc_s_fmt_vid_out_mplane    = vidioc_s_fmt_vid_out,
1381 
1382         .vidioc_reqbufs         = v4l2_m2m_ioctl_reqbufs,
1383         .vidioc_querybuf        = v4l2_m2m_ioctl_querybuf,
1384         .vidioc_qbuf            = v4l2_m2m_ioctl_qbuf,
1385         .vidioc_dqbuf           = v4l2_m2m_ioctl_dqbuf,
1386         .vidioc_prepare_buf     = v4l2_m2m_ioctl_prepare_buf,
1387         .vidioc_create_bufs     = v4l2_m2m_ioctl_create_bufs,
1388         .vidioc_expbuf          = v4l2_m2m_ioctl_expbuf,
1389 
1390         .vidioc_streamon        = v4l2_m2m_ioctl_streamon,
1391         .vidioc_streamoff       = v4l2_m2m_ioctl_streamoff,
1392 
1393         .vidioc_g_selection     = vidioc_g_selection,
1394         .vidioc_s_selection     = vidioc_s_selection,
1395 
1396         .vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
1397         .vidioc_encoder_cmd     = vicodec_encoder_cmd,
1398         .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
1399         .vidioc_decoder_cmd     = vicodec_decoder_cmd,
1400         .vidioc_enum_framesizes = vicodec_enum_framesizes,
1401 
1402         .vidioc_subscribe_event = vicodec_subscribe_event,
1403         .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1404 };
1405 
1406 
1407 /*
1408  * Queue operations
1409  */
1410 
1411 static int vicodec_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
1412                                unsigned int *nplanes, unsigned int sizes[],
1413                                struct device *alloc_devs[])
1414 {
1415         struct vicodec_ctx *ctx = vb2_get_drv_priv(vq);
1416         struct vicodec_q_data *q_data = get_q_data(ctx, vq->type);
1417         unsigned int size = q_data->sizeimage;
1418 
1419         if (*nplanes)
1420                 return sizes[0] < size ? -EINVAL : 0;
1421 
1422         *nplanes = 1;
1423         sizes[0] = size;
1424         q_data->vb2_sizeimage = size;
1425         return 0;
1426 }
1427 
1428 static int vicodec_buf_out_validate(struct vb2_buffer *vb)
1429 {
1430         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1431 
1432         vbuf->field = V4L2_FIELD_NONE;
1433         return 0;
1434 }
1435 
1436 static int vicodec_buf_prepare(struct vb2_buffer *vb)
1437 {
1438         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1439         struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1440         struct vicodec_q_data *q_data;
1441 
1442         dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
1443 
1444         q_data = get_q_data(ctx, vb->vb2_queue->type);
1445         if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
1446                 if (vbuf->field == V4L2_FIELD_ANY)
1447                         vbuf->field = V4L2_FIELD_NONE;
1448                 if (vbuf->field != V4L2_FIELD_NONE) {
1449                         dprintk(ctx->dev, "%s field isn't supported\n",
1450                                         __func__);
1451                         return -EINVAL;
1452                 }
1453         }
1454 
1455         if (vb2_plane_size(vb, 0) < q_data->vb2_sizeimage) {
1456                 dprintk(ctx->dev,
1457                         "%s data will not fit into plane (%lu < %lu)\n",
1458                         __func__, vb2_plane_size(vb, 0),
1459                         (long)q_data->vb2_sizeimage);
1460                 return -EINVAL;
1461         }
1462 
1463         return 0;
1464 }
1465 
1466 static void vicodec_buf_queue(struct vb2_buffer *vb)
1467 {
1468         struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1469         struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1470         unsigned int sz = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
1471         u8 *p_src = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
1472         u8 *p = p_src;
1473         struct vb2_queue *vq_out = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
1474                                                    V4L2_BUF_TYPE_VIDEO_OUTPUT);
1475         struct vb2_queue *vq_cap = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
1476                                                    V4L2_BUF_TYPE_VIDEO_CAPTURE);
1477         bool header_valid = false;
1478         static const struct v4l2_event rs_event = {
1479                 .type = V4L2_EVENT_SOURCE_CHANGE,
1480                 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
1481         };
1482 
1483         if (vb2_is_streaming(vq_cap)) {
1484                 if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type) &&
1485                     ctx->next_is_last) {
1486                         unsigned int i;
1487 
1488                         for (i = 0; i < vb->num_planes; i++)
1489                                 vb->planes[i].bytesused = 0;
1490                         vbuf->flags = V4L2_BUF_FLAG_LAST;
1491                         vbuf->field = V4L2_FIELD_NONE;
1492                         vbuf->sequence = get_q_data(ctx, vb->vb2_queue->type)->sequence++;
1493                         vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
1494                         ctx->is_draining = false;
1495                         ctx->has_stopped = true;
1496                         ctx->next_is_last = false;
1497                         v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
1498                         return;
1499                 }
1500         }
1501 
1502         /* buf_queue handles only the first source change event */
1503         if (ctx->first_source_change_sent) {
1504                 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1505                 return;
1506         }
1507 
1508         /*
1509          * if both queues are streaming, the source change event is
1510          * handled in job_ready
1511          */
1512         if (vb2_is_streaming(vq_cap) && vb2_is_streaming(vq_out)) {
1513                 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1514                 return;
1515         }
1516 
1517         /*
1518          * source change event is relevant only for the stateful decoder
1519          * in the compressed stream
1520          */
1521         if (ctx->is_stateless || ctx->is_enc ||
1522             !V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
1523                 v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1524                 return;
1525         }
1526 
1527         do {
1528                 enum vb2_buffer_state state =
1529                         get_next_header(ctx, &p, p_src + sz - p);
1530 
1531                 if (ctx->header_size < sizeof(struct fwht_cframe_hdr)) {
1532                         v4l2_m2m_buf_done(vbuf, state);
1533                         return;
1534                 }
1535                 header_valid = is_header_valid(&ctx->state.header);
1536                 /*
1537                  * p points right after the end of the header in the
1538                  * buffer. If the header is invalid we set p to point
1539                  * to the next byte after the start of the header
1540                  */
1541                 if (!header_valid) {
1542                         p = p - sizeof(struct fwht_cframe_hdr) + 1;
1543                         if (p < p_src)
1544                                 p = p_src;
1545                         ctx->header_size = 0;
1546                         ctx->comp_magic_cnt = 0;
1547                 }
1548 
1549         } while (!header_valid);
1550 
1551         ctx->cur_buf_offset = p - p_src;
1552         update_capture_data_from_header(ctx);
1553         ctx->first_source_change_sent = true;
1554         v4l2_event_queue_fh(&ctx->fh, &rs_event);
1555         v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
1556 }
1557 
1558 static void vicodec_return_bufs(struct vb2_queue *q, u32 state)
1559 {
1560         struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
1561         struct vb2_v4l2_buffer *vbuf;
1562 
1563         for (;;) {
1564                 if (V4L2_TYPE_IS_OUTPUT(q->type))
1565                         vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
1566                 else
1567                         vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
1568                 if (vbuf == NULL)
1569                         return;
1570                 v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req,
1571                                            &ctx->hdl);
1572                 spin_lock(ctx->lock);
1573                 v4l2_m2m_buf_done(vbuf, state);
1574                 spin_unlock(ctx->lock);
1575         }
1576 }
1577 
1578 static unsigned int total_frame_size(struct vicodec_q_data *q_data)
1579 {
1580         unsigned int size;
1581         unsigned int chroma_div;
1582 
1583         if (!q_data->info) {
1584                 WARN_ON(1);
1585                 return 0;
1586         }
1587         size = q_data->coded_width * q_data->coded_height;
1588         chroma_div = q_data->info->width_div * q_data->info->height_div;
1589 
1590         if (q_data->info->components_num == 4)
1591                 return 2 * size + 2 * (size / chroma_div);
1592         else if (q_data->info->components_num == 3)
1593                 return size + 2 * (size / chroma_div);
1594         return size;
1595 }
1596 
1597 static int vicodec_start_streaming(struct vb2_queue *q,
1598                                    unsigned int count)
1599 {
1600         struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
1601         struct vicodec_q_data *q_data = get_q_data(ctx, q->type);
1602         struct v4l2_fwht_state *state = &ctx->state;
1603         const struct v4l2_fwht_pixfmt_info *info = q_data->info;
1604         unsigned int size = q_data->coded_width * q_data->coded_height;
1605         unsigned int chroma_div;
1606         unsigned int total_planes_size;
1607         u8 *new_comp_frame = NULL;
1608 
1609         chroma_div = info->width_div * info->height_div;
1610         q_data->sequence = 0;
1611 
1612         if (V4L2_TYPE_IS_OUTPUT(q->type))
1613                 ctx->last_src_buf = NULL;
1614 
1615         state->gop_cnt = 0;
1616 
1617         if ((V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) ||
1618             (!V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc))
1619                 return 0;
1620 
1621         if (info->id == V4L2_PIX_FMT_FWHT ||
1622             info->id == V4L2_PIX_FMT_FWHT_STATELESS) {
1623                 vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
1624                 return -EINVAL;
1625         }
1626         total_planes_size = total_frame_size(q_data);
1627         ctx->comp_max_size = total_planes_size;
1628 
1629         state->visible_width = q_data->visible_width;
1630         state->visible_height = q_data->visible_height;
1631         state->coded_width = q_data->coded_width;
1632         state->coded_height = q_data->coded_height;
1633         state->stride = q_data->coded_width *
1634                                 info->bytesperline_mult;
1635 
1636         if (ctx->is_stateless) {
1637                 state->ref_stride = state->stride;
1638                 return 0;
1639         }
1640         state->ref_stride = q_data->coded_width * info->luma_alpha_step;
1641 
1642         state->ref_frame.buf = kvmalloc(total_planes_size, GFP_KERNEL);
1643         state->ref_frame.luma = state->ref_frame.buf;
1644         new_comp_frame = kvmalloc(ctx->comp_max_size, GFP_KERNEL);
1645 
1646         if (!state->ref_frame.luma || !new_comp_frame) {
1647                 kvfree(state->ref_frame.luma);
1648                 kvfree(new_comp_frame);
1649                 vicodec_return_bufs(q, VB2_BUF_STATE_QUEUED);
1650                 return -ENOMEM;
1651         }
1652         /*
1653          * if state->compressed_frame was already allocated then
1654          * it contain data of the first frame of the new resolution
1655          */
1656         if (state->compressed_frame) {
1657                 if (ctx->comp_size > ctx->comp_max_size)
1658                         ctx->comp_size = ctx->comp_max_size;
1659 
1660                 memcpy(new_comp_frame,
1661                        state->compressed_frame, ctx->comp_size);
1662         }
1663 
1664         kvfree(state->compressed_frame);
1665         state->compressed_frame = new_comp_frame;
1666 
1667         if (info->components_num < 3) {
1668                 state->ref_frame.cb = NULL;
1669                 state->ref_frame.cr = NULL;
1670                 state->ref_frame.alpha = NULL;
1671                 return 0;
1672         }
1673 
1674         state->ref_frame.cb = state->ref_frame.luma + size;
1675         state->ref_frame.cr = state->ref_frame.cb + size / chroma_div;
1676 
1677         if (info->components_num == 4)
1678                 state->ref_frame.alpha =
1679                         state->ref_frame.cr + size / chroma_div;
1680         else
1681                 state->ref_frame.alpha = NULL;
1682 
1683         return 0;
1684 }
1685 
1686 static void vicodec_stop_streaming(struct vb2_queue *q)
1687 {
1688         struct vicodec_ctx *ctx = vb2_get_drv_priv(q);
1689 
1690         vicodec_return_bufs(q, VB2_BUF_STATE_ERROR);
1691 
1692         if (V4L2_TYPE_IS_OUTPUT(q->type)) {
1693                 if (ctx->is_draining) {
1694                         struct vb2_v4l2_buffer *next_dst_buf;
1695 
1696                         spin_lock(ctx->lock);
1697                         ctx->last_src_buf = NULL;
1698                         next_dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
1699                         if (!next_dst_buf) {
1700                                 ctx->next_is_last = true;
1701                         } else {
1702                                 next_dst_buf->flags |= V4L2_BUF_FLAG_LAST;
1703                                 vb2_buffer_done(&next_dst_buf->vb2_buf, VB2_BUF_STATE_DONE);
1704                                 ctx->is_draining = false;
1705                                 ctx->has_stopped = true;
1706                                 v4l2_event_queue_fh(&ctx->fh, &vicodec_eos_event);
1707                         }
1708                         spin_unlock(ctx->lock);
1709                 }
1710         } else {
1711                 ctx->is_draining = false;
1712                 ctx->has_stopped = false;
1713                 ctx->next_is_last = false;
1714         }
1715         if (!ctx->is_enc && V4L2_TYPE_IS_OUTPUT(q->type))
1716                 ctx->first_source_change_sent = false;
1717 
1718         if ((!V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) ||
1719             (V4L2_TYPE_IS_OUTPUT(q->type) && ctx->is_enc)) {
1720                 if (!ctx->is_stateless)
1721                         kvfree(ctx->state.ref_frame.buf);
1722                 ctx->state.ref_frame.buf = NULL;
1723                 ctx->state.ref_frame.luma = NULL;
1724                 ctx->comp_max_size = 0;
1725                 ctx->source_changed = false;
1726         }
1727         if (V4L2_TYPE_IS_OUTPUT(q->type) && !ctx->is_enc) {
1728                 ctx->cur_buf_offset = 0;
1729                 ctx->comp_size = 0;
1730                 ctx->header_size = 0;
1731                 ctx->comp_magic_cnt = 0;
1732                 ctx->comp_has_frame = 0;
1733                 ctx->comp_has_next_frame = 0;
1734         }
1735 }
1736 
1737 static void vicodec_buf_request_complete(struct vb2_buffer *vb)
1738 {
1739         struct vicodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
1740 
1741         v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->hdl);
1742 }
1743 
1744 
1745 static const struct vb2_ops vicodec_qops = {
1746         .queue_setup            = vicodec_queue_setup,
1747         .buf_out_validate       = vicodec_buf_out_validate,
1748         .buf_prepare            = vicodec_buf_prepare,
1749         .buf_queue              = vicodec_buf_queue,
1750         .buf_request_complete   = vicodec_buf_request_complete,
1751         .start_streaming        = vicodec_start_streaming,
1752         .stop_streaming         = vicodec_stop_streaming,
1753         .wait_prepare           = vb2_ops_wait_prepare,
1754         .wait_finish            = vb2_ops_wait_finish,
1755 };
1756 
1757 static int queue_init(void *priv, struct vb2_queue *src_vq,
1758                       struct vb2_queue *dst_vq)
1759 {
1760         struct vicodec_ctx *ctx = priv;
1761         int ret;
1762 
1763         src_vq->type = (multiplanar ?
1764                         V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
1765                         V4L2_BUF_TYPE_VIDEO_OUTPUT);
1766         src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1767         src_vq->drv_priv = ctx;
1768         src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1769         src_vq->ops = &vicodec_qops;
1770         src_vq->mem_ops = &vb2_vmalloc_memops;
1771         src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1772         if (ctx->is_enc)
1773                 src_vq->lock = &ctx->dev->stateful_enc.mutex;
1774         else if (ctx->is_stateless)
1775                 src_vq->lock = &ctx->dev->stateless_dec.mutex;
1776         else
1777                 src_vq->lock = &ctx->dev->stateful_dec.mutex;
1778         src_vq->supports_requests = ctx->is_stateless;
1779         src_vq->requires_requests = ctx->is_stateless;
1780         ret = vb2_queue_init(src_vq);
1781         if (ret)
1782                 return ret;
1783 
1784         dst_vq->type = (multiplanar ?
1785                         V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
1786                         V4L2_BUF_TYPE_VIDEO_CAPTURE);
1787         dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1788         dst_vq->drv_priv = ctx;
1789         dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
1790         dst_vq->ops = &vicodec_qops;
1791         dst_vq->mem_ops = &vb2_vmalloc_memops;
1792         dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1793         dst_vq->lock = src_vq->lock;
1794 
1795         return vb2_queue_init(dst_vq);
1796 }
1797 
1798 static int vicodec_try_ctrl(struct v4l2_ctrl *ctrl)
1799 {
1800         struct vicodec_ctx *ctx = container_of(ctrl->handler,
1801                         struct vicodec_ctx, hdl);
1802         const struct v4l2_ctrl_fwht_params *params;
1803         struct vicodec_q_data *q_dst = get_q_data(ctx,
1804                         V4L2_BUF_TYPE_VIDEO_CAPTURE);
1805 
1806         switch (ctrl->id) {
1807         case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS:
1808                 if (!q_dst->info)
1809                         return -EINVAL;
1810                 params = ctrl->p_new.p_fwht_params;
1811                 if (params->width > q_dst->coded_width ||
1812                     params->width < MIN_WIDTH ||
1813                     params->height > q_dst->coded_height ||
1814                     params->height < MIN_HEIGHT)
1815                         return -EINVAL;
1816                 if (!validate_by_version(params->flags, params->version))
1817                         return -EINVAL;
1818                 if (!validate_stateless_params_flags(params, q_dst->info))
1819                         return -EINVAL;
1820                 return 0;
1821         default:
1822                 return 0;
1823         }
1824         return 0;
1825 }
1826 
1827 static void update_header_from_stateless_params(struct vicodec_ctx *ctx,
1828                                                 const struct v4l2_ctrl_fwht_params *params)
1829 {
1830         struct fwht_cframe_hdr *p_hdr = &ctx->state.header;
1831 
1832         p_hdr->magic1 = FWHT_MAGIC1;
1833         p_hdr->magic2 = FWHT_MAGIC2;
1834         p_hdr->version = htonl(params->version);
1835         p_hdr->width = htonl(params->width);
1836         p_hdr->height = htonl(params->height);
1837         p_hdr->flags = htonl(params->flags);
1838         p_hdr->colorspace = htonl(params->colorspace);
1839         p_hdr->xfer_func = htonl(params->xfer_func);
1840         p_hdr->ycbcr_enc = htonl(params->ycbcr_enc);
1841         p_hdr->quantization = htonl(params->quantization);
1842 }
1843 
1844 static int vicodec_s_ctrl(struct v4l2_ctrl *ctrl)
1845 {
1846         struct vicodec_ctx *ctx = container_of(ctrl->handler,
1847                                                struct vicodec_ctx, hdl);
1848         const struct v4l2_ctrl_fwht_params *params;
1849 
1850         switch (ctrl->id) {
1851         case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
1852                 ctx->state.gop_size = ctrl->val;
1853                 return 0;
1854         case V4L2_CID_FWHT_I_FRAME_QP:
1855                 ctx->state.i_frame_qp = ctrl->val;
1856                 return 0;
1857         case V4L2_CID_FWHT_P_FRAME_QP:
1858                 ctx->state.p_frame_qp = ctrl->val;
1859                 return 0;
1860         case V4L2_CID_MPEG_VIDEO_FWHT_PARAMS:
1861                 params = ctrl->p_new.p_fwht_params;
1862                 update_header_from_stateless_params(ctx, params);
1863                 ctx->state.ref_frame_ts = params->backward_ref_ts;
1864                 return 0;
1865         }
1866         return -EINVAL;
1867 }
1868 
1869 static const struct v4l2_ctrl_ops vicodec_ctrl_ops = {
1870         .s_ctrl = vicodec_s_ctrl,
1871         .try_ctrl = vicodec_try_ctrl,
1872 };
1873 
1874 static const struct v4l2_ctrl_config vicodec_ctrl_stateless_state = {
1875         .ops            = &vicodec_ctrl_ops,
1876         .id             = V4L2_CID_MPEG_VIDEO_FWHT_PARAMS,
1877         .elem_size      = sizeof(struct v4l2_ctrl_fwht_params),
1878 };
1879 
1880 /*
1881  * File operations
1882  */
1883 static int vicodec_open(struct file *file)
1884 {
1885         const struct v4l2_fwht_pixfmt_info *info = v4l2_fwht_get_pixfmt(0);
1886         struct video_device *vfd = video_devdata(file);
1887         struct vicodec_dev *dev = video_drvdata(file);
1888         struct vicodec_ctx *ctx = NULL;
1889         struct v4l2_ctrl_handler *hdl;
1890         unsigned int raw_size;
1891         unsigned int comp_size;
1892         int rc = 0;
1893 
1894         if (mutex_lock_interruptible(vfd->lock))
1895                 return -ERESTARTSYS;
1896         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
1897         if (!ctx) {
1898                 rc = -ENOMEM;
1899                 goto open_unlock;
1900         }
1901 
1902         if (vfd == &dev->stateful_enc.vfd)
1903                 ctx->is_enc = true;
1904         else if (vfd == &dev->stateless_dec.vfd)
1905                 ctx->is_stateless = true;
1906 
1907         v4l2_fh_init(&ctx->fh, video_devdata(file));
1908         file->private_data = &ctx->fh;
1909         ctx->dev = dev;
1910         hdl = &ctx->hdl;
1911         v4l2_ctrl_handler_init(hdl, 5);
1912         v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_MPEG_VIDEO_GOP_SIZE,
1913                           1, 16, 1, 10);
1914         v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_I_FRAME_QP,
1915                           1, 31, 1, 20);
1916         v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops, V4L2_CID_FWHT_P_FRAME_QP,
1917                           1, 31, 1, 20);
1918         if (ctx->is_enc)
1919                 v4l2_ctrl_new_std(hdl, &vicodec_ctrl_ops,
1920                                   V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 1, 1, 1);
1921         if (ctx->is_stateless)
1922                 v4l2_ctrl_new_custom(hdl, &vicodec_ctrl_stateless_state, NULL);
1923         if (hdl->error) {
1924                 rc = hdl->error;
1925                 v4l2_ctrl_handler_free(hdl);
1926                 kfree(ctx);
1927                 goto open_unlock;
1928         }
1929         ctx->fh.ctrl_handler = hdl;
1930         v4l2_ctrl_handler_setup(hdl);
1931 
1932         if (ctx->is_enc)
1933                 ctx->q_data[V4L2_M2M_SRC].info = info;
1934         else if (ctx->is_stateless)
1935                 ctx->q_data[V4L2_M2M_SRC].info = &pixfmt_stateless_fwht;
1936         else
1937                 ctx->q_data[V4L2_M2M_SRC].info = &pixfmt_fwht;
1938         ctx->q_data[V4L2_M2M_SRC].coded_width = 1280;
1939         ctx->q_data[V4L2_M2M_SRC].coded_height = 720;
1940         ctx->q_data[V4L2_M2M_SRC].visible_width = 1280;
1941         ctx->q_data[V4L2_M2M_SRC].visible_height = 720;
1942         raw_size = 1280 * 720 * info->sizeimage_mult / info->sizeimage_div;
1943         comp_size = 1280 * 720 * pixfmt_fwht.sizeimage_mult /
1944                                  pixfmt_fwht.sizeimage_div;
1945         if (ctx->is_enc)
1946                 ctx->q_data[V4L2_M2M_SRC].sizeimage = raw_size;
1947         else if (ctx->is_stateless)
1948                 ctx->q_data[V4L2_M2M_SRC].sizeimage = comp_size;
1949         else
1950                 ctx->q_data[V4L2_M2M_SRC].sizeimage =
1951                         comp_size + sizeof(struct fwht_cframe_hdr);
1952         ctx->q_data[V4L2_M2M_DST] = ctx->q_data[V4L2_M2M_SRC];
1953         if (ctx->is_enc) {
1954                 ctx->q_data[V4L2_M2M_DST].info = &pixfmt_fwht;
1955                 ctx->q_data[V4L2_M2M_DST].sizeimage =
1956                         comp_size + sizeof(struct fwht_cframe_hdr);
1957         } else {
1958                 ctx->q_data[V4L2_M2M_DST].info = info;
1959                 ctx->q_data[V4L2_M2M_DST].sizeimage = raw_size;
1960         }
1961 
1962         ctx->state.colorspace = V4L2_COLORSPACE_REC709;
1963 
1964         if (ctx->is_enc) {
1965                 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_enc.m2m_dev,
1966                                                     ctx, &queue_init);
1967                 ctx->lock = &dev->stateful_enc.lock;
1968         } else if (ctx->is_stateless) {
1969                 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateless_dec.m2m_dev,
1970                                                     ctx, &queue_init);
1971                 ctx->lock = &dev->stateless_dec.lock;
1972         } else {
1973                 ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->stateful_dec.m2m_dev,
1974                                                     ctx, &queue_init);
1975                 ctx->lock = &dev->stateful_dec.lock;
1976         }
1977 
1978         if (IS_ERR(ctx->fh.m2m_ctx)) {
1979                 rc = PTR_ERR(ctx->fh.m2m_ctx);
1980 
1981                 v4l2_ctrl_handler_free(hdl);
1982                 v4l2_fh_exit(&ctx->fh);
1983                 kfree(ctx);
1984                 goto open_unlock;
1985         }
1986 
1987         v4l2_fh_add(&ctx->fh);
1988 
1989 open_unlock:
1990         mutex_unlock(vfd->lock);
1991         return rc;
1992 }
1993 
1994 static int vicodec_release(struct file *file)
1995 {
1996         struct video_device *vfd = video_devdata(file);
1997         struct vicodec_ctx *ctx = file2ctx(file);
1998 
1999         mutex_lock(vfd->lock);
2000         v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
2001         mutex_unlock(vfd->lock);
2002         v4l2_fh_del(&ctx->fh);
2003         v4l2_fh_exit(&ctx->fh);
2004         v4l2_ctrl_handler_free(&ctx->hdl);
2005         kvfree(ctx->state.compressed_frame);
2006         kfree(ctx);
2007 
2008         return 0;
2009 }
2010 
2011 static int vicodec_request_validate(struct media_request *req)
2012 {
2013         struct media_request_object *obj;
2014         struct v4l2_ctrl_handler *parent_hdl, *hdl;
2015         struct vicodec_ctx *ctx = NULL;
2016         struct v4l2_ctrl *ctrl;
2017         unsigned int count;
2018 
2019         list_for_each_entry(obj, &req->objects, list) {
2020                 struct vb2_buffer *vb;
2021 
2022                 if (vb2_request_object_is_buffer(obj)) {
2023                         vb = container_of(obj, struct vb2_buffer, req_obj);
2024                         ctx = vb2_get_drv_priv(vb->vb2_queue);
2025 
2026                         break;
2027                 }
2028         }
2029 
2030         if (!ctx) {
2031                 pr_err("No buffer was provided with the request\n");
2032                 return -ENOENT;
2033         }
2034 
2035         count = vb2_request_buffer_cnt(req);
2036         if (!count) {
2037                 v4l2_info(&ctx->dev->v4l2_dev,
2038                           "No buffer was provided with the request\n");
2039                 return -ENOENT;
2040         } else if (count > 1) {
2041                 v4l2_info(&ctx->dev->v4l2_dev,
2042                           "More than one buffer was provided with the request\n");
2043                 return -EINVAL;
2044         }
2045 
2046         parent_hdl = &ctx->hdl;
2047 
2048         hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl);
2049         if (!hdl) {
2050                 v4l2_info(&ctx->dev->v4l2_dev, "Missing codec control\n");
2051                 return -ENOENT;
2052         }
2053         ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl,
2054                                                vicodec_ctrl_stateless_state.id);
2055         if (!ctrl) {
2056                 v4l2_info(&ctx->dev->v4l2_dev,
2057                           "Missing required codec control\n");
2058                 return -ENOENT;
2059         }
2060 
2061         return vb2_request_validate(req);
2062 }
2063 
2064 static const struct v4l2_file_operations vicodec_fops = {
2065         .owner          = THIS_MODULE,
2066         .open           = vicodec_open,
2067         .release        = vicodec_release,
2068         .poll           = v4l2_m2m_fop_poll,
2069         .unlocked_ioctl = video_ioctl2,
2070         .mmap           = v4l2_m2m_fop_mmap,
2071 };
2072 
2073 static const struct video_device vicodec_videodev = {
2074         .name           = VICODEC_NAME,
2075         .vfl_dir        = VFL_DIR_M2M,
2076         .fops           = &vicodec_fops,
2077         .ioctl_ops      = &vicodec_ioctl_ops,
2078         .minor          = -1,
2079         .release        = video_device_release_empty,
2080 };
2081 
2082 static const struct media_device_ops vicodec_m2m_media_ops = {
2083         .req_validate   = vicodec_request_validate,
2084         .req_queue      = v4l2_m2m_request_queue,
2085 };
2086 
2087 static const struct v4l2_m2m_ops m2m_ops = {
2088         .device_run     = device_run,
2089         .job_ready      = job_ready,
2090 };
2091 
2092 static int register_instance(struct vicodec_dev *dev,
2093                              struct vicodec_dev_instance *dev_instance,
2094                              const char *name, bool is_enc)
2095 {
2096         struct video_device *vfd;
2097         int ret;
2098 
2099         spin_lock_init(&dev_instance->lock);
2100         mutex_init(&dev_instance->mutex);
2101         dev_instance->m2m_dev = v4l2_m2m_init(&m2m_ops);
2102         if (IS_ERR(dev_instance->m2m_dev)) {
2103                 v4l2_err(&dev->v4l2_dev, "Failed to init vicodec enc device\n");
2104                 return PTR_ERR(dev_instance->m2m_dev);
2105         }
2106 
2107         dev_instance->vfd = vicodec_videodev;
2108         vfd = &dev_instance->vfd;
2109         vfd->lock = &dev_instance->mutex;
2110         vfd->v4l2_dev = &dev->v4l2_dev;
2111         strscpy(vfd->name, name, sizeof(vfd->name));
2112         vfd->device_caps = V4L2_CAP_STREAMING |
2113                 (multiplanar ? V4L2_CAP_VIDEO_M2M_MPLANE : V4L2_CAP_VIDEO_M2M);
2114         if (is_enc) {
2115                 v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
2116                 v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
2117         } else {
2118                 v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
2119                 v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
2120         }
2121         video_set_drvdata(vfd, dev);
2122 
2123         ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
2124         if (ret) {
2125                 v4l2_err(&dev->v4l2_dev, "Failed to register video device '%s'\n", name);
2126                 v4l2_m2m_release(dev_instance->m2m_dev);
2127                 return ret;
2128         }
2129         v4l2_info(&dev->v4l2_dev, "Device '%s' registered as /dev/video%d\n",
2130                   name, vfd->num);
2131         return 0;
2132 }
2133 
2134 static void vicodec_v4l2_dev_release(struct v4l2_device *v4l2_dev)
2135 {
2136         struct vicodec_dev *dev = container_of(v4l2_dev, struct vicodec_dev, v4l2_dev);
2137 
2138         v4l2_device_unregister(&dev->v4l2_dev);
2139         v4l2_m2m_release(dev->stateful_enc.m2m_dev);
2140         v4l2_m2m_release(dev->stateful_dec.m2m_dev);
2141         v4l2_m2m_release(dev->stateless_dec.m2m_dev);
2142 #ifdef CONFIG_MEDIA_CONTROLLER
2143         media_device_cleanup(&dev->mdev);
2144 #endif
2145         kfree(dev);
2146 }
2147 
2148 static int vicodec_probe(struct platform_device *pdev)
2149 {
2150         struct vicodec_dev *dev;
2151         int ret;
2152 
2153         dev = kzalloc(sizeof(*dev), GFP_KERNEL);
2154         if (!dev)
2155                 return -ENOMEM;
2156 
2157         ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
2158         if (ret)
2159                 goto free_dev;
2160 
2161         dev->v4l2_dev.release = vicodec_v4l2_dev_release;
2162 
2163 #ifdef CONFIG_MEDIA_CONTROLLER
2164         dev->mdev.dev = &pdev->dev;
2165         strscpy(dev->mdev.model, "vicodec", sizeof(dev->mdev.model));
2166         strscpy(dev->mdev.bus_info, "platform:vicodec",
2167                 sizeof(dev->mdev.bus_info));
2168         media_device_init(&dev->mdev);
2169         dev->mdev.ops = &vicodec_m2m_media_ops;
2170         dev->v4l2_dev.mdev = &dev->mdev;
2171 #endif
2172 
2173         platform_set_drvdata(pdev, dev);
2174 
2175         if (register_instance(dev, &dev->stateful_enc,
2176                               "stateful-encoder", true))
2177                 goto unreg_dev;
2178 
2179         if (register_instance(dev, &dev->stateful_dec,
2180                               "stateful-decoder", false))
2181                 goto unreg_sf_enc;
2182 
2183         if (register_instance(dev, &dev->stateless_dec,
2184                               "stateless-decoder", false))
2185                 goto unreg_sf_dec;
2186 
2187 #ifdef CONFIG_MEDIA_CONTROLLER
2188         ret = v4l2_m2m_register_media_controller(dev->stateful_enc.m2m_dev,
2189                                                  &dev->stateful_enc.vfd,
2190                                                  MEDIA_ENT_F_PROC_VIDEO_ENCODER);
2191         if (ret) {
2192                 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for enc\n");
2193                 goto unreg_m2m;
2194         }
2195 
2196         ret = v4l2_m2m_register_media_controller(dev->stateful_dec.m2m_dev,
2197                                                  &dev->stateful_dec.vfd,
2198                                                  MEDIA_ENT_F_PROC_VIDEO_DECODER);
2199         if (ret) {
2200                 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for dec\n");
2201                 goto unreg_m2m_sf_enc_mc;
2202         }
2203 
2204         ret = v4l2_m2m_register_media_controller(dev->stateless_dec.m2m_dev,
2205                                                  &dev->stateless_dec.vfd,
2206                                                  MEDIA_ENT_F_PROC_VIDEO_DECODER);
2207         if (ret) {
2208                 v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller for stateless dec\n");
2209                 goto unreg_m2m_sf_dec_mc;
2210         }
2211 
2212         ret = media_device_register(&dev->mdev);
2213         if (ret) {
2214                 v4l2_err(&dev->v4l2_dev, "Failed to register mem2mem media device\n");
2215                 goto unreg_m2m_sl_dec_mc;
2216         }
2217 #endif
2218         return 0;
2219 
2220 #ifdef CONFIG_MEDIA_CONTROLLER
2221 unreg_m2m_sl_dec_mc:
2222         v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev);
2223 unreg_m2m_sf_dec_mc:
2224         v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev);
2225 unreg_m2m_sf_enc_mc:
2226         v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev);
2227 unreg_m2m:
2228         video_unregister_device(&dev->stateless_dec.vfd);
2229         v4l2_m2m_release(dev->stateless_dec.m2m_dev);
2230 #endif
2231 unreg_sf_dec:
2232         video_unregister_device(&dev->stateful_dec.vfd);
2233         v4l2_m2m_release(dev->stateful_dec.m2m_dev);
2234 unreg_sf_enc:
2235         video_unregister_device(&dev->stateful_enc.vfd);
2236         v4l2_m2m_release(dev->stateful_enc.m2m_dev);
2237 unreg_dev:
2238         v4l2_device_unregister(&dev->v4l2_dev);
2239 free_dev:
2240         kfree(dev);
2241 
2242         return ret;
2243 }
2244 
2245 static int vicodec_remove(struct platform_device *pdev)
2246 {
2247         struct vicodec_dev *dev = platform_get_drvdata(pdev);
2248 
2249         v4l2_info(&dev->v4l2_dev, "Removing " VICODEC_NAME);
2250 
2251 #ifdef CONFIG_MEDIA_CONTROLLER
2252         media_device_unregister(&dev->mdev);
2253         v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev);
2254         v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev);
2255         v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev);
2256 #endif
2257 
2258         video_unregister_device(&dev->stateful_enc.vfd);
2259         video_unregister_device(&dev->stateful_dec.vfd);
2260         video_unregister_device(&dev->stateless_dec.vfd);
2261         v4l2_device_put(&dev->v4l2_dev);
2262 
2263         return 0;
2264 }
2265 
2266 static struct platform_driver vicodec_pdrv = {
2267         .probe          = vicodec_probe,
2268         .remove         = vicodec_remove,
2269         .driver         = {
2270                 .name   = VICODEC_NAME,
2271         },
2272 };
2273 
2274 static void __exit vicodec_exit(void)
2275 {
2276         platform_driver_unregister(&vicodec_pdrv);
2277         platform_device_unregister(&vicodec_pdev);
2278 }
2279 
2280 static int __init vicodec_init(void)
2281 {
2282         int ret;
2283 
2284         ret = platform_device_register(&vicodec_pdev);
2285         if (ret)
2286                 return ret;
2287 
2288         ret = platform_driver_register(&vicodec_pdrv);
2289         if (ret)
2290                 platform_device_unregister(&vicodec_pdev);
2291 
2292         return ret;
2293 }
2294 
2295 module_init(vicodec_init);
2296 module_exit(vicodec_exit);

/* [<][>][^][v][top][bottom][index][help] */