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_pm_get(struct venus_inst *inst)
 542{
 543        struct venus_core *core = inst->core;
 544        struct device *dev = core->dev_enc;
 545        int ret;
 546
 547        mutex_lock(&core->pm_lock);
 548        ret = pm_runtime_resume_and_get(dev);
 549        mutex_unlock(&core->pm_lock);
 550
 551        return ret < 0 ? ret : 0;
 552}
 553
 554static int venc_pm_put(struct venus_inst *inst, bool autosuspend)
 555{
 556        struct venus_core *core = inst->core;
 557        struct device *dev = core->dev_enc;
 558        int ret;
 559
 560        mutex_lock(&core->pm_lock);
 561
 562        if (autosuspend)
 563                ret = pm_runtime_put_autosuspend(dev);
 564        else
 565                ret = pm_runtime_put_sync(dev);
 566
 567        mutex_unlock(&core->pm_lock);
 568
 569        return ret < 0 ? ret : 0;
 570}
 571
 572static int venc_pm_get_put(struct venus_inst *inst)
 573{
 574        struct venus_core *core = inst->core;
 575        struct device *dev = core->dev_enc;
 576        int ret = 0;
 577
 578        mutex_lock(&core->pm_lock);
 579
 580        if (pm_runtime_suspended(dev)) {
 581                ret = pm_runtime_resume_and_get(dev);
 582                if (ret < 0)
 583                        goto error;
 584
 585                ret = pm_runtime_put_autosuspend(dev);
 586        }
 587
 588error:
 589        mutex_unlock(&core->pm_lock);
 590
 591        return ret < 0 ? ret : 0;
 592}
 593
 594static void venc_pm_touch(struct venus_inst *inst)
 595{
 596        pm_runtime_mark_last_busy(inst->core->dev_enc);
 597}
 598
 599static int venc_set_properties(struct venus_inst *inst)
 600{
 601        struct venc_controls *ctr = &inst->controls.enc;
 602        struct hfi_intra_period intra_period;
 603        struct hfi_framerate frate;
 604        struct hfi_bitrate brate;
 605        struct hfi_idr_period idrp;
 606        struct hfi_quantization quant;
 607        struct hfi_quantization_range quant_range;
 608        struct hfi_enable en;
 609        struct hfi_ltr_mode ltr_mode;
 610        struct hfi_intra_refresh intra_refresh = {};
 611        u32 ptype, rate_control, bitrate;
 612        u32 profile, level;
 613        int ret;
 614
 615        ret = venus_helper_set_work_mode(inst);
 616        if (ret)
 617                return ret;
 618
 619        ptype = HFI_PROPERTY_CONFIG_FRAME_RATE;
 620        frate.buffer_type = HFI_BUFFER_OUTPUT;
 621        frate.framerate = inst->fps * (1 << 16);
 622
 623        ret = hfi_session_set_property(inst, ptype, &frate);
 624        if (ret)
 625                return ret;
 626
 627        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264) {
 628                struct hfi_h264_vui_timing_info info;
 629                struct hfi_h264_entropy_control entropy;
 630                struct hfi_h264_db_control deblock;
 631                struct hfi_h264_8x8_transform h264_transform;
 632
 633                ptype = HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO;
 634                info.enable = 1;
 635                info.fixed_framerate = 1;
 636                info.time_scale = NSEC_PER_SEC;
 637
 638                ret = hfi_session_set_property(inst, ptype, &info);
 639                if (ret)
 640                        return ret;
 641
 642                ptype = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
 643                entropy.entropy_mode = venc_v4l2_to_hfi(
 644                                          V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
 645                                          ctr->h264_entropy_mode);
 646                entropy.cabac_model = HFI_H264_CABAC_MODEL_0;
 647
 648                ret = hfi_session_set_property(inst, ptype, &entropy);
 649                if (ret)
 650                        return ret;
 651
 652                ptype = HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL;
 653                deblock.mode = venc_v4l2_to_hfi(
 654                                      V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
 655                                      ctr->h264_loop_filter_mode);
 656                deblock.slice_alpha_offset = ctr->h264_loop_filter_alpha;
 657                deblock.slice_beta_offset = ctr->h264_loop_filter_beta;
 658
 659                ret = hfi_session_set_property(inst, ptype, &deblock);
 660                if (ret)
 661                        return ret;
 662
 663                ptype = HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8;
 664                h264_transform.enable_type = 0;
 665                if (ctr->profile.h264 == HFI_H264_PROFILE_HIGH ||
 666                    ctr->profile.h264 == HFI_H264_PROFILE_CONSTRAINED_HIGH)
 667                        h264_transform.enable_type = ctr->h264_8x8_transform;
 668
 669                ret = hfi_session_set_property(inst, ptype, &h264_transform);
 670                if (ret)
 671                        return ret;
 672
 673        }
 674
 675        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
 676            inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 677                /* IDR periodicity, n:
 678                 * n = 0 - only the first I-frame is IDR frame
 679                 * n = 1 - all I-frames will be IDR frames
 680                 * n > 1 - every n-th I-frame will be IDR frame
 681                 */
 682                ptype = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD;
 683                idrp.idr_period = 0;
 684                ret = hfi_session_set_property(inst, ptype, &idrp);
 685                if (ret)
 686                        return ret;
 687        }
 688
 689        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 690                struct hfi_hdr10_pq_sei hdr10;
 691                unsigned int c;
 692
 693                ptype = HFI_PROPERTY_PARAM_VENC_HDR10_PQ_SEI;
 694
 695                for (c = 0; c < 3; c++) {
 696                        hdr10.mastering.display_primaries_x[c] =
 697                                ctr->mastering.display_primaries_x[c];
 698                        hdr10.mastering.display_primaries_y[c] =
 699                                ctr->mastering.display_primaries_y[c];
 700                }
 701
 702                hdr10.mastering.white_point_x = ctr->mastering.white_point_x;
 703                hdr10.mastering.white_point_y = ctr->mastering.white_point_y;
 704                hdr10.mastering.max_display_mastering_luminance =
 705                        ctr->mastering.max_display_mastering_luminance;
 706                hdr10.mastering.min_display_mastering_luminance =
 707                        ctr->mastering.min_display_mastering_luminance;
 708
 709                hdr10.cll.max_content_light = ctr->cll.max_content_light_level;
 710                hdr10.cll.max_pic_average_light =
 711                        ctr->cll.max_pic_average_light_level;
 712
 713                ret = hfi_session_set_property(inst, ptype, &hdr10);
 714                if (ret)
 715                        return ret;
 716        }
 717
 718        if (ctr->num_b_frames) {
 719                u32 max_num_b_frames = NUM_B_FRAMES_MAX;
 720
 721                ptype = HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES;
 722                ret = hfi_session_set_property(inst, ptype, &max_num_b_frames);
 723                if (ret)
 724                        return ret;
 725        }
 726
 727        ptype = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD;
 728        intra_period.pframes = ctr->num_p_frames;
 729        intra_period.bframes = ctr->num_b_frames;
 730
 731        ret = hfi_session_set_property(inst, ptype, &intra_period);
 732        if (ret)
 733                return ret;
 734
 735        if (!ctr->rc_enable)
 736                rate_control = HFI_RATE_CONTROL_OFF;
 737        else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
 738                rate_control = ctr->frame_skip_mode ? HFI_RATE_CONTROL_VBR_VFR :
 739                                                      HFI_RATE_CONTROL_VBR_CFR;
 740        else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
 741                rate_control = ctr->frame_skip_mode ? HFI_RATE_CONTROL_CBR_VFR :
 742                                                      HFI_RATE_CONTROL_CBR_CFR;
 743        else if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
 744                rate_control = HFI_RATE_CONTROL_CQ;
 745
 746        ptype = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
 747        ret = hfi_session_set_property(inst, ptype, &rate_control);
 748        if (ret)
 749                return ret;
 750
 751        if (rate_control == HFI_RATE_CONTROL_CQ && ctr->const_quality) {
 752                struct hfi_heic_frame_quality quality = {};
 753
 754                ptype = HFI_PROPERTY_CONFIG_HEIC_FRAME_QUALITY;
 755                quality.frame_quality = ctr->const_quality;
 756                ret = hfi_session_set_property(inst, ptype, &quality);
 757                if (ret)
 758                        return ret;
 759        }
 760
 761        if (!ctr->bitrate)
 762                bitrate = 64000;
 763        else
 764                bitrate = ctr->bitrate;
 765
 766        ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
 767        brate.bitrate = bitrate;
 768        brate.layer_id = 0;
 769
 770        ret = hfi_session_set_property(inst, ptype, &brate);
 771        if (ret)
 772                return ret;
 773
 774        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
 775            inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 776                ptype = HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER;
 777                if (ctr->header_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE)
 778                        en.enable = 0;
 779                else
 780                        en.enable = 1;
 781
 782                ret = hfi_session_set_property(inst, ptype, &en);
 783                if (ret)
 784                        return ret;
 785        }
 786
 787        if (!ctr->bitrate_peak)
 788                bitrate *= 2;
 789        else
 790                bitrate = ctr->bitrate_peak;
 791
 792        ptype = HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE;
 793        brate.bitrate = bitrate;
 794        brate.layer_id = 0;
 795
 796        ret = hfi_session_set_property(inst, ptype, &brate);
 797        if (ret)
 798                return ret;
 799
 800        ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP;
 801        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 802                quant.qp_i = ctr->hevc_i_qp;
 803                quant.qp_p = ctr->hevc_p_qp;
 804                quant.qp_b = ctr->hevc_b_qp;
 805        } else {
 806                quant.qp_i = ctr->h264_i_qp;
 807                quant.qp_p = ctr->h264_p_qp;
 808                quant.qp_b = ctr->h264_b_qp;
 809        }
 810        quant.layer_id = 0;
 811        ret = hfi_session_set_property(inst, ptype, &quant);
 812        if (ret)
 813                return ret;
 814
 815        ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP_RANGE;
 816        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 817                quant_range.min_qp = ctr->hevc_min_qp;
 818                quant_range.max_qp = ctr->hevc_max_qp;
 819        } else {
 820                quant_range.min_qp = ctr->h264_min_qp;
 821                quant_range.max_qp = ctr->h264_max_qp;
 822        }
 823        quant_range.layer_id = 0;
 824        ret = hfi_session_set_property(inst, ptype, &quant_range);
 825        if (ret)
 826                return ret;
 827
 828        ptype = HFI_PROPERTY_PARAM_VENC_LTRMODE;
 829        ltr_mode.ltr_count = ctr->ltr_count;
 830        ltr_mode.ltr_mode = HFI_LTR_MODE_MANUAL;
 831        ltr_mode.trust_mode = 1;
 832        ret = hfi_session_set_property(inst, ptype, &ltr_mode);
 833        if (ret)
 834                return ret;
 835
 836        switch (inst->hfi_codec) {
 837        case HFI_VIDEO_CODEC_H264:
 838                profile = ctr->profile.h264;
 839                level = ctr->level.h264;
 840                break;
 841        case HFI_VIDEO_CODEC_MPEG4:
 842                profile = ctr->profile.mpeg4;
 843                level = ctr->level.mpeg4;
 844                break;
 845        case HFI_VIDEO_CODEC_VP8:
 846                profile = ctr->profile.vp8;
 847                level = 0;
 848                break;
 849        case HFI_VIDEO_CODEC_VP9:
 850                profile = ctr->profile.vp9;
 851                level = ctr->level.vp9;
 852                break;
 853        case HFI_VIDEO_CODEC_HEVC:
 854                profile = ctr->profile.hevc;
 855                level = ctr->level.hevc;
 856                break;
 857        case HFI_VIDEO_CODEC_MPEG2:
 858        default:
 859                profile = 0;
 860                level = 0;
 861                break;
 862        }
 863
 864        ret = venus_helper_set_profile_level(inst, profile, level);
 865        if (ret)
 866                return ret;
 867
 868        if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
 869            inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) {
 870                struct hfi_enable en = {};
 871
 872                ptype = HFI_PROPERTY_PARAM_VENC_H264_GENERATE_AUDNAL;
 873
 874                if (ctr->aud_enable)
 875                        en.enable = 1;
 876
 877                ret = hfi_session_set_property(inst, ptype, &en);
 878        }
 879
 880        if ((inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
 881             inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) &&
 882            (rate_control == HFI_RATE_CONTROL_CBR_VFR ||
 883             rate_control == HFI_RATE_CONTROL_CBR_CFR)) {
 884                intra_refresh.mode = HFI_INTRA_REFRESH_NONE;
 885                intra_refresh.cir_mbs = 0;
 886
 887                if (ctr->intra_refresh_period) {
 888                        u32 mbs;
 889
 890                        mbs = ALIGN(inst->width, 16) * ALIGN(inst->height, 16);
 891                        mbs /= 16 * 16;
 892                        if (mbs % ctr->intra_refresh_period)
 893                                mbs++;
 894                        mbs /= ctr->intra_refresh_period;
 895
 896                        intra_refresh.mode = HFI_INTRA_REFRESH_RANDOM;
 897                        intra_refresh.cir_mbs = mbs;
 898                }
 899
 900                ptype = HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
 901
 902                ret = hfi_session_set_property(inst, ptype, &intra_refresh);
 903                if (ret)
 904                        return ret;
 905        }
 906
 907        return 0;
 908}
 909
 910static int venc_init_session(struct venus_inst *inst)
 911{
 912        int ret;
 913
 914        ret = venus_helper_session_init(inst);
 915        if (ret == -EALREADY)
 916                return 0;
 917        else if (ret)
 918                return ret;
 919
 920        ret = venus_helper_set_stride(inst, inst->out_width,
 921                                      inst->out_height);
 922        if (ret)
 923                goto deinit;
 924
 925        ret = venus_helper_set_input_resolution(inst, inst->width,
 926                                                inst->height);
 927        if (ret)
 928                goto deinit;
 929
 930        ret = venus_helper_set_output_resolution(inst, inst->width,
 931                                                 inst->height,
 932                                                 HFI_BUFFER_OUTPUT);
 933        if (ret)
 934                goto deinit;
 935
 936        ret = venus_helper_set_color_format(inst, inst->fmt_out->pixfmt);
 937        if (ret)
 938                goto deinit;
 939
 940        ret = venc_set_properties(inst);
 941        if (ret)
 942                goto deinit;
 943
 944        return 0;
 945deinit:
 946        hfi_session_deinit(inst);
 947        return ret;
 948}
 949
 950static int venc_out_num_buffers(struct venus_inst *inst, unsigned int *num)
 951{
 952        struct hfi_buffer_requirements bufreq;
 953        int ret;
 954
 955        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
 956        if (ret)
 957                return ret;
 958
 959        *num = bufreq.count_actual;
 960
 961        return 0;
 962}
 963
 964static int venc_queue_setup(struct vb2_queue *q,
 965                            unsigned int *num_buffers, unsigned int *num_planes,
 966                            unsigned int sizes[], struct device *alloc_devs[])
 967{
 968        struct venus_inst *inst = vb2_get_drv_priv(q);
 969        struct venus_core *core = inst->core;
 970        unsigned int num, min = 4;
 971        int ret;
 972
 973        if (*num_planes) {
 974                if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
 975                    *num_planes != inst->fmt_out->num_planes)
 976                        return -EINVAL;
 977
 978                if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
 979                    *num_planes != inst->fmt_cap->num_planes)
 980                        return -EINVAL;
 981
 982                if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
 983                    sizes[0] < inst->input_buf_size)
 984                        return -EINVAL;
 985
 986                if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
 987                    sizes[0] < inst->output_buf_size)
 988                        return -EINVAL;
 989
 990                return 0;
 991        }
 992
 993        if (test_bit(0, &core->sys_error)) {
 994                if (inst->nonblock)
 995                        return -EAGAIN;
 996
 997                ret = wait_event_interruptible(core->sys_err_done,
 998                                               !test_bit(0, &core->sys_error));
 999                if (ret)
1000                        return ret;
1001        }
1002
1003        ret = venc_pm_get(inst);
1004        if (ret)
1005                return ret;
1006
1007        mutex_lock(&inst->lock);
1008        ret = venc_init_session(inst);
1009        mutex_unlock(&inst->lock);
1010
1011        if (ret)
1012                goto put_power;
1013
1014        ret = venc_pm_put(inst, false);
1015        if (ret)
1016                return ret;
1017
1018        switch (q->type) {
1019        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1020                *num_planes = inst->fmt_out->num_planes;
1021
1022                ret = venc_out_num_buffers(inst, &num);
1023                if (ret)
1024                        break;
1025
1026                num = max(num, min);
1027                *num_buffers = max(*num_buffers, num);
1028                inst->num_input_bufs = *num_buffers;
1029
1030                sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt,
1031                                                    inst->out_width,
1032                                                    inst->out_height);
1033                inst->input_buf_size = sizes[0];
1034                break;
1035        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1036                *num_planes = inst->fmt_cap->num_planes;
1037                *num_buffers = max(*num_buffers, min);
1038                inst->num_output_bufs = *num_buffers;
1039                sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt,
1040                                                    inst->width,
1041                                                    inst->height);
1042                sizes[0] = max(sizes[0], inst->output_buf_size);
1043                inst->output_buf_size = sizes[0];
1044                break;
1045        default:
1046                ret = -EINVAL;
1047                break;
1048        }
1049
1050        return ret;
1051put_power:
1052        venc_pm_put(inst, false);
1053        return ret;
1054}
1055
1056static int venc_buf_init(struct vb2_buffer *vb)
1057{
1058        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1059
1060        inst->buf_count++;
1061
1062        return venus_helper_vb2_buf_init(vb);
1063}
1064
1065static void venc_release_session(struct venus_inst *inst)
1066{
1067        int ret;
1068
1069        venc_pm_get(inst);
1070
1071        mutex_lock(&inst->lock);
1072
1073        ret = hfi_session_deinit(inst);
1074        if (ret || inst->session_error)
1075                hfi_session_abort(inst);
1076
1077        mutex_unlock(&inst->lock);
1078
1079        venus_pm_load_scale(inst);
1080        INIT_LIST_HEAD(&inst->registeredbufs);
1081        venus_pm_release_core(inst);
1082
1083        venc_pm_put(inst, false);
1084}
1085
1086static void venc_buf_cleanup(struct vb2_buffer *vb)
1087{
1088        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1089        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1090        struct venus_buffer *buf = to_venus_buffer(vbuf);
1091
1092        mutex_lock(&inst->lock);
1093        if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1094                if (!list_empty(&inst->registeredbufs))
1095                        list_del_init(&buf->reg_list);
1096        mutex_unlock(&inst->lock);
1097
1098        inst->buf_count--;
1099        if (!inst->buf_count)
1100                venc_release_session(inst);
1101}
1102
1103static int venc_verify_conf(struct venus_inst *inst)
1104{
1105        enum hfi_version ver = inst->core->res->hfi_version;
1106        struct hfi_buffer_requirements bufreq;
1107        int ret;
1108
1109        if (!inst->num_input_bufs || !inst->num_output_bufs)
1110                return -EINVAL;
1111
1112        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
1113        if (ret)
1114                return ret;
1115
1116        if (inst->num_output_bufs < bufreq.count_actual ||
1117            inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
1118                return -EINVAL;
1119
1120        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
1121        if (ret)
1122                return ret;
1123
1124        if (inst->num_input_bufs < bufreq.count_actual ||
1125            inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
1126                return -EINVAL;
1127
1128        return 0;
1129}
1130
1131static int venc_start_streaming(struct vb2_queue *q, unsigned int count)
1132{
1133        struct venus_inst *inst = vb2_get_drv_priv(q);
1134        int ret;
1135
1136        mutex_lock(&inst->lock);
1137
1138        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1139                inst->streamon_out = 1;
1140        else
1141                inst->streamon_cap = 1;
1142
1143        if (!(inst->streamon_out & inst->streamon_cap)) {
1144                mutex_unlock(&inst->lock);
1145                return 0;
1146        }
1147
1148        venus_helper_init_instance(inst);
1149
1150        inst->sequence_cap = 0;
1151        inst->sequence_out = 0;
1152
1153        ret = venc_pm_get(inst);
1154        if (ret)
1155                goto error;
1156
1157        ret = venus_pm_acquire_core(inst);
1158        if (ret)
1159                goto put_power;
1160
1161        ret = venc_pm_put(inst, true);
1162        if (ret)
1163                goto error;
1164
1165        ret = venc_set_properties(inst);
1166        if (ret)
1167                goto error;
1168
1169        ret = venc_verify_conf(inst);
1170        if (ret)
1171                goto error;
1172
1173        ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
1174                                        inst->num_output_bufs, 0);
1175        if (ret)
1176                goto error;
1177
1178        ret = venus_helper_vb2_start_streaming(inst);
1179        if (ret)
1180                goto error;
1181
1182        mutex_unlock(&inst->lock);
1183
1184        return 0;
1185
1186put_power:
1187        venc_pm_put(inst, false);
1188error:
1189        venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
1190        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1191                inst->streamon_out = 0;
1192        else
1193                inst->streamon_cap = 0;
1194        mutex_unlock(&inst->lock);
1195        return ret;
1196}
1197
1198static void venc_vb2_buf_queue(struct vb2_buffer *vb)
1199{
1200        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1201
1202        venc_pm_get_put(inst);
1203
1204        mutex_lock(&inst->lock);
1205        venus_helper_vb2_buf_queue(vb);
1206        mutex_unlock(&inst->lock);
1207}
1208
1209static const struct vb2_ops venc_vb2_ops = {
1210        .queue_setup = venc_queue_setup,
1211        .buf_init = venc_buf_init,
1212        .buf_cleanup = venc_buf_cleanup,
1213        .buf_prepare = venus_helper_vb2_buf_prepare,
1214        .start_streaming = venc_start_streaming,
1215        .stop_streaming = venus_helper_vb2_stop_streaming,
1216        .buf_queue = venc_vb2_buf_queue,
1217};
1218
1219static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type,
1220                          u32 tag, u32 bytesused, u32 data_offset, u32 flags,
1221                          u32 hfi_flags, u64 timestamp_us)
1222{
1223        struct vb2_v4l2_buffer *vbuf;
1224        struct vb2_buffer *vb;
1225        unsigned int type;
1226
1227        venc_pm_touch(inst);
1228
1229        if (buf_type == HFI_BUFFER_INPUT)
1230                type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1231        else
1232                type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1233
1234        vbuf = venus_helper_find_buf(inst, type, tag);
1235        if (!vbuf)
1236                return;
1237
1238        vbuf->flags = flags;
1239
1240        if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1241                vb = &vbuf->vb2_buf;
1242                vb2_set_plane_payload(vb, 0, bytesused + data_offset);
1243                vb->planes[0].data_offset = data_offset;
1244                vb->timestamp = timestamp_us * NSEC_PER_USEC;
1245                vbuf->sequence = inst->sequence_cap++;
1246        } else {
1247                vbuf->sequence = inst->sequence_out++;
1248        }
1249
1250        v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
1251}
1252
1253static void venc_event_notify(struct venus_inst *inst, u32 event,
1254                              struct hfi_event_data *data)
1255{
1256        struct device *dev = inst->core->dev_enc;
1257
1258        venc_pm_touch(inst);
1259
1260        if (event == EVT_SESSION_ERROR) {
1261                inst->session_error = true;
1262                venus_helper_vb2_queue_error(inst);
1263                dev_err(dev, "enc: event session error %x\n", inst->error);
1264        }
1265}
1266
1267static const struct hfi_inst_ops venc_hfi_ops = {
1268        .buf_done = venc_buf_done,
1269        .event_notify = venc_event_notify,
1270};
1271
1272static const struct v4l2_m2m_ops venc_m2m_ops = {
1273        .device_run = venus_helper_m2m_device_run,
1274        .job_abort = venus_helper_m2m_job_abort,
1275};
1276
1277static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
1278                          struct vb2_queue *dst_vq)
1279{
1280        struct venus_inst *inst = priv;
1281        int ret;
1282
1283        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1284        src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1285        src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1286        src_vq->ops = &venc_vb2_ops;
1287        src_vq->mem_ops = &vb2_dma_contig_memops;
1288        src_vq->drv_priv = inst;
1289        src_vq->buf_struct_size = sizeof(struct venus_buffer);
1290        src_vq->allow_zero_bytesused = 1;
1291        src_vq->min_buffers_needed = 1;
1292        src_vq->dev = inst->core->dev;
1293        if (inst->core->res->hfi_version == HFI_VERSION_1XX)
1294                src_vq->bidirectional = 1;
1295        ret = vb2_queue_init(src_vq);
1296        if (ret)
1297                return ret;
1298
1299        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1300        dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
1301        dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1302        dst_vq->ops = &venc_vb2_ops;
1303        dst_vq->mem_ops = &vb2_dma_contig_memops;
1304        dst_vq->drv_priv = inst;
1305        dst_vq->buf_struct_size = sizeof(struct venus_buffer);
1306        dst_vq->allow_zero_bytesused = 1;
1307        dst_vq->min_buffers_needed = 1;
1308        dst_vq->dev = inst->core->dev;
1309        return vb2_queue_init(dst_vq);
1310}
1311
1312static void venc_inst_init(struct venus_inst *inst)
1313{
1314        inst->fmt_cap = &venc_formats[3];
1315        inst->fmt_out = &venc_formats[0];
1316        inst->width = 1280;
1317        inst->height = ALIGN(720, 32);
1318        inst->out_width = 1280;
1319        inst->out_height = 720;
1320        inst->fps = 15;
1321        inst->timeperframe.numerator = 1;
1322        inst->timeperframe.denominator = 15;
1323        inst->hfi_codec = HFI_VIDEO_CODEC_H264;
1324}
1325
1326static int venc_open(struct file *file)
1327{
1328        struct venus_core *core = video_drvdata(file);
1329        struct venus_inst *inst;
1330        int ret;
1331
1332        inst = kzalloc(sizeof(*inst), GFP_KERNEL);
1333        if (!inst)
1334                return -ENOMEM;
1335
1336        INIT_LIST_HEAD(&inst->dpbbufs);
1337        INIT_LIST_HEAD(&inst->registeredbufs);
1338        INIT_LIST_HEAD(&inst->internalbufs);
1339        INIT_LIST_HEAD(&inst->list);
1340        mutex_init(&inst->lock);
1341
1342        inst->core = core;
1343        inst->session_type = VIDC_SESSION_TYPE_ENC;
1344        inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
1345        inst->core_acquired = false;
1346        inst->nonblock = file->f_flags & O_NONBLOCK;
1347
1348        venus_helper_init_instance(inst);
1349
1350        ret = venc_ctrl_init(inst);
1351        if (ret)
1352                goto err_free;
1353
1354        ret = hfi_session_create(inst, &venc_hfi_ops);
1355        if (ret)
1356                goto err_ctrl_deinit;
1357
1358        venc_inst_init(inst);
1359
1360        /*
1361         * create m2m device for every instance, the m2m context scheduling
1362         * is made by firmware side so we do not need to care about.
1363         */
1364        inst->m2m_dev = v4l2_m2m_init(&venc_m2m_ops);
1365        if (IS_ERR(inst->m2m_dev)) {
1366                ret = PTR_ERR(inst->m2m_dev);
1367                goto err_session_destroy;
1368        }
1369
1370        inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
1371        if (IS_ERR(inst->m2m_ctx)) {
1372                ret = PTR_ERR(inst->m2m_ctx);
1373                goto err_m2m_release;
1374        }
1375
1376        v4l2_fh_init(&inst->fh, core->vdev_enc);
1377
1378        inst->fh.ctrl_handler = &inst->ctrl_handler;
1379        v4l2_fh_add(&inst->fh);
1380        inst->fh.m2m_ctx = inst->m2m_ctx;
1381        file->private_data = &inst->fh;
1382
1383        return 0;
1384
1385err_m2m_release:
1386        v4l2_m2m_release(inst->m2m_dev);
1387err_session_destroy:
1388        hfi_session_destroy(inst);
1389err_ctrl_deinit:
1390        venc_ctrl_deinit(inst);
1391err_free:
1392        kfree(inst);
1393        return ret;
1394}
1395
1396static int venc_close(struct file *file)
1397{
1398        struct venus_inst *inst = to_inst(file);
1399
1400        venc_pm_get(inst);
1401
1402        v4l2_m2m_ctx_release(inst->m2m_ctx);
1403        v4l2_m2m_release(inst->m2m_dev);
1404        venc_ctrl_deinit(inst);
1405        hfi_session_destroy(inst);
1406        mutex_destroy(&inst->lock);
1407        v4l2_fh_del(&inst->fh);
1408        v4l2_fh_exit(&inst->fh);
1409
1410        venc_pm_put(inst, false);
1411
1412        kfree(inst);
1413        return 0;
1414}
1415
1416static const struct v4l2_file_operations venc_fops = {
1417        .owner = THIS_MODULE,
1418        .open = venc_open,
1419        .release = venc_close,
1420        .unlocked_ioctl = video_ioctl2,
1421        .poll = v4l2_m2m_fop_poll,
1422        .mmap = v4l2_m2m_fop_mmap,
1423};
1424
1425static int venc_probe(struct platform_device *pdev)
1426{
1427        struct device *dev = &pdev->dev;
1428        struct video_device *vdev;
1429        struct venus_core *core;
1430        int ret;
1431
1432        if (!dev->parent)
1433                return -EPROBE_DEFER;
1434
1435        core = dev_get_drvdata(dev->parent);
1436        if (!core)
1437                return -EPROBE_DEFER;
1438
1439        platform_set_drvdata(pdev, core);
1440
1441        if (core->pm_ops->venc_get) {
1442                ret = core->pm_ops->venc_get(dev);
1443                if (ret)
1444                        return ret;
1445        }
1446
1447        vdev = video_device_alloc();
1448        if (!vdev)
1449                return -ENOMEM;
1450
1451        strscpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name));
1452        vdev->release = video_device_release;
1453        vdev->fops = &venc_fops;
1454        vdev->ioctl_ops = &venc_ioctl_ops;
1455        vdev->vfl_dir = VFL_DIR_M2M;
1456        vdev->v4l2_dev = &core->v4l2_dev;
1457        vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
1458
1459        ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1460        if (ret)
1461                goto err_vdev_release;
1462
1463        core->vdev_enc = vdev;
1464        core->dev_enc = dev;
1465
1466        video_set_drvdata(vdev, core);
1467        pm_runtime_set_autosuspend_delay(dev, 2000);
1468        pm_runtime_use_autosuspend(dev);
1469        pm_runtime_enable(dev);
1470
1471        return 0;
1472
1473err_vdev_release:
1474        video_device_release(vdev);
1475        return ret;
1476}
1477
1478static int venc_remove(struct platform_device *pdev)
1479{
1480        struct venus_core *core = dev_get_drvdata(pdev->dev.parent);
1481
1482        video_unregister_device(core->vdev_enc);
1483        pm_runtime_disable(core->dev_enc);
1484
1485        if (core->pm_ops->venc_put)
1486                core->pm_ops->venc_put(core->dev_enc);
1487
1488        return 0;
1489}
1490
1491static __maybe_unused int venc_runtime_suspend(struct device *dev)
1492{
1493        struct venus_core *core = dev_get_drvdata(dev);
1494        const struct venus_pm_ops *pm_ops = core->pm_ops;
1495        int ret = 0;
1496
1497        if (pm_ops->venc_power)
1498                ret = pm_ops->venc_power(dev, POWER_OFF);
1499
1500        return ret;
1501}
1502
1503static __maybe_unused int venc_runtime_resume(struct device *dev)
1504{
1505        struct venus_core *core = dev_get_drvdata(dev);
1506        const struct venus_pm_ops *pm_ops = core->pm_ops;
1507        int ret = 0;
1508
1509        if (pm_ops->venc_power)
1510                ret = pm_ops->venc_power(dev, POWER_ON);
1511
1512        return ret;
1513}
1514
1515static const struct dev_pm_ops venc_pm_ops = {
1516        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1517                                pm_runtime_force_resume)
1518        SET_RUNTIME_PM_OPS(venc_runtime_suspend, venc_runtime_resume, NULL)
1519};
1520
1521static const struct of_device_id venc_dt_match[] = {
1522        { .compatible = "venus-encoder" },
1523        { }
1524};
1525MODULE_DEVICE_TABLE(of, venc_dt_match);
1526
1527static struct platform_driver qcom_venus_enc_driver = {
1528        .probe = venc_probe,
1529        .remove = venc_remove,
1530        .driver = {
1531                .name = "qcom-venus-encoder",
1532                .of_match_table = venc_dt_match,
1533                .pm = &venc_pm_ops,
1534        },
1535};
1536module_platform_driver(qcom_venus_enc_driver);
1537
1538MODULE_ALIAS("platform:qcom-venus-encoder");
1539MODULE_DESCRIPTION("Qualcomm Venus video encoder driver");
1540MODULE_LICENSE("GPL v2");
1541