linux/drivers/media/platform/qcom/venus/venc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
   4 * Copyright (C) 2017 Linaro Ltd.
   5 */
   6#include <linux/clk.h>
   7#include <linux/module.h>
   8#include <linux/mod_devicetable.h>
   9#include <linux/platform_device.h>
  10#include <linux/pm_runtime.h>
  11#include <linux/slab.h>
  12#include <media/v4l2-mem2mem.h>
  13#include <media/videobuf2-dma-contig.h>
  14#include <media/v4l2-ioctl.h>
  15#include <media/v4l2-event.h>
  16#include <media/v4l2-ctrls.h>
  17
  18#include "hfi_venus_io.h"
  19#include "hfi_parser.h"
  20#include "core.h"
  21#include "helpers.h"
  22#include "venc.h"
  23#include "pm_helpers.h"
  24
  25#define NUM_B_FRAMES_MAX        4
  26
  27/*
  28 * Three resons to keep MPLANE formats (despite that the number of planes
  29 * currently is one):
  30 * - the MPLANE formats allow only one plane to be used
  31 * - the downstream driver use MPLANE formats too
  32 * - future firmware versions could add support for >1 planes
  33 */
  34static const struct venus_format venc_formats[] = {
  35        {
  36                .pixfmt = V4L2_PIX_FMT_NV12,
  37                .num_planes = 1,
  38                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  39        }, {
  40                .pixfmt = V4L2_PIX_FMT_MPEG4,
  41                .num_planes = 1,
  42                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
  43        }, {
  44                .pixfmt = V4L2_PIX_FMT_H263,
  45                .num_planes = 1,
  46                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
  47        }, {
  48                .pixfmt = V4L2_PIX_FMT_H264,
  49                .num_planes = 1,
  50                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
  51        }, {
  52                .pixfmt = V4L2_PIX_FMT_VP8,
  53                .num_planes = 1,
  54                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
  55        }, {
  56                .pixfmt = V4L2_PIX_FMT_HEVC,
  57                .num_planes = 1,
  58                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
  59        },
  60};
  61
  62static const struct venus_format *
  63find_format(struct venus_inst *inst, u32 pixfmt, u32 type)
  64{
  65        const struct venus_format *fmt = venc_formats;
  66        unsigned int size = ARRAY_SIZE(venc_formats);
  67        unsigned int i;
  68
  69        for (i = 0; i < size; i++) {
  70                if (fmt[i].pixfmt == pixfmt)
  71                        break;
  72        }
  73
  74        if (i == size || fmt[i].type != type)
  75                return NULL;
  76
  77        if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
  78            !venus_helper_check_codec(inst, fmt[i].pixfmt))
  79                return NULL;
  80
  81        return &fmt[i];
  82}
  83
  84static const struct venus_format *
  85find_format_by_index(struct venus_inst *inst, unsigned int index, u32 type)
  86{
  87        const struct venus_format *fmt = venc_formats;
  88        unsigned int size = ARRAY_SIZE(venc_formats);
  89        unsigned int i, k = 0;
  90
  91        if (index > size)
  92                return NULL;
  93
  94        for (i = 0; i < size; i++) {
  95                bool valid;
  96
  97                if (fmt[i].type != type)
  98                        continue;
  99                valid = type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ||
 100                        venus_helper_check_codec(inst, fmt[i].pixfmt);
 101                if (k == index && valid)
 102                        break;
 103                if (valid)
 104                        k++;
 105        }
 106
 107        if (i == size)
 108                return NULL;
 109
 110        return &fmt[i];
 111}
 112
 113static int venc_v4l2_to_hfi(int id, int value)
 114{
 115        switch (id) {
 116        case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
 117                switch (value) {
 118                case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
 119                default:
 120                        return HFI_H264_ENTROPY_CAVLC;
 121                case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
 122                        return HFI_H264_ENTROPY_CABAC;
 123                }
 124        case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
 125                switch (value) {
 126                case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED:
 127                default:
 128                        return HFI_H264_DB_MODE_ALL_BOUNDARY;
 129                case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED:
 130                        return HFI_H264_DB_MODE_DISABLE;
 131                case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY:
 132                        return HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
 133                }
 134        }
 135
 136        return 0;
 137}
 138
 139static int
 140venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
 141{
 142        strscpy(cap->driver, "qcom-venus", sizeof(cap->driver));
 143        strscpy(cap->card, "Qualcomm Venus video encoder", sizeof(cap->card));
 144        strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
 145
 146        return 0;
 147}
 148
 149static int venc_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
 150{
 151        struct venus_inst *inst = to_inst(file);
 152        const struct venus_format *fmt;
 153
 154        fmt = find_format_by_index(inst, f->index, f->type);
 155
 156        memset(f->reserved, 0, sizeof(f->reserved));
 157
 158        if (!fmt)
 159                return -EINVAL;
 160
 161        f->pixelformat = fmt->pixfmt;
 162
 163        return 0;
 164}
 165
 166static const struct venus_format *
 167venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
 168{
 169        struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
 170        struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt;
 171        const struct venus_format *fmt;
 172        u32 sizeimage;
 173
 174        memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved));
 175        memset(pixmp->reserved, 0, sizeof(pixmp->reserved));
 176
 177        fmt = find_format(inst, pixmp->pixelformat, f->type);
 178        if (!fmt) {
 179                if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 180                        pixmp->pixelformat = V4L2_PIX_FMT_H264;
 181                else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 182                        pixmp->pixelformat = V4L2_PIX_FMT_NV12;
 183                else
 184                        return NULL;
 185                fmt = find_format(inst, pixmp->pixelformat, f->type);
 186                if (!fmt)
 187                        return NULL;
 188        }
 189
 190        pixmp->width = clamp(pixmp->width, frame_width_min(inst),
 191                             frame_width_max(inst));
 192        pixmp->height = clamp(pixmp->height, frame_height_min(inst),
 193                              frame_height_max(inst));
 194
 195        if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 196                pixmp->width = ALIGN(pixmp->width, 128);
 197                pixmp->height = ALIGN(pixmp->height, 32);
 198        }
 199
 200        pixmp->width = ALIGN(pixmp->width, 2);
 201        pixmp->height = ALIGN(pixmp->height, 2);
 202
 203        if (pixmp->field == V4L2_FIELD_ANY)
 204                pixmp->field = V4L2_FIELD_NONE;
 205        pixmp->num_planes = fmt->num_planes;
 206        pixmp->flags = 0;
 207
 208        sizeimage = venus_helper_get_framesz(pixmp->pixelformat,
 209                                             pixmp->width,
 210                                             pixmp->height);
 211        pfmt[0].sizeimage = max(ALIGN(pfmt[0].sizeimage, SZ_4K), sizeimage);
 212
 213        if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 214                pfmt[0].bytesperline = ALIGN(pixmp->width, 128);
 215        else
 216                pfmt[0].bytesperline = 0;
 217
 218        return fmt;
 219}
 220
 221static int venc_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
 222{
 223        struct venus_inst *inst = to_inst(file);
 224
 225        venc_try_fmt_common(inst, f);
 226
 227        return 0;
 228}
 229
 230static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
 231{
 232        struct venus_inst *inst = to_inst(file);
 233        struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
 234        struct v4l2_pix_format_mplane orig_pixmp;
 235        const struct venus_format *fmt;
 236        struct v4l2_format format;
 237        u32 pixfmt_out = 0, pixfmt_cap = 0;
 238        struct vb2_queue *q;
 239
 240        q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
 241        if (!q)
 242                return -EINVAL;
 243
 244        if (vb2_is_busy(q))
 245                return -EBUSY;
 246
 247        orig_pixmp = *pixmp;
 248
 249        fmt = venc_try_fmt_common(inst, f);
 250        if (!fmt)
 251                return -EINVAL;
 252
 253        if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 254                pixfmt_out = pixmp->pixelformat;
 255                pixfmt_cap = inst->fmt_cap->pixfmt;
 256        } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 257                pixfmt_cap = pixmp->pixelformat;
 258                pixfmt_out = inst->fmt_out->pixfmt;
 259        }
 260
 261        memset(&format, 0, sizeof(format));
 262
 263        format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
 264        format.fmt.pix_mp.pixelformat = pixfmt_out;
 265        format.fmt.pix_mp.width = orig_pixmp.width;
 266        format.fmt.pix_mp.height = orig_pixmp.height;
 267        venc_try_fmt_common(inst, &format);
 268
 269        if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 270                inst->out_width = format.fmt.pix_mp.width;
 271                inst->out_height = format.fmt.pix_mp.height;
 272                inst->colorspace = pixmp->colorspace;
 273                inst->ycbcr_enc = pixmp->ycbcr_enc;
 274                inst->quantization = pixmp->quantization;
 275                inst->xfer_func = pixmp->xfer_func;
 276        }
 277
 278        memset(&format, 0, sizeof(format));
 279
 280        format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 281        format.fmt.pix_mp.pixelformat = pixfmt_cap;
 282        format.fmt.pix_mp.width = orig_pixmp.width;
 283        format.fmt.pix_mp.height = orig_pixmp.height;
 284        venc_try_fmt_common(inst, &format);
 285
 286        inst->width = format.fmt.pix_mp.width;
 287        inst->height = format.fmt.pix_mp.height;
 288
 289        if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 290                inst->fmt_out = fmt;
 291        else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 292                inst->fmt_cap = fmt;
 293                inst->output_buf_size = pixmp->plane_fmt[0].sizeimage;
 294        }
 295
 296        return 0;
 297}
 298
 299static int venc_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
 300{
 301        struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
 302        struct venus_inst *inst = to_inst(file);
 303        const struct venus_format *fmt;
 304
 305        if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 306                fmt = inst->fmt_cap;
 307        else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 308                fmt = inst->fmt_out;
 309        else
 310                return -EINVAL;
 311
 312        pixmp->pixelformat = fmt->pixfmt;
 313
 314        if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 315                pixmp->width = inst->width;
 316                pixmp->height = inst->height;
 317                pixmp->colorspace = inst->colorspace;
 318                pixmp->ycbcr_enc = inst->ycbcr_enc;
 319                pixmp->quantization = inst->quantization;
 320                pixmp->xfer_func = inst->xfer_func;
 321        } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 322                pixmp->width = inst->out_width;
 323                pixmp->height = inst->out_height;
 324        }
 325
 326        venc_try_fmt_common(inst, f);
 327
 328        return 0;
 329}
 330
 331static int
 332venc_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
 333{
 334        struct venus_inst *inst = to_inst(file);
 335
 336        if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
 337                return -EINVAL;
 338
 339        switch (s->target) {
 340        case V4L2_SEL_TGT_CROP_DEFAULT:
 341        case V4L2_SEL_TGT_CROP_BOUNDS:
 342                s->r.width = inst->out_width;
 343                s->r.height = inst->out_height;
 344                break;
 345        case V4L2_SEL_TGT_CROP:
 346                s->r.width = inst->width;
 347                s->r.height = inst->height;
 348                break;
 349        default:
 350                return -EINVAL;
 351        }
 352
 353        s->r.top = 0;
 354        s->r.left = 0;
 355
 356        return 0;
 357}
 358
 359static int
 360venc_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
 361{
 362        struct venus_inst *inst = to_inst(file);
 363
 364        if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
 365                return -EINVAL;
 366
 367        if (s->r.width > inst->out_width ||
 368            s->r.height > inst->out_height)
 369                return -EINVAL;
 370
 371        s->r.width = ALIGN(s->r.width, 2);
 372        s->r.height = ALIGN(s->r.height, 2);
 373
 374        switch (s->target) {
 375        case V4L2_SEL_TGT_CROP:
 376                s->r.top = 0;
 377                s->r.left = 0;
 378                inst->width = s->r.width;
 379                inst->height = s->r.height;
 380                break;
 381        default:
 382                return -EINVAL;
 383        }
 384
 385        return 0;
 386}
 387
 388static int venc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
 389{
 390        struct venus_inst *inst = to_inst(file);
 391        struct v4l2_outputparm *out = &a->parm.output;
 392        struct v4l2_fract *timeperframe = &out->timeperframe;
 393        u64 us_per_frame, fps;
 394
 395        if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
 396            a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 397                return -EINVAL;
 398
 399        memset(out->reserved, 0, sizeof(out->reserved));
 400
 401        if (!timeperframe->denominator)
 402                timeperframe->denominator = inst->timeperframe.denominator;
 403        if (!timeperframe->numerator)
 404                timeperframe->numerator = inst->timeperframe.numerator;
 405
 406        out->capability = V4L2_CAP_TIMEPERFRAME;
 407
 408        us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
 409        do_div(us_per_frame, timeperframe->denominator);
 410
 411        if (!us_per_frame)
 412                return -EINVAL;
 413
 414        fps = (u64)USEC_PER_SEC;
 415        do_div(fps, us_per_frame);
 416
 417        inst->timeperframe = *timeperframe;
 418        inst->fps = fps;
 419
 420        return 0;
 421}
 422
 423static int venc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
 424{
 425        struct venus_inst *inst = to_inst(file);
 426
 427        if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
 428            a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 429                return -EINVAL;
 430
 431        a->parm.output.capability |= V4L2_CAP_TIMEPERFRAME;
 432        a->parm.output.timeperframe = inst->timeperframe;
 433
 434        return 0;
 435}
 436
 437static int venc_enum_framesizes(struct file *file, void *fh,
 438                                struct v4l2_frmsizeenum *fsize)
 439{
 440        struct venus_inst *inst = to_inst(file);
 441        const struct venus_format *fmt;
 442
 443        fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
 444
 445        fmt = find_format(inst, fsize->pixel_format,
 446                          V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 447        if (!fmt) {
 448                fmt = find_format(inst, fsize->pixel_format,
 449                                  V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 450                if (!fmt)
 451                        return -EINVAL;
 452        }
 453
 454        if (fsize->index)
 455                return -EINVAL;
 456
 457        fsize->stepwise.min_width = frame_width_min(inst);
 458        fsize->stepwise.max_width = frame_width_max(inst);
 459        fsize->stepwise.step_width = frame_width_step(inst);
 460        fsize->stepwise.min_height = frame_height_min(inst);
 461        fsize->stepwise.max_height = frame_height_max(inst);
 462        fsize->stepwise.step_height = frame_height_step(inst);
 463
 464        return 0;
 465}
 466
 467static int venc_enum_frameintervals(struct file *file, void *fh,
 468                                    struct v4l2_frmivalenum *fival)
 469{
 470        struct venus_inst *inst = to_inst(file);
 471        const struct venus_format *fmt;
 472        unsigned int framerate_factor = 1;
 473
 474        fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
 475
 476        fmt = find_format(inst, fival->pixel_format,
 477                          V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 478        if (!fmt) {
 479                fmt = find_format(inst, fival->pixel_format,
 480                                  V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 481                if (!fmt)
 482                        return -EINVAL;
 483        }
 484
 485        if (fival->index)
 486                return -EINVAL;
 487
 488        if (!fival->width || !fival->height)
 489                return -EINVAL;
 490
 491        if (fival->width > frame_width_max(inst) ||
 492            fival->width < frame_width_min(inst) ||
 493            fival->height > frame_height_max(inst) ||
 494            fival->height < frame_height_min(inst))
 495                return -EINVAL;
 496
 497        if (IS_V1(inst->core)) {
 498                /* framerate is reported in 1/65535 fps unit */
 499                framerate_factor = (1 << 16);
 500        }
 501
 502        fival->stepwise.min.numerator = 1;
 503        fival->stepwise.min.denominator = frate_max(inst) / framerate_factor;
 504        fival->stepwise.max.numerator = 1;
 505        fival->stepwise.max.denominator = frate_min(inst) / framerate_factor;
 506        fival->stepwise.step.numerator = 1;
 507        fival->stepwise.step.denominator = frate_max(inst) / framerate_factor;
 508
 509        return 0;
 510}
 511
 512static const struct v4l2_ioctl_ops venc_ioctl_ops = {
 513        .vidioc_querycap = venc_querycap,
 514        .vidioc_enum_fmt_vid_cap = venc_enum_fmt,
 515        .vidioc_enum_fmt_vid_out = venc_enum_fmt,
 516        .vidioc_s_fmt_vid_cap_mplane = venc_s_fmt,
 517        .vidioc_s_fmt_vid_out_mplane = venc_s_fmt,
 518        .vidioc_g_fmt_vid_cap_mplane = venc_g_fmt,
 519        .vidioc_g_fmt_vid_out_mplane = venc_g_fmt,
 520        .vidioc_try_fmt_vid_cap_mplane = venc_try_fmt,
 521        .vidioc_try_fmt_vid_out_mplane = venc_try_fmt,
 522        .vidioc_g_selection = venc_g_selection,
 523        .vidioc_s_selection = venc_s_selection,
 524        .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
 525        .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
 526        .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
 527        .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
 528        .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
 529        .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
 530        .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
 531        .vidioc_streamon = v4l2_m2m_ioctl_streamon,
 532        .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
 533        .vidioc_s_parm = venc_s_parm,
 534        .vidioc_g_parm = venc_g_parm,
 535        .vidioc_enum_framesizes = venc_enum_framesizes,
 536        .vidioc_enum_frameintervals = venc_enum_frameintervals,
 537        .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
 538        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 539};
 540
 541static int venc_set_properties(struct venus_inst *inst)
 542{
 543        struct venc_controls *ctr = &inst->controls.enc;
 544        struct hfi_intra_period intra_period;
 545        struct hfi_framerate frate;
 546        struct hfi_bitrate brate;
 547        struct hfi_idr_period idrp;
 548        struct hfi_quantization quant;
 549        struct hfi_quantization_range quant_range;
 550        struct hfi_enable en;
 551        struct hfi_ltr_mode ltr_mode;
 552        struct hfi_intra_refresh intra_refresh = {};
 553        u32 ptype, rate_control, bitrate;
 554        u32 profile, level;
 555        int ret;
 556
 557        ret = venus_helper_set_work_mode(inst);
 558        if (ret)
 559                return ret;
 560
 561        ptype = HFI_PROPERTY_CONFIG_FRAME_RATE;
 562        frate.buffer_type = HFI_BUFFER_OUTPUT;
 563        frate.framerate = inst->fps * (1 << 16);
 564
 565        ret = hfi_session_set_property(inst, ptype, &frate);
 566        if (ret)
 567                return ret;
 568
 569        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264) {
 570                struct hfi_h264_vui_timing_info info;
 571                struct hfi_h264_entropy_control entropy;
 572                struct hfi_h264_db_control deblock;
 573                struct hfi_h264_8x8_transform h264_transform;
 574
 575                ptype = HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO;
 576                info.enable = 1;
 577                info.fixed_framerate = 1;
 578                info.time_scale = NSEC_PER_SEC;
 579
 580                ret = hfi_session_set_property(inst, ptype, &info);
 581                if (ret)
 582                        return ret;
 583
 584                ptype = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
 585                entropy.entropy_mode = venc_v4l2_to_hfi(
 586                                          V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
 587                                          ctr->h264_entropy_mode);
 588                entropy.cabac_model = HFI_H264_CABAC_MODEL_0;
 589
 590                ret = hfi_session_set_property(inst, ptype, &entropy);
 591                if (ret)
 592                        return ret;
 593
 594                ptype = HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL;
 595                deblock.mode = venc_v4l2_to_hfi(
 596                                      V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
 597                                      ctr->h264_loop_filter_mode);
 598                deblock.slice_alpha_offset = ctr->h264_loop_filter_alpha;
 599                deblock.slice_beta_offset = ctr->h264_loop_filter_beta;
 600
 601                ret = hfi_session_set_property(inst, ptype, &deblock);
 602                if (ret)
 603                        return ret;
 604
 605                ptype = HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8;
 606                h264_transform.enable_type = 0;
 607                if (ctr->profile.h264 == HFI_H264_PROFILE_HIGH ||
 608                    ctr->profile.h264 == HFI_H264_PROFILE_CONSTRAINED_HIGH)
 609                        h264_transform.enable_type = ctr->h264_8x8_transform;
 610
 611                ret = hfi_session_set_property(inst, ptype, &h264_transform);
 612                if (ret)
 613                        return ret;
 614
 615        }
 616
 617        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
 618            inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 619                /* IDR periodicity, n:
 620                 * n = 0 - only the first I-frame is IDR frame
 621                 * n = 1 - all I-frames will be IDR frames
 622                 * n > 1 - every n-th I-frame will be IDR frame
 623                 */
 624                ptype = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD;
 625                idrp.idr_period = 0;
 626                ret = hfi_session_set_property(inst, ptype, &idrp);
 627                if (ret)
 628                        return ret;
 629        }
 630
 631        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 632                struct hfi_hdr10_pq_sei hdr10;
 633                unsigned int c;
 634
 635                ptype = HFI_PROPERTY_PARAM_VENC_HDR10_PQ_SEI;
 636
 637                for (c = 0; c < 3; c++) {
 638                        hdr10.mastering.display_primaries_x[c] =
 639                                ctr->mastering.display_primaries_x[c];
 640                        hdr10.mastering.display_primaries_y[c] =
 641                                ctr->mastering.display_primaries_y[c];
 642                }
 643
 644                hdr10.mastering.white_point_x = ctr->mastering.white_point_x;
 645                hdr10.mastering.white_point_y = ctr->mastering.white_point_y;
 646                hdr10.mastering.max_display_mastering_luminance =
 647                        ctr->mastering.max_display_mastering_luminance;
 648                hdr10.mastering.min_display_mastering_luminance =
 649                        ctr->mastering.min_display_mastering_luminance;
 650
 651                hdr10.cll.max_content_light = ctr->cll.max_content_light_level;
 652                hdr10.cll.max_pic_average_light =
 653                        ctr->cll.max_pic_average_light_level;
 654
 655                ret = hfi_session_set_property(inst, ptype, &hdr10);
 656                if (ret)
 657                        return ret;
 658        }
 659
 660        if (ctr->num_b_frames) {
 661                u32 max_num_b_frames = NUM_B_FRAMES_MAX;
 662
 663                ptype = HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES;
 664                ret = hfi_session_set_property(inst, ptype, &max_num_b_frames);
 665                if (ret)
 666                        return ret;
 667        }
 668
 669        ptype = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD;
 670        intra_period.pframes = ctr->num_p_frames;
 671        intra_period.bframes = ctr->num_b_frames;
 672
 673        ret = hfi_session_set_property(inst, ptype, &intra_period);
 674        if (ret)
 675                return ret;
 676
 677        if (!ctr->rc_enable)
 678                rate_control = HFI_RATE_CONTROL_OFF;
 679        else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
 680                rate_control = ctr->frame_skip_mode ? HFI_RATE_CONTROL_VBR_VFR :
 681                                                      HFI_RATE_CONTROL_VBR_CFR;
 682        else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
 683                rate_control = ctr->frame_skip_mode ? HFI_RATE_CONTROL_CBR_VFR :
 684                                                      HFI_RATE_CONTROL_CBR_CFR;
 685        else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
 686                rate_control = HFI_RATE_CONTROL_CQ;
 687
 688        ptype = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
 689        ret = hfi_session_set_property(inst, ptype, &rate_control);
 690        if (ret)
 691                return ret;
 692
 693        if (rate_control == HFI_RATE_CONTROL_CQ && ctr->const_quality) {
 694                struct hfi_heic_frame_quality quality = {};
 695
 696                ptype = HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY;
 697                quality.frame_quality = ctr->const_quality;
 698                ret = hfi_session_set_property(inst, ptype, &quality);
 699                if (ret)
 700                        return ret;
 701        }
 702
 703        if (!ctr->bitrate)
 704                bitrate = 64000;
 705        else
 706                bitrate = ctr->bitrate;
 707
 708        ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
 709        brate.bitrate = bitrate;
 710        brate.layer_id = 0;
 711
 712        ret = hfi_session_set_property(inst, ptype, &brate);
 713        if (ret)
 714                return ret;
 715
 716        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
 717            inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 718                ptype = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER;
 719                if (ctr->header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE)
 720                        en.enable = 0;
 721                else
 722                        en.enable = 1;
 723
 724                ret = hfi_session_set_property(inst, ptype, &en);
 725                if (ret)
 726                        return ret;
 727        }
 728
 729        if (!ctr->bitrate_peak)
 730                bitrate *= 2;
 731        else
 732                bitrate = ctr->bitrate_peak;
 733
 734        ptype = HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE;
 735        brate.bitrate = bitrate;
 736        brate.layer_id = 0;
 737
 738        ret = hfi_session_set_property(inst, ptype, &brate);
 739        if (ret)
 740                return ret;
 741
 742        ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP;
 743        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 744                quant.qp_i = ctr->hevc_i_qp;
 745                quant.qp_p = ctr->hevc_p_qp;
 746                quant.qp_b = ctr->hevc_b_qp;
 747        } else {
 748                quant.qp_i = ctr->h264_i_qp;
 749                quant.qp_p = ctr->h264_p_qp;
 750                quant.qp_b = ctr->h264_b_qp;
 751        }
 752        quant.layer_id = 0;
 753        ret = hfi_session_set_property(inst, ptype, &quant);
 754        if (ret)
 755                return ret;
 756
 757        ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE;
 758        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 759                quant_range.min_qp = ctr->hevc_min_qp;
 760                quant_range.max_qp = ctr->hevc_max_qp;
 761        } else {
 762                quant_range.min_qp = ctr->h264_min_qp;
 763                quant_range.max_qp = ctr->h264_max_qp;
 764        }
 765        quant_range.layer_id = 0;
 766        ret = hfi_session_set_property(inst, ptype, &quant_range);
 767        if (ret)
 768                return ret;
 769
 770        ptype = HFI_PROPERTY_PARAM_VENC_LTRMODE;
 771        ltr_mode.ltr_count = ctr->ltr_count;
 772        ltr_mode.ltr_mode = HFI_LTR_MODE_MANUAL;
 773        ltr_mode.trust_mode = 1;
 774        ret = hfi_session_set_property(inst, ptype, &ltr_mode);
 775        if (ret)
 776                return ret;
 777
 778        switch (inst->hfi_codec) {
 779        case HFI_VIDEO_CODEC_H264:
 780                profile = ctr->profile.h264;
 781                level = ctr->level.h264;
 782                break;
 783        case HFI_VIDEO_CODEC_MPEG4:
 784                profile = ctr->profile.mpeg4;
 785                level = ctr->level.mpeg4;
 786                break;
 787        case HFI_VIDEO_CODEC_VP8:
 788                profile = ctr->profile.vp8;
 789                level = 0;
 790                break;
 791        case HFI_VIDEO_CODEC_VP9:
 792                profile = ctr->profile.vp9;
 793                level = ctr->level.vp9;
 794                break;
 795        case HFI_VIDEO_CODEC_HEVC:
 796                profile = ctr->profile.hevc;
 797                level = ctr->level.hevc;
 798                break;
 799        case HFI_VIDEO_CODEC_MPEG2:
 800        default:
 801                profile = 0;
 802                level = 0;
 803                break;
 804        }
 805
 806        ret = venus_helper_set_profile_level(inst, profile, level);
 807        if (ret)
 808                return ret;
 809
 810        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
 811            inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 812                struct hfi_enable en = {};
 813
 814                ptype = HFI_PROPERTY_PARAM_VENC_H264_GENERATE_AUDNAL;
 815
 816                if (ctr->aud_enable)
 817                        en.enable = 1;
 818
 819                ret = hfi_session_set_property(inst, ptype, &en);
 820        }
 821
 822        if ((inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
 823             inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) &&
 824            (rate_control == HFI_RATE_CONTROL_CBR_VFR ||
 825             rate_control == HFI_RATE_CONTROL_CBR_CFR)) {
 826                intra_refresh.mode = HFI_INTRA_REFRESH_NONE;
 827                intra_refresh.cir_mbs = 0;
 828
 829                if (ctr->intra_refresh_period) {
 830                        u32 mbs;
 831
 832                        mbs = ALIGN(inst->width, 16) * ALIGN(inst->height, 16);
 833                        mbs /= 16 * 16;
 834                        if (mbs % ctr->intra_refresh_period)
 835                                mbs++;
 836                        mbs /= ctr->intra_refresh_period;
 837
 838                        intra_refresh.mode = HFI_INTRA_REFRESH_RANDOM;
 839                        intra_refresh.cir_mbs = mbs;
 840                }
 841
 842                ptype = HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
 843
 844                ret = hfi_session_set_property(inst, ptype, &intra_refresh);
 845                if (ret)
 846                        return ret;
 847        }
 848
 849        return 0;
 850}
 851
 852static int venc_init_session(struct venus_inst *inst)
 853{
 854        int ret;
 855
 856        ret = venus_helper_session_init(inst);
 857        if (ret == -EALREADY)
 858                return 0;
 859        else if (ret)
 860                return ret;
 861
 862        ret = venus_helper_set_stride(inst, inst->out_width,
 863                                      inst->out_height);
 864        if (ret)
 865                goto deinit;
 866
 867        ret = venus_helper_set_input_resolution(inst, inst->width,
 868                                                inst->height);
 869        if (ret)
 870                goto deinit;
 871
 872        ret = venus_helper_set_output_resolution(inst, inst->width,
 873                                                 inst->height,
 874                                                 HFI_BUFFER_OUTPUT);
 875        if (ret)
 876                goto deinit;
 877
 878        ret = venus_helper_set_color_format(inst, inst->fmt_out->pixfmt);
 879        if (ret)
 880                goto deinit;
 881
 882        ret = venc_set_properties(inst);
 883        if (ret)
 884                goto deinit;
 885
 886        return 0;
 887deinit:
 888        hfi_session_deinit(inst);
 889        return ret;
 890}
 891
 892static int venc_out_num_buffers(struct venus_inst *inst, unsigned int *num)
 893{
 894        struct hfi_buffer_requirements bufreq;
 895        int ret;
 896
 897        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
 898        if (ret)
 899                return ret;
 900
 901        *num = bufreq.count_actual;
 902
 903        return 0;
 904}
 905
 906static int venc_queue_setup(struct vb2_queue *q,
 907                            unsigned int *num_buffers, unsigned int *num_planes,
 908                            unsigned int sizes[], struct device *alloc_devs[])
 909{
 910        struct venus_inst *inst = vb2_get_drv_priv(q);
 911        unsigned int num, min = 4;
 912        int ret;
 913
 914        if (*num_planes) {
 915                if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
 916                    *num_planes != inst->fmt_out->num_planes)
 917                        return -EINVAL;
 918
 919                if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
 920                    *num_planes != inst->fmt_cap->num_planes)
 921                        return -EINVAL;
 922
 923                if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
 924                    sizes[0] < inst->input_buf_size)
 925                        return -EINVAL;
 926
 927                if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
 928                    sizes[0] < inst->output_buf_size)
 929                        return -EINVAL;
 930
 931                return 0;
 932        }
 933
 934        mutex_lock(&inst->lock);
 935        ret = venc_init_session(inst);
 936        mutex_unlock(&inst->lock);
 937
 938        if (ret)
 939                return ret;
 940
 941        switch (q->type) {
 942        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 943                *num_planes = inst->fmt_out->num_planes;
 944
 945                ret = venc_out_num_buffers(inst, &num);
 946                if (ret)
 947                        break;
 948
 949                num = max(num, min);
 950                *num_buffers = max(*num_buffers, num);
 951                inst->num_input_bufs = *num_buffers;
 952
 953                sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt,
 954                                                    inst->out_width,
 955                                                    inst->out_height);
 956                inst->input_buf_size = sizes[0];
 957                break;
 958        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 959                *num_planes = inst->fmt_cap->num_planes;
 960                *num_buffers = max(*num_buffers, min);
 961                inst->num_output_bufs = *num_buffers;
 962                sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt,
 963                                                    inst->width,
 964                                                    inst->height);
 965                sizes[0] = max(sizes[0], inst->output_buf_size);
 966                inst->output_buf_size = sizes[0];
 967                break;
 968        default:
 969                ret = -EINVAL;
 970                break;
 971        }
 972
 973        return ret;
 974}
 975
 976static int venc_buf_init(struct vb2_buffer *vb)
 977{
 978        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
 979
 980        inst->buf_count++;
 981
 982        return venus_helper_vb2_buf_init(vb);
 983}
 984
 985static void venc_release_session(struct venus_inst *inst)
 986{
 987        int ret;
 988
 989        mutex_lock(&inst->lock);
 990
 991        ret = hfi_session_deinit(inst);
 992        if (ret || inst->session_error)
 993                hfi_session_abort(inst);
 994
 995        mutex_unlock(&inst->lock);
 996
 997        venus_pm_load_scale(inst);
 998        INIT_LIST_HEAD(&inst->registeredbufs);
 999        venus_pm_release_core(inst);
1000}
1001
1002static void venc_buf_cleanup(struct vb2_buffer *vb)
1003{
1004        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1005        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1006        struct venus_buffer *buf = to_venus_buffer(vbuf);
1007
1008        mutex_lock(&inst->lock);
1009        if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1010                if (!list_empty(&inst->registeredbufs))
1011                        list_del_init(&buf->reg_list);
1012        mutex_unlock(&inst->lock);
1013
1014        inst->buf_count--;
1015        if (!inst->buf_count)
1016                venc_release_session(inst);
1017}
1018
1019static int venc_verify_conf(struct venus_inst *inst)
1020{
1021        enum hfi_version ver = inst->core->res->hfi_version;
1022        struct hfi_buffer_requirements bufreq;
1023        int ret;
1024
1025        if (!inst->num_input_bufs || !inst->num_output_bufs)
1026                return -EINVAL;
1027
1028        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
1029        if (ret)
1030                return ret;
1031
1032        if (inst->num_output_bufs < bufreq.count_actual ||
1033            inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
1034                return -EINVAL;
1035
1036        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
1037        if (ret)
1038                return ret;
1039
1040        if (inst->num_input_bufs < bufreq.count_actual ||
1041            inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
1042                return -EINVAL;
1043
1044        return 0;
1045}
1046
1047static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
1048{
1049        struct venus_inst *inst = vb2_get_drv_priv(q);
1050        int ret;
1051
1052        mutex_lock(&inst->lock);
1053
1054        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1055                inst->streamon_out = 1;
1056        else
1057                inst->streamon_cap = 1;
1058
1059        if (!(inst->streamon_out & inst->streamon_cap)) {
1060                mutex_unlock(&inst->lock);
1061                return 0;
1062        }
1063
1064        venus_helper_init_instance(inst);
1065
1066        inst->sequence_cap = 0;
1067        inst->sequence_out = 0;
1068
1069        ret = venus_pm_acquire_core(inst);
1070        if (ret)
1071                goto error;
1072
1073        ret = venc_set_properties(inst);
1074        if (ret)
1075                goto error;
1076
1077        ret = venc_verify_conf(inst);
1078        if (ret)
1079                goto error;
1080
1081        ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
1082                                        inst->num_output_bufs, 0);
1083        if (ret)
1084                goto error;
1085
1086        ret = venus_helper_vb2_start_streaming(inst);
1087        if (ret)
1088                goto error;
1089
1090        mutex_unlock(&inst->lock);
1091
1092        return 0;
1093
1094error:
1095        venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
1096        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1097                inst->streamon_out = 0;
1098        else
1099                inst->streamon_cap = 0;
1100        mutex_unlock(&inst->lock);
1101        return ret;
1102}
1103
1104static void venc_vb2_buf_queue(struct vb2_buffer *vb)
1105{
1106        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1107
1108        mutex_lock(&inst->lock);
1109        venus_helper_vb2_buf_queue(vb);
1110        mutex_unlock(&inst->lock);
1111}
1112
1113static const struct vb2_ops venc_vb2_ops = {
1114        .queue_setup = venc_queue_setup,
1115        .buf_init = venc_buf_init,
1116        .buf_cleanup = venc_buf_cleanup,
1117        .buf_prepare = venus_helper_vb2_buf_prepare,
1118        .start_streaming = venc_start_streaming,
1119        .stop_streaming = venus_helper_vb2_stop_streaming,
1120        .buf_queue = venc_vb2_buf_queue,
1121};
1122
1123static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type,
1124                          u32 tag, u32 bytesused, u32 data_offset, u32 flags,
1125                          u32 hfi_flags, u64 timestamp_us)
1126{
1127        struct vb2_v4l2_buffer *vbuf;
1128        struct vb2_buffer *vb;
1129        unsigned int type;
1130
1131        if (buf_type == HFI_BUFFER_INPUT)
1132                type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1133        else
1134                type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1135
1136        vbuf = venus_helper_find_buf(inst, type, tag);
1137        if (!vbuf)
1138                return;
1139
1140        vbuf->flags = flags;
1141
1142        if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1143                vb = &vbuf->vb2_buf;
1144                vb2_set_plane_payload(vb, 0, bytesused + data_offset);
1145                vb->planes[0].data_offset = data_offset;
1146                vb->timestamp = timestamp_us * NSEC_PER_USEC;
1147                vbuf->sequence = inst->sequence_cap++;
1148        } else {
1149                vbuf->sequence = inst->sequence_out++;
1150        }
1151
1152        v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
1153}
1154
1155static void venc_event_notify(struct venus_inst *inst, u32 event,
1156                              struct hfi_event_data *data)
1157{
1158        struct device *dev = inst->core->dev_enc;
1159
1160        if (event == EVT_SESSION_ERROR) {
1161                inst->session_error = true;
1162                dev_err(dev, "enc: event session error %x\n", inst->error);
1163        }
1164}
1165
1166static const struct hfi_inst_ops venc_hfi_ops = {
1167        .buf_done = venc_buf_done,
1168        .event_notify = venc_event_notify,
1169};
1170
1171static const struct v4l2_m2m_ops venc_m2m_ops = {
1172        .device_run = venus_helper_m2m_device_run,
1173        .job_abort = venus_helper_m2m_job_abort,
1174};
1175
1176static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
1177                          struct vb2_queue *dst_vq)
1178{
1179        struct venus_inst *inst = priv;
1180        int ret;
1181
1182        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1183        src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1184        src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1185        src_vq->ops = &venc_vb2_ops;
1186        src_vq->mem_ops = &vb2_dma_contig_memops;
1187        src_vq->drv_priv = inst;
1188        src_vq->buf_struct_size = sizeof(struct venus_buffer);
1189        src_vq->allow_zero_bytesused = 1;
1190        src_vq->min_buffers_needed = 1;
1191        src_vq->dev = inst->core->dev;
1192        if (inst->core->res->hfi_version == HFI_VERSION_1XX)
1193                src_vq->bidirectional = 1;
1194        ret = vb2_queue_init(src_vq);
1195        if (ret)
1196                return ret;
1197
1198        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1199        dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1200        dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1201        dst_vq->ops = &venc_vb2_ops;
1202        dst_vq->mem_ops = &vb2_dma_contig_memops;
1203        dst_vq->drv_priv = inst;
1204        dst_vq->buf_struct_size = sizeof(struct venus_buffer);
1205        dst_vq->allow_zero_bytesused = 1;
1206        dst_vq->min_buffers_needed = 1;
1207        dst_vq->dev = inst->core->dev;
1208        return vb2_queue_init(dst_vq);
1209}
1210
1211static void venc_inst_init(struct venus_inst *inst)
1212{
1213        inst->fmt_cap = &venc_formats[3];
1214        inst->fmt_out = &venc_formats[0];
1215        inst->width = 1280;
1216        inst->height = ALIGN(720, 32);
1217        inst->out_width = 1280;
1218        inst->out_height = 720;
1219        inst->fps = 15;
1220        inst->timeperframe.numerator = 1;
1221        inst->timeperframe.denominator = 15;
1222        inst->hfi_codec = HFI_VIDEO_CODEC_H264;
1223}
1224
1225static int venc_open(struct file *file)
1226{
1227        struct venus_core *core = video_drvdata(file);
1228        struct venus_inst *inst;
1229        int ret;
1230
1231        inst = kzalloc(sizeof(*inst), GFP_KERNEL);
1232        if (!inst)
1233                return -ENOMEM;
1234
1235        INIT_LIST_HEAD(&inst->dpbbufs);
1236        INIT_LIST_HEAD(&inst->registeredbufs);
1237        INIT_LIST_HEAD(&inst->internalbufs);
1238        INIT_LIST_HEAD(&inst->list);
1239        mutex_init(&inst->lock);
1240
1241        inst->core = core;
1242        inst->session_type = VIDC_SESSION_TYPE_ENC;
1243        inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
1244        inst->core_acquired = false;
1245
1246        venus_helper_init_instance(inst);
1247
1248        ret = pm_runtime_resume_and_get(core->dev_enc);
1249        if (ret < 0)
1250                goto err_free;
1251
1252        ret = venc_ctrl_init(inst);
1253        if (ret)
1254                goto err_put_sync;
1255
1256        ret = hfi_session_create(inst, &venc_hfi_ops);
1257        if (ret)
1258                goto err_ctrl_deinit;
1259
1260        venc_inst_init(inst);
1261
1262        /*
1263         * create m2m device for every instance, the m2m context scheduling
1264         * is made by firmware side so we do not need to care about.
1265         */
1266        inst->m2m_dev = v4l2_m2m_init(&venc_m2m_ops);
1267        if (IS_ERR(inst->m2m_dev)) {
1268                ret = PTR_ERR(inst->m2m_dev);
1269                goto err_session_destroy;
1270        }
1271
1272        inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
1273        if (IS_ERR(inst->m2m_ctx)) {
1274                ret = PTR_ERR(inst->m2m_ctx);
1275                goto err_m2m_release;
1276        }
1277
1278        v4l2_fh_init(&inst->fh, core->vdev_enc);
1279
1280        inst->fh.ctrl_handler = &inst->ctrl_handler;
1281        v4l2_fh_add(&inst->fh);
1282        inst->fh.m2m_ctx = inst->m2m_ctx;
1283        file->private_data = &inst->fh;
1284
1285        return 0;
1286
1287err_m2m_release:
1288        v4l2_m2m_release(inst->m2m_dev);
1289err_session_destroy:
1290        hfi_session_destroy(inst);
1291err_ctrl_deinit:
1292        venc_ctrl_deinit(inst);
1293err_put_sync:
1294        pm_runtime_put_sync(core->dev_enc);
1295err_free:
1296        kfree(inst);
1297        return ret;
1298}
1299
1300static int venc_close(struct file *file)
1301{
1302        struct venus_inst *inst = to_inst(file);
1303
1304        v4l2_m2m_ctx_release(inst->m2m_ctx);
1305        v4l2_m2m_release(inst->m2m_dev);
1306        venc_ctrl_deinit(inst);
1307        hfi_session_destroy(inst);
1308        mutex_destroy(&inst->lock);
1309        v4l2_fh_del(&inst->fh);
1310        v4l2_fh_exit(&inst->fh);
1311
1312        pm_runtime_put_sync(inst->core->dev_enc);
1313
1314        kfree(inst);
1315        return 0;
1316}
1317
1318static const struct v4l2_file_operations venc_fops = {
1319        .owner = THIS_MODULE,
1320        .open = venc_open,
1321        .release = venc_close,
1322        .unlocked_ioctl = video_ioctl2,
1323        .poll = v4l2_m2m_fop_poll,
1324        .mmap = v4l2_m2m_fop_mmap,
1325};
1326
1327static int venc_probe(struct platform_device *pdev)
1328{
1329        struct device *dev = &pdev->dev;
1330        struct video_device *vdev;
1331        struct venus_core *core;
1332        int ret;
1333
1334        if (!dev->parent)
1335                return -EPROBE_DEFER;
1336
1337        core = dev_get_drvdata(dev->parent);
1338        if (!core)
1339                return -EPROBE_DEFER;
1340
1341        platform_set_drvdata(pdev, core);
1342
1343        if (core->pm_ops->venc_get) {
1344                ret = core->pm_ops->venc_get(dev);
1345                if (ret)
1346                        return ret;
1347        }
1348
1349        vdev = video_device_alloc();
1350        if (!vdev)
1351                return -ENOMEM;
1352
1353        strscpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name));
1354        vdev->release = video_device_release;
1355        vdev->fops = &venc_fops;
1356        vdev->ioctl_ops = &venc_ioctl_ops;
1357        vdev->vfl_dir = VFL_DIR_M2M;
1358        vdev->v4l2_dev = &core->v4l2_dev;
1359        vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
1360
1361        ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1362        if (ret)
1363                goto err_vdev_release;
1364
1365        core->vdev_enc = vdev;
1366        core->dev_enc = dev;
1367
1368        video_set_drvdata(vdev, core);
1369        pm_runtime_enable(dev);
1370
1371        return 0;
1372
1373err_vdev_release:
1374        video_device_release(vdev);
1375        return ret;
1376}
1377
1378static int venc_remove(struct platform_device *pdev)
1379{
1380        struct venus_core *core = dev_get_drvdata(pdev->dev.parent);
1381
1382        video_unregister_device(core->vdev_enc);
1383        pm_runtime_disable(core->dev_enc);
1384
1385        if (core->pm_ops->venc_put)
1386                core->pm_ops->venc_put(core->dev_enc);
1387
1388        return 0;
1389}
1390
1391static __maybe_unused int venc_runtime_suspend(struct device *dev)
1392{
1393        struct venus_core *core = dev_get_drvdata(dev);
1394        const struct venus_pm_ops *pm_ops = core->pm_ops;
1395        int ret = 0;
1396
1397        if (pm_ops->venc_power)
1398                ret = pm_ops->venc_power(dev, POWER_OFF);
1399
1400        return ret;
1401}
1402
1403static __maybe_unused int venc_runtime_resume(struct device *dev)
1404{
1405        struct venus_core *core = dev_get_drvdata(dev);
1406        const struct venus_pm_ops *pm_ops = core->pm_ops;
1407        int ret = 0;
1408
1409        if (pm_ops->venc_power)
1410                ret = pm_ops->venc_power(dev, POWER_ON);
1411
1412        return ret;
1413}
1414
1415static const struct dev_pm_ops venc_pm_ops = {
1416        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1417                                pm_runtime_force_resume)
1418        SET_RUNTIME_PM_OPS(venc_runtime_suspend, venc_runtime_resume, NULL)
1419};
1420
1421static const struct of_device_id venc_dt_match[] = {
1422        { .compatible = "venus-encoder" },
1423        { }
1424};
1425MODULE_DEVICE_TABLE(of, venc_dt_match);
1426
1427static struct platform_driver qcom_venus_enc_driver = {
1428        .probe = venc_probe,
1429        .remove = venc_remove,
1430        .driver = {
1431                .name = "qcom-venus-encoder",
1432                .of_match_table = venc_dt_match,
1433                .pm = &venc_pm_ops,
1434        },
1435};
1436module_platform_driver(qcom_venus_enc_driver);
1437
1438MODULE_ALIAS("platform:qcom-venus-encoder");
1439MODULE_DESCRIPTION("Qualcomm Venus video encoder driver");
1440MODULE_LICENSE("GPL v2");
1441