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 273 if (vb2_is_busy(q)) 274 return -EBUSY; 275 276 switch (f->type) { 277 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 278 return iris_venc_s_fmt_input(inst, f); 279 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 280 return iris_venc_s_fmt_output(inst, f); 281 default: 282 return -EINVAL; 283 } 284 } 285 286 int iris_venc_validate_format(struct iris_inst *inst, u32 pixelformat) 287 { 288 const struct iris_fmt *fmt = NULL; 289 290 if (pixelformat != V4L2_PIX_FMT_NV12) { 291 fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 292 if (!fmt) 293 return -EINVAL; 294 } 295 296 return 0; 297 } 298 299 int iris_venc_subscribe_event(struct iris_inst *inst, 300 const struct v4l2_event_subscription *sub) 301 { 302 switch (sub->type) { 303 case V4L2_EVENT_EOS: 304 return v4l2_event_subscribe(&inst->fh, sub, 0, NULL); 305 case V4L2_EVENT_CTRL: 306 return v4l2_ctrl_subscribe_event(&inst->fh, sub); 307 default: 308 return -EINVAL; 309 } 310 } 311 312 int iris_venc_s_selection(struct iris_inst *inst, struct v4l2_selection *s) 313 { 314 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 315 return -EINVAL; 316 317 switch (s->target) { 318 case V4L2_SEL_TGT_CROP: 319 s->r.left = 0; 320 s->r.top = 0; 321 322 if (s->r.width > inst->fmt_src->fmt.pix_mp.width || 323 s->r.height > inst->fmt_src->fmt.pix_mp.height) 324 return -EINVAL; 325 326 inst->crop.left = s->r.left; 327 inst->crop.top = s->r.top; 328 inst->crop.width = s->r.width; 329 inst->crop.height = s->r.height; 330 inst->fmt_dst->fmt.pix_mp.width = inst->crop.width; 331 inst->fmt_dst->fmt.pix_mp.height = inst->crop.height; 332 return iris_venc_s_fmt_output(inst, inst->fmt_dst); 333 default: 334 return -EINVAL; 335 } 336 } 337 338 int iris_venc_s_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm) 339 { 340 struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps; 341 struct vb2_queue *src_q = v4l2_m2m_get_src_vq(inst->m2m_ctx); 342 struct vb2_queue *dst_q = v4l2_m2m_get_dst_vq(inst->m2m_ctx); 343 struct v4l2_fract *timeperframe = NULL; 344 u32 default_rate = DEFAULT_FPS; 345 bool is_frame_rate = false; 346 u64 us_per_frame, fps; 347 u32 max_rate; 348 349 int ret = 0; 350 351 if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 352 timeperframe = &s_parm->parm.output.timeperframe; 353 max_rate = caps->max_operating_rate; 354 s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; 355 } else { 356 timeperframe = &s_parm->parm.capture.timeperframe; 357 is_frame_rate = true; 358 max_rate = caps->max_frame_rate; 359 s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; 360 } 361 362 if (!timeperframe->denominator || !timeperframe->numerator) { 363 if (!timeperframe->numerator) 364 timeperframe->numerator = 1; 365 if (!timeperframe->denominator) 366 timeperframe->denominator = default_rate; 367 } 368 369 us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC; 370 do_div(us_per_frame, timeperframe->denominator); 371 372 if (!us_per_frame) 373 return -EINVAL; 374 375 fps = (u64)USEC_PER_SEC; 376 do_div(fps, us_per_frame); 377 if (fps > max_rate) { 378 ret = -ENOMEM; 379 goto reset_rate; 380 } 381 382 if (is_frame_rate) 383 inst->frame_rate = (u32)fps; 384 else 385 inst->operating_rate = (u32)fps; 386 387 if ((s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && vb2_is_streaming(src_q)) || 388 (s_parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && vb2_is_streaming(dst_q))) { 389 ret = iris_check_core_mbpf(inst); 390 if (ret) 391 goto reset_rate; 392 ret = iris_check_core_mbps(inst); 393 if (ret) 394 goto reset_rate; 395 } 396 397 return 0; 398 399 reset_rate: 400 if (ret) { 401 if (is_frame_rate) 402 inst->frame_rate = default_rate; 403 else 404 inst->operating_rate = default_rate; 405 } 406 407 return ret; 408 } 409 410 int iris_venc_g_param(struct iris_inst *inst, struct v4l2_streamparm *s_parm) 411 { 412 struct v4l2_fract *timeperframe = NULL; 413 414 if (s_parm->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 415 timeperframe = &s_parm->parm.output.timeperframe; 416 timeperframe->numerator = 1; 417 timeperframe->denominator = inst->operating_rate; 418 s_parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; 419 } else { 420 timeperframe = &s_parm->parm.capture.timeperframe; 421 timeperframe->numerator = 1; 422 timeperframe->denominator = inst->frame_rate; 423 s_parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; 424 } 425 426 return 0; 427 } 428 429 int iris_venc_streamon_input(struct iris_inst *inst) 430 { 431 int ret; 432 433 ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 434 if (ret) 435 return ret; 436 437 ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP); 438 if (ret) 439 return ret; 440 441 iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 442 443 ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 444 if (ret) 445 return ret; 446 447 ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 448 if (ret) 449 return ret; 450 451 ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 452 if (ret) 453 return ret; 454 455 return iris_process_streamon_input(inst); 456 } 457 458 int iris_venc_streamon_output(struct iris_inst *inst) 459 { 460 int ret; 461 462 ret = iris_set_properties(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 463 if (ret) 464 goto error; 465 466 ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP); 467 if (ret) 468 return ret; 469 470 iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 471 472 ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 473 if (ret) 474 goto error; 475 476 ret = iris_create_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 477 if (ret) 478 goto error; 479 480 ret = iris_queue_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 481 if (ret) 482 goto error; 483 484 ret = iris_process_streamon_output(inst); 485 if (ret) 486 goto error; 487 488 return ret; 489 490 error: 491 iris_session_streamoff(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 492 493 return ret; 494 } 495 496 int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer *vbuf) 497 { 498 struct iris_buffer *buf = to_iris_buffer(vbuf); 499 struct vb2_buffer *vb2 = &vbuf->vb2_buf; 500 struct vb2_queue *q; 501 int ret; 502 503 ret = iris_vb2_buffer_to_driver(vb2, buf); 504 if (ret) 505 return ret; 506 507 if (buf->type == BUF_INPUT) 508 iris_set_ts_metadata(inst, vbuf); 509 510 q = v4l2_m2m_get_vq(inst->m2m_ctx, vb2->type); 511 if (!vb2_is_streaming(q)) { 512 buf->attr |= BUF_ATTR_DEFERRED; 513 return 0; 514 } 515 516 iris_scale_power(inst); 517 518 return iris_queue_buffer(inst, buf); 519 } 520 521 int iris_venc_start_cmd(struct iris_inst *inst) 522 { 523 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 524 enum iris_inst_sub_state clear_sub_state = 0; 525 struct vb2_queue *dst_vq; 526 int ret; 527 528 dst_vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx); 529 530 if (inst->sub_state & IRIS_INST_SUB_DRAIN && 531 inst->sub_state & IRIS_INST_SUB_DRAIN_LAST) { 532 vb2_clear_last_buffer_dequeued(dst_vq); 533 clear_sub_state = IRIS_INST_SUB_DRAIN | IRIS_INST_SUB_DRAIN_LAST; 534 if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) { 535 if (hfi_ops->session_resume_drain) { 536 ret = hfi_ops->session_resume_drain(inst, 537 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 538 if (ret) 539 return ret; 540 } 541 clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE; 542 } 543 if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE) { 544 if (hfi_ops->session_resume_drain) { 545 ret = hfi_ops->session_resume_drain(inst, 546 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 547 if (ret) 548 return ret; 549 } 550 clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE; 551 } 552 } else { 553 dev_err(inst->core->dev, "start called before receiving last_flag\n"); 554 iris_inst_change_state(inst, IRIS_INST_ERROR); 555 return -EBUSY; 556 } 557 558 inst->last_buffer_dequeued = false; 559 560 return iris_inst_change_sub_state(inst, clear_sub_state, 0); 561 } 562 563 int iris_venc_stop_cmd(struct iris_inst *inst) 564 { 565 const struct iris_hfi_command_ops *hfi_ops = inst->core->hfi_ops; 566 int ret; 567 568 ret = hfi_ops->session_drain(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 569 if (ret) 570 return ret; 571 572 ret = iris_inst_change_sub_state(inst, 0, IRIS_INST_SUB_DRAIN); 573 574 iris_scale_power(inst); 575 576 return ret; 577 } 578