linux/drivers/media/platform/qcom/venus/vdec.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-ioctl.h>
  13#include <media/v4l2-event.h>
  14#include <media/v4l2-ctrls.h>
  15#include <media/v4l2-mem2mem.h>
  16#include <media/videobuf2-dma-contig.h>
  17
  18#include "hfi_venus_io.h"
  19#include "hfi_parser.h"
  20#include "core.h"
  21#include "helpers.h"
  22#include "vdec.h"
  23#include "pm_helpers.h"
  24
  25/*
  26 * Three resons to keep MPLANE formats (despite that the number of planes
  27 * currently is one):
  28 * - the MPLANE formats allow only one plane to be used
  29 * - the downstream driver use MPLANE formats too
  30 * - future firmware versions could add support for >1 planes
  31 */
  32static const struct venus_format vdec_formats[] = {
  33        {
  34                .pixfmt = V4L2_PIX_FMT_QC08C,
  35                .num_planes = 1,
  36                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
  37        }, {
  38                .pixfmt = V4L2_PIX_FMT_QC10C,
  39                .num_planes = 1,
  40                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
  41        },{
  42                .pixfmt = V4L2_PIX_FMT_NV12,
  43                .num_planes = 1,
  44                .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
  45        }, {
  46                .pixfmt = V4L2_PIX_FMT_MPEG4,
  47                .num_planes = 1,
  48                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  49                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
  50        }, {
  51                .pixfmt = V4L2_PIX_FMT_MPEG2,
  52                .num_planes = 1,
  53                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  54                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
  55        }, {
  56                .pixfmt = V4L2_PIX_FMT_H263,
  57                .num_planes = 1,
  58                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  59                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
  60        }, {
  61                .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,
  62                .num_planes = 1,
  63                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  64                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
  65        }, {
  66                .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,
  67                .num_planes = 1,
  68                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  69                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
  70        }, {
  71                .pixfmt = V4L2_PIX_FMT_H264,
  72                .num_planes = 1,
  73                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  74                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
  75        }, {
  76                .pixfmt = V4L2_PIX_FMT_VP8,
  77                .num_planes = 1,
  78                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  79                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
  80        }, {
  81                .pixfmt = V4L2_PIX_FMT_VP9,
  82                .num_planes = 1,
  83                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  84                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
  85        }, {
  86                .pixfmt = V4L2_PIX_FMT_XVID,
  87                .num_planes = 1,
  88                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  89                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
  90        }, {
  91                .pixfmt = V4L2_PIX_FMT_HEVC,
  92                .num_planes = 1,
  93                .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
  94                .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,
  95        },
  96};
  97
  98static const struct venus_format *
  99find_format(struct venus_inst *inst, u32 pixfmt, u32 type)
 100{
 101        const struct venus_format *fmt = vdec_formats;
 102        unsigned int size = ARRAY_SIZE(vdec_formats);
 103        unsigned int i;
 104
 105        for (i = 0; i < size; i++) {
 106                if (fmt[i].pixfmt == pixfmt)
 107                        break;
 108        }
 109
 110        if (i == size || fmt[i].type != type)
 111                return NULL;
 112
 113        if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
 114            !venus_helper_check_codec(inst, fmt[i].pixfmt))
 115                return NULL;
 116
 117        if (V4L2_TYPE_IS_CAPTURE(type) &&
 118            !venus_helper_check_format(inst, fmt[i].pixfmt))
 119                return NULL;
 120
 121        if (V4L2_TYPE_IS_CAPTURE(type) && fmt[i].pixfmt == V4L2_PIX_FMT_QC10C &&
 122            !(inst->bit_depth == VIDC_BITDEPTH_10))
 123                return NULL;
 124
 125        return &fmt[i];
 126}
 127
 128static const struct venus_format *
 129find_format_by_index(struct venus_inst *inst, unsigned int index, u32 type)
 130{
 131        const struct venus_format *fmt = vdec_formats;
 132        unsigned int size = ARRAY_SIZE(vdec_formats);
 133        unsigned int i, k = 0;
 134
 135        if (index > size)
 136                return NULL;
 137
 138        for (i = 0; i < size; i++) {
 139                bool valid;
 140
 141                if (fmt[i].type != type)
 142                        continue;
 143
 144                if (V4L2_TYPE_IS_OUTPUT(type)) {
 145                        valid = venus_helper_check_codec(inst, fmt[i].pixfmt);
 146                } else if (V4L2_TYPE_IS_CAPTURE(type)) {
 147                        valid = venus_helper_check_format(inst, fmt[i].pixfmt);
 148
 149                        if (fmt[i].pixfmt == V4L2_PIX_FMT_QC10C &&
 150                            !(inst->bit_depth == VIDC_BITDEPTH_10))
 151                                valid = false;
 152                }
 153
 154                if (k == index && valid)
 155                        break;
 156                if (valid)
 157                        k++;
 158        }
 159
 160        if (i == size)
 161                return NULL;
 162
 163        return &fmt[i];
 164}
 165
 166static const struct venus_format *
 167vdec_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 szimage;
 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_NV12;
 181                else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 182                        pixmp->pixelformat = V4L2_PIX_FMT_H264;
 183                else
 184                        return NULL;
 185                fmt = find_format(inst, pixmp->pixelformat, f->type);
 186        }
 187
 188        pixmp->width = clamp(pixmp->width, frame_width_min(inst),
 189                             frame_width_max(inst));
 190        pixmp->height = clamp(pixmp->height, frame_height_min(inst),
 191                              frame_height_max(inst));
 192
 193        if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 194                pixmp->height = ALIGN(pixmp->height, 32);
 195
 196        if (pixmp->field == V4L2_FIELD_ANY)
 197                pixmp->field = V4L2_FIELD_NONE;
 198        pixmp->num_planes = fmt->num_planes;
 199        pixmp->flags = 0;
 200
 201        szimage = venus_helper_get_framesz(pixmp->pixelformat, pixmp->width,
 202                                           pixmp->height);
 203
 204        if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 205                pfmt[0].sizeimage = szimage;
 206                pfmt[0].bytesperline = ALIGN(pixmp->width, 128);
 207        } else {
 208                pfmt[0].sizeimage = clamp_t(u32, pfmt[0].sizeimage, 0, SZ_8M);
 209                pfmt[0].sizeimage = max(pfmt[0].sizeimage, szimage);
 210                pfmt[0].bytesperline = 0;
 211        }
 212
 213        return fmt;
 214}
 215
 216static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
 217{
 218        struct venus_inst *inst = to_inst(file);
 219
 220        vdec_try_fmt_common(inst, f);
 221
 222        return 0;
 223}
 224
 225static int vdec_check_src_change(struct venus_inst *inst)
 226{
 227        int ret;
 228
 229        if (inst->subscriptions & V4L2_EVENT_SOURCE_CHANGE &&
 230            inst->codec_state == VENUS_DEC_STATE_INIT &&
 231            !inst->reconfig)
 232                return -EINVAL;
 233
 234        if (inst->subscriptions & V4L2_EVENT_SOURCE_CHANGE)
 235                return 0;
 236
 237        /*
 238         * The code snippet below is a workaround for backward compatibility
 239         * with applications which doesn't support V4L2 events. It will be
 240         * dropped in future once those applications are fixed.
 241         */
 242
 243        if (inst->codec_state != VENUS_DEC_STATE_INIT)
 244                goto done;
 245
 246        ret = wait_event_timeout(inst->reconf_wait, inst->reconfig,
 247                                 msecs_to_jiffies(100));
 248        if (!ret)
 249                return -EINVAL;
 250
 251        if (!(inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) ||
 252            !inst->reconfig)
 253                dev_dbg(inst->core->dev, VDBGH "wrong state\n");
 254
 255done:
 256        return 0;
 257}
 258
 259static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
 260{
 261        struct venus_inst *inst = to_inst(file);
 262        const struct venus_format *fmt = NULL;
 263        struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
 264        int ret;
 265
 266        if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 267                fmt = inst->fmt_cap;
 268        else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 269                fmt = inst->fmt_out;
 270
 271        if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 272                ret = vdec_check_src_change(inst);
 273                if (ret)
 274                        return ret;
 275        }
 276
 277        pixmp->pixelformat = fmt->pixfmt;
 278
 279        if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 280                pixmp->width = inst->width;
 281                pixmp->height = inst->height;
 282                pixmp->colorspace = inst->colorspace;
 283                pixmp->ycbcr_enc = inst->ycbcr_enc;
 284                pixmp->quantization = inst->quantization;
 285                pixmp->xfer_func = inst->xfer_func;
 286        } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 287                pixmp->width = inst->out_width;
 288                pixmp->height = inst->out_height;
 289        }
 290
 291        vdec_try_fmt_common(inst, f);
 292
 293        return 0;
 294}
 295
 296static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
 297{
 298        struct venus_inst *inst = to_inst(file);
 299        struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;
 300        struct v4l2_pix_format_mplane orig_pixmp;
 301        const struct venus_format *fmt;
 302        struct v4l2_format format;
 303        u32 pixfmt_out = 0, pixfmt_cap = 0;
 304        struct vb2_queue *q;
 305
 306        q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type);
 307        if (!q)
 308                return -EINVAL;
 309
 310        if (vb2_is_busy(q))
 311                return -EBUSY;
 312
 313        orig_pixmp = *pixmp;
 314
 315        fmt = vdec_try_fmt_common(inst, f);
 316
 317        if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 318                pixfmt_out = pixmp->pixelformat;
 319                pixfmt_cap = inst->fmt_cap->pixfmt;
 320        } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 321                pixfmt_cap = pixmp->pixelformat;
 322                pixfmt_out = inst->fmt_out->pixfmt;
 323        }
 324
 325        memset(&format, 0, sizeof(format));
 326
 327        format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
 328        format.fmt.pix_mp.pixelformat = pixfmt_out;
 329        format.fmt.pix_mp.width = orig_pixmp.width;
 330        format.fmt.pix_mp.height = orig_pixmp.height;
 331        vdec_try_fmt_common(inst, &format);
 332
 333        if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 334                inst->out_width = format.fmt.pix_mp.width;
 335                inst->out_height = format.fmt.pix_mp.height;
 336                inst->colorspace = pixmp->colorspace;
 337                inst->ycbcr_enc = pixmp->ycbcr_enc;
 338                inst->quantization = pixmp->quantization;
 339                inst->xfer_func = pixmp->xfer_func;
 340                inst->input_buf_size = pixmp->plane_fmt[0].sizeimage;
 341        }
 342
 343        memset(&format, 0, sizeof(format));
 344
 345        format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
 346        format.fmt.pix_mp.pixelformat = pixfmt_cap;
 347        format.fmt.pix_mp.width = orig_pixmp.width;
 348        format.fmt.pix_mp.height = orig_pixmp.height;
 349        vdec_try_fmt_common(inst, &format);
 350
 351        inst->width = format.fmt.pix_mp.width;
 352        inst->height = format.fmt.pix_mp.height;
 353        inst->crop.top = 0;
 354        inst->crop.left = 0;
 355        inst->crop.width = inst->width;
 356        inst->crop.height = inst->height;
 357
 358        if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 359                inst->fmt_out = fmt;
 360        else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 361                inst->fmt_cap = fmt;
 362                inst->output2_buf_size =
 363                        venus_helper_get_framesz(pixfmt_cap, orig_pixmp.width, orig_pixmp.height);
 364        }
 365
 366        return 0;
 367}
 368
 369static int
 370vdec_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
 371{
 372        struct venus_inst *inst = to_inst(file);
 373
 374        if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
 375            s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
 376                return -EINVAL;
 377
 378        s->r.top = 0;
 379        s->r.left = 0;
 380
 381        switch (s->target) {
 382        case V4L2_SEL_TGT_CROP_BOUNDS:
 383        case V4L2_SEL_TGT_CROP_DEFAULT:
 384        case V4L2_SEL_TGT_CROP:
 385                if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
 386                        return -EINVAL;
 387                s->r.width = inst->out_width;
 388                s->r.height = inst->out_height;
 389                break;
 390        case V4L2_SEL_TGT_COMPOSE_BOUNDS:
 391        case V4L2_SEL_TGT_COMPOSE_PADDED:
 392                if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 393                        return -EINVAL;
 394                s->r.width = inst->width;
 395                s->r.height = inst->height;
 396                break;
 397        case V4L2_SEL_TGT_COMPOSE_DEFAULT:
 398        case V4L2_SEL_TGT_COMPOSE:
 399                if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 400                        return -EINVAL;
 401                s->r = inst->crop;
 402                break;
 403        default:
 404                return -EINVAL;
 405        }
 406
 407        return 0;
 408}
 409
 410static int
 411vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
 412{
 413        strscpy(cap->driver, "qcom-venus", sizeof(cap->driver));
 414        strscpy(cap->card, "Qualcomm Venus video decoder", sizeof(cap->card));
 415        strscpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info));
 416
 417        return 0;
 418}
 419
 420static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
 421{
 422        struct venus_inst *inst = to_inst(file);
 423        const struct venus_format *fmt;
 424
 425        memset(f->reserved, 0, sizeof(f->reserved));
 426
 427        fmt = find_format_by_index(inst, f->index, f->type);
 428        if (!fmt)
 429                return -EINVAL;
 430
 431        f->pixelformat = fmt->pixfmt;
 432        f->flags = fmt->flags;
 433
 434        return 0;
 435}
 436
 437static int vdec_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
 438{
 439        struct venus_inst *inst = to_inst(file);
 440        struct v4l2_captureparm *cap = &a->parm.capture;
 441        struct v4l2_fract *timeperframe = &cap->timeperframe;
 442        u64 us_per_frame, fps;
 443
 444        if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
 445            a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 446                return -EINVAL;
 447
 448        memset(cap->reserved, 0, sizeof(cap->reserved));
 449        if (!timeperframe->denominator)
 450                timeperframe->denominator = inst->timeperframe.denominator;
 451        if (!timeperframe->numerator)
 452                timeperframe->numerator = inst->timeperframe.numerator;
 453        cap->readbuffers = 0;
 454        cap->extendedmode = 0;
 455        cap->capability = V4L2_CAP_TIMEPERFRAME;
 456        us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC;
 457        do_div(us_per_frame, timeperframe->denominator);
 458
 459        if (!us_per_frame)
 460                return -EINVAL;
 461
 462        fps = (u64)USEC_PER_SEC;
 463        do_div(fps, us_per_frame);
 464
 465        inst->fps = fps;
 466        inst->timeperframe = *timeperframe;
 467
 468        return 0;
 469}
 470
 471static int vdec_enum_framesizes(struct file *file, void *fh,
 472                                struct v4l2_frmsizeenum *fsize)
 473{
 474        struct venus_inst *inst = to_inst(file);
 475        const struct venus_format *fmt;
 476
 477        fmt = find_format(inst, fsize->pixel_format,
 478                          V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
 479        if (!fmt) {
 480                fmt = find_format(inst, fsize->pixel_format,
 481                                  V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 482                if (!fmt)
 483                        return -EINVAL;
 484        }
 485
 486        if (fsize->index)
 487                return -EINVAL;
 488
 489        fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
 490
 491        fsize->stepwise.min_width = frame_width_min(inst);
 492        fsize->stepwise.max_width = frame_width_max(inst);
 493        fsize->stepwise.step_width = frame_width_step(inst);
 494        fsize->stepwise.min_height = frame_height_min(inst);
 495        fsize->stepwise.max_height = frame_height_max(inst);
 496        fsize->stepwise.step_height = frame_height_step(inst);
 497
 498        return 0;
 499}
 500
 501static int vdec_subscribe_event(struct v4l2_fh *fh,
 502                                const struct v4l2_event_subscription *sub)
 503{
 504        struct venus_inst *inst = container_of(fh, struct venus_inst, fh);
 505        int ret;
 506
 507        switch (sub->type) {
 508        case V4L2_EVENT_EOS:
 509                return v4l2_event_subscribe(fh, sub, 2, NULL);
 510        case V4L2_EVENT_SOURCE_CHANGE:
 511                ret = v4l2_src_change_event_subscribe(fh, sub);
 512                if (ret)
 513                        return ret;
 514                inst->subscriptions |= V4L2_EVENT_SOURCE_CHANGE;
 515                return 0;
 516        case V4L2_EVENT_CTRL:
 517                return v4l2_ctrl_subscribe_event(fh, sub);
 518        default:
 519                return -EINVAL;
 520        }
 521}
 522
 523static int
 524vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
 525{
 526        struct venus_inst *inst = to_inst(file);
 527        struct hfi_frame_data fdata = {0};
 528        int ret;
 529
 530        ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);
 531        if (ret)
 532                return ret;
 533
 534        mutex_lock(&inst->lock);
 535
 536        if (cmd->cmd == V4L2_DEC_CMD_STOP) {
 537                /*
 538                 * Implement V4L2_DEC_CMD_STOP by enqueue an empty buffer on
 539                 * decoder input to signal EOS.
 540                 */
 541                if (!(inst->streamon_out && inst->streamon_cap))
 542                        goto unlock;
 543
 544                fdata.buffer_type = HFI_BUFFER_INPUT;
 545                fdata.flags |= HFI_BUFFERFLAG_EOS;
 546                if (IS_V6(inst->core))
 547                        fdata.device_addr = 0;
 548                else
 549                        fdata.device_addr = 0xdeadb000;
 550
 551                ret = hfi_session_process_buf(inst, &fdata);
 552
 553                if (!ret && inst->codec_state == VENUS_DEC_STATE_DECODING) {
 554                        inst->codec_state = VENUS_DEC_STATE_DRAIN;
 555                        inst->drain_active = true;
 556                }
 557        }
 558
 559unlock:
 560        mutex_unlock(&inst->lock);
 561        return ret;
 562}
 563
 564static const struct v4l2_ioctl_ops vdec_ioctl_ops = {
 565        .vidioc_querycap = vdec_querycap,
 566        .vidioc_enum_fmt_vid_cap = vdec_enum_fmt,
 567        .vidioc_enum_fmt_vid_out = vdec_enum_fmt,
 568        .vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt,
 569        .vidioc_s_fmt_vid_out_mplane = vdec_s_fmt,
 570        .vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt,
 571        .vidioc_g_fmt_vid_out_mplane = vdec_g_fmt,
 572        .vidioc_try_fmt_vid_cap_mplane = vdec_try_fmt,
 573        .vidioc_try_fmt_vid_out_mplane = vdec_try_fmt,
 574        .vidioc_g_selection = vdec_g_selection,
 575        .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
 576        .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
 577        .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
 578        .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
 579        .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
 580        .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
 581        .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
 582        .vidioc_streamon = v4l2_m2m_ioctl_streamon,
 583        .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
 584        .vidioc_s_parm = vdec_s_parm,
 585        .vidioc_enum_framesizes = vdec_enum_framesizes,
 586        .vidioc_subscribe_event = vdec_subscribe_event,
 587        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 588        .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
 589        .vidioc_decoder_cmd = vdec_decoder_cmd,
 590};
 591
 592static int vdec_pm_get(struct venus_inst *inst)
 593{
 594        struct venus_core *core = inst->core;
 595        struct device *dev = core->dev_dec;
 596        int ret;
 597
 598        mutex_lock(&core->pm_lock);
 599        ret = pm_runtime_resume_and_get(dev);
 600        mutex_unlock(&core->pm_lock);
 601
 602        return ret;
 603}
 604
 605static int vdec_pm_put(struct venus_inst *inst, bool autosuspend)
 606{
 607        struct venus_core *core = inst->core;
 608        struct device *dev = core->dev_dec;
 609        int ret;
 610
 611        mutex_lock(&core->pm_lock);
 612
 613        if (autosuspend)
 614                ret = pm_runtime_put_autosuspend(dev);
 615        else
 616                ret = pm_runtime_put_sync(dev);
 617
 618        mutex_unlock(&core->pm_lock);
 619
 620        return ret < 0 ? ret : 0;
 621}
 622
 623static int vdec_pm_get_put(struct venus_inst *inst)
 624{
 625        struct venus_core *core = inst->core;
 626        struct device *dev = core->dev_dec;
 627        int ret = 0;
 628
 629        mutex_lock(&core->pm_lock);
 630
 631        if (pm_runtime_suspended(dev)) {
 632                ret = pm_runtime_resume_and_get(dev);
 633                if (ret < 0)
 634                        goto error;
 635
 636                ret = pm_runtime_put_autosuspend(dev);
 637        }
 638
 639error:
 640        mutex_unlock(&core->pm_lock);
 641
 642        return ret < 0 ? ret : 0;
 643}
 644
 645static void vdec_pm_touch(struct venus_inst *inst)
 646{
 647        pm_runtime_mark_last_busy(inst->core->dev_dec);
 648}
 649
 650static int vdec_set_properties(struct venus_inst *inst)
 651{
 652        struct vdec_controls *ctr = &inst->controls.dec;
 653        struct hfi_enable en = { .enable = 1 };
 654        u32 ptype, decode_order, conceal;
 655        int ret;
 656
 657        if (ctr->post_loop_deb_mode) {
 658                ptype = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
 659                ret = hfi_session_set_property(inst, ptype, &en);
 660                if (ret)
 661                        return ret;
 662        }
 663
 664        if (ctr->display_delay_enable && ctr->display_delay == 0) {
 665                ptype = HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER;
 666                decode_order = HFI_OUTPUT_ORDER_DECODE;
 667                ret = hfi_session_set_property(inst, ptype, &decode_order);
 668                if (ret)
 669                        return ret;
 670        }
 671
 672        ptype = HFI_PROPERTY_PARAM_VDEC_CONCEAL_COLOR;
 673        conceal = ctr->conceal_color & 0xffff;
 674        conceal |= ((ctr->conceal_color >> 16) & 0xffff) << 10;
 675        conceal |= ((ctr->conceal_color >> 32) & 0xffff) << 20;
 676
 677        ret = hfi_session_set_property(inst, ptype, &conceal);
 678        if (ret)
 679                return ret;
 680
 681        return 0;
 682}
 683
 684static int vdec_set_work_route(struct venus_inst *inst)
 685{
 686        u32 ptype = HFI_PROPERTY_PARAM_WORK_ROUTE;
 687        struct hfi_video_work_route wr;
 688
 689        if (!IS_V6(inst->core))
 690                return 0;
 691
 692        wr.video_work_route = inst->core->res->num_vpp_pipes;
 693
 694        return hfi_session_set_property(inst, ptype, &wr);
 695}
 696
 697#define is_ubwc_fmt(fmt) (!!((fmt) & HFI_COLOR_FORMAT_UBWC_BASE))
 698
 699static int vdec_output_conf(struct venus_inst *inst)
 700{
 701        struct venus_core *core = inst->core;
 702        struct hfi_enable en = { .enable = 1 };
 703        struct hfi_buffer_requirements bufreq;
 704        u32 width = inst->width;
 705        u32 height = inst->height;
 706        u32 out_fmt, out2_fmt;
 707        bool ubwc = false;
 708        u32 ptype;
 709        int ret;
 710
 711        ret = venus_helper_set_work_mode(inst);
 712        if (ret)
 713                return ret;
 714
 715        if (core->res->hfi_version == HFI_VERSION_1XX) {
 716                ptype = HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
 717                ret = hfi_session_set_property(inst, ptype, &en);
 718                if (ret)
 719                        return ret;
 720        }
 721
 722        /* Force searching UBWC formats for bigger then HD resolutions */
 723        if (width > 1920 && height > ALIGN(1080, 32))
 724                ubwc = true;
 725
 726        /* For Venus v4/v6 UBWC format is mandatory */
 727        if (IS_V4(core) || IS_V6(core))
 728                ubwc = true;
 729
 730        ret = venus_helper_get_out_fmts(inst, inst->fmt_cap->pixfmt, &out_fmt,
 731                                        &out2_fmt, ubwc);
 732        if (ret)
 733                return ret;
 734
 735        inst->output_buf_size =
 736                        venus_helper_get_framesz_raw(out_fmt, width, height);
 737        inst->output2_buf_size =
 738                        venus_helper_get_framesz_raw(out2_fmt, width, height);
 739
 740        if (is_ubwc_fmt(out_fmt)) {
 741                inst->opb_buftype = HFI_BUFFER_OUTPUT2;
 742                inst->opb_fmt = out2_fmt;
 743                inst->dpb_buftype = HFI_BUFFER_OUTPUT;
 744                inst->dpb_fmt = out_fmt;
 745        } else if (is_ubwc_fmt(out2_fmt)) {
 746                inst->opb_buftype = HFI_BUFFER_OUTPUT;
 747                inst->opb_fmt = out_fmt;
 748                inst->dpb_buftype = HFI_BUFFER_OUTPUT2;
 749                inst->dpb_fmt = out2_fmt;
 750        } else {
 751                inst->opb_buftype = HFI_BUFFER_OUTPUT;
 752                inst->opb_fmt = out_fmt;
 753                inst->dpb_buftype = 0;
 754                inst->dpb_fmt = 0;
 755        }
 756
 757        ret = venus_helper_set_raw_format(inst, inst->opb_fmt,
 758                                          inst->opb_buftype);
 759        if (ret)
 760                return ret;
 761
 762        ret = venus_helper_set_format_constraints(inst);
 763        if (ret)
 764                return ret;
 765
 766        if (inst->dpb_fmt) {
 767                ret = venus_helper_set_multistream(inst, false, true);
 768                if (ret)
 769                        return ret;
 770
 771                ret = venus_helper_set_raw_format(inst, inst->dpb_fmt,
 772                                                  inst->dpb_buftype);
 773                if (ret)
 774                        return ret;
 775
 776                ret = venus_helper_set_output_resolution(inst, width, height,
 777                                                         HFI_BUFFER_OUTPUT2);
 778                if (ret)
 779                        return ret;
 780        }
 781
 782        if (IS_V3(core) || IS_V4(core) || IS_V6(core)) {
 783                ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
 784                if (ret)
 785                        return ret;
 786
 787                if (bufreq.size > inst->output_buf_size)
 788                        return -EINVAL;
 789
 790                if (inst->dpb_fmt) {
 791                        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT2,
 792                                                      &bufreq);
 793                        if (ret)
 794                                return ret;
 795
 796                        if (bufreq.size > inst->output2_buf_size)
 797                                return -EINVAL;
 798                }
 799
 800                if (inst->output2_buf_size) {
 801                        ret = venus_helper_set_bufsize(inst,
 802                                                       inst->output2_buf_size,
 803                                                       HFI_BUFFER_OUTPUT2);
 804                        if (ret)
 805                                return ret;
 806                }
 807
 808                if (inst->output_buf_size) {
 809                        ret = venus_helper_set_bufsize(inst,
 810                                                       inst->output_buf_size,
 811                                                       HFI_BUFFER_OUTPUT);
 812                        if (ret)
 813                                return ret;
 814                }
 815        }
 816
 817        ret = venus_helper_set_dyn_bufmode(inst);
 818        if (ret)
 819                return ret;
 820
 821        return 0;
 822}
 823
 824static int vdec_session_init(struct venus_inst *inst)
 825{
 826        int ret;
 827
 828        ret = venus_helper_session_init(inst);
 829        if (ret == -EALREADY)
 830                return 0;
 831        else if (ret)
 832                return ret;
 833
 834        ret = venus_helper_set_input_resolution(inst, frame_width_min(inst),
 835                                                frame_height_min(inst));
 836        if (ret)
 837                goto deinit;
 838
 839        return 0;
 840deinit:
 841        hfi_session_deinit(inst);
 842        return ret;
 843}
 844
 845static int vdec_num_buffers(struct venus_inst *inst, unsigned int *in_num,
 846                            unsigned int *out_num)
 847{
 848        enum hfi_version ver = inst->core->res->hfi_version;
 849        struct hfi_buffer_requirements bufreq;
 850        int ret;
 851
 852        *in_num = *out_num = 0;
 853
 854        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
 855        if (ret)
 856                return ret;
 857
 858        *in_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
 859
 860        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
 861        if (ret)
 862                return ret;
 863
 864        *out_num = HFI_BUFREQ_COUNT_MIN(&bufreq, ver);
 865
 866        return 0;
 867}
 868
 869static int vdec_queue_setup(struct vb2_queue *q,
 870                            unsigned int *num_buffers, unsigned int *num_planes,
 871                            unsigned int sizes[], struct device *alloc_devs[])
 872{
 873        struct venus_inst *inst = vb2_get_drv_priv(q);
 874        struct venus_core *core = inst->core;
 875        unsigned int in_num, out_num;
 876        int ret = 0;
 877
 878        if (*num_planes) {
 879                unsigned int output_buf_size = venus_helper_get_opb_size(inst);
 880
 881                if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
 882                    *num_planes != inst->fmt_out->num_planes)
 883                        return -EINVAL;
 884
 885                if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
 886                    *num_planes != inst->fmt_cap->num_planes)
 887                        return -EINVAL;
 888
 889                if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
 890                    sizes[0] < inst->input_buf_size)
 891                        return -EINVAL;
 892
 893                if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
 894                    sizes[0] < output_buf_size)
 895                        return -EINVAL;
 896
 897                return 0;
 898        }
 899
 900        if (test_bit(0, &core->sys_error)) {
 901                if (inst->nonblock)
 902                        return -EAGAIN;
 903
 904                ret = wait_event_interruptible(core->sys_err_done,
 905                                               !test_bit(0, &core->sys_error));
 906                if (ret)
 907                        return ret;
 908        }
 909
 910        ret = vdec_pm_get(inst);
 911        if (ret)
 912                return ret;
 913
 914        ret = vdec_session_init(inst);
 915        if (ret)
 916                goto put_power;
 917
 918        ret = vdec_num_buffers(inst, &in_num, &out_num);
 919        if (ret)
 920                goto put_power;
 921
 922        ret = vdec_pm_put(inst, false);
 923        if (ret)
 924                return ret;
 925
 926        switch (q->type) {
 927        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 928                *num_planes = inst->fmt_out->num_planes;
 929                sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt,
 930                                                    inst->out_width,
 931                                                    inst->out_height);
 932                sizes[0] = max(sizes[0], inst->input_buf_size);
 933                inst->input_buf_size = sizes[0];
 934                *num_buffers = max(*num_buffers, in_num);
 935                inst->num_input_bufs = *num_buffers;
 936                inst->num_output_bufs = out_num;
 937                break;
 938        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 939                *num_planes = inst->fmt_cap->num_planes;
 940                sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt,
 941                                                    inst->width,
 942                                                    inst->height);
 943                inst->output_buf_size = sizes[0];
 944                *num_buffers = max(*num_buffers, out_num);
 945                inst->num_output_bufs = *num_buffers;
 946
 947                mutex_lock(&inst->lock);
 948                if (inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP)
 949                        inst->codec_state = VENUS_DEC_STATE_STOPPED;
 950                mutex_unlock(&inst->lock);
 951                break;
 952        default:
 953                ret = -EINVAL;
 954                break;
 955        }
 956
 957        return ret;
 958
 959put_power:
 960        vdec_pm_put(inst, false);
 961        return ret;
 962}
 963
 964static int vdec_verify_conf(struct venus_inst *inst)
 965{
 966        enum hfi_version ver = inst->core->res->hfi_version;
 967        struct hfi_buffer_requirements bufreq;
 968        int ret;
 969
 970        if (!inst->num_input_bufs || !inst->num_output_bufs)
 971                return -EINVAL;
 972
 973        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq);
 974        if (ret)
 975                return ret;
 976
 977        if (inst->num_output_bufs < bufreq.count_actual ||
 978            inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
 979                return -EINVAL;
 980
 981        ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq);
 982        if (ret)
 983                return ret;
 984
 985        if (inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver))
 986                return -EINVAL;
 987
 988        return 0;
 989}
 990
 991static int vdec_start_capture(struct venus_inst *inst)
 992{
 993        int ret;
 994
 995        if (!inst->streamon_out)
 996                return 0;
 997
 998        if (inst->codec_state == VENUS_DEC_STATE_DECODING) {
 999                if (inst->reconfig)
1000                        goto reconfigure;
1001
1002                venus_helper_queue_dpb_bufs(inst);
1003                venus_helper_process_initial_cap_bufs(inst);
1004                inst->streamon_cap = 1;
1005                return 0;
1006        }
1007
1008        if (inst->codec_state != VENUS_DEC_STATE_STOPPED)
1009                return 0;
1010
1011reconfigure:
1012        ret = vdec_output_conf(inst);
1013        if (ret)
1014                return ret;
1015
1016        ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
1017                                        VB2_MAX_FRAME, VB2_MAX_FRAME);
1018        if (ret)
1019                return ret;
1020
1021        ret = venus_helper_intbufs_realloc(inst);
1022        if (ret)
1023                goto err;
1024
1025        venus_pm_load_scale(inst);
1026
1027        inst->next_buf_last = false;
1028
1029        ret = venus_helper_alloc_dpb_bufs(inst);
1030        if (ret)
1031                goto err;
1032
1033        ret = hfi_session_continue(inst);
1034        if (ret)
1035                goto free_dpb_bufs;
1036
1037        ret = venus_helper_queue_dpb_bufs(inst);
1038        if (ret)
1039                goto free_dpb_bufs;
1040
1041        ret = venus_helper_process_initial_cap_bufs(inst);
1042        if (ret)
1043                goto free_dpb_bufs;
1044
1045        inst->codec_state = VENUS_DEC_STATE_DECODING;
1046
1047        if (inst->drain_active)
1048                inst->codec_state = VENUS_DEC_STATE_DRAIN;
1049
1050        inst->streamon_cap = 1;
1051        inst->sequence_cap = 0;
1052        inst->reconfig = false;
1053        inst->drain_active = false;
1054
1055        return 0;
1056
1057free_dpb_bufs:
1058        venus_helper_free_dpb_bufs(inst);
1059err:
1060        return ret;
1061}
1062
1063static int vdec_start_output(struct venus_inst *inst)
1064{
1065        int ret;
1066
1067        if (inst->codec_state == VENUS_DEC_STATE_SEEK) {
1068                ret = venus_helper_process_initial_out_bufs(inst);
1069                if (inst->next_buf_last)
1070                        inst->codec_state = VENUS_DEC_STATE_DRC;
1071                else
1072                        inst->codec_state = VENUS_DEC_STATE_DECODING;
1073                goto done;
1074        }
1075
1076        if (inst->codec_state == VENUS_DEC_STATE_INIT ||
1077            inst->codec_state == VENUS_DEC_STATE_CAPTURE_SETUP) {
1078                ret = venus_helper_process_initial_out_bufs(inst);
1079                goto done;
1080        }
1081
1082        if (inst->codec_state != VENUS_DEC_STATE_DEINIT)
1083                return -EINVAL;
1084
1085        venus_helper_init_instance(inst);
1086        inst->sequence_out = 0;
1087        inst->reconfig = false;
1088        inst->next_buf_last = false;
1089
1090        ret = vdec_set_properties(inst);
1091        if (ret)
1092                return ret;
1093
1094        ret = vdec_set_work_route(inst);
1095        if (ret)
1096                return ret;
1097
1098        ret = vdec_output_conf(inst);
1099        if (ret)
1100                return ret;
1101
1102        ret = vdec_verify_conf(inst);
1103        if (ret)
1104                return ret;
1105
1106        ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs,
1107                                        VB2_MAX_FRAME, VB2_MAX_FRAME);
1108        if (ret)
1109                return ret;
1110
1111        ret = venus_helper_vb2_start_streaming(inst);
1112        if (ret)
1113                return ret;
1114
1115        ret = venus_helper_process_initial_out_bufs(inst);
1116        if (ret)
1117                return ret;
1118
1119        inst->codec_state = VENUS_DEC_STATE_INIT;
1120
1121done:
1122        inst->streamon_out = 1;
1123        return ret;
1124}
1125
1126static int vdec_start_streaming(struct vb2_queue *q, unsigned int count)
1127{
1128        struct venus_inst *inst = vb2_get_drv_priv(q);
1129        int ret;
1130
1131        mutex_lock(&inst->lock);
1132
1133        if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1134                ret = vdec_start_capture(inst);
1135        } else {
1136                ret = vdec_pm_get(inst);
1137                if (ret)
1138                        goto error;
1139
1140                ret = venus_pm_acquire_core(inst);
1141                if (ret)
1142                        goto put_power;
1143
1144                ret = vdec_pm_put(inst, true);
1145                if (ret)
1146                        goto error;
1147
1148                ret = vdec_start_output(inst);
1149        }
1150
1151        if (ret)
1152                goto error;
1153
1154        mutex_unlock(&inst->lock);
1155        return 0;
1156
1157put_power:
1158        vdec_pm_put(inst, false);
1159error:
1160        venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_QUEUED);
1161        mutex_unlock(&inst->lock);
1162        return ret;
1163}
1164
1165static void vdec_cancel_dst_buffers(struct venus_inst *inst)
1166{
1167        struct vb2_v4l2_buffer *buf;
1168
1169        while ((buf = v4l2_m2m_dst_buf_remove(inst->m2m_ctx)))
1170                v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
1171}
1172
1173static int vdec_stop_capture(struct venus_inst *inst)
1174{
1175        int ret = 0;
1176
1177        switch (inst->codec_state) {
1178        case VENUS_DEC_STATE_DECODING:
1179                ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true);
1180                fallthrough;
1181        case VENUS_DEC_STATE_DRAIN:
1182                inst->codec_state = VENUS_DEC_STATE_STOPPED;
1183                inst->drain_active = false;
1184                fallthrough;
1185        case VENUS_DEC_STATE_SEEK:
1186                vdec_cancel_dst_buffers(inst);
1187                break;
1188        case VENUS_DEC_STATE_DRC:
1189                ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, true);
1190                inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
1191                venus_helper_free_dpb_bufs(inst);
1192                break;
1193        default:
1194                break;
1195        }
1196
1197        return ret;
1198}
1199
1200static int vdec_stop_output(struct venus_inst *inst)
1201{
1202        int ret = 0;
1203
1204        switch (inst->codec_state) {
1205        case VENUS_DEC_STATE_DECODING:
1206        case VENUS_DEC_STATE_DRAIN:
1207        case VENUS_DEC_STATE_STOPPED:
1208        case VENUS_DEC_STATE_DRC:
1209                ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true);
1210                inst->codec_state = VENUS_DEC_STATE_SEEK;
1211                break;
1212        case VENUS_DEC_STATE_INIT:
1213        case VENUS_DEC_STATE_CAPTURE_SETUP:
1214                ret = hfi_session_flush(inst, HFI_FLUSH_INPUT, true);
1215                break;
1216        default:
1217                break;
1218        }
1219
1220        return ret;
1221}
1222
1223static void vdec_stop_streaming(struct vb2_queue *q)
1224{
1225        struct venus_inst *inst = vb2_get_drv_priv(q);
1226        int ret = -EINVAL;
1227
1228        vdec_pm_get_put(inst);
1229
1230        mutex_lock(&inst->lock);
1231
1232        if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1233                ret = vdec_stop_capture(inst);
1234        else
1235                ret = vdec_stop_output(inst);
1236
1237        venus_helper_buffers_done(inst, q->type, VB2_BUF_STATE_ERROR);
1238
1239        inst->session_error = 0;
1240
1241        if (ret)
1242                goto unlock;
1243
1244        if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
1245                inst->streamon_out = 0;
1246        else
1247                inst->streamon_cap = 0;
1248
1249unlock:
1250        mutex_unlock(&inst->lock);
1251}
1252
1253static void vdec_session_release(struct venus_inst *inst)
1254{
1255        struct venus_core *core = inst->core;
1256        int ret, abort = 0;
1257
1258        vdec_pm_get(inst);
1259
1260        mutex_lock(&inst->lock);
1261        inst->codec_state = VENUS_DEC_STATE_DEINIT;
1262
1263        ret = hfi_session_stop(inst);
1264        abort = (ret && ret != -EINVAL) ? 1 : 0;
1265        ret = hfi_session_unload_res(inst);
1266        abort = (ret && ret != -EINVAL) ? 1 : 0;
1267        ret = venus_helper_unregister_bufs(inst);
1268        abort = (ret && ret != -EINVAL) ? 1 : 0;
1269        ret = venus_helper_intbufs_free(inst);
1270        abort = (ret && ret != -EINVAL) ? 1 : 0;
1271        ret = hfi_session_deinit(inst);
1272        abort = (ret && ret != -EINVAL) ? 1 : 0;
1273
1274        if (inst->session_error || test_bit(0, &core->sys_error))
1275                abort = 1;
1276
1277        if (abort)
1278                hfi_session_abort(inst);
1279
1280        venus_helper_free_dpb_bufs(inst);
1281        venus_pm_load_scale(inst);
1282        INIT_LIST_HEAD(&inst->registeredbufs);
1283        mutex_unlock(&inst->lock);
1284
1285        venus_pm_release_core(inst);
1286        vdec_pm_put(inst, false);
1287}
1288
1289static int vdec_buf_init(struct vb2_buffer *vb)
1290{
1291        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1292
1293        inst->buf_count++;
1294
1295        return venus_helper_vb2_buf_init(vb);
1296}
1297
1298static void vdec_buf_cleanup(struct vb2_buffer *vb)
1299{
1300        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1301        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1302        struct venus_buffer *buf = to_venus_buffer(vbuf);
1303
1304        mutex_lock(&inst->lock);
1305        if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
1306                if (!list_empty(&inst->registeredbufs))
1307                        list_del_init(&buf->reg_list);
1308        mutex_unlock(&inst->lock);
1309
1310        inst->buf_count--;
1311        if (!inst->buf_count)
1312                vdec_session_release(inst);
1313}
1314
1315static void vdec_vb2_buf_queue(struct vb2_buffer *vb)
1316{
1317        struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
1318        struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1319        static const struct v4l2_event eos = { .type = V4L2_EVENT_EOS };
1320
1321        vdec_pm_get_put(inst);
1322
1323        mutex_lock(&inst->lock);
1324
1325        if (inst->next_buf_last && V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&
1326            inst->codec_state == VENUS_DEC_STATE_DRC) {
1327                vbuf->flags |= V4L2_BUF_FLAG_LAST;
1328                vbuf->sequence = inst->sequence_cap++;
1329                vbuf->field = V4L2_FIELD_NONE;
1330                vb2_set_plane_payload(vb, 0, 0);
1331                v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
1332                v4l2_event_queue_fh(&inst->fh, &eos);
1333                inst->next_buf_last = false;
1334                mutex_unlock(&inst->lock);
1335                return;
1336        }
1337
1338        venus_helper_vb2_buf_queue(vb);
1339        mutex_unlock(&inst->lock);
1340}
1341
1342static const struct vb2_ops vdec_vb2_ops = {
1343        .queue_setup = vdec_queue_setup,
1344        .buf_init = vdec_buf_init,
1345        .buf_cleanup = vdec_buf_cleanup,
1346        .buf_prepare = venus_helper_vb2_buf_prepare,
1347        .start_streaming = vdec_start_streaming,
1348        .stop_streaming = vdec_stop_streaming,
1349        .buf_queue = vdec_vb2_buf_queue,
1350};
1351
1352static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
1353                          u32 tag, u32 bytesused, u32 data_offset, u32 flags,
1354                          u32 hfi_flags, u64 timestamp_us)
1355{
1356        enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
1357        struct vb2_v4l2_buffer *vbuf;
1358        struct vb2_buffer *vb;
1359        unsigned int type;
1360
1361        vdec_pm_touch(inst);
1362
1363        if (buf_type == HFI_BUFFER_INPUT)
1364                type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1365        else
1366                type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1367
1368        vbuf = venus_helper_find_buf(inst, type, tag);
1369        if (!vbuf) {
1370                venus_helper_change_dpb_owner(inst, vbuf, type, buf_type, tag);
1371                return;
1372        }
1373
1374        vbuf->flags = flags;
1375        vbuf->field = V4L2_FIELD_NONE;
1376        vb = &vbuf->vb2_buf;
1377
1378        if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
1379                vb2_set_plane_payload(vb, 0, bytesused);
1380                vb->planes[0].data_offset = data_offset;
1381                vb->timestamp = timestamp_us * NSEC_PER_USEC;
1382                vbuf->sequence = inst->sequence_cap++;
1383
1384                if (vbuf->flags & V4L2_BUF_FLAG_LAST) {
1385                        const struct v4l2_event ev = { .type = V4L2_EVENT_EOS };
1386
1387                        v4l2_event_queue_fh(&inst->fh, &ev);
1388
1389                        if (inst->codec_state == VENUS_DEC_STATE_DRAIN) {
1390                                inst->drain_active = false;
1391                                inst->codec_state = VENUS_DEC_STATE_STOPPED;
1392                        }
1393                }
1394
1395                if (!bytesused)
1396                        state = VB2_BUF_STATE_ERROR;
1397        } else {
1398                vbuf->sequence = inst->sequence_out++;
1399        }
1400
1401        venus_helper_get_ts_metadata(inst, timestamp_us, vbuf);
1402
1403        if (hfi_flags & HFI_BUFFERFLAG_READONLY)
1404                venus_helper_acquire_buf_ref(vbuf);
1405
1406        if (hfi_flags & HFI_BUFFERFLAG_DATACORRUPT)
1407                state = VB2_BUF_STATE_ERROR;
1408
1409        if (hfi_flags & HFI_BUFFERFLAG_DROP_FRAME) {
1410                state = VB2_BUF_STATE_ERROR;
1411                vb2_set_plane_payload(vb, 0, 0);
1412                vb->timestamp = 0;
1413        }
1414
1415        v4l2_m2m_buf_done(vbuf, state);
1416}
1417
1418static void vdec_event_change(struct venus_inst *inst,
1419                              struct hfi_event_data *ev_data, bool sufficient)
1420{
1421        static const struct v4l2_event ev = {
1422                .type = V4L2_EVENT_SOURCE_CHANGE,
1423                .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION };
1424        struct device *dev = inst->core->dev_dec;
1425        struct v4l2_format format = {};
1426
1427        mutex_lock(&inst->lock);
1428
1429        format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1430        format.fmt.pix_mp.pixelformat = inst->fmt_cap->pixfmt;
1431        format.fmt.pix_mp.width = ev_data->width;
1432        format.fmt.pix_mp.height = ev_data->height;
1433
1434        vdec_try_fmt_common(inst, &format);
1435
1436        inst->width = format.fmt.pix_mp.width;
1437        inst->height = format.fmt.pix_mp.height;
1438        /*
1439         * Some versions of the firmware do not report crop information for
1440         * all codecs. For these cases, set the crop to the coded resolution.
1441         */
1442        if (ev_data->input_crop.width > 0 && ev_data->input_crop.height > 0) {
1443                inst->crop.left = ev_data->input_crop.left;
1444                inst->crop.top = ev_data->input_crop.top;
1445                inst->crop.width = ev_data->input_crop.width;
1446                inst->crop.height = ev_data->input_crop.height;
1447        } else {
1448                inst->crop.left = 0;
1449                inst->crop.top = 0;
1450                inst->crop.width = ev_data->width;
1451                inst->crop.height = ev_data->height;
1452        }
1453
1454        inst->fw_min_cnt = ev_data->buf_count;
1455        /* overwriting this to 11 for vp9 due to fw bug */
1456        if (inst->hfi_codec == HFI_VIDEO_CODEC_VP9)
1457                inst->fw_min_cnt = 11;
1458
1459        inst->out_width = ev_data->width;
1460        inst->out_height = ev_data->height;
1461
1462        if (inst->bit_depth != ev_data->bit_depth)
1463                inst->bit_depth = ev_data->bit_depth;
1464
1465        if (inst->pic_struct != ev_data->pic_struct)
1466                inst->pic_struct = ev_data->pic_struct;
1467
1468        dev_dbg(dev, VDBGM "event %s sufficient resources (%ux%u)\n",
1469                sufficient ? "" : "not", ev_data->width, ev_data->height);
1470
1471        switch (inst->codec_state) {
1472        case VENUS_DEC_STATE_INIT:
1473                inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
1474                break;
1475        case VENUS_DEC_STATE_DECODING:
1476        case VENUS_DEC_STATE_DRAIN:
1477                inst->codec_state = VENUS_DEC_STATE_DRC;
1478                break;
1479        default:
1480                break;
1481        }
1482
1483        /*
1484         * The assumption is that the firmware have to return the last buffer
1485         * before this event is received in the v4l2 driver. Also the firmware
1486         * itself doesn't mark the last decoder output buffer with HFI EOS flag.
1487         */
1488
1489        if (inst->codec_state == VENUS_DEC_STATE_DRC) {
1490                int ret;
1491
1492                inst->next_buf_last = true;
1493
1494                ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT, false);
1495                if (ret)
1496                        dev_dbg(dev, VDBGH "flush output error %d\n", ret);
1497        }
1498
1499        inst->next_buf_last = true;
1500        inst->reconfig = true;
1501        v4l2_event_queue_fh(&inst->fh, &ev);
1502        wake_up(&inst->reconf_wait);
1503
1504        mutex_unlock(&inst->lock);
1505}
1506
1507static void vdec_event_notify(struct venus_inst *inst, u32 event,
1508                              struct hfi_event_data *data)
1509{
1510        struct venus_core *core = inst->core;
1511        struct device *dev = core->dev_dec;
1512
1513        vdec_pm_touch(inst);
1514
1515        switch (event) {
1516        case EVT_SESSION_ERROR:
1517                inst->session_error = true;
1518                venus_helper_vb2_queue_error(inst);
1519                dev_err(dev, "dec: event session error %x\n", inst->error);
1520                break;
1521        case EVT_SYS_EVENT_CHANGE:
1522                switch (data->event_type) {
1523                case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES:
1524                        vdec_event_change(inst, data, true);
1525                        break;
1526                case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES:
1527                        vdec_event_change(inst, data, false);
1528                        break;
1529                case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
1530                        venus_helper_release_buf_ref(inst, data->tag);
1531                        break;
1532                default:
1533                        break;
1534                }
1535                break;
1536        default:
1537                break;
1538        }
1539}
1540
1541static void vdec_flush_done(struct venus_inst *inst)
1542{
1543        dev_dbg(inst->core->dev_dec, VDBGH "flush done\n");
1544}
1545
1546static const struct hfi_inst_ops vdec_hfi_ops = {
1547        .buf_done = vdec_buf_done,
1548        .event_notify = vdec_event_notify,
1549        .flush_done = vdec_flush_done,
1550};
1551
1552static void vdec_inst_init(struct venus_inst *inst)
1553{
1554        inst->hfi_codec = HFI_VIDEO_CODEC_H264;
1555        inst->fmt_out = &vdec_formats[8];
1556        inst->fmt_cap = &vdec_formats[0];
1557        inst->width = frame_width_min(inst);
1558        inst->height = ALIGN(frame_height_min(inst), 32);
1559        inst->crop.left = 0;
1560        inst->crop.top = 0;
1561        inst->crop.width = inst->width;
1562        inst->crop.height = inst->height;
1563        inst->fw_min_cnt = 8;
1564        inst->out_width = frame_width_min(inst);
1565        inst->out_height = frame_height_min(inst);
1566        inst->fps = 30;
1567        inst->timeperframe.numerator = 1;
1568        inst->timeperframe.denominator = 30;
1569        inst->opb_buftype = HFI_BUFFER_OUTPUT;
1570}
1571
1572static void vdec_m2m_device_run(void *priv)
1573{
1574}
1575
1576static const struct v4l2_m2m_ops vdec_m2m_ops = {
1577        .device_run = vdec_m2m_device_run,
1578        .job_abort = venus_helper_m2m_job_abort,
1579};
1580
1581static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
1582                          struct vb2_queue *dst_vq)
1583{
1584        struct venus_inst *inst = priv;
1585        int ret;
1586
1587        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1588        src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
1589        src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1590        src_vq->ops = &vdec_vb2_ops;
1591        src_vq->mem_ops = &vb2_dma_contig_memops;
1592        src_vq->drv_priv = inst;
1593        src_vq->buf_struct_size = sizeof(struct venus_buffer);
1594        src_vq->allow_zero_bytesused = 1;
1595        src_vq->min_buffers_needed = 0;
1596        src_vq->dev = inst->core->dev;
1597        ret = vb2_queue_init(src_vq);
1598        if (ret)
1599                return ret;
1600
1601        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1602        dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
1603        dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
1604        dst_vq->ops = &vdec_vb2_ops;
1605        dst_vq->mem_ops = &vb2_dma_contig_memops;
1606        dst_vq->drv_priv = inst;
1607        dst_vq->buf_struct_size = sizeof(struct venus_buffer);
1608        dst_vq->allow_zero_bytesused = 1;
1609        dst_vq->min_buffers_needed = 0;
1610        dst_vq->dev = inst->core->dev;
1611        return vb2_queue_init(dst_vq);
1612}
1613
1614static int vdec_open(struct file *file)
1615{
1616        struct venus_core *core = video_drvdata(file);
1617        struct venus_inst *inst;
1618        int ret;
1619
1620        inst = kzalloc(sizeof(*inst), GFP_KERNEL);
1621        if (!inst)
1622                return -ENOMEM;
1623
1624        INIT_LIST_HEAD(&inst->dpbbufs);
1625        INIT_LIST_HEAD(&inst->registeredbufs);
1626        INIT_LIST_HEAD(&inst->internalbufs);
1627        INIT_LIST_HEAD(&inst->list);
1628        mutex_init(&inst->lock);
1629
1630        inst->core = core;
1631        inst->session_type = VIDC_SESSION_TYPE_DEC;
1632        inst->num_output_bufs = 1;
1633        inst->codec_state = VENUS_DEC_STATE_DEINIT;
1634        inst->buf_count = 0;
1635        inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
1636        inst->core_acquired = false;
1637        inst->bit_depth = VIDC_BITDEPTH_8;
1638        inst->pic_struct = HFI_INTERLACE_FRAME_PROGRESSIVE;
1639        init_waitqueue_head(&inst->reconf_wait);
1640        inst->nonblock = file->f_flags & O_NONBLOCK;
1641
1642        venus_helper_init_instance(inst);
1643
1644        ret = vdec_ctrl_init(inst);
1645        if (ret)
1646                goto err_free;
1647
1648        ret = hfi_session_create(inst, &vdec_hfi_ops);
1649        if (ret)
1650                goto err_ctrl_deinit;
1651
1652        vdec_inst_init(inst);
1653
1654        ida_init(&inst->dpb_ids);
1655
1656        /*
1657         * create m2m device for every instance, the m2m context scheduling
1658         * is made by firmware side so we do not need to care about.
1659         */
1660        inst->m2m_dev = v4l2_m2m_init(&vdec_m2m_ops);
1661        if (IS_ERR(inst->m2m_dev)) {
1662                ret = PTR_ERR(inst->m2m_dev);
1663                goto err_session_destroy;
1664        }
1665
1666        inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
1667        if (IS_ERR(inst->m2m_ctx)) {
1668                ret = PTR_ERR(inst->m2m_ctx);
1669                goto err_m2m_release;
1670        }
1671
1672        v4l2_fh_init(&inst->fh, core->vdev_dec);
1673
1674        inst->fh.ctrl_handler = &inst->ctrl_handler;
1675        v4l2_fh_add(&inst->fh);
1676        inst->fh.m2m_ctx = inst->m2m_ctx;
1677        file->private_data = &inst->fh;
1678
1679        return 0;
1680
1681err_m2m_release:
1682        v4l2_m2m_release(inst->m2m_dev);
1683err_session_destroy:
1684        hfi_session_destroy(inst);
1685err_ctrl_deinit:
1686        vdec_ctrl_deinit(inst);
1687err_free:
1688        kfree(inst);
1689        return ret;
1690}
1691
1692static int vdec_close(struct file *file)
1693{
1694        struct venus_inst *inst = to_inst(file);
1695
1696        vdec_pm_get(inst);
1697
1698        v4l2_m2m_ctx_release(inst->m2m_ctx);
1699        v4l2_m2m_release(inst->m2m_dev);
1700        vdec_ctrl_deinit(inst);
1701        ida_destroy(&inst->dpb_ids);
1702        hfi_session_destroy(inst);
1703        mutex_destroy(&inst->lock);
1704        v4l2_fh_del(&inst->fh);
1705        v4l2_fh_exit(&inst->fh);
1706
1707        vdec_pm_put(inst, false);
1708
1709        kfree(inst);
1710        return 0;
1711}
1712
1713static const struct v4l2_file_operations vdec_fops = {
1714        .owner = THIS_MODULE,
1715        .open = vdec_open,
1716        .release = vdec_close,
1717        .unlocked_ioctl = video_ioctl2,
1718        .poll = v4l2_m2m_fop_poll,
1719        .mmap = v4l2_m2m_fop_mmap,
1720};
1721
1722static int vdec_probe(struct platform_device *pdev)
1723{
1724        struct device *dev = &pdev->dev;
1725        struct video_device *vdev;
1726        struct venus_core *core;
1727        int ret;
1728
1729        if (!dev->parent)
1730                return -EPROBE_DEFER;
1731
1732        core = dev_get_drvdata(dev->parent);
1733        if (!core)
1734                return -EPROBE_DEFER;
1735
1736        platform_set_drvdata(pdev, core);
1737
1738        if (core->pm_ops->vdec_get) {
1739                ret = core->pm_ops->vdec_get(dev);
1740                if (ret)
1741                        return ret;
1742        }
1743
1744        vdev = video_device_alloc();
1745        if (!vdev)
1746                return -ENOMEM;
1747
1748        strscpy(vdev->name, "qcom-venus-decoder", sizeof(vdev->name));
1749        vdev->release = video_device_release;
1750        vdev->fops = &vdec_fops;
1751        vdev->ioctl_ops = &vdec_ioctl_ops;
1752        vdev->vfl_dir = VFL_DIR_M2M;
1753        vdev->v4l2_dev = &core->v4l2_dev;
1754        vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
1755
1756        ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1757        if (ret)
1758                goto err_vdev_release;
1759
1760        core->vdev_dec = vdev;
1761        core->dev_dec = dev;
1762
1763        video_set_drvdata(vdev, core);
1764        pm_runtime_set_autosuspend_delay(dev, 2000);
1765        pm_runtime_use_autosuspend(dev);
1766        pm_runtime_enable(dev);
1767
1768        return 0;
1769
1770err_vdev_release:
1771        video_device_release(vdev);
1772        return ret;
1773}
1774
1775static int vdec_remove(struct platform_device *pdev)
1776{
1777        struct venus_core *core = dev_get_drvdata(pdev->dev.parent);
1778
1779        video_unregister_device(core->vdev_dec);
1780        pm_runtime_disable(core->dev_dec);
1781
1782        if (core->pm_ops->vdec_put)
1783                core->pm_ops->vdec_put(core->dev_dec);
1784
1785        return 0;
1786}
1787
1788static __maybe_unused int vdec_runtime_suspend(struct device *dev)
1789{
1790        struct venus_core *core = dev_get_drvdata(dev);
1791        const struct venus_pm_ops *pm_ops = core->pm_ops;
1792        int ret = 0;
1793
1794        if (pm_ops->vdec_power)
1795                ret = pm_ops->vdec_power(dev, POWER_OFF);
1796
1797        return ret;
1798}
1799
1800static __maybe_unused int vdec_runtime_resume(struct device *dev)
1801{
1802        struct venus_core *core = dev_get_drvdata(dev);
1803        const struct venus_pm_ops *pm_ops = core->pm_ops;
1804        int ret = 0;
1805
1806        if (pm_ops->vdec_power)
1807                ret = pm_ops->vdec_power(dev, POWER_ON);
1808
1809        return ret;
1810}
1811
1812static const struct dev_pm_ops vdec_pm_ops = {
1813        SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1814                                pm_runtime_force_resume)
1815        SET_RUNTIME_PM_OPS(vdec_runtime_suspend, vdec_runtime_resume, NULL)
1816};
1817
1818static const struct of_device_id vdec_dt_match[] = {
1819        { .compatible = "venus-decoder" },
1820        { }
1821};
1822MODULE_DEVICE_TABLE(of, vdec_dt_match);
1823
1824static struct platform_driver qcom_venus_dec_driver = {
1825        .probe = vdec_probe,
1826        .remove = vdec_remove,
1827        .driver = {
1828                .name = "qcom-venus-decoder",
1829                .of_match_table = vdec_dt_match,
1830                .pm = &vdec_pm_ops,
1831        },
1832};
1833module_platform_driver(qcom_venus_dec_driver);
1834
1835MODULE_ALIAS("platform:qcom-venus-decoder");
1836MODULE_DESCRIPTION("Qualcomm Venus video decoder driver");
1837MODULE_LICENSE("GPL v2");
1838