1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include <media/v4l2-event.h> 7 #include <media/v4l2-mem2mem.h> 8 9 #include "iris_buffer.h" 10 #include "iris_common.h" 11 #include "iris_ctrls.h" 12 #include "iris_instance.h" 13 #include "iris_power.h" 14 #include "iris_venc.h" 15 #include "iris_vpu_buffer.h" 16 17 int iris_venc_inst_init(struct iris_inst *inst) 18 { 19 struct iris_core *core = inst->core; 20 struct v4l2_format *f; 21 22 inst->fmt_src = kzalloc(sizeof(*inst->fmt_src), GFP_KERNEL); 23 inst->fmt_dst = kzalloc(sizeof(*inst->fmt_dst), GFP_KERNEL); 24 if (!inst->fmt_src || !inst->fmt_dst) { 25 kfree(inst->fmt_src); 26 kfree(inst->fmt_dst); 27 return -ENOMEM; 28 } 29 30 f = inst->fmt_dst; 31 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 32 f->fmt.pix_mp.width = DEFAULT_WIDTH; 33 f->fmt.pix_mp.height = DEFAULT_HEIGHT; 34 f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264; 35 inst->codec = f->fmt.pix_mp.pixelformat; 36 f->fmt.pix_mp.num_planes = 1; 37 f->fmt.pix_mp.plane_fmt[0].bytesperline = 0; 38 f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); 39 f->fmt.pix_mp.field = V4L2_FIELD_NONE; 40 f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; 41 f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; 42 f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 43 f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; 44 inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); 45 inst->buffers[BUF_OUTPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; 46 47 f = inst->fmt_src; 48 f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 49 f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12; 50 f->fmt.pix_mp.width = ALIGN(DEFAULT_WIDTH, 128); 51 f->fmt.pix_mp.height = ALIGN(DEFAULT_HEIGHT, 32); 52 f->fmt.pix_mp.num_planes = 1; 53 f->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(DEFAULT_WIDTH, 128); 54 f->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); 55 f->fmt.pix_mp.field = V4L2_FIELD_NONE; 56 f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; 57 f->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_DEFAULT; 58 f->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 59 f->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; 60 inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); 61 inst->buffers[BUF_INPUT].size = f->fmt.pix_mp.plane_fmt[0].sizeimage; 62 63 inst->crop.left = 0; 64 inst->crop.top = 0; 65 inst->crop.width = f->fmt.pix_mp.width; 66 inst->crop.height = f->fmt.pix_mp.height; 67 68 inst->operating_rate = DEFAULT_FPS; 69 inst->frame_rate = DEFAULT_FPS; 70 71 memcpy(&inst->fw_caps[0], &core->inst_fw_caps_enc[0], 72 INST_FW_CAP_MAX * sizeof(struct platform_inst_fw_cap)); 73 74 return iris_ctrls_init(inst); 75 } 76 77 void iris_venc_inst_deinit(struct iris_inst *inst) 78 { 79 kfree(inst->fmt_dst); 80 kfree(inst->fmt_src); 81 } 82 83 static const struct iris_fmt iris_venc_formats[] = { 84 [IRIS_FMT_H264] = { 85 .pixfmt = V4L2_PIX_FMT_H264, 86 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 87 }, 88 [IRIS_FMT_HEVC] = { 89 .pixfmt = V4L2_PIX_FMT_HEVC, 90 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 91 }, 92 }; 93 94 static const struct iris_fmt * 95 find_format(struct iris_inst *inst, u32 pixfmt, u32 type) 96 { 97 const struct iris_fmt *fmt = iris_venc_formats; 98 unsigned int size = ARRAY_SIZE(iris_venc_formats); 99 unsigned int i; 100 101 for (i = 0; i < size; i++) { 102 if (fmt[i].pixfmt == pixfmt) 103 break; 104 } 105 106 if (i == size || fmt[i].type != type) 107 return NULL; 108 109 return &fmt[i]; 110 } 111 112 static const struct iris_fmt * 113 find_format_by_index(struct iris_inst *inst, u32 index, u32 type) 114 { 115 const struct iris_fmt *fmt = iris_venc_formats; 116 unsigned int size = ARRAY_SIZE(iris_venc_formats); 117 118 if (index >= size || fmt[index].type != type) 119 return NULL; 120 121 return &fmt[index]; 122 } 123 124 int iris_venc_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f) 125 { 126 const struct iris_fmt *fmt; 127 128 switch (f->type) { 129 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 130 if (f->index) 131 return -EINVAL; 132 f->pixelformat = V4L2_PIX_FMT_NV12; 133 break; 134 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 135 fmt = find_format_by_index(inst, f->index, f->type); 136 if (!fmt) 137 return -EINVAL; 138 139 f->pixelformat = fmt->pixfmt; 140 f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL; 141 break; 142 default: 143 return -EINVAL; 144 } 145 146 return 0; 147 } 148 149 int iris_venc_try_fmt(struct iris_inst *inst, struct v4l2_format *f) 150 { 151 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 152 const struct iris_fmt *fmt; 153 struct v4l2_format *f_inst; 154 155 memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); 156 fmt = find_format(inst, pixmp->pixelformat, f->type); 157 switch (f->type) { 158 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 159 if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) { 160 f_inst = inst->fmt_src; 161 f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; 162 f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; 163 f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; 164 } 165 break; 166 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 167 if (!fmt) { 168 f_inst = inst->fmt_dst; 169 f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width; 170 f->fmt.pix_mp.height = f_inst->fmt.pix_mp.height; 171 f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat; 172 } 173 break; 174 default: 175 return -EINVAL; 176 } 177 178 if (pixmp->field == V4L2_FIELD_ANY) 179 pixmp->field = V4L2_FIELD_NONE; 180 181 pixmp->num_planes = 1; 182 183 return 0; 184 } 185 186 static int iris_venc_s_fmt_output(struct iris_inst *inst, struct v4l2_format *f) 187 { 188 struct v4l2_format *fmt; 189 190 iris_venc_try_fmt(inst, f); 191 192 if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type))) 193 return -EINVAL; 194 195 fmt = inst->fmt_dst; 196 fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 197 fmt->fmt.pix_mp.num_planes = 1; 198 fmt->fmt.pix_mp.plane_fmt[0].bytesperline = 0; 199 fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT); 200 201 if (f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_DEFAULT && 202 f->fmt.pix_mp.colorspace != V4L2_COLORSPACE_REC709) 203 f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; 204 fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; 205 fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; 206 fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; 207 fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; 208 209 inst->buffers[BUF_OUTPUT].min_count = iris_vpu_buf_count(inst, BUF_OUTPUT); 210 inst->buffers[BUF_OUTPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; 211 fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; 212 inst->codec = f->fmt.pix_mp.pixelformat; 213 memcpy(f, fmt, sizeof(struct v4l2_format)); 214 215 return 0; 216 } 217 218 static int iris_venc_s_fmt_input(struct iris_inst *inst, struct v4l2_format *f) 219 { 220 struct v4l2_format *fmt, *output_fmt; 221 222 iris_venc_try_fmt(inst, f); 223 224 if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) 225 return -EINVAL; 226 227 fmt = inst->fmt_src; 228 fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 229 fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128); 230 fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32); 231 fmt->fmt.pix_mp.num_planes = 1; 232 fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; 233 fmt->fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(f->fmt.pix_mp.width, 128); 234 fmt->fmt.pix_mp.plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_INPUT); 235 236 fmt->fmt.pix_mp.colorspace = f->fmt.pix_mp.colorspace; 237 fmt->fmt.pix_mp.xfer_func = f->fmt.pix_mp.xfer_func; 238 fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; 239 fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; 240 241 output_fmt = inst->fmt_dst; 242 output_fmt->fmt.pix_mp.width = fmt->fmt.pix_mp.width; 243 output_fmt->fmt.pix_mp.height = fmt->fmt.pix_mp.height; 244 output_fmt->fmt.pix_mp.colorspace = fmt->fmt.pix_mp.colorspace; 245 output_fmt->fmt.pix_mp.xfer_func = fmt->fmt.pix_mp.xfer_func; 246 output_fmt->fmt.pix_mp.ycbcr_enc = fmt->fmt.pix_mp.ycbcr_enc; 247 output_fmt->fmt.pix_mp.quantization = fmt->fmt.pix_mp.quantization; 248 249 inst->buffers[BUF_INPUT].min_count = iris_vpu_buf_count(inst, BUF_INPUT); 250 inst->buffers[BUF_INPUT].size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; 251 252 if (f->fmt.pix_mp.width != inst->crop.width || 253 f->fmt.pix_mp.height != inst->crop.height) { 254 inst->crop.top = 0; 255 inst->crop.left = 0; 256 inst->crop.width = fmt->fmt.pix_mp.width; 257 inst->crop.height = fmt->fmt.pix_mp.height; 258 259 iris_venc_s_fmt_output(inst, output_fmt); 260 } 261 262 memcpy(f, fmt, sizeof(struct v4l2_format)); 263 264 return 0; 265 } 266 267 int iris_venc_s_fmt(struct iris_inst *inst, struct v4l2_format *f) 268 { 269 struct vb2_queue *q; 270 271 q = v4l2_m2m_get_vq(inst->m2m_ctx, f->type); 272 if (!q) 273 return -EINVAL; 274 275 if (vb2_is_busy(q)) 276 return -EBUSY; 277 278 switch (f->type) { 279 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 280 return iris_venc_s_fmt_input(inst, f); 281 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 282 return iris_venc_s_fmt_output(inst, f); 283 default: 284 return -EINVAL; 285 } 286 } 287 288 int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat) 289 { 290 const struct iris_fmt *fmt = NULL; 291 292 if (pixelformat != V4L2_PIX_FMT_NV12) { 293 fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 294 if (!fmt) 295 return -EINVAL; 296 } 297 298 return 0; 299 } 300 301 int iris_venc_subscribe_event(struct iris_inst *inst, 302 const struct v4l2_event_subscription *sub) 303 { 304 switch (sub->type) { 305 case V4L2_EVENT_EOS: 306 return v4l2_event_subscribe(&inst->fh, sub, 0, NULL); 307 case V4L2_EVENT_CTRL: 308 return v4l2_ctrl_subscribe_event(&inst->fh, sub); 309 default: 310 return -EINVAL; 311 } 312 } 313 314 int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s) 315 { 316 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 317 return -EINVAL; 318 319 switch (s->target) { 320 case V4L2_SEL_TGT_CROP: 321 s->r.left = 0; 322 s->r.top = 0; 323 324 if (s->r.width > inst->fmt_src->fmt.pix_mp.width || 325 s->r.height > inst->fmt_src->fmt.pix_mp.height) 326 return -EINVAL; 327 328 inst->crop.left = s->r.left; 329 inst->crop.top = s->r.top; 330 inst->crop.width = s->r.width; 331 inst->crop.height = s->r.height; 332 inst->fmt_dst->fmt.pix_mp.width = inst->crop.width; 333 inst->fmt_dst->fmt.pix_mp.height = inst->crop.height; 334 return iris_venc_s_fmt_output(inst, inst->fmt_dst); 335 default: 336 return -EINVAL; 337 } 338 } 339 340 int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm) 341 { 342 struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; 343 struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); 344 struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); 345 struct v4l2_fract *timeperframe = NULL; 346 u32 default_rate = DEFAULT_FPS; 347 bool is_frame_rate = false; 348 u64 us_per_frame, fps; 349 u32 max_rate; 350 351 int ret = 0; 352 353 if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 354 timeperframe = &s_parm->parm.output.timeperframe; 355 max_rate = caps->max_operating_rate; 356 s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; 357 } else { 358 timeperframe = &s_parm->parm.capture.timeperframe; 359 is_frame_rate = true; 360 max_rate = caps->max_frame_rate; 361 s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; 362 } 363 364 if (!timeperframe->denominator || !timeperframe->numerator) { 365 if (!timeperframe->numerator) 366 timeperframe->numerator = 1; 367 if (!timeperframe->denominator) 368 timeperframe->denominator = default_rate; 369 } 370 371 us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC; 372 do_div(us_per_frame, timeperframe->denominator); 373 374 if (!us_per_frame) 375 return -EINVAL; 376 377 fps = (u64)USEC_PER_SEC; 378 do_div(fps, us_per_frame); 379 if (fps > max_rate) { 380 ret = -ENOMEM; 381 goto reset_rate; 382 } 383 384 if (is_frame_rate) 385 inst->frame_rate = (u32)fps; 386 else 387 inst->operating_rate = (u32)fps; 388 389 if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && vb2_is_streaming(src_q)) || 390 (s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && vb2_is_streaming(dst_q))) { 391 ret = iris_check_core_mbpf(inst); 392 if (ret) 393 goto reset_rate; 394 ret = iris_check_core_mbps(inst); 395 if (ret) 396 goto reset_rate; 397 } 398 399 return 0; 400 401 reset_rate: 402 if (ret) { 403 if (is_frame_rate) 404 inst->frame_rate = default_rate; 405 else 406 inst->operating_rate = default_rate; 407 } 408 409 return ret; 410 } 411 412 int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm) 413 { 414 struct v4l2_fract *timeperframe = NULL; 415 416 if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 417 timeperframe = &s_parm->parm.output.timeperframe; 418 timeperframe->numerator = 1; 419 timeperframe->denominator = inst->operating_rate; 420 s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; 421 } else { 422 timeperframe = &s_parm->parm.capture.timeperframe; 423 timeperframe->numerator = 1; 424 timeperframe->denominator = inst->frame_rate; 425 s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; 426 } 427 428 return 0; 429 } 430 431 int iris_venc_streamon_input(struct iris_inst *inst) 432 { 433 int ret; 434 435 ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 436 if (ret) 437 return ret; 438 439 ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP); 440 if (ret) 441 return ret; 442 443 iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 444 445 ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 446 if (ret) 447 return ret; 448 449 ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 450 if (ret) 451 return ret; 452 453 ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 454 if (ret) 455 return ret; 456 457 return iris_process_streamon_input(inst); 458 } 459 460 int iris_venc_streamon_output(struct iris_inst *inst) 461 { 462 int ret; 463 464 ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 465 if (ret) 466 goto error; 467 468 ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP); 469 if (ret) 470 return ret; 471 472 iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 473 474 ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 475 if (ret) 476 goto error; 477 478 ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 479 if (ret) 480 goto error; 481 482 ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 483 if (ret) 484 goto error; 485 486 ret = iris_process_streamon_output(inst); 487 if (ret) 488 goto error; 489 490 return ret; 491 492 error: 493 iris_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 494 495 return ret; 496 } 497 498 int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) 499 { 500 struct iris_buffer *buf = to_iris_buffer(vbuf); 501 struct vb2_buffer *vb2 = &vbuf->vb2_buf; 502 struct vb2_queue *q; 503 int ret; 504 505 ret = iris_vb2_buffer_to_driver(vb2, buf); 506 if (ret) 507 return ret; 508 509 if (buf->type == BUF_INPUT) 510 iris_set_ts_metadata(inst, vbuf); 511 512 q = v4l2_m2m_get_vq(inst->m2m_ctx, vb2->type); 513 if (!vb2_is_streaming(q)) { 514 buf->attr |= BUF_ATTR_DEFERRED; 515 return 0; 516 } 517 518 iris_scale_power(inst); 519 520 return iris_queue_buffer(inst, buf); 521 } 522 523 int iris_venc_start_cmd(struct iris_inst *inst) 524 { 525 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 526 enum iris_inst_sub_state clear_sub_state = 0; 527 struct vb2_queue *dst_vq; 528 int ret; 529 530 dst_vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx); 531 532 if (inst->sub_state & IRIS_INST_SUB_DRAIN && 533 inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) { 534 vb2_clear_last_buffer_dequeued(dst_vq); 535 clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; 536 if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { 537 if (hfi_ops->session_resume_drain) { 538 ret = hfi_ops->session_resume_drain(inst, 539 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 540 if (ret) 541 return ret; 542 } 543 clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; 544 } 545 if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) { 546 if (hfi_ops->session_resume_drain) { 547 ret = hfi_ops->session_resume_drain(inst, 548 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 549 if (ret) 550 return ret; 551 } 552 clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; 553 } 554 } else { 555 dev_err(inst->core->dev, "start called before receiving last_flag\n"); 556 iris_inst_change_state(inst, IRIS_INST_ERROR); 557 return -EBUSY; 558 } 559 560 inst->last_buffer_dequeued = false; 561 562 return iris_inst_change_sub_state(inst, clear_sub_state, 0); 563 } 564 565 int iris_venc_stop_cmd(struct iris_inst *inst) 566 { 567 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 568 int ret; 569 570 ret = hfi_ops->session_drain(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 571 if (ret) 572 return ret; 573 574 ret = iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_DRAIN); 575 576 iris_scale_power(inst); 577 578 return ret; 579 } 580