vpu_v4l2.c (19072B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright 2020-2021 NXP 4 */ 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/pm_runtime.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_core.h" 23#include "vpu_v4l2.h" 24#include "vpu_msgs.h" 25#include "vpu_helpers.h" 26 27void vpu_inst_lock(struct vpu_inst *inst) 28{ 29 mutex_lock(&inst->lock); 30} 31 32void vpu_inst_unlock(struct vpu_inst *inst) 33{ 34 mutex_unlock(&inst->lock); 35} 36 37dma_addr_t vpu_get_vb_phy_addr(struct vb2_buffer *vb, u32 plane_no) 38{ 39 if (plane_no >= vb->num_planes) 40 return 0; 41 return vb2_dma_contig_plane_dma_addr(vb, plane_no) + 42 vb->planes[plane_no].data_offset; 43} 44 45unsigned int vpu_get_vb_length(struct vb2_buffer *vb, u32 plane_no) 46{ 47 if (plane_no >= vb->num_planes) 48 return 0; 49 return vb2_plane_size(vb, plane_no) - vb->planes[plane_no].data_offset; 50} 51 52void vpu_set_buffer_state(struct vb2_v4l2_buffer *vbuf, unsigned int state) 53{ 54 struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf); 55 56 vpu_buf->state = state; 57} 58 59unsigned int vpu_get_buffer_state(struct vb2_v4l2_buffer *vbuf) 60{ 61 struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf); 62 63 return vpu_buf->state; 64} 65 66void vpu_v4l2_set_error(struct vpu_inst *inst) 67{ 68 struct vb2_queue *src_q; 69 struct vb2_queue *dst_q; 70 71 vpu_inst_lock(inst); 72 dev_err(inst->dev, "some error occurs in codec\n"); 73 if (inst->fh.m2m_ctx) { 74 src_q = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx); 75 dst_q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); 76 src_q->error = 1; 77 dst_q->error = 1; 78 wake_up(&src_q->done_wq); 79 wake_up(&dst_q->done_wq); 80 } 81 vpu_inst_unlock(inst); 82} 83 84int vpu_notify_eos(struct vpu_inst *inst) 85{ 86 static const struct v4l2_event ev = { 87 .id = 0, 88 .type = V4L2_EVENT_EOS 89 }; 90 91 vpu_trace(inst->dev, "[%d]\n", inst->id); 92 v4l2_event_queue_fh(&inst->fh, &ev); 93 94 return 0; 95} 96 97int vpu_notify_source_change(struct vpu_inst *inst) 98{ 99 static const struct v4l2_event ev = { 100 .id = 0, 101 .type = V4L2_EVENT_SOURCE_CHANGE, 102 .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION 103 }; 104 105 vpu_trace(inst->dev, "[%d]\n", inst->id); 106 v4l2_event_queue_fh(&inst->fh, &ev); 107 return 0; 108} 109 110int vpu_set_last_buffer_dequeued(struct vpu_inst *inst) 111{ 112 struct vb2_queue *q; 113 114 if (!inst || !inst->fh.m2m_ctx) 115 return -EINVAL; 116 117 q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); 118 if (!list_empty(&q->done_list)) 119 return -EINVAL; 120 121 if (q->last_buffer_dequeued) 122 return 0; 123 vpu_trace(inst->dev, "last buffer dequeued\n"); 124 q->last_buffer_dequeued = true; 125 wake_up(&q->done_wq); 126 vpu_notify_eos(inst); 127 return 0; 128} 129 130bool vpu_is_source_empty(struct vpu_inst *inst) 131{ 132 struct v4l2_m2m_buffer *buf = NULL; 133 134 if (!inst->fh.m2m_ctx) 135 return true; 136 v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) { 137 if (vpu_get_buffer_state(&buf->vb) == VPU_BUF_STATE_IDLE) 138 return false; 139 } 140 return true; 141} 142 143const struct vpu_format *vpu_try_fmt_common(struct vpu_inst *inst, struct v4l2_format *f) 144{ 145 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 146 u32 type = f->type; 147 u32 stride = 1; 148 u32 bytesperline; 149 u32 sizeimage; 150 const struct vpu_format *fmt; 151 const struct vpu_core_resources *res; 152 int i; 153 154 fmt = vpu_helper_find_format(inst, type, pixmp->pixelformat); 155 if (!fmt) { 156 fmt = vpu_helper_enum_format(inst, type, 0); 157 if (!fmt) 158 return NULL; 159 pixmp->pixelformat = fmt->pixfmt; 160 } 161 162 res = vpu_get_resource(inst); 163 if (res) 164 stride = res->stride; 165 if (pixmp->width) 166 pixmp->width = vpu_helper_valid_frame_width(inst, pixmp->width); 167 if (pixmp->height) 168 pixmp->height = vpu_helper_valid_frame_height(inst, pixmp->height); 169 pixmp->flags = fmt->flags; 170 pixmp->num_planes = fmt->num_planes; 171 if (pixmp->field == V4L2_FIELD_ANY) 172 pixmp->field = V4L2_FIELD_NONE; 173 for (i = 0; i < pixmp->num_planes; i++) { 174 bytesperline = max_t(s32, pixmp->plane_fmt[i].bytesperline, 0); 175 sizeimage = vpu_helper_get_plane_size(pixmp->pixelformat, 176 pixmp->width, 177 pixmp->height, 178 i, 179 stride, 180 pixmp->field > V4L2_FIELD_NONE ? 1 : 0, 181 &bytesperline); 182 sizeimage = max_t(s32, pixmp->plane_fmt[i].sizeimage, sizeimage); 183 pixmp->plane_fmt[i].bytesperline = bytesperline; 184 pixmp->plane_fmt[i].sizeimage = sizeimage; 185 } 186 187 return fmt; 188} 189 190static bool vpu_check_ready(struct vpu_inst *inst, u32 type) 191{ 192 if (!inst) 193 return false; 194 if (inst->state == VPU_CODEC_STATE_DEINIT || inst->id < 0) 195 return false; 196 if (!inst->ops->check_ready) 197 return true; 198 return call_vop(inst, check_ready, type); 199} 200 201int vpu_process_output_buffer(struct vpu_inst *inst) 202{ 203 struct v4l2_m2m_buffer *buf = NULL; 204 struct vb2_v4l2_buffer *vbuf = NULL; 205 206 if (!inst || !inst->fh.m2m_ctx) 207 return -EINVAL; 208 209 if (!vpu_check_ready(inst, inst->out_format.type)) 210 return -EINVAL; 211 212 v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) { 213 vbuf = &buf->vb; 214 if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_IDLE) 215 break; 216 vbuf = NULL; 217 } 218 219 if (!vbuf) 220 return -EINVAL; 221 222 dev_dbg(inst->dev, "[%d]frame id = %d / %d\n", 223 inst->id, vbuf->sequence, inst->sequence); 224 return call_vop(inst, process_output, &vbuf->vb2_buf); 225} 226 227int vpu_process_capture_buffer(struct vpu_inst *inst) 228{ 229 struct v4l2_m2m_buffer *buf = NULL; 230 struct vb2_v4l2_buffer *vbuf = NULL; 231 232 if (!inst || !inst->fh.m2m_ctx) 233 return -EINVAL; 234 235 if (!vpu_check_ready(inst, inst->cap_format.type)) 236 return -EINVAL; 237 238 v4l2_m2m_for_each_dst_buf(inst->fh.m2m_ctx, buf) { 239 vbuf = &buf->vb; 240 if (vpu_get_buffer_state(vbuf) == VPU_BUF_STATE_IDLE) 241 break; 242 vbuf = NULL; 243 } 244 if (!vbuf) 245 return -EINVAL; 246 247 return call_vop(inst, process_capture, &vbuf->vb2_buf); 248} 249 250struct vb2_v4l2_buffer *vpu_next_src_buf(struct vpu_inst *inst) 251{ 252 struct vb2_v4l2_buffer *src_buf = v4l2_m2m_next_src_buf(inst->fh.m2m_ctx); 253 254 if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE) 255 return NULL; 256 257 while (vpu_vb_is_codecconfig(src_buf)) { 258 v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx); 259 vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE); 260 v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE); 261 262 src_buf = v4l2_m2m_next_src_buf(inst->fh.m2m_ctx); 263 if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE) 264 return NULL; 265 } 266 267 return src_buf; 268} 269 270void vpu_skip_frame(struct vpu_inst *inst, int count) 271{ 272 struct vb2_v4l2_buffer *src_buf; 273 enum vb2_buffer_state state; 274 int i = 0; 275 276 if (count <= 0) 277 return; 278 279 while (i < count) { 280 src_buf = v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx); 281 if (!src_buf || vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_IDLE) 282 return; 283 if (vpu_get_buffer_state(src_buf) == VPU_BUF_STATE_DECODED) 284 state = VB2_BUF_STATE_DONE; 285 else 286 state = VB2_BUF_STATE_ERROR; 287 i++; 288 vpu_set_buffer_state(src_buf, VPU_BUF_STATE_IDLE); 289 v4l2_m2m_buf_done(src_buf, state); 290 } 291} 292 293struct vb2_v4l2_buffer *vpu_find_buf_by_sequence(struct vpu_inst *inst, u32 type, u32 sequence) 294{ 295 struct v4l2_m2m_buffer *buf = NULL; 296 struct vb2_v4l2_buffer *vbuf = NULL; 297 298 if (!inst || !inst->fh.m2m_ctx) 299 return NULL; 300 301 if (V4L2_TYPE_IS_OUTPUT(type)) { 302 v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) { 303 vbuf = &buf->vb; 304 if (vbuf->sequence == sequence) 305 break; 306 vbuf = NULL; 307 } 308 } else { 309 v4l2_m2m_for_each_dst_buf(inst->fh.m2m_ctx, buf) { 310 vbuf = &buf->vb; 311 if (vbuf->sequence == sequence) 312 break; 313 vbuf = NULL; 314 } 315 } 316 317 return vbuf; 318} 319 320struct vb2_v4l2_buffer *vpu_find_buf_by_idx(struct vpu_inst *inst, u32 type, u32 idx) 321{ 322 struct v4l2_m2m_buffer *buf = NULL; 323 struct vb2_v4l2_buffer *vbuf = NULL; 324 325 if (!inst || !inst->fh.m2m_ctx) 326 return NULL; 327 328 if (V4L2_TYPE_IS_OUTPUT(type)) { 329 v4l2_m2m_for_each_src_buf(inst->fh.m2m_ctx, buf) { 330 vbuf = &buf->vb; 331 if (vbuf->vb2_buf.index == idx) 332 break; 333 vbuf = NULL; 334 } 335 } else { 336 v4l2_m2m_for_each_dst_buf(inst->fh.m2m_ctx, buf) { 337 vbuf = &buf->vb; 338 if (vbuf->vb2_buf.index == idx) 339 break; 340 vbuf = NULL; 341 } 342 } 343 344 return vbuf; 345} 346 347int vpu_get_num_buffers(struct vpu_inst *inst, u32 type) 348{ 349 struct vb2_queue *q; 350 351 if (!inst || !inst->fh.m2m_ctx) 352 return -EINVAL; 353 354 if (V4L2_TYPE_IS_OUTPUT(type)) 355 q = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx); 356 else 357 q = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx); 358 359 return q->num_buffers; 360} 361 362static void vpu_m2m_device_run(void *priv) 363{ 364} 365 366static void vpu_m2m_job_abort(void *priv) 367{ 368 struct vpu_inst *inst = priv; 369 struct v4l2_m2m_ctx *m2m_ctx = inst->fh.m2m_ctx; 370 371 v4l2_m2m_job_finish(m2m_ctx->m2m_dev, m2m_ctx); 372} 373 374static const struct v4l2_m2m_ops vpu_m2m_ops = { 375 .device_run = vpu_m2m_device_run, 376 .job_abort = vpu_m2m_job_abort 377}; 378 379static int vpu_vb2_queue_setup(struct vb2_queue *vq, 380 unsigned int *buf_count, 381 unsigned int *plane_count, 382 unsigned int psize[], 383 struct device *allocators[]) 384{ 385 struct vpu_inst *inst = vb2_get_drv_priv(vq); 386 struct vpu_format *cur_fmt; 387 int i; 388 389 cur_fmt = vpu_get_format(inst, vq->type); 390 391 if (*plane_count) { 392 if (*plane_count != cur_fmt->num_planes) 393 return -EINVAL; 394 for (i = 0; i < cur_fmt->num_planes; i++) { 395 if (psize[i] < cur_fmt->sizeimage[i]) 396 return -EINVAL; 397 } 398 return 0; 399 } 400 401 if (V4L2_TYPE_IS_OUTPUT(vq->type)) 402 *buf_count = max_t(unsigned int, *buf_count, inst->min_buffer_out); 403 else 404 *buf_count = max_t(unsigned int, *buf_count, inst->min_buffer_cap); 405 *plane_count = cur_fmt->num_planes; 406 for (i = 0; i < cur_fmt->num_planes; i++) 407 psize[i] = cur_fmt->sizeimage[i]; 408 409 return 0; 410} 411 412static int vpu_vb2_buf_init(struct vb2_buffer *vb) 413{ 414 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 415 416 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_IDLE); 417 return 0; 418} 419 420static int vpu_vb2_buf_out_validate(struct vb2_buffer *vb) 421{ 422 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 423 424 vbuf->field = V4L2_FIELD_NONE; 425 426 return 0; 427} 428 429static int vpu_vb2_buf_prepare(struct vb2_buffer *vb) 430{ 431 struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 432 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 433 struct vpu_format *cur_fmt; 434 u32 i; 435 436 cur_fmt = vpu_get_format(inst, vb->type); 437 for (i = 0; i < cur_fmt->num_planes; i++) { 438 if (vpu_get_vb_length(vb, i) < cur_fmt->sizeimage[i]) { 439 dev_dbg(inst->dev, "[%d] %s buf[%d] is invalid\n", 440 inst->id, vpu_type_name(vb->type), vb->index); 441 vpu_set_buffer_state(vbuf, VPU_BUF_STATE_ERROR); 442 } 443 } 444 445 return 0; 446} 447 448static void vpu_vb2_buf_finish(struct vb2_buffer *vb) 449{ 450 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 451 struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 452 struct vb2_queue *q = vb->vb2_queue; 453 454 if (vbuf->flags & V4L2_BUF_FLAG_LAST) 455 vpu_notify_eos(inst); 456 457 if (list_empty(&q->done_list)) 458 call_void_vop(inst, on_queue_empty, q->type); 459} 460 461void vpu_vb2_buffers_return(struct vpu_inst *inst, unsigned int type, enum vb2_buffer_state state) 462{ 463 struct vb2_v4l2_buffer *buf; 464 465 if (V4L2_TYPE_IS_OUTPUT(type)) { 466 while ((buf = v4l2_m2m_src_buf_remove(inst->fh.m2m_ctx))) { 467 vpu_set_buffer_state(buf, VPU_BUF_STATE_IDLE); 468 v4l2_m2m_buf_done(buf, state); 469 } 470 } else { 471 while ((buf = v4l2_m2m_dst_buf_remove(inst->fh.m2m_ctx))) { 472 vpu_set_buffer_state(buf, VPU_BUF_STATE_IDLE); 473 v4l2_m2m_buf_done(buf, state); 474 } 475 } 476} 477 478static int vpu_vb2_start_streaming(struct vb2_queue *q, unsigned int count) 479{ 480 struct vpu_inst *inst = vb2_get_drv_priv(q); 481 struct vpu_format *fmt = vpu_get_format(inst, q->type); 482 int ret; 483 484 vpu_inst_unlock(inst); 485 ret = vpu_inst_register(inst); 486 vpu_inst_lock(inst); 487 if (ret) { 488 vpu_vb2_buffers_return(inst, q->type, VB2_BUF_STATE_QUEUED); 489 return ret; 490 } 491 492 vpu_trace(inst->dev, "[%d] %s %c%c%c%c %dx%d %u(%u) %u(%u) %u(%u) %d\n", 493 inst->id, vpu_type_name(q->type), 494 fmt->pixfmt, 495 fmt->pixfmt >> 8, 496 fmt->pixfmt >> 16, 497 fmt->pixfmt >> 24, 498 fmt->width, fmt->height, 499 fmt->sizeimage[0], fmt->bytesperline[0], 500 fmt->sizeimage[1], fmt->bytesperline[1], 501 fmt->sizeimage[2], fmt->bytesperline[2], 502 q->num_buffers); 503 call_void_vop(inst, start, q->type); 504 vb2_clear_last_buffer_dequeued(q); 505 506 return 0; 507} 508 509static void vpu_vb2_stop_streaming(struct vb2_queue *q) 510{ 511 struct vpu_inst *inst = vb2_get_drv_priv(q); 512 513 vpu_trace(inst->dev, "[%d] %s\n", inst->id, vpu_type_name(q->type)); 514 515 call_void_vop(inst, stop, q->type); 516 vpu_vb2_buffers_return(inst, q->type, VB2_BUF_STATE_ERROR); 517 if (V4L2_TYPE_IS_OUTPUT(q->type)) 518 inst->sequence = 0; 519} 520 521static void vpu_vb2_buf_queue(struct vb2_buffer *vb) 522{ 523 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 524 struct vpu_inst *inst = vb2_get_drv_priv(vb->vb2_queue); 525 526 if (V4L2_TYPE_IS_OUTPUT(vb->type)) 527 vbuf->sequence = inst->sequence++; 528 529 v4l2_m2m_buf_queue(inst->fh.m2m_ctx, vbuf); 530 vpu_process_output_buffer(inst); 531 vpu_process_capture_buffer(inst); 532} 533 534static const struct vb2_ops vpu_vb2_ops = { 535 .queue_setup = vpu_vb2_queue_setup, 536 .buf_init = vpu_vb2_buf_init, 537 .buf_out_validate = vpu_vb2_buf_out_validate, 538 .buf_prepare = vpu_vb2_buf_prepare, 539 .buf_finish = vpu_vb2_buf_finish, 540 .start_streaming = vpu_vb2_start_streaming, 541 .stop_streaming = vpu_vb2_stop_streaming, 542 .buf_queue = vpu_vb2_buf_queue, 543 .wait_prepare = vb2_ops_wait_prepare, 544 .wait_finish = vb2_ops_wait_finish, 545}; 546 547static int vpu_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq) 548{ 549 struct vpu_inst *inst = priv; 550 int ret; 551 552 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 553 inst->out_format.type = src_vq->type; 554 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 555 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 556 src_vq->ops = &vpu_vb2_ops; 557 src_vq->mem_ops = &vb2_dma_contig_memops; 558 if (inst->type == VPU_CORE_TYPE_DEC && inst->use_stream_buffer) 559 src_vq->mem_ops = &vb2_vmalloc_memops; 560 src_vq->drv_priv = inst; 561 src_vq->buf_struct_size = sizeof(struct vpu_vb2_buffer); 562 src_vq->min_buffers_needed = 1; 563 src_vq->dev = inst->vpu->dev; 564 src_vq->lock = &inst->lock; 565 ret = vb2_queue_init(src_vq); 566 if (ret) 567 return ret; 568 569 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 570 inst->cap_format.type = dst_vq->type; 571 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 572 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 573 dst_vq->ops = &vpu_vb2_ops; 574 dst_vq->mem_ops = &vb2_dma_contig_memops; 575 if (inst->type == VPU_CORE_TYPE_ENC && inst->use_stream_buffer) 576 dst_vq->mem_ops = &vb2_vmalloc_memops; 577 dst_vq->drv_priv = inst; 578 dst_vq->buf_struct_size = sizeof(struct vpu_vb2_buffer); 579 dst_vq->min_buffers_needed = 1; 580 dst_vq->dev = inst->vpu->dev; 581 dst_vq->lock = &inst->lock; 582 ret = vb2_queue_init(dst_vq); 583 if (ret) { 584 vb2_queue_release(src_vq); 585 return ret; 586 } 587 588 return 0; 589} 590 591static int vpu_v4l2_release(struct vpu_inst *inst) 592{ 593 vpu_trace(inst->vpu->dev, "%p\n", inst); 594 595 vpu_release_core(inst->core); 596 put_device(inst->dev); 597 598 if (inst->workqueue) { 599 cancel_work_sync(&inst->msg_work); 600 destroy_workqueue(inst->workqueue); 601 inst->workqueue = NULL; 602 } 603 604 v4l2_ctrl_handler_free(&inst->ctrl_handler); 605 mutex_destroy(&inst->lock); 606 v4l2_fh_del(&inst->fh); 607 v4l2_fh_exit(&inst->fh); 608 609 call_void_vop(inst, cleanup); 610 611 return 0; 612} 613 614int vpu_v4l2_open(struct file *file, struct vpu_inst *inst) 615{ 616 struct vpu_dev *vpu = video_drvdata(file); 617 struct vpu_func *func; 618 int ret = 0; 619 620 if (!inst || !inst->ops) 621 return -EINVAL; 622 623 if (inst->type == VPU_CORE_TYPE_ENC) 624 func = &vpu->encoder; 625 else 626 func = &vpu->decoder; 627 628 atomic_set(&inst->ref_count, 0); 629 vpu_inst_get(inst); 630 inst->vpu = vpu; 631 inst->core = vpu_request_core(vpu, inst->type); 632 if (inst->core) 633 inst->dev = get_device(inst->core->dev); 634 mutex_init(&inst->lock); 635 INIT_LIST_HEAD(&inst->cmd_q); 636 inst->id = VPU_INST_NULL_ID; 637 inst->release = vpu_v4l2_release; 638 inst->pid = current->pid; 639 inst->tgid = current->tgid; 640 inst->min_buffer_cap = 2; 641 inst->min_buffer_out = 2; 642 v4l2_fh_init(&inst->fh, func->vfd); 643 v4l2_fh_add(&inst->fh); 644 645 ret = call_vop(inst, ctrl_init); 646 if (ret) 647 goto error; 648 649 inst->fh.m2m_ctx = v4l2_m2m_ctx_init(func->m2m_dev, inst, vpu_m2m_queue_init); 650 if (IS_ERR(inst->fh.m2m_ctx)) { 651 dev_err(vpu->dev, "v4l2_m2m_ctx_init fail\n"); 652 ret = PTR_ERR(inst->fh.m2m_ctx); 653 goto error; 654 } 655 656 inst->fh.ctrl_handler = &inst->ctrl_handler; 657 file->private_data = &inst->fh; 658 inst->state = VPU_CODEC_STATE_DEINIT; 659 inst->workqueue = alloc_workqueue("vpu_inst", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); 660 if (inst->workqueue) { 661 INIT_WORK(&inst->msg_work, vpu_inst_run_work); 662 ret = kfifo_init(&inst->msg_fifo, 663 inst->msg_buffer, 664 rounddown_pow_of_two(sizeof(inst->msg_buffer))); 665 if (ret) { 666 destroy_workqueue(inst->workqueue); 667 inst->workqueue = NULL; 668 } 669 } 670 vpu_trace(vpu->dev, "tgid = %d, pid = %d, type = %s, inst = %p\n", 671 inst->tgid, inst->pid, vpu_core_type_desc(inst->type), inst); 672 673 return 0; 674error: 675 vpu_inst_put(inst); 676 return ret; 677} 678 679int vpu_v4l2_close(struct file *file) 680{ 681 struct vpu_dev *vpu = video_drvdata(file); 682 struct vpu_inst *inst = to_inst(file); 683 684 vpu_trace(vpu->dev, "tgid = %d, pid = %d, inst = %p\n", inst->tgid, inst->pid, inst); 685 686 vpu_inst_lock(inst); 687 if (inst->fh.m2m_ctx) { 688 v4l2_m2m_ctx_release(inst->fh.m2m_ctx); 689 inst->fh.m2m_ctx = NULL; 690 } 691 vpu_inst_unlock(inst); 692 693 call_void_vop(inst, release); 694 vpu_inst_unregister(inst); 695 vpu_inst_put(inst); 696 697 return 0; 698} 699 700int vpu_add_func(struct vpu_dev *vpu, struct vpu_func *func) 701{ 702 struct video_device *vfd; 703 int ret; 704 705 if (!vpu || !func) 706 return -EINVAL; 707 708 if (func->vfd) 709 return 0; 710 711 func->m2m_dev = v4l2_m2m_init(&vpu_m2m_ops); 712 if (IS_ERR(func->m2m_dev)) { 713 dev_err(vpu->dev, "v4l2_m2m_init fail\n"); 714 func->vfd = NULL; 715 return PTR_ERR(func->m2m_dev); 716 } 717 718 vfd = video_device_alloc(); 719 if (!vfd) { 720 v4l2_m2m_release(func->m2m_dev); 721 dev_err(vpu->dev, "alloc vpu decoder video device fail\n"); 722 return -ENOMEM; 723 } 724 vfd->release = video_device_release; 725 vfd->vfl_dir = VFL_DIR_M2M; 726 vfd->v4l2_dev = &vpu->v4l2_dev; 727 vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; 728 if (func->type == VPU_CORE_TYPE_ENC) { 729 strscpy(vfd->name, "amphion-vpu-encoder", sizeof(vfd->name)); 730 vfd->fops = venc_get_fops(); 731 vfd->ioctl_ops = venc_get_ioctl_ops(); 732 } else { 733 strscpy(vfd->name, "amphion-vpu-decoder", sizeof(vfd->name)); 734 vfd->fops = vdec_get_fops(); 735 vfd->ioctl_ops = vdec_get_ioctl_ops(); 736 } 737 738 ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1); 739 if (ret) { 740 video_device_release(vfd); 741 v4l2_m2m_release(func->m2m_dev); 742 return ret; 743 } 744 video_set_drvdata(vfd, vpu); 745 func->vfd = vfd; 746 747 ret = v4l2_m2m_register_media_controller(func->m2m_dev, func->vfd, func->function); 748 if (ret) { 749 v4l2_m2m_release(func->m2m_dev); 750 func->m2m_dev = NULL; 751 video_unregister_device(func->vfd); 752 func->vfd = NULL; 753 return ret; 754 } 755 756 return 0; 757} 758 759void vpu_remove_func(struct vpu_func *func) 760{ 761 if (!func) 762 return; 763 764 if (func->m2m_dev) { 765 v4l2_m2m_unregister_media_controller(func->m2m_dev); 766 v4l2_m2m_release(func->m2m_dev); 767 func->m2m_dev = NULL; 768 } 769 if (func->vfd) { 770 video_unregister_device(func->vfd); 771 func->vfd = NULL; 772 } 773}