1766 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright 2020-2021 NXP4 */5 6#include <linux/init.h>7#include <linux/interconnect.h>8#include <linux/ioctl.h>9#include <linux/list.h>10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/vmalloc.h>13#include <linux/videodev2.h>14#include <media/v4l2-device.h>15#include <media/v4l2-event.h>16#include <media/v4l2-mem2mem.h>17#include <media/v4l2-ioctl.h>18#include <media/videobuf2-v4l2.h>19#include <media/videobuf2-dma-contig.h>20#include <media/videobuf2-vmalloc.h>21#include "vpu.h"22#include "vpu_defs.h"23#include "vpu_core.h"24#include "vpu_helpers.h"25#include "vpu_v4l2.h"26#include "vpu_cmds.h"27#include "vpu_rpc.h"28 29#define VDEC_MIN_BUFFER_CAP 830#define VDEC_MIN_BUFFER_OUT 831 32struct vdec_fs_info {33 char name[8];34 u32 type;35 u32 max_count;36 u32 req_count;37 u32 count;38 u32 index;39 u32 size;40 struct vpu_buffer buffer[32];41 u32 tag;42};43 44struct vdec_t {45 u32 seq_hdr_found;46 struct vpu_buffer udata;47 struct vpu_decode_params params;48 struct vpu_dec_codec_info codec_info;49 enum vpu_codec_state state;50 51 struct vpu_vb2_buffer *slots[VB2_MAX_FRAME];52 u32 req_frame_count;53 struct vdec_fs_info mbi;54 struct vdec_fs_info dcp;55 u32 seq_tag;56 57 bool reset_codec;58 bool fixed_fmt;59 u32 decoded_frame_count;60 u32 display_frame_count;61 u32 sequence;62 u32 eos_received;63 bool is_source_changed;64 u32 source_change;65 u32 drain;66 bool aborting;67};68 69static const struct vpu_format vdec_formats[] = {70 {71 .pixfmt = V4L2_PIX_FMT_NV12M_8L128,72 .mem_planes = 2,73 .comp_planes = 2,74 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,75 .sibling = V4L2_PIX_FMT_NV12_8L128,76 },77 {78 .pixfmt = V4L2_PIX_FMT_NV12_8L128,79 .mem_planes = 1,80 .comp_planes = 2,81 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,82 .sibling = V4L2_PIX_FMT_NV12M_8L128,83 },84 {85 .pixfmt = V4L2_PIX_FMT_NV12M_10BE_8L128,86 .mem_planes = 2,87 .comp_planes = 2,88 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,89 .sibling = V4L2_PIX_FMT_NV12_10BE_8L128,90 },91 {92 .pixfmt = V4L2_PIX_FMT_NV12_10BE_8L128,93 .mem_planes = 1,94 .comp_planes = 2,95 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,96 .sibling = V4L2_PIX_FMT_NV12M_10BE_8L12897 },98 {99 .pixfmt = V4L2_PIX_FMT_H264,100 .mem_planes = 1,101 .comp_planes = 1,102 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,103 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED104 },105 {106 .pixfmt = V4L2_PIX_FMT_H264_MVC,107 .mem_planes = 1,108 .comp_planes = 1,109 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,110 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED111 },112 {113 .pixfmt = V4L2_PIX_FMT_HEVC,114 .mem_planes = 1,115 .comp_planes = 1,116 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,117 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED118 },119 {120 .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_G,121 .mem_planes = 1,122 .comp_planes = 1,123 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,124 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED125 },126 {127 .pixfmt = V4L2_PIX_FMT_VC1_ANNEX_L,128 .mem_planes = 1,129 .comp_planes = 1,130 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,131 .flags = V4L2_FMT_FLAG_COMPRESSED132 },133 {134 .pixfmt = V4L2_PIX_FMT_MPEG2,135 .mem_planes = 1,136 .comp_planes = 1,137 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,138 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED139 },140 {141 .pixfmt = V4L2_PIX_FMT_MPEG4,142 .mem_planes = 1,143 .comp_planes = 1,144 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,145 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED146 },147 {148 .pixfmt = V4L2_PIX_FMT_XVID,149 .mem_planes = 1,150 .comp_planes = 1,151 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,152 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED153 },154 {155 .pixfmt = V4L2_PIX_FMT_VP8,156 .mem_planes = 1,157 .comp_planes = 1,158 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,159 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED160 },161 {162 .pixfmt = V4L2_PIX_FMT_H263,163 .mem_planes = 1,164 .comp_planes = 1,165 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,166 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED167 },168 {169 .pixfmt = V4L2_PIX_FMT_SPK,170 .mem_planes = 1,171 .comp_planes = 1,172 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,173 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED174 },175 {176 .pixfmt = V4L2_PIX_FMT_RV30,177 .mem_planes = 1,178 .comp_planes = 1,179 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,180 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED181 },182 {183 .pixfmt = V4L2_PIX_FMT_RV40,184 .mem_planes = 1,185 .comp_planes = 1,186 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,187 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION | V4L2_FMT_FLAG_COMPRESSED188 },189 {0, 0, 0, 0},190};191 192static int vdec_op_s_ctrl(struct v4l2_ctrl *ctrl)193{194 struct vpu_inst *inst = ctrl_to_inst(ctrl);195 struct vdec_t *vdec = inst->priv;196 int ret = 0;197 198 switch (ctrl->id) {199 case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:200 vdec->params.display_delay_enable = ctrl->val;201 break;202 case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:203 vdec->params.display_delay = ctrl->val;204 break;205 default:206 ret = -EINVAL;207 break;208 }209 210 return ret;211}212 213static const struct v4l2_ctrl_ops vdec_ctrl_ops = {214 .s_ctrl = vdec_op_s_ctrl,215 .g_volatile_ctrl = vpu_helper_g_volatile_ctrl,216};217 218static int vdec_ctrl_init(struct vpu_inst *inst)219{220 struct v4l2_ctrl *ctrl;221 int ret;222 223 ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 20);224 if (ret)225 return ret;226 227 v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,228 V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,229 0, 0, 1, 0);230 231 v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,232 V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,233 0, 1, 1, 0);234 235 ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,236 V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 2);237 if (ctrl)238 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;239 240 ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, &vdec_ctrl_ops,241 V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 2);242 if (ctrl)243 ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;244 245 if (inst->ctrl_handler.error) {246 ret = inst->ctrl_handler.error;247 v4l2_ctrl_handler_free(&inst->ctrl_handler);248 return ret;249 }250 251 ret = v4l2_ctrl_handler_setup(&inst->ctrl_handler);252 if (ret) {253 dev_err(inst->dev, "[%d] setup ctrls fail, ret = %d\n", inst->id, ret);254 v4l2_ctrl_handler_free(&inst->ctrl_handler);255 return ret;256 }257 258 return 0;259}260 261static void vdec_handle_resolution_change(struct vpu_inst *inst)262{263 struct vdec_t *vdec = inst->priv;264 struct vb2_queue *q;265 266 if (!inst->fh.m2m_ctx)267 return;268 269 if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)270 return;271 if (!vdec->source_change)272 return;273 274 q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);275 if (!list_empty(&q->done_list))276 return;277 278 vdec->source_change--;279 vpu_notify_source_change(inst);280 vpu_set_last_buffer_dequeued(inst, false);281}282 283static int vdec_update_state(struct vpu_inst *inst, enum vpu_codec_state state, u32 force)284{285 struct vdec_t *vdec = inst->priv;286 enum vpu_codec_state pre_state = inst->state;287 288 if (state == VPU_CODEC_STATE_SEEK) {289 if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)290 vdec->state = inst->state;291 else292 vdec->state = VPU_CODEC_STATE_ACTIVE;293 }294 if (inst->state != VPU_CODEC_STATE_SEEK || force)295 inst->state = state;296 else if (state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)297 vdec->state = VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE;298 299 if (inst->state != pre_state)300 vpu_trace(inst->dev, "[%d] %s -> %s\n", inst->id,301 vpu_codec_state_name(pre_state), vpu_codec_state_name(inst->state));302 303 if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)304 vdec_handle_resolution_change(inst);305 306 return 0;307}308 309static void vdec_set_last_buffer_dequeued(struct vpu_inst *inst)310{311 struct vdec_t *vdec = inst->priv;312 313 if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)314 return;315 316 if (vdec->eos_received) {317 if (!vpu_set_last_buffer_dequeued(inst, true)) {318 vdec->eos_received--;319 vdec_update_state(inst, VPU_CODEC_STATE_DRAIN, 0);320 }321 }322}323 324static int vdec_querycap(struct file *file, void *fh, struct v4l2_capability *cap)325{326 strscpy(cap->driver, "amphion-vpu", sizeof(cap->driver));327 strscpy(cap->card, "amphion vpu decoder", sizeof(cap->card));328 strscpy(cap->bus_info, "platform: amphion-vpu", sizeof(cap->bus_info));329 330 return 0;331}332 333static int vdec_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)334{335 struct vpu_inst *inst = to_inst(file);336 struct vdec_t *vdec = inst->priv;337 const struct vpu_format *fmt;338 int ret = -EINVAL;339 340 vpu_inst_lock(inst);341 if (V4L2_TYPE_IS_CAPTURE(f->type) && vdec->fixed_fmt) {342 fmt = vpu_get_format(inst, f->type);343 if (f->index == 1)344 fmt = vpu_helper_find_sibling(inst, f->type, fmt->pixfmt);345 if (f->index > 1)346 fmt = NULL;347 } else {348 fmt = vpu_helper_enum_format(inst, f->type, f->index);349 }350 if (!fmt)351 goto exit;352 353 memset(f->reserved, 0, sizeof(f->reserved));354 f->pixelformat = fmt->pixfmt;355 f->flags = fmt->flags;356 ret = 0;357exit:358 vpu_inst_unlock(inst);359 return ret;360}361 362static int vdec_g_fmt(struct file *file, void *fh, struct v4l2_format *f)363{364 struct vpu_inst *inst = to_inst(file);365 struct vdec_t *vdec = inst->priv;366 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;367 struct vpu_format *cur_fmt;368 int i;369 370 vpu_inst_lock(inst);371 cur_fmt = vpu_get_format(inst, f->type);372 373 pixmp->pixelformat = cur_fmt->pixfmt;374 pixmp->num_planes = cur_fmt->mem_planes;375 pixmp->width = cur_fmt->width;376 pixmp->height = cur_fmt->height;377 pixmp->field = cur_fmt->field;378 pixmp->flags = cur_fmt->flags;379 for (i = 0; i < pixmp->num_planes; i++) {380 pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i];381 pixmp->plane_fmt[i].sizeimage = vpu_get_fmt_plane_size(cur_fmt, i);382 }383 384 f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries;385 f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars;386 f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs;387 f->fmt.pix_mp.quantization = vdec->codec_info.full_range;388 vpu_inst_unlock(inst);389 390 return 0;391}392 393static int vdec_try_fmt(struct file *file, void *fh, struct v4l2_format *f)394{395 struct vpu_inst *inst = to_inst(file);396 struct vdec_t *vdec = inst->priv;397 struct vpu_format fmt;398 399 vpu_inst_lock(inst);400 if (V4L2_TYPE_IS_CAPTURE(f->type) && vdec->fixed_fmt) {401 struct vpu_format *cap_fmt = vpu_get_format(inst, f->type);402 403 if (!vpu_helper_match_format(inst, cap_fmt->type, cap_fmt->pixfmt,404 f->fmt.pix_mp.pixelformat))405 f->fmt.pix_mp.pixelformat = cap_fmt->pixfmt;406 }407 408 vpu_try_fmt_common(inst, f, &fmt);409 410 if (vdec->fixed_fmt) {411 f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries;412 f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars;413 f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs;414 f->fmt.pix_mp.quantization = vdec->codec_info.full_range;415 } else {416 f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT;417 f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT;418 f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;419 f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT;420 }421 vpu_inst_unlock(inst);422 423 return 0;424}425 426static int vdec_s_fmt_common(struct vpu_inst *inst, struct v4l2_format *f)427{428 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;429 struct vpu_format fmt;430 struct vpu_format *cur_fmt;431 struct vb2_queue *q;432 struct vdec_t *vdec = inst->priv;433 int i;434 435 if (!inst->fh.m2m_ctx)436 return -EINVAL;437 438 q = v4l2_m2m_get_vq(inst->fh.m2m_ctx, f->type);439 if (!q)440 return -EINVAL;441 if (vb2_is_busy(q))442 return -EBUSY;443 444 if (vpu_try_fmt_common(inst, f, &fmt))445 return -EINVAL;446 447 cur_fmt = vpu_get_format(inst, f->type);448 if (V4L2_TYPE_IS_OUTPUT(f->type) && inst->state != VPU_CODEC_STATE_DEINIT) {449 if (cur_fmt->pixfmt != fmt.pixfmt) {450 vdec->reset_codec = true;451 vdec->fixed_fmt = false;452 }453 }454 if (V4L2_TYPE_IS_OUTPUT(f->type) || !vdec->fixed_fmt) {455 memcpy(cur_fmt, &fmt, sizeof(*cur_fmt));456 } else {457 if (vpu_helper_match_format(inst, f->type, cur_fmt->pixfmt, pixmp->pixelformat)) {458 cur_fmt->pixfmt = fmt.pixfmt;459 cur_fmt->mem_planes = fmt.mem_planes;460 }461 pixmp->pixelformat = cur_fmt->pixfmt;462 pixmp->num_planes = cur_fmt->mem_planes;463 pixmp->width = cur_fmt->width;464 pixmp->height = cur_fmt->height;465 for (i = 0; i < pixmp->num_planes; i++) {466 pixmp->plane_fmt[i].bytesperline = cur_fmt->bytesperline[i];467 pixmp->plane_fmt[i].sizeimage = vpu_get_fmt_plane_size(cur_fmt, i);468 }469 pixmp->field = cur_fmt->field;470 }471 472 if (!vdec->fixed_fmt) {473 if (V4L2_TYPE_IS_OUTPUT(f->type)) {474 vdec->params.codec_format = cur_fmt->pixfmt;475 vdec->codec_info.color_primaries = f->fmt.pix_mp.colorspace;476 vdec->codec_info.transfer_chars = f->fmt.pix_mp.xfer_func;477 vdec->codec_info.matrix_coeffs = f->fmt.pix_mp.ycbcr_enc;478 vdec->codec_info.full_range = f->fmt.pix_mp.quantization;479 } else {480 vdec->params.output_format = cur_fmt->pixfmt;481 inst->crop.left = 0;482 inst->crop.top = 0;483 inst->crop.width = cur_fmt->width;484 inst->crop.height = cur_fmt->height;485 }486 }487 488 vpu_trace(inst->dev, "[%d] %c%c%c%c %dx%d\n", inst->id,489 f->fmt.pix_mp.pixelformat,490 f->fmt.pix_mp.pixelformat >> 8,491 f->fmt.pix_mp.pixelformat >> 16,492 f->fmt.pix_mp.pixelformat >> 24,493 f->fmt.pix_mp.width,494 f->fmt.pix_mp.height);495 496 return 0;497}498 499static int vdec_s_fmt(struct file *file, void *fh, struct v4l2_format *f)500{501 struct vpu_inst *inst = to_inst(file);502 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp;503 struct vdec_t *vdec = inst->priv;504 int ret = 0;505 506 vpu_inst_lock(inst);507 ret = vdec_s_fmt_common(inst, f);508 if (ret)509 goto exit;510 511 if (V4L2_TYPE_IS_OUTPUT(f->type) && !vdec->fixed_fmt) {512 struct v4l2_format fc;513 514 memset(&fc, 0, sizeof(fc));515 fc.type = inst->cap_format.type;516 fc.fmt.pix_mp.pixelformat = inst->cap_format.pixfmt;517 fc.fmt.pix_mp.width = pixmp->width;518 fc.fmt.pix_mp.height = pixmp->height;519 vdec_s_fmt_common(inst, &fc);520 }521 522 f->fmt.pix_mp.colorspace = vdec->codec_info.color_primaries;523 f->fmt.pix_mp.xfer_func = vdec->codec_info.transfer_chars;524 f->fmt.pix_mp.ycbcr_enc = vdec->codec_info.matrix_coeffs;525 f->fmt.pix_mp.quantization = vdec->codec_info.full_range;526 527exit:528 vpu_inst_unlock(inst);529 return ret;530}531 532static int vdec_g_selection(struct file *file, void *fh, struct v4l2_selection *s)533{534 struct vpu_inst *inst = to_inst(file);535 536 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)537 return -EINVAL;538 539 switch (s->target) {540 case V4L2_SEL_TGT_COMPOSE:541 case V4L2_SEL_TGT_COMPOSE_DEFAULT:542 case V4L2_SEL_TGT_COMPOSE_PADDED:543 s->r = inst->crop;544 break;545 case V4L2_SEL_TGT_COMPOSE_BOUNDS:546 s->r.left = 0;547 s->r.top = 0;548 s->r.width = inst->cap_format.width;549 s->r.height = inst->cap_format.height;550 break;551 default:552 return -EINVAL;553 }554 555 return 0;556}557 558static int vdec_drain(struct vpu_inst *inst)559{560 struct vdec_t *vdec = inst->priv;561 562 if (!inst->fh.m2m_ctx)563 return 0;564 565 if (!vdec->drain)566 return 0;567 568 if (!vpu_is_source_empty(inst))569 return 0;570 571 if (!vdec->params.frame_count) {572 vpu_set_last_buffer_dequeued(inst, true);573 return 0;574 }575 576 vpu_iface_add_scode(inst, SCODE_PADDING_EOS);577 vdec->params.end_flag = 1;578 vpu_iface_set_decode_params(inst, &vdec->params, 1);579 vdec->drain = 0;580 vpu_trace(inst->dev, "[%d] frame_count = %d\n", inst->id, vdec->params.frame_count);581 582 return 0;583}584 585static int vdec_cmd_start(struct vpu_inst *inst)586{587 struct vdec_t *vdec = inst->priv;588 589 switch (inst->state) {590 case VPU_CODEC_STATE_STARTED:591 case VPU_CODEC_STATE_DRAIN:592 case VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE:593 vdec_update_state(inst, VPU_CODEC_STATE_ACTIVE, 0);594 break;595 default:596 break;597 }598 vpu_process_capture_buffer(inst);599 if (vdec->eos_received)600 vdec_set_last_buffer_dequeued(inst);601 return 0;602}603 604static int vdec_cmd_stop(struct vpu_inst *inst)605{606 struct vdec_t *vdec = inst->priv;607 608 vpu_trace(inst->dev, "[%d]\n", inst->id);609 610 if (inst->state == VPU_CODEC_STATE_DEINIT) {611 vpu_set_last_buffer_dequeued(inst, true);612 } else {613 vdec->drain = 1;614 vdec_drain(inst);615 }616 617 return 0;618}619 620static int vdec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)621{622 struct vpu_inst *inst = to_inst(file);623 int ret;624 625 ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, cmd);626 if (ret)627 return ret;628 629 vpu_inst_lock(inst);630 switch (cmd->cmd) {631 case V4L2_DEC_CMD_START:632 vdec_cmd_start(inst);633 break;634 case V4L2_DEC_CMD_STOP:635 vdec_cmd_stop(inst);636 break;637 default:638 break;639 }640 vpu_inst_unlock(inst);641 642 return 0;643}644 645static int vdec_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)646{647 switch (sub->type) {648 case V4L2_EVENT_EOS:649 return v4l2_event_subscribe(fh, sub, 0, NULL);650 case V4L2_EVENT_SOURCE_CHANGE:651 return v4l2_src_change_event_subscribe(fh, sub);652 case V4L2_EVENT_CTRL:653 return v4l2_ctrl_subscribe_event(fh, sub);654 default:655 return -EINVAL;656 }657 658 return 0;659}660 661static const struct v4l2_ioctl_ops vdec_ioctl_ops = {662 .vidioc_querycap = vdec_querycap,663 .vidioc_enum_fmt_vid_cap = vdec_enum_fmt,664 .vidioc_enum_fmt_vid_out = vdec_enum_fmt,665 .vidioc_g_fmt_vid_cap_mplane = vdec_g_fmt,666 .vidioc_g_fmt_vid_out_mplane = vdec_g_fmt,667 .vidioc_try_fmt_vid_cap_mplane = vdec_try_fmt,668 .vidioc_try_fmt_vid_out_mplane = vdec_try_fmt,669 .vidioc_s_fmt_vid_cap_mplane = vdec_s_fmt,670 .vidioc_s_fmt_vid_out_mplane = vdec_s_fmt,671 .vidioc_g_selection = vdec_g_selection,672 .vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,673 .vidioc_decoder_cmd = vdec_decoder_cmd,674 .vidioc_subscribe_event = vdec_subscribe_event,675 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,676 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,677 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,678 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,679 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf,680 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf,681 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,682 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,683 .vidioc_streamon = v4l2_m2m_ioctl_streamon,684 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,685};686 687static bool vdec_check_ready(struct vpu_inst *inst, unsigned int type)688{689 struct vdec_t *vdec = inst->priv;690 691 if (V4L2_TYPE_IS_OUTPUT(type))692 return true;693 694 if (vdec->req_frame_count)695 return true;696 697 return false;698}699 700static struct vb2_v4l2_buffer *vdec_get_src_buffer(struct vpu_inst *inst, u32 count)701{702 if (count > 1)703 vpu_skip_frame(inst, count - 1);704 705 return vpu_next_src_buf(inst);706}707 708static int vdec_frame_decoded(struct vpu_inst *inst, void *arg)709{710 struct vdec_t *vdec = inst->priv;711 struct vpu_dec_pic_info *info = arg;712 struct vpu_vb2_buffer *vpu_buf;713 struct vb2_v4l2_buffer *vbuf;714 struct vb2_v4l2_buffer *src_buf;715 int ret = 0;716 717 if (!info || info->id >= ARRAY_SIZE(vdec->slots))718 return -EINVAL;719 720 vpu_inst_lock(inst);721 vpu_buf = vdec->slots[info->id];722 if (!vpu_buf) {723 dev_err(inst->dev, "[%d] decoded invalid frame[%d]\n", inst->id, info->id);724 ret = -EINVAL;725 goto exit;726 }727 vbuf = &vpu_buf->m2m_buf.vb;728 src_buf = vdec_get_src_buffer(inst, info->consumed_count);729 if (src_buf) {730 v4l2_m2m_buf_copy_metadata(src_buf, vbuf, true);731 if (info->consumed_count) {732 v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx);733 vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE);734 v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);735 } else {736 vpu_set_buffer_state(src_buf, VPU_BUF_STATE_DECODED);737 }738 }739 if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED)740 dev_info(inst->dev, "[%d] buf[%d] has been decoded\n", inst->id, info->id);741 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_DECODED);742 vdec->decoded_frame_count++;743 if (vdec->params.display_delay_enable) {744 struct vpu_format *cur_fmt;745 746 cur_fmt = vpu_get_format(inst, inst->cap_format.type);747 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_READY);748 for (int i = 0; i < vbuf->vb2_buf.num_planes; i++)749 vb2_set_plane_payload(&vbuf->vb2_buf,750 i, vpu_get_fmt_plane_size(cur_fmt, i));751 vbuf->field = cur_fmt->field;752 vbuf->sequence = vdec->sequence++;753 dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);754 755 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);756 vdec->display_frame_count++;757 }758exit:759 vpu_inst_unlock(inst);760 761 return ret;762}763 764static struct vpu_vb2_buffer *vdec_find_buffer(struct vpu_inst *inst, u32 luma)765{766 struct vdec_t *vdec = inst->priv;767 int i;768 769 for (i = 0; i < ARRAY_SIZE(vdec->slots); i++) {770 if (!vdec->slots[i])771 continue;772 if (luma == vdec->slots[i]->luma)773 return vdec->slots[i];774 }775 776 return NULL;777}778 779static void vdec_buf_done(struct vpu_inst *inst, struct vpu_frame_info *frame)780{781 struct vdec_t *vdec = inst->priv;782 struct vpu_format *cur_fmt;783 struct vpu_vb2_buffer *vpu_buf;784 struct vb2_v4l2_buffer *vbuf;785 int i;786 787 if (!frame)788 return;789 790 vpu_inst_lock(inst);791 if (!vdec->params.display_delay_enable)792 vdec->sequence++;793 vpu_buf = vdec_find_buffer(inst, frame->luma);794 vpu_inst_unlock(inst);795 if (!vpu_buf) {796 dev_err(inst->dev, "[%d] can't find buffer, id = %d, addr = 0x%x\n",797 inst->id, frame->id, frame->luma);798 return;799 }800 if (frame->skipped) {801 dev_dbg(inst->dev, "[%d] frame skip\n", inst->id);802 return;803 }804 805 cur_fmt = vpu_get_format(inst, inst->cap_format.type);806 vbuf = &vpu_buf->m2m_buf.vb;807 if (vbuf->vb2_buf.index != frame->id)808 dev_err(inst->dev, "[%d] buffer id(%d, %d) dismatch\n",809 inst->id, vbuf->vb2_buf.index, frame->id);810 811 if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_READY && vdec->params.display_delay_enable)812 return;813 814 if (vpu_get_buffer_state(vbuf) != VPU_BUF_STATE_DECODED)815 dev_err(inst->dev, "[%d] buffer(%d) ready without decoded\n", inst->id, frame->id);816 817 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_READY);818 for (i = 0; i < vbuf->vb2_buf.num_planes; i++)819 vb2_set_plane_payload(&vbuf->vb2_buf, i, vpu_get_fmt_plane_size(cur_fmt, i));820 vbuf->field = cur_fmt->field;821 vbuf->sequence = vdec->sequence;822 dev_dbg(inst->dev, "[%d][OUTPUT TS]%32lld\n", inst->id, vbuf->vb2_buf.timestamp);823 824 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);825 vpu_inst_lock(inst);826 vdec->display_frame_count++;827 vpu_inst_unlock(inst);828 dev_dbg(inst->dev, "[%d] decoded : %d, display : %d, sequence : %d\n",829 inst->id, vdec->decoded_frame_count, vdec->display_frame_count, vdec->sequence);830}831 832static void vdec_stop_done(struct vpu_inst *inst)833{834 struct vdec_t *vdec = inst->priv;835 836 vpu_inst_lock(inst);837 vdec_update_state(inst, VPU_CODEC_STATE_DEINIT, 0);838 vdec->seq_hdr_found = 0;839 vdec->req_frame_count = 0;840 vdec->reset_codec = false;841 vdec->fixed_fmt = false;842 vdec->params.end_flag = 0;843 vdec->drain = 0;844 vdec->params.frame_count = 0;845 vdec->decoded_frame_count = 0;846 vdec->display_frame_count = 0;847 vdec->sequence = 0;848 vdec->eos_received = 0;849 vdec->is_source_changed = false;850 vdec->source_change = 0;851 inst->total_input_count = 0;852 vpu_inst_unlock(inst);853}854 855static bool vdec_check_source_change(struct vpu_inst *inst)856{857 struct vdec_t *vdec = inst->priv;858 const struct vpu_format *sibling;859 860 if (!inst->fh.m2m_ctx)861 return false;862 863 if (vdec->reset_codec)864 return false;865 866 sibling = vpu_helper_find_sibling(inst, inst->cap_format.type, inst->cap_format.pixfmt);867 if (sibling && vdec->codec_info.pixfmt == sibling->pixfmt)868 vdec->codec_info.pixfmt = inst->cap_format.pixfmt;869 870 if (!vb2_is_streaming(v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx)))871 return true;872 if (inst->cap_format.pixfmt != vdec->codec_info.pixfmt)873 return true;874 if (inst->cap_format.width != vdec->codec_info.decoded_width)875 return true;876 if (inst->cap_format.height != vdec->codec_info.decoded_height)877 return true;878 if (vpu_get_num_buffers(inst, inst->cap_format.type) < inst->min_buffer_cap)879 return true;880 if (inst->crop.left != vdec->codec_info.offset_x)881 return true;882 if (inst->crop.top != vdec->codec_info.offset_y)883 return true;884 if (inst->crop.width != vdec->codec_info.width)885 return true;886 if (inst->crop.height != vdec->codec_info.height)887 return true;888 889 return false;890}891 892static void vdec_init_fmt(struct vpu_inst *inst)893{894 struct vdec_t *vdec = inst->priv;895 struct v4l2_format f;896 897 memset(&f, 0, sizeof(f));898 f.type = inst->cap_format.type;899 f.fmt.pix_mp.pixelformat = vdec->codec_info.pixfmt;900 f.fmt.pix_mp.width = vdec->codec_info.decoded_width;901 f.fmt.pix_mp.height = vdec->codec_info.decoded_height;902 if (vdec->codec_info.progressive)903 f.fmt.pix_mp.field = V4L2_FIELD_NONE;904 else905 f.fmt.pix_mp.field = V4L2_FIELD_SEQ_TB;906 vpu_try_fmt_common(inst, &f, &inst->cap_format);907 908 inst->out_format.width = vdec->codec_info.width;909 inst->out_format.height = vdec->codec_info.height;910}911 912static void vdec_init_crop(struct vpu_inst *inst)913{914 struct vdec_t *vdec = inst->priv;915 916 inst->crop.left = vdec->codec_info.offset_x;917 inst->crop.top = vdec->codec_info.offset_y;918 inst->crop.width = vdec->codec_info.width;919 inst->crop.height = vdec->codec_info.height;920}921 922static void vdec_init_mbi(struct vpu_inst *inst)923{924 struct vdec_t *vdec = inst->priv;925 926 vdec->mbi.size = vdec->codec_info.mbi_size;927 vdec->mbi.max_count = ARRAY_SIZE(vdec->mbi.buffer);928 scnprintf(vdec->mbi.name, sizeof(vdec->mbi.name), "mbi");929 vdec->mbi.type = MEM_RES_MBI;930 vdec->mbi.tag = vdec->seq_tag;931}932 933static void vdec_init_dcp(struct vpu_inst *inst)934{935 struct vdec_t *vdec = inst->priv;936 937 vdec->dcp.size = vdec->codec_info.dcp_size;938 vdec->dcp.max_count = ARRAY_SIZE(vdec->dcp.buffer);939 scnprintf(vdec->dcp.name, sizeof(vdec->dcp.name), "dcp");940 vdec->dcp.type = MEM_RES_DCP;941 vdec->dcp.tag = vdec->seq_tag;942}943 944static void vdec_request_one_fs(struct vdec_fs_info *fs)945{946 fs->req_count++;947 if (fs->req_count > fs->max_count)948 fs->req_count = fs->max_count;949}950 951static int vdec_alloc_fs_buffer(struct vpu_inst *inst, struct vdec_fs_info *fs)952{953 struct vpu_buffer *buffer;954 955 if (!fs->size)956 return -EINVAL;957 958 if (fs->count >= fs->req_count)959 return -EINVAL;960 961 buffer = &fs->buffer[fs->count];962 if (buffer->virt && buffer->length >= fs->size)963 return 0;964 965 vpu_free_dma(buffer);966 buffer->length = fs->size;967 return vpu_alloc_dma(inst->core, buffer);968}969 970static void vdec_alloc_fs(struct vpu_inst *inst, struct vdec_fs_info *fs)971{972 int ret;973 974 while (fs->count < fs->req_count) {975 ret = vdec_alloc_fs_buffer(inst, fs);976 if (ret)977 break;978 fs->count++;979 }980}981 982static void vdec_clear_fs(struct vdec_fs_info *fs)983{984 u32 i;985 986 if (!fs)987 return;988 989 for (i = 0; i < ARRAY_SIZE(fs->buffer); i++)990 vpu_free_dma(&fs->buffer[i]);991 memset(fs, 0, sizeof(*fs));992}993 994static int vdec_response_fs(struct vpu_inst *inst, struct vdec_fs_info *fs)995{996 struct vpu_fs_info info;997 int ret;998 999 if (fs->index >= fs->count)1000 return 0;1001 1002 memset(&info, 0, sizeof(info));1003 info.id = fs->index;1004 info.type = fs->type;1005 info.tag = fs->tag;1006 info.luma_addr = fs->buffer[fs->index].phys;1007 info.luma_size = fs->buffer[fs->index].length;1008 ret = vpu_session_alloc_fs(inst, &info);1009 if (ret)1010 return ret;1011 1012 fs->index++;1013 return 0;1014}1015 1016static int vdec_response_frame_abnormal(struct vpu_inst *inst)1017{1018 struct vdec_t *vdec = inst->priv;1019 struct vpu_fs_info info;1020 int ret;1021 1022 if (!vdec->req_frame_count)1023 return 0;1024 1025 memset(&info, 0, sizeof(info));1026 info.type = MEM_RES_FRAME;1027 info.tag = vdec->seq_tag + 0xf0;1028 ret = vpu_session_alloc_fs(inst, &info);1029 if (ret)1030 return ret;1031 vdec->req_frame_count--;1032 1033 return 0;1034}1035 1036static int vdec_response_frame(struct vpu_inst *inst, struct vb2_v4l2_buffer *vbuf)1037{1038 struct vdec_t *vdec = inst->priv;1039 struct vpu_vb2_buffer *vpu_buf;1040 struct vpu_fs_info info;1041 int ret;1042 1043 if (inst->state != VPU_CODEC_STATE_ACTIVE)1044 return -EINVAL;1045 1046 if (vdec->aborting)1047 return -EINVAL;1048 1049 if (!vdec->req_frame_count)1050 return -EINVAL;1051 1052 if (!vbuf)1053 return -EINVAL;1054 1055 if (vdec->slots[vbuf->vb2_buf.index]) {1056 dev_err(inst->dev, "[%d] repeat alloc fs %d\n",1057 inst->id, vbuf->vb2_buf.index);1058 return -EINVAL;1059 }1060 1061 dev_dbg(inst->dev, "[%d] state = %s, alloc fs %d, tag = 0x%x\n",1062 inst->id, vpu_codec_state_name(inst->state), vbuf->vb2_buf.index, vdec->seq_tag);1063 vpu_buf = to_vpu_vb2_buffer(vbuf);1064 1065 memset(&info, 0, sizeof(info));1066 info.id = vbuf->vb2_buf.index;1067 info.type = MEM_RES_FRAME;1068 info.tag = vdec->seq_tag;1069 info.luma_addr = vpu_get_vb_phy_addr(&vbuf->vb2_buf, 0);1070 info.luma_size = inst->cap_format.sizeimage[0];1071 if (vbuf->vb2_buf.num_planes > 1)1072 info.chroma_addr = vpu_get_vb_phy_addr(&vbuf->vb2_buf, 1);1073 else1074 info.chroma_addr = info.luma_addr + info.luma_size;1075 info.chromau_size = inst->cap_format.sizeimage[1];1076 info.bytesperline = inst->cap_format.bytesperline[0];1077 ret = vpu_session_alloc_fs(inst, &info);1078 if (ret)1079 return ret;1080 1081 vpu_buf->tag = info.tag;1082 vpu_buf->luma = info.luma_addr;1083 vpu_buf->chroma_u = info.chroma_addr;1084 vpu_buf->chroma_v = 0;1085 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_INUSE);1086 vdec->slots[info.id] = vpu_buf;1087 vdec->req_frame_count--;1088 1089 return 0;1090}1091 1092static void vdec_response_fs_request(struct vpu_inst *inst, bool force)1093{1094 struct vdec_t *vdec = inst->priv;1095 int i;1096 int ret;1097 1098 if (force) {1099 for (i = vdec->req_frame_count; i > 0; i--)1100 vdec_response_frame_abnormal(inst);1101 return;1102 }1103 1104 for (i = vdec->req_frame_count; i > 0; i--) {1105 ret = vpu_process_capture_buffer(inst);1106 if (ret)1107 break;1108 if (vdec->eos_received)1109 break;1110 }1111 1112 for (i = vdec->mbi.index; i < vdec->mbi.count; i++) {1113 if (vdec_response_fs(inst, &vdec->mbi))1114 break;1115 if (vdec->eos_received)1116 break;1117 }1118 for (i = vdec->dcp.index; i < vdec->dcp.count; i++) {1119 if (vdec_response_fs(inst, &vdec->dcp))1120 break;1121 if (vdec->eos_received)1122 break;1123 }1124}1125 1126static void vdec_response_fs_release(struct vpu_inst *inst, u32 id, u32 tag)1127{1128 struct vpu_fs_info info;1129 1130 memset(&info, 0, sizeof(info));1131 info.id = id;1132 info.tag = tag;1133 vpu_session_release_fs(inst, &info);1134}1135 1136static void vdec_recycle_buffer(struct vpu_inst *inst, struct vb2_v4l2_buffer *vbuf)1137{1138 if (!inst->fh.m2m_ctx)1139 return;1140 if (vbuf->vb2_buf.state != VB2_BUF_STATE_ACTIVE)1141 return;1142 if (vpu_find_buf_by_idx(inst, vbuf->vb2_buf.type, vbuf->vb2_buf.index))1143 return;1144 v4l2_m2m_buf_queue(inst->fh.m2m_ctx, vbuf);1145}1146 1147static void vdec_clear_slots(struct vpu_inst *inst)1148{1149 struct vdec_t *vdec = inst->priv;1150 struct vpu_vb2_buffer *vpu_buf;1151 struct vb2_v4l2_buffer *vbuf;1152 int i;1153 1154 for (i = 0; i < ARRAY_SIZE(vdec->slots); i++) {1155 if (!vdec->slots[i])1156 continue;1157 1158 vpu_buf = vdec->slots[i];1159 vbuf = &vpu_buf->m2m_buf.vb;1160 1161 vpu_trace(inst->dev, "clear slot %d\n", i);1162 vdec_response_fs_release(inst, i, vpu_buf->tag);1163 vdec_recycle_buffer(inst, vbuf);1164 vdec->slots[i]->state = VPU_BUF_STATE_IDLE;1165 vdec->slots[i] = NULL;1166 }1167}1168 1169static void vdec_event_seq_hdr(struct vpu_inst *inst, struct vpu_dec_codec_info *hdr)1170{1171 struct vdec_t *vdec = inst->priv;1172 1173 vpu_inst_lock(inst);1174 memcpy(&vdec->codec_info, hdr, sizeof(vdec->codec_info));1175 1176 vpu_trace(inst->dev, "[%d] %d x %d, crop : (%d, %d) %d x %d, %d, %d\n",1177 inst->id,1178 vdec->codec_info.decoded_width,1179 vdec->codec_info.decoded_height,1180 vdec->codec_info.offset_x,1181 vdec->codec_info.offset_y,1182 vdec->codec_info.width,1183 vdec->codec_info.height,1184 hdr->num_ref_frms,1185 hdr->num_dpb_frms);1186 inst->min_buffer_cap = hdr->num_ref_frms + hdr->num_dpb_frms;1187 vdec->is_source_changed = vdec_check_source_change(inst);1188 vdec_init_fmt(inst);1189 vdec_init_crop(inst);1190 vdec_init_mbi(inst);1191 vdec_init_dcp(inst);1192 if (!vdec->seq_hdr_found) {1193 vdec->seq_tag = vdec->codec_info.tag;1194 if (vdec->is_source_changed) {1195 vdec_update_state(inst, VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE, 0);1196 vdec->source_change++;1197 vdec_handle_resolution_change(inst);1198 vdec->is_source_changed = false;1199 }1200 }1201 if (vdec->seq_tag != vdec->codec_info.tag) {1202 vdec_response_fs_request(inst, true);1203 vpu_trace(inst->dev, "[%d] seq tag change: %d -> %d\n",1204 inst->id, vdec->seq_tag, vdec->codec_info.tag);1205 }1206 vdec->seq_hdr_found++;1207 vdec->fixed_fmt = true;1208 vpu_inst_unlock(inst);1209}1210 1211static void vdec_event_resolution_change(struct vpu_inst *inst)1212{1213 struct vdec_t *vdec = inst->priv;1214 1215 vpu_trace(inst->dev, "[%d]\n", inst->id);1216 vpu_inst_lock(inst);1217 vdec->seq_tag = vdec->codec_info.tag;1218 vdec_clear_fs(&vdec->mbi);1219 vdec_clear_fs(&vdec->dcp);1220 vdec_clear_slots(inst);1221 vdec_init_mbi(inst);1222 vdec_init_dcp(inst);1223 if (vdec->is_source_changed) {1224 vdec_update_state(inst, VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE, 0);1225 vdec->source_change++;1226 vdec_handle_resolution_change(inst);1227 vdec->is_source_changed = false;1228 }1229 vpu_inst_unlock(inst);1230}1231 1232static void vdec_event_req_fs(struct vpu_inst *inst, struct vpu_fs_info *fs)1233{1234 struct vdec_t *vdec = inst->priv;1235 1236 if (!fs)1237 return;1238 1239 vpu_inst_lock(inst);1240 1241 switch (fs->type) {1242 case MEM_RES_FRAME:1243 vdec->req_frame_count++;1244 break;1245 case MEM_RES_MBI:1246 vdec_request_one_fs(&vdec->mbi);1247 break;1248 case MEM_RES_DCP:1249 vdec_request_one_fs(&vdec->dcp);1250 break;1251 default:1252 break;1253 }1254 1255 vdec_alloc_fs(inst, &vdec->mbi);1256 vdec_alloc_fs(inst, &vdec->dcp);1257 1258 vdec_response_fs_request(inst, false);1259 1260 vpu_inst_unlock(inst);1261}1262 1263static void vdec_evnet_rel_fs(struct vpu_inst *inst, struct vpu_fs_info *fs)1264{1265 struct vdec_t *vdec = inst->priv;1266 struct vpu_vb2_buffer *vpu_buf;1267 struct vb2_v4l2_buffer *vbuf;1268 1269 if (!fs || fs->id >= ARRAY_SIZE(vdec->slots))1270 return;1271 if (fs->type != MEM_RES_FRAME)1272 return;1273 1274 if (fs->id >= vpu_get_num_buffers(inst, inst->cap_format.type)) {1275 dev_err(inst->dev, "[%d] invalid fs(%d) to release\n", inst->id, fs->id);1276 return;1277 }1278 1279 vpu_inst_lock(inst);1280 vpu_buf = vdec->slots[fs->id];1281 vdec->slots[fs->id] = NULL;1282 1283 if (!vpu_buf) {1284 dev_dbg(inst->dev, "[%d] fs[%d] has bee released\n", inst->id, fs->id);1285 goto exit;1286 }1287 1288 vbuf = &vpu_buf->m2m_buf.vb;1289 if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_DECODED) {1290 dev_dbg(inst->dev, "[%d] frame skip\n", inst->id);1291 vdec->sequence++;1292 }1293 1294 vdec_response_fs_release(inst, fs->id, vpu_buf->tag);1295 if (vpu_get_buffer_state(vbuf) != VPU_BUF_STATE_READY)1296 vdec_recycle_buffer(inst, vbuf);1297 1298 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE);1299 vpu_process_capture_buffer(inst);1300 1301exit:1302 vpu_inst_unlock(inst);1303}1304 1305static void vdec_event_eos(struct vpu_inst *inst)1306{1307 struct vdec_t *vdec = inst->priv;1308 1309 vpu_trace(inst->dev, "[%d] input : %d, decoded : %d, display : %d, sequence : %d\n",1310 inst->id,1311 vdec->params.frame_count,1312 vdec->decoded_frame_count,1313 vdec->display_frame_count,1314 vdec->sequence);1315 vpu_inst_lock(inst);1316 vdec->eos_received++;1317 vdec->fixed_fmt = false;1318 inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP;1319 vdec_set_last_buffer_dequeued(inst);1320 vpu_inst_unlock(inst);1321}1322 1323static void vdec_event_notify(struct vpu_inst *inst, u32 event, void *data)1324{1325 switch (event) {1326 case VPU_MSG_ID_SEQ_HDR_FOUND:1327 vdec_event_seq_hdr(inst, data);1328 break;1329 case VPU_MSG_ID_RES_CHANGE:1330 vdec_event_resolution_change(inst);1331 break;1332 case VPU_MSG_ID_FRAME_REQ:1333 vdec_event_req_fs(inst, data);1334 break;1335 case VPU_MSG_ID_FRAME_RELEASE:1336 vdec_evnet_rel_fs(inst, data);1337 break;1338 case VPU_MSG_ID_PIC_EOS:1339 vdec_event_eos(inst);1340 break;1341 default:1342 break;1343 }1344}1345 1346static int vdec_process_output(struct vpu_inst *inst, struct vb2_buffer *vb)1347{1348 struct vdec_t *vdec = inst->priv;1349 struct vb2_v4l2_buffer *vbuf;1350 struct vpu_rpc_buffer_desc desc;1351 u32 free_space;1352 int ret;1353 1354 vbuf = to_vb2_v4l2_buffer(vb);1355 dev_dbg(inst->dev, "[%d] dec output [%d] %d : %ld\n",1356 inst->id, vbuf->sequence, vb->index, vb2_get_plane_payload(vb, 0));1357 1358 if (inst->state == VPU_CODEC_STATE_DEINIT)1359 return -EINVAL;1360 if (vdec->reset_codec)1361 return -EINVAL;1362 1363 if (inst->state == VPU_CODEC_STATE_STARTED)1364 vdec_update_state(inst, VPU_CODEC_STATE_ACTIVE, 0);1365 1366 ret = vpu_iface_get_stream_buffer_desc(inst, &desc);1367 if (ret)1368 return ret;1369 1370 free_space = vpu_helper_get_free_space(inst);1371 if (free_space < vb2_get_plane_payload(vb, 0) + 0x40000)1372 return -ENOMEM;1373 1374 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_INUSE);1375 ret = vpu_iface_input_frame(inst, vb);1376 if (ret < 0)1377 return -ENOMEM;1378 1379 dev_dbg(inst->dev, "[%d][INPUT TS]%32lld\n", inst->id, vb->timestamp);1380 vdec->params.frame_count++;1381 1382 if (vdec->drain)1383 vdec_drain(inst);1384 1385 return 0;1386}1387 1388static int vdec_process_capture(struct vpu_inst *inst, struct vb2_buffer *vb)1389{1390 struct vdec_t *vdec = inst->priv;1391 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1392 int ret;1393 1394 if (inst->state == VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE)1395 return -EINVAL;1396 if (vdec->reset_codec)1397 return -EINVAL;1398 1399 ret = vdec_response_frame(inst, vbuf);1400 if (ret)1401 return ret;1402 v4l2_m2m_dst_buf_remove_by_buf(inst->fh.m2m_ctx, vbuf);1403 return 0;1404}1405 1406static void vdec_on_queue_empty(struct vpu_inst *inst, u32 type)1407{1408 struct vdec_t *vdec = inst->priv;1409 1410 if (V4L2_TYPE_IS_OUTPUT(type))1411 return;1412 1413 vdec_handle_resolution_change(inst);1414 if (vdec->eos_received)1415 vdec_set_last_buffer_dequeued(inst);1416}1417 1418static void vdec_abort(struct vpu_inst *inst)1419{1420 struct vdec_t *vdec = inst->priv;1421 struct vpu_rpc_buffer_desc desc;1422 int ret;1423 1424 vpu_trace(inst->dev, "[%d] state = %s\n", inst->id, vpu_codec_state_name(inst->state));1425 1426 vdec->aborting = true;1427 vpu_iface_add_scode(inst, SCODE_PADDING_ABORT);1428 vdec->params.end_flag = 1;1429 vpu_iface_set_decode_params(inst, &vdec->params, 1);1430 1431 vpu_session_abort(inst);1432 1433 ret = vpu_iface_get_stream_buffer_desc(inst, &desc);1434 if (!ret)1435 vpu_iface_update_stream_buffer(inst, desc.rptr, 1);1436 1437 vpu_session_rst_buf(inst);1438 vpu_trace(inst->dev, "[%d] input : %d, decoded : %d, display : %d, sequence : %d\n",1439 inst->id,1440 vdec->params.frame_count,1441 vdec->decoded_frame_count,1442 vdec->display_frame_count,1443 vdec->sequence);1444 if (!vdec->seq_hdr_found)1445 vdec->reset_codec = true;1446 vdec->params.end_flag = 0;1447 vdec->drain = 0;1448 vdec->params.frame_count = 0;1449 vdec->decoded_frame_count = 0;1450 vdec->display_frame_count = 0;1451 vdec->sequence = 0;1452 vdec->aborting = false;1453 inst->extra_size = 0;1454}1455 1456static void vdec_stop(struct vpu_inst *inst, bool free)1457{1458 struct vdec_t *vdec = inst->priv;1459 1460 vdec_clear_slots(inst);1461 if (inst->state != VPU_CODEC_STATE_DEINIT)1462 vpu_session_stop(inst);1463 vdec_clear_fs(&vdec->mbi);1464 vdec_clear_fs(&vdec->dcp);1465 if (free) {1466 vpu_free_dma(&vdec->udata);1467 vpu_free_dma(&inst->stream_buffer);1468 }1469 vdec_update_state(inst, VPU_CODEC_STATE_DEINIT, 1);1470 vdec->reset_codec = false;1471}1472 1473static void vdec_release(struct vpu_inst *inst)1474{1475 if (inst->id != VPU_INST_NULL_ID)1476 vpu_trace(inst->dev, "[%d]\n", inst->id);1477 vdec_stop(inst, true);1478}1479 1480static void vdec_cleanup(struct vpu_inst *inst)1481{1482 struct vdec_t *vdec;1483 1484 if (!inst)1485 return;1486 1487 vdec = inst->priv;1488 vfree(vdec);1489 inst->priv = NULL;1490 vfree(inst);1491}1492 1493static void vdec_init_params(struct vdec_t *vdec)1494{1495 vdec->params.frame_count = 0;1496 vdec->params.end_flag = 0;1497}1498 1499static int vdec_start(struct vpu_inst *inst)1500{1501 struct vdec_t *vdec = inst->priv;1502 int stream_buffer_size;1503 int ret;1504 1505 if (inst->state != VPU_CODEC_STATE_DEINIT)1506 return 0;1507 1508 vpu_trace(inst->dev, "[%d]\n", inst->id);1509 if (!vdec->udata.virt) {1510 vdec->udata.length = 0x1000;1511 ret = vpu_alloc_dma(inst->core, &vdec->udata);1512 if (ret) {1513 dev_err(inst->dev, "[%d] alloc udata fail\n", inst->id);1514 goto error;1515 }1516 }1517 1518 if (!inst->stream_buffer.virt) {1519 stream_buffer_size = vpu_iface_get_stream_buffer_size(inst->core);1520 if (stream_buffer_size > 0) {1521 inst->stream_buffer.length = stream_buffer_size;1522 ret = vpu_alloc_dma(inst->core, &inst->stream_buffer);1523 if (ret) {1524 dev_err(inst->dev, "[%d] alloc stream buffer fail\n", inst->id);1525 goto error;1526 }1527 inst->use_stream_buffer = true;1528 }1529 }1530 1531 if (inst->use_stream_buffer)1532 vpu_iface_config_stream_buffer(inst, &inst->stream_buffer);1533 vpu_iface_init_instance(inst);1534 vdec->params.udata.base = vdec->udata.phys;1535 vdec->params.udata.size = vdec->udata.length;1536 ret = vpu_iface_set_decode_params(inst, &vdec->params, 0);1537 if (ret) {1538 dev_err(inst->dev, "[%d] set decode params fail\n", inst->id);1539 goto error;1540 }1541 1542 vdec_init_params(vdec);1543 ret = vpu_session_start(inst);1544 if (ret) {1545 dev_err(inst->dev, "[%d] start fail\n", inst->id);1546 goto error;1547 }1548 1549 vdec_update_state(inst, VPU_CODEC_STATE_STARTED, 0);1550 1551 return 0;1552error:1553 vpu_free_dma(&vdec->udata);1554 vpu_free_dma(&inst->stream_buffer);1555 return ret;1556}1557 1558static int vdec_start_session(struct vpu_inst *inst, u32 type)1559{1560 struct vdec_t *vdec = inst->priv;1561 int ret = 0;1562 1563 if (V4L2_TYPE_IS_OUTPUT(type)) {1564 if (vdec->reset_codec)1565 vdec_stop(inst, false);1566 if (inst->state == VPU_CODEC_STATE_DEINIT) {1567 ret = vdec_start(inst);1568 if (ret)1569 return ret;1570 }1571 }1572 1573 if (V4L2_TYPE_IS_OUTPUT(type)) {1574 vdec_update_state(inst, vdec->state, 1);1575 vdec->eos_received = 0;1576 vpu_process_output_buffer(inst);1577 } else {1578 vdec_cmd_start(inst);1579 }1580 if (inst->state == VPU_CODEC_STATE_ACTIVE)1581 vdec_response_fs_request(inst, false);1582 1583 return ret;1584}1585 1586static int vdec_stop_session(struct vpu_inst *inst, u32 type)1587{1588 struct vdec_t *vdec = inst->priv;1589 1590 if (inst->state == VPU_CODEC_STATE_DEINIT)1591 return 0;1592 1593 if (V4L2_TYPE_IS_OUTPUT(type)) {1594 vdec_update_state(inst, VPU_CODEC_STATE_SEEK, 0);1595 vdec->drain = 0;1596 vdec_abort(inst);1597 } else {1598 if (inst->state != VPU_CODEC_STATE_DYAMIC_RESOLUTION_CHANGE) {1599 if (vb2_is_streaming(v4l2_m2m_get_src_vq(inst->fh.m2m_ctx)))1600 vdec_abort(inst);1601 vdec->eos_received = 0;1602 }1603 vdec_clear_slots(inst);1604 }1605 1606 return 0;1607}1608 1609static int vdec_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i)1610{1611 struct vdec_t *vdec = inst->priv;1612 int num = -1;1613 1614 switch (i) {1615 case 0:1616 num = scnprintf(str, size,1617 "req_frame_count = %d\ninterlaced = %d\n",1618 vdec->req_frame_count,1619 vdec->codec_info.progressive ? 0 : 1);1620 break;1621 case 1:1622 num = scnprintf(str, size,1623 "mbi: size = 0x%x request = %d, alloc = %d, response = %d\n",1624 vdec->mbi.size,1625 vdec->mbi.req_count,1626 vdec->mbi.count,1627 vdec->mbi.index);1628 break;1629 case 2:1630 num = scnprintf(str, size,1631 "dcp: size = 0x%x request = %d, alloc = %d, response = %d\n",1632 vdec->dcp.size,1633 vdec->dcp.req_count,1634 vdec->dcp.count,1635 vdec->dcp.index);1636 break;1637 case 3:1638 num = scnprintf(str, size, "input_frame_count = %d\n", vdec->params.frame_count);1639 break;1640 case 4:1641 num = scnprintf(str, size, "decoded_frame_count = %d\n", vdec->decoded_frame_count);1642 break;1643 case 5:1644 num = scnprintf(str, size, "display_frame_count = %d\n", vdec->display_frame_count);1645 break;1646 case 6:1647 num = scnprintf(str, size, "sequence = %d\n", vdec->sequence);1648 break;1649 case 7:1650 num = scnprintf(str, size, "drain = %d, eos = %d, source_change = %d\n",1651 vdec->drain, vdec->eos_received, vdec->source_change);1652 break;1653 case 8:1654 num = scnprintf(str, size, "fps = %d/%d\n",1655 vdec->codec_info.frame_rate.numerator,1656 vdec->codec_info.frame_rate.denominator);1657 break;1658 case 9:1659 num = scnprintf(str, size, "colorspace: %d, %d, %d, %d (%d)\n",1660 vdec->codec_info.color_primaries,1661 vdec->codec_info.transfer_chars,1662 vdec->codec_info.matrix_coeffs,1663 vdec->codec_info.full_range,1664 vdec->codec_info.vui_present);1665 break;1666 default:1667 break;1668 }1669 1670 return num;1671}1672 1673static struct vpu_inst_ops vdec_inst_ops = {1674 .ctrl_init = vdec_ctrl_init,1675 .check_ready = vdec_check_ready,1676 .buf_done = vdec_buf_done,1677 .get_one_frame = vdec_frame_decoded,1678 .stop_done = vdec_stop_done,1679 .event_notify = vdec_event_notify,1680 .release = vdec_release,1681 .cleanup = vdec_cleanup,1682 .start = vdec_start_session,1683 .stop = vdec_stop_session,1684 .process_output = vdec_process_output,1685 .process_capture = vdec_process_capture,1686 .on_queue_empty = vdec_on_queue_empty,1687 .get_debug_info = vdec_get_debug_info,1688 .wait_prepare = vpu_inst_unlock,1689 .wait_finish = vpu_inst_lock,1690};1691 1692static void vdec_init(struct file *file)1693{1694 struct vpu_inst *inst = to_inst(file);1695 struct v4l2_format f;1696 1697 memset(&f, 0, sizeof(f));1698 f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;1699 f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;1700 f.fmt.pix_mp.width = 1280;1701 f.fmt.pix_mp.height = 720;1702 f.fmt.pix_mp.field = V4L2_FIELD_NONE;1703 vdec_s_fmt(file, &inst->fh, &f);1704 1705 memset(&f, 0, sizeof(f));1706 f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;1707 f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M_8L128;1708 f.fmt.pix_mp.width = 1280;1709 f.fmt.pix_mp.height = 720;1710 f.fmt.pix_mp.field = V4L2_FIELD_NONE;1711 vdec_s_fmt(file, &inst->fh, &f);1712}1713 1714static int vdec_open(struct file *file)1715{1716 struct vpu_inst *inst;1717 struct vdec_t *vdec;1718 int ret;1719 1720 inst = vzalloc(sizeof(*inst));1721 if (!inst)1722 return -ENOMEM;1723 1724 vdec = vzalloc(sizeof(*vdec));1725 if (!vdec) {1726 vfree(inst);1727 return -ENOMEM;1728 }1729 1730 inst->ops = &vdec_inst_ops;1731 inst->formats = vdec_formats;1732 inst->type = VPU_CORE_TYPE_DEC;1733 inst->priv = vdec;1734 1735 ret = vpu_v4l2_open(file, inst);1736 if (ret)1737 return ret;1738 1739 vdec->fixed_fmt = false;1740 vdec->state = VPU_CODEC_STATE_ACTIVE;1741 inst->min_buffer_cap = VDEC_MIN_BUFFER_CAP;1742 inst->min_buffer_out = VDEC_MIN_BUFFER_OUT;1743 vdec_init(file);1744 1745 return 0;1746}1747 1748static const struct v4l2_file_operations vdec_fops = {1749 .owner = THIS_MODULE,1750 .open = vdec_open,1751 .release = vpu_v4l2_close,1752 .unlocked_ioctl = video_ioctl2,1753 .poll = v4l2_m2m_fop_poll,1754 .mmap = v4l2_m2m_fop_mmap,1755};1756 1757const struct v4l2_ioctl_ops *vdec_get_ioctl_ops(void)1758{1759 return &vdec_ioctl_ops;1760}1761 1762const struct v4l2_file_operations *vdec_get_fops(void)1763{1764 return &vdec_fops;1765}1766