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