1 /* 2 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. 3 * Copyright (C) 2017 Linaro Ltd. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 and 7 * only version 2 as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 */ 15 #include <linux/clk.h> 16 #include <linux/module.h> 17 #include <linux/mod_devicetable.h> 18 #include <linux/platform_device.h> 19 #include <linux/pm_runtime.h> 20 #include <linux/slab.h> 21 #include <media/v4l2-mem2mem.h> 22 #include <media/videobuf2-dma-sg.h> 23 #include <media/v4l2-ioctl.h> 24 #include <media/v4l2-event.h> 25 #include <media/v4l2-ctrls.h> 26 27 #include "hfi_venus_io.h" 28 #include "hfi_parser.h" 29 #include "core.h" 30 #include "helpers.h" 31 #include "venc.h" 32 33 #define NUM_B_FRAMES_MAX 4 34 35 /* 36 * Three resons to keep MPLANE formats (despite that the number of planes 37 * currently is one): 38 * - the MPLANE formats allow only one plane to be used 39 * - the downstream driver use MPLANE formats too 40 * - future firmware versions could add support for >1 planes 41 */ 42 static const struct venus_format venc_formats[] = { 43 { 44 .pixfmt = V4L2_PIX_FMT_NV12, 45 .num_planes = 1, 46 .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 47 }, { 48 .pixfmt = V4L2_PIX_FMT_MPEG4, 49 .num_planes = 1, 50 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 51 }, { 52 .pixfmt = V4L2_PIX_FMT_H263, 53 .num_planes = 1, 54 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 55 }, { 56 .pixfmt = V4L2_PIX_FMT_H264, 57 .num_planes = 1, 58 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 59 }, { 60 .pixfmt = V4L2_PIX_FMT_VP8, 61 .num_planes = 1, 62 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 63 }, { 64 .pixfmt = V4L2_PIX_FMT_HEVC, 65 .num_planes = 1, 66 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 67 }, 68 }; 69 70 static const struct venus_format * 71 find_format(struct venus_inst *inst, u32 pixfmt, u32 type) 72 { 73 const struct venus_format *fmt = venc_formats; 74 unsigned int size = ARRAY_SIZE(venc_formats); 75 unsigned int i; 76 77 for (i = 0; i < size; i++) { 78 if (fmt[i].pixfmt == pixfmt) 79 break; 80 } 81 82 if (i == size || fmt[i].type != type) 83 return NULL; 84 85 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 86 !venus_helper_check_codec(inst, fmt[i].pixfmt)) 87 return NULL; 88 89 return &fmt[i]; 90 } 91 92 static const struct venus_format * 93 find_format_by_index(struct venus_inst *inst, unsigned int index, u32 type) 94 { 95 const struct venus_format *fmt = venc_formats; 96 unsigned int size = ARRAY_SIZE(venc_formats); 97 unsigned int i, k = 0; 98 99 if (index > size) 100 return NULL; 101 102 for (i = 0; i < size; i++) { 103 bool valid; 104 105 if (fmt[i].type != type) 106 continue; 107 valid = type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || 108 venus_helper_check_codec(inst, fmt[i].pixfmt); 109 if (k == index && valid) 110 break; 111 if (valid) 112 k++; 113 } 114 115 if (i == size) 116 return NULL; 117 118 return &fmt[i]; 119 } 120 121 static int venc_v4l2_to_hfi(int id, int value) 122 { 123 switch (id) { 124 case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL: 125 switch (value) { 126 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0: 127 default: 128 return HFI_MPEG4_LEVEL_0; 129 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B: 130 return HFI_MPEG4_LEVEL_0b; 131 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_1: 132 return HFI_MPEG4_LEVEL_1; 133 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_2: 134 return HFI_MPEG4_LEVEL_2; 135 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_3: 136 return HFI_MPEG4_LEVEL_3; 137 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_4: 138 return HFI_MPEG4_LEVEL_4; 139 case V4L2_MPEG_VIDEO_MPEG4_LEVEL_5: 140 return HFI_MPEG4_LEVEL_5; 141 } 142 case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE: 143 switch (value) { 144 case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE: 145 default: 146 return HFI_MPEG4_PROFILE_SIMPLE; 147 case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE: 148 return HFI_MPEG4_PROFILE_ADVANCEDSIMPLE; 149 } 150 case V4L2_CID_MPEG_VIDEO_H264_PROFILE: 151 switch (value) { 152 case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: 153 return HFI_H264_PROFILE_BASELINE; 154 case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: 155 return HFI_H264_PROFILE_CONSTRAINED_BASE; 156 case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: 157 return HFI_H264_PROFILE_MAIN; 158 case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: 159 default: 160 return HFI_H264_PROFILE_HIGH; 161 } 162 case V4L2_CID_MPEG_VIDEO_H264_LEVEL: 163 switch (value) { 164 case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: 165 return HFI_H264_LEVEL_1; 166 case V4L2_MPEG_VIDEO_H264_LEVEL_1B: 167 return HFI_H264_LEVEL_1b; 168 case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: 169 return HFI_H264_LEVEL_11; 170 case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: 171 return HFI_H264_LEVEL_12; 172 case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: 173 return HFI_H264_LEVEL_13; 174 case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: 175 return HFI_H264_LEVEL_2; 176 case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: 177 return HFI_H264_LEVEL_21; 178 case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: 179 return HFI_H264_LEVEL_22; 180 case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: 181 return HFI_H264_LEVEL_3; 182 case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: 183 return HFI_H264_LEVEL_31; 184 case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: 185 return HFI_H264_LEVEL_32; 186 case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: 187 return HFI_H264_LEVEL_4; 188 case V4L2_MPEG_VIDEO_H264_LEVEL_4_1: 189 return HFI_H264_LEVEL_41; 190 case V4L2_MPEG_VIDEO_H264_LEVEL_4_2: 191 return HFI_H264_LEVEL_42; 192 case V4L2_MPEG_VIDEO_H264_LEVEL_5_0: 193 default: 194 return HFI_H264_LEVEL_5; 195 case V4L2_MPEG_VIDEO_H264_LEVEL_5_1: 196 return HFI_H264_LEVEL_51; 197 } 198 case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE: 199 switch (value) { 200 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC: 201 default: 202 return HFI_H264_ENTROPY_CAVLC; 203 case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC: 204 return HFI_H264_ENTROPY_CABAC; 205 } 206 case V4L2_CID_MPEG_VIDEO_VP8_PROFILE: 207 switch (value) { 208 case 0: 209 default: 210 return HFI_VPX_PROFILE_VERSION_0; 211 case 1: 212 return HFI_VPX_PROFILE_VERSION_1; 213 case 2: 214 return HFI_VPX_PROFILE_VERSION_2; 215 case 3: 216 return HFI_VPX_PROFILE_VERSION_3; 217 } 218 case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE: 219 switch (value) { 220 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED: 221 default: 222 return HFI_H264_DB_MODE_ALL_BOUNDARY; 223 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED: 224 return HFI_H264_DB_MODE_DISABLE; 225 case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY: 226 return HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY; 227 } 228 case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE: 229 switch (value) { 230 case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN: 231 default: 232 return HFI_HEVC_PROFILE_MAIN; 233 case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE: 234 return HFI_HEVC_PROFILE_MAIN_STILL_PIC; 235 case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10: 236 return HFI_HEVC_PROFILE_MAIN10; 237 } 238 case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL: 239 switch (value) { 240 case V4L2_MPEG_VIDEO_HEVC_LEVEL_1: 241 default: 242 return HFI_HEVC_LEVEL_1; 243 case V4L2_MPEG_VIDEO_HEVC_LEVEL_2: 244 return HFI_HEVC_LEVEL_2; 245 case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1: 246 return HFI_HEVC_LEVEL_21; 247 case V4L2_MPEG_VIDEO_HEVC_LEVEL_3: 248 return HFI_HEVC_LEVEL_3; 249 case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1: 250 return HFI_HEVC_LEVEL_31; 251 case V4L2_MPEG_VIDEO_HEVC_LEVEL_4: 252 return HFI_HEVC_LEVEL_4; 253 case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1: 254 return HFI_HEVC_LEVEL_41; 255 case V4L2_MPEG_VIDEO_HEVC_LEVEL_5: 256 return HFI_HEVC_LEVEL_5; 257 case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1: 258 return HFI_HEVC_LEVEL_51; 259 case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2: 260 return HFI_HEVC_LEVEL_52; 261 case V4L2_MPEG_VIDEO_HEVC_LEVEL_6: 262 return HFI_HEVC_LEVEL_6; 263 case V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1: 264 return HFI_HEVC_LEVEL_61; 265 case V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2: 266 return HFI_HEVC_LEVEL_62; 267 } 268 } 269 270 return 0; 271 } 272 273 static int 274 venc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) 275 { 276 strlcpy(cap->driver, "qcom-venus", sizeof(cap->driver)); 277 strlcpy(cap->card, "Qualcomm Venus video encoder", sizeof(cap->card)); 278 strlcpy(cap->bus_info, "platform:qcom-venus", sizeof(cap->bus_info)); 279 280 return 0; 281 } 282 283 static int venc_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f) 284 { 285 struct venus_inst *inst = to_inst(file); 286 const struct venus_format *fmt; 287 288 fmt = find_format_by_index(inst, f->index, f->type); 289 290 memset(f->reserved, 0, sizeof(f->reserved)); 291 292 if (!fmt) 293 return -EINVAL; 294 295 f->pixelformat = fmt->pixfmt; 296 297 return 0; 298 } 299 300 static const struct venus_format * 301 venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f) 302 { 303 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 304 struct v4l2_plane_pix_format *pfmt = pixmp->plane_fmt; 305 const struct venus_format *fmt; 306 307 memset(pfmt[0].reserved, 0, sizeof(pfmt[0].reserved)); 308 memset(pixmp->reserved, 0, sizeof(pixmp->reserved)); 309 310 fmt = find_format(inst, pixmp->pixelformat, f->type); 311 if (!fmt) { 312 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 313 pixmp->pixelformat = V4L2_PIX_FMT_H264; 314 else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 315 pixmp->pixelformat = V4L2_PIX_FMT_NV12; 316 else 317 return NULL; 318 fmt = find_format(inst, pixmp->pixelformat, f->type); 319 } 320 321 pixmp->width = clamp(pixmp->width, frame_width_min(inst), 322 frame_width_max(inst)); 323 pixmp->height = clamp(pixmp->height, frame_height_min(inst), 324 frame_height_max(inst)); 325 326 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 327 pixmp->height = ALIGN(pixmp->height, 32); 328 329 pixmp->width = ALIGN(pixmp->width, 2); 330 pixmp->height = ALIGN(pixmp->height, 2); 331 332 if (pixmp->field == V4L2_FIELD_ANY) 333 pixmp->field = V4L2_FIELD_NONE; 334 pixmp->num_planes = fmt->num_planes; 335 pixmp->flags = 0; 336 337 pfmt[0].sizeimage = venus_helper_get_framesz(pixmp->pixelformat, 338 pixmp->width, 339 pixmp->height); 340 341 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 342 pfmt[0].bytesperline = ALIGN(pixmp->width, 128); 343 else 344 pfmt[0].bytesperline = 0; 345 346 return fmt; 347 } 348 349 static int venc_try_fmt(struct file *file, void *fh, struct v4l2_format *f) 350 { 351 struct venus_inst *inst = to_inst(file); 352 353 venc_try_fmt_common(inst, f); 354 355 return 0; 356 } 357 358 static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f) 359 { 360 struct venus_inst *inst = to_inst(file); 361 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 362 struct v4l2_pix_format_mplane orig_pixmp; 363 const struct venus_format *fmt; 364 struct v4l2_format format; 365 u32 pixfmt_out = 0, pixfmt_cap = 0; 366 367 orig_pixmp = *pixmp; 368 369 fmt = venc_try_fmt_common(inst, f); 370 if (!fmt) 371 return -EINVAL; 372 373 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 374 pixfmt_out = pixmp->pixelformat; 375 pixfmt_cap = inst->fmt_cap->pixfmt; 376 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 377 pixfmt_cap = pixmp->pixelformat; 378 pixfmt_out = inst->fmt_out->pixfmt; 379 } 380 381 memset(&format, 0, sizeof(format)); 382 383 format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 384 format.fmt.pix_mp.pixelformat = pixfmt_out; 385 format.fmt.pix_mp.width = orig_pixmp.width; 386 format.fmt.pix_mp.height = orig_pixmp.height; 387 venc_try_fmt_common(inst, &format); 388 389 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 390 inst->out_width = format.fmt.pix_mp.width; 391 inst->out_height = format.fmt.pix_mp.height; 392 inst->colorspace = pixmp->colorspace; 393 inst->ycbcr_enc = pixmp->ycbcr_enc; 394 inst->quantization = pixmp->quantization; 395 inst->xfer_func = pixmp->xfer_func; 396 } 397 398 memset(&format, 0, sizeof(format)); 399 400 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 401 format.fmt.pix_mp.pixelformat = pixfmt_cap; 402 format.fmt.pix_mp.width = orig_pixmp.width; 403 format.fmt.pix_mp.height = orig_pixmp.height; 404 venc_try_fmt_common(inst, &format); 405 406 inst->width = format.fmt.pix_mp.width; 407 inst->height = format.fmt.pix_mp.height; 408 409 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 410 inst->fmt_out = fmt; 411 else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 412 inst->fmt_cap = fmt; 413 414 return 0; 415 } 416 417 static int venc_g_fmt(struct file *file, void *fh, struct v4l2_format *f) 418 { 419 struct v4l2_pix_format_mplane *pixmp = &f->fmt.pix_mp; 420 struct venus_inst *inst = to_inst(file); 421 const struct venus_format *fmt; 422 423 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 424 fmt = inst->fmt_cap; 425 else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 426 fmt = inst->fmt_out; 427 else 428 return -EINVAL; 429 430 pixmp->pixelformat = fmt->pixfmt; 431 432 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 433 pixmp->width = inst->width; 434 pixmp->height = inst->height; 435 pixmp->colorspace = inst->colorspace; 436 pixmp->ycbcr_enc = inst->ycbcr_enc; 437 pixmp->quantization = inst->quantization; 438 pixmp->xfer_func = inst->xfer_func; 439 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 440 pixmp->width = inst->out_width; 441 pixmp->height = inst->out_height; 442 } 443 444 venc_try_fmt_common(inst, f); 445 446 return 0; 447 } 448 449 static int 450 venc_g_selection(struct file *file, void *fh, struct v4l2_selection *s) 451 { 452 struct venus_inst *inst = to_inst(file); 453 454 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 455 return -EINVAL; 456 457 switch (s->target) { 458 case V4L2_SEL_TGT_CROP_DEFAULT: 459 case V4L2_SEL_TGT_CROP_BOUNDS: 460 s->r.width = inst->width; 461 s->r.height = inst->height; 462 break; 463 case V4L2_SEL_TGT_CROP: 464 s->r.width = inst->out_width; 465 s->r.height = inst->out_height; 466 break; 467 default: 468 return -EINVAL; 469 } 470 471 s->r.top = 0; 472 s->r.left = 0; 473 474 return 0; 475 } 476 477 static int 478 venc_s_selection(struct file *file, void *fh, struct v4l2_selection *s) 479 { 480 struct venus_inst *inst = to_inst(file); 481 482 if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 483 return -EINVAL; 484 485 switch (s->target) { 486 case V4L2_SEL_TGT_CROP: 487 if (s->r.width != inst->out_width || 488 s->r.height != inst->out_height || 489 s->r.top != 0 || s->r.left != 0) 490 return -EINVAL; 491 break; 492 default: 493 return -EINVAL; 494 } 495 496 return 0; 497 } 498 499 static int venc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a) 500 { 501 struct venus_inst *inst = to_inst(file); 502 struct v4l2_outputparm *out = &a->parm.output; 503 struct v4l2_fract *timeperframe = &out->timeperframe; 504 u64 us_per_frame, fps; 505 506 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 507 a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 508 return -EINVAL; 509 510 memset(out->reserved, 0, sizeof(out->reserved)); 511 512 if (!timeperframe->denominator) 513 timeperframe->denominator = inst->timeperframe.denominator; 514 if (!timeperframe->numerator) 515 timeperframe->numerator = inst->timeperframe.numerator; 516 517 out->capability = V4L2_CAP_TIMEPERFRAME; 518 519 us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC; 520 do_div(us_per_frame, timeperframe->denominator); 521 522 if (!us_per_frame) 523 return -EINVAL; 524 525 fps = (u64)USEC_PER_SEC; 526 do_div(fps, us_per_frame); 527 528 inst->timeperframe = *timeperframe; 529 inst->fps = fps; 530 531 return 0; 532 } 533 534 static int venc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a) 535 { 536 struct venus_inst *inst = to_inst(file); 537 538 if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 539 a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 540 return -EINVAL; 541 542 a->parm.output.capability |= V4L2_CAP_TIMEPERFRAME; 543 a->parm.output.timeperframe = inst->timeperframe; 544 545 return 0; 546 } 547 548 static int venc_enum_framesizes(struct file *file, void *fh, 549 struct v4l2_frmsizeenum *fsize) 550 { 551 struct venus_inst *inst = to_inst(file); 552 const struct venus_format *fmt; 553 554 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 555 556 fmt = find_format(inst, fsize->pixel_format, 557 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 558 if (!fmt) { 559 fmt = find_format(inst, fsize->pixel_format, 560 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 561 if (!fmt) 562 return -EINVAL; 563 } 564 565 if (fsize->index) 566 return -EINVAL; 567 568 fsize->stepwise.min_width = frame_width_min(inst); 569 fsize->stepwise.max_width = frame_width_max(inst); 570 fsize->stepwise.step_width = frame_width_step(inst); 571 fsize->stepwise.min_height = frame_height_min(inst); 572 fsize->stepwise.max_height = frame_height_max(inst); 573 fsize->stepwise.step_height = frame_height_step(inst); 574 575 return 0; 576 } 577 578 static int venc_enum_frameintervals(struct file *file, void *fh, 579 struct v4l2_frmivalenum *fival) 580 { 581 struct venus_inst *inst = to_inst(file); 582 const struct venus_format *fmt; 583 584 fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; 585 586 fmt = find_format(inst, fival->pixel_format, 587 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 588 if (!fmt) { 589 fmt = find_format(inst, fival->pixel_format, 590 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); 591 if (!fmt) 592 return -EINVAL; 593 } 594 595 if (fival->index) 596 return -EINVAL; 597 598 if (!fival->width || !fival->height) 599 return -EINVAL; 600 601 if (fival->width > frame_width_max(inst) || 602 fival->width < frame_width_min(inst) || 603 fival->height > frame_height_max(inst) || 604 fival->height < frame_height_min(inst)) 605 return -EINVAL; 606 607 fival->stepwise.min.numerator = 1; 608 fival->stepwise.min.denominator = frate_max(inst); 609 fival->stepwise.max.numerator = 1; 610 fival->stepwise.max.denominator = frate_min(inst); 611 fival->stepwise.step.numerator = 1; 612 fival->stepwise.step.denominator = frate_max(inst); 613 614 return 0; 615 } 616 617 static const struct v4l2_ioctl_ops venc_ioctl_ops = { 618 .vidioc_querycap = venc_querycap, 619 .vidioc_enum_fmt_vid_cap_mplane = venc_enum_fmt, 620 .vidioc_enum_fmt_vid_out_mplane = venc_enum_fmt, 621 .vidioc_s_fmt_vid_cap_mplane = venc_s_fmt, 622 .vidioc_s_fmt_vid_out_mplane = venc_s_fmt, 623 .vidioc_g_fmt_vid_cap_mplane = venc_g_fmt, 624 .vidioc_g_fmt_vid_out_mplane = venc_g_fmt, 625 .vidioc_try_fmt_vid_cap_mplane = venc_try_fmt, 626 .vidioc_try_fmt_vid_out_mplane = venc_try_fmt, 627 .vidioc_g_selection = venc_g_selection, 628 .vidioc_s_selection = venc_s_selection, 629 .vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs, 630 .vidioc_querybuf = v4l2_m2m_ioctl_querybuf, 631 .vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs, 632 .vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf, 633 .vidioc_qbuf = v4l2_m2m_ioctl_qbuf, 634 .vidioc_expbuf = v4l2_m2m_ioctl_expbuf, 635 .vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf, 636 .vidioc_streamon = v4l2_m2m_ioctl_streamon, 637 .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, 638 .vidioc_s_parm = venc_s_parm, 639 .vidioc_g_parm = venc_g_parm, 640 .vidioc_enum_framesizes = venc_enum_framesizes, 641 .vidioc_enum_frameintervals = venc_enum_frameintervals, 642 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 643 .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 644 }; 645 646 static int venc_set_properties(struct venus_inst *inst) 647 { 648 struct venc_controls *ctr = &inst->controls.enc; 649 struct hfi_intra_period intra_period; 650 struct hfi_profile_level pl; 651 struct hfi_framerate frate; 652 struct hfi_bitrate brate; 653 struct hfi_idr_period idrp; 654 u32 ptype, rate_control, bitrate, profile = 0, level = 0; 655 int ret; 656 657 ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2); 658 if (ret) 659 return ret; 660 661 ret = venus_helper_set_core_usage(inst, VIDC_CORE_ID_2); 662 if (ret) 663 return ret; 664 665 ptype = HFI_PROPERTY_CONFIG_FRAME_RATE; 666 frate.buffer_type = HFI_BUFFER_OUTPUT; 667 frate.framerate = inst->fps * (1 << 16); 668 669 ret = hfi_session_set_property(inst, ptype, &frate); 670 if (ret) 671 return ret; 672 673 if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264) { 674 struct hfi_h264_vui_timing_info info; 675 struct hfi_h264_entropy_control entropy; 676 struct hfi_h264_db_control deblock; 677 678 ptype = HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO; 679 info.enable = 1; 680 info.fixed_framerate = 1; 681 info.time_scale = NSEC_PER_SEC; 682 683 ret = hfi_session_set_property(inst, ptype, &info); 684 if (ret) 685 return ret; 686 687 ptype = HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL; 688 entropy.entropy_mode = venc_v4l2_to_hfi( 689 V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, 690 ctr->h264_entropy_mode); 691 entropy.cabac_model = HFI_H264_CABAC_MODEL_0; 692 693 ret = hfi_session_set_property(inst, ptype, &entropy); 694 if (ret) 695 return ret; 696 697 ptype = HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL; 698 deblock.mode = venc_v4l2_to_hfi( 699 V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, 700 ctr->h264_loop_filter_mode); 701 deblock.slice_alpha_offset = ctr->h264_loop_filter_alpha; 702 deblock.slice_beta_offset = ctr->h264_loop_filter_beta; 703 704 ret = hfi_session_set_property(inst, ptype, &deblock); 705 if (ret) 706 return ret; 707 } 708 709 /* IDR periodicity, n: 710 * n = 0 - only the first I-frame is IDR frame 711 * n = 1 - all I-frames will be IDR frames 712 * n > 1 - every n-th I-frame will be IDR frame 713 */ 714 ptype = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD; 715 idrp.idr_period = 0; 716 ret = hfi_session_set_property(inst, ptype, &idrp); 717 if (ret) 718 return ret; 719 720 if (ctr->num_b_frames) { 721 u32 max_num_b_frames = NUM_B_FRAMES_MAX; 722 723 ptype = HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES; 724 ret = hfi_session_set_property(inst, ptype, &max_num_b_frames); 725 if (ret) 726 return ret; 727 } 728 729 ptype = HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD; 730 intra_period.pframes = ctr->num_p_frames; 731 intra_period.bframes = ctr->num_b_frames; 732 733 ret = hfi_session_set_property(inst, ptype, &intra_period); 734 if (ret) 735 return ret; 736 737 if (ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) 738 rate_control = HFI_RATE_CONTROL_VBR_CFR; 739 else 740 rate_control = HFI_RATE_CONTROL_CBR_CFR; 741 742 ptype = HFI_PROPERTY_PARAM_VENC_RATE_CONTROL; 743 ret = hfi_session_set_property(inst, ptype, &rate_control); 744 if (ret) 745 return ret; 746 747 if (!ctr->bitrate) 748 bitrate = 64000; 749 else 750 bitrate = ctr->bitrate; 751 752 ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE; 753 brate.bitrate = bitrate; 754 brate.layer_id = 0; 755 756 ret = hfi_session_set_property(inst, ptype, &brate); 757 if (ret) 758 return ret; 759 760 if (!ctr->bitrate_peak) 761 bitrate *= 2; 762 else 763 bitrate = ctr->bitrate_peak; 764 765 ptype = HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE; 766 brate.bitrate = bitrate; 767 brate.layer_id = 0; 768 769 ret = hfi_session_set_property(inst, ptype, &brate); 770 if (ret) 771 return ret; 772 773 if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264) { 774 profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_H264_PROFILE, 775 ctr->profile.h264); 776 level = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_H264_LEVEL, 777 ctr->level.h264); 778 } else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_VP8) { 779 profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_VP8_PROFILE, 780 ctr->profile.vpx); 781 level = 0; 782 } else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_MPEG4) { 783 profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE, 784 ctr->profile.mpeg4); 785 level = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL, 786 ctr->level.mpeg4); 787 } else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H263) { 788 profile = 0; 789 level = 0; 790 } else if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) { 791 profile = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, 792 ctr->profile.hevc); 793 level = venc_v4l2_to_hfi(V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, 794 ctr->level.hevc); 795 } 796 797 ptype = HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT; 798 pl.profile = profile; 799 pl.level = level; 800 801 ret = hfi_session_set_property(inst, ptype, &pl); 802 if (ret) 803 return ret; 804 805 return 0; 806 } 807 808 static int venc_init_session(struct venus_inst *inst) 809 { 810 int ret; 811 812 ret = hfi_session_init(inst, inst->fmt_cap->pixfmt); 813 if (ret) 814 return ret; 815 816 ret = venus_helper_set_input_resolution(inst, inst->width, 817 inst->height); 818 if (ret) 819 goto deinit; 820 821 ret = venus_helper_set_output_resolution(inst, inst->width, 822 inst->height, 823 HFI_BUFFER_OUTPUT); 824 if (ret) 825 goto deinit; 826 827 ret = venus_helper_set_color_format(inst, inst->fmt_out->pixfmt); 828 if (ret) 829 goto deinit; 830 831 ret = venc_set_properties(inst); 832 if (ret) 833 goto deinit; 834 835 return 0; 836 deinit: 837 hfi_session_deinit(inst); 838 return ret; 839 } 840 841 static int venc_out_num_buffers(struct venus_inst *inst, unsigned int *num) 842 { 843 struct hfi_buffer_requirements bufreq; 844 int ret; 845 846 ret = venc_init_session(inst); 847 if (ret) 848 return ret; 849 850 ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); 851 852 *num = bufreq.count_actual; 853 854 hfi_session_deinit(inst); 855 856 return ret; 857 } 858 859 static int venc_queue_setup(struct vb2_queue *q, 860 unsigned int *num_buffers, unsigned int *num_planes, 861 unsigned int sizes[], struct device *alloc_devs[]) 862 { 863 struct venus_inst *inst = vb2_get_drv_priv(q); 864 unsigned int num, min = 4; 865 int ret = 0; 866 867 if (*num_planes) { 868 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && 869 *num_planes != inst->fmt_out->num_planes) 870 return -EINVAL; 871 872 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 873 *num_planes != inst->fmt_cap->num_planes) 874 return -EINVAL; 875 876 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && 877 sizes[0] < inst->input_buf_size) 878 return -EINVAL; 879 880 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && 881 sizes[0] < inst->output_buf_size) 882 return -EINVAL; 883 884 return 0; 885 } 886 887 switch (q->type) { 888 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 889 *num_planes = inst->fmt_out->num_planes; 890 891 ret = venc_out_num_buffers(inst, &num); 892 if (ret) 893 break; 894 895 num = max(num, min); 896 *num_buffers = max(*num_buffers, num); 897 inst->num_input_bufs = *num_buffers; 898 899 sizes[0] = venus_helper_get_framesz(inst->fmt_out->pixfmt, 900 inst->width, 901 inst->height); 902 inst->input_buf_size = sizes[0]; 903 break; 904 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 905 *num_planes = inst->fmt_cap->num_planes; 906 *num_buffers = max(*num_buffers, min); 907 inst->num_output_bufs = *num_buffers; 908 sizes[0] = venus_helper_get_framesz(inst->fmt_cap->pixfmt, 909 inst->width, 910 inst->height); 911 inst->output_buf_size = sizes[0]; 912 break; 913 default: 914 ret = -EINVAL; 915 break; 916 } 917 918 return ret; 919 } 920 921 static int venc_verify_conf(struct venus_inst *inst) 922 { 923 enum hfi_version ver = inst->core->res->hfi_version; 924 struct hfi_buffer_requirements bufreq; 925 int ret; 926 927 if (!inst->num_input_bufs || !inst->num_output_bufs) 928 return -EINVAL; 929 930 ret = venus_helper_get_bufreq(inst, HFI_BUFFER_OUTPUT, &bufreq); 931 if (ret) 932 return ret; 933 934 if (inst->num_output_bufs < bufreq.count_actual || 935 inst->num_output_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver)) 936 return -EINVAL; 937 938 ret = venus_helper_get_bufreq(inst, HFI_BUFFER_INPUT, &bufreq); 939 if (ret) 940 return ret; 941 942 if (inst->num_input_bufs < bufreq.count_actual || 943 inst->num_input_bufs < HFI_BUFREQ_COUNT_MIN(&bufreq, ver)) 944 return -EINVAL; 945 946 return 0; 947 } 948 949 static int venc_start_streaming(struct vb2_queue *q, unsigned int count) 950 { 951 struct venus_inst *inst = vb2_get_drv_priv(q); 952 int ret; 953 954 mutex_lock(&inst->lock); 955 956 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 957 inst->streamon_out = 1; 958 else 959 inst->streamon_cap = 1; 960 961 if (!(inst->streamon_out & inst->streamon_cap)) { 962 mutex_unlock(&inst->lock); 963 return 0; 964 } 965 966 venus_helper_init_instance(inst); 967 968 inst->sequence_cap = 0; 969 inst->sequence_out = 0; 970 971 ret = venc_init_session(inst); 972 if (ret) 973 goto bufs_done; 974 975 ret = venc_set_properties(inst); 976 if (ret) 977 goto deinit_sess; 978 979 ret = venc_verify_conf(inst); 980 if (ret) 981 goto deinit_sess; 982 983 ret = venus_helper_set_num_bufs(inst, inst->num_input_bufs, 984 inst->num_output_bufs, 0); 985 if (ret) 986 goto deinit_sess; 987 988 ret = venus_helper_vb2_start_streaming(inst); 989 if (ret) 990 goto deinit_sess; 991 992 mutex_unlock(&inst->lock); 993 994 return 0; 995 996 deinit_sess: 997 hfi_session_deinit(inst); 998 bufs_done: 999 venus_helper_buffers_done(inst, VB2_BUF_STATE_QUEUED); 1000 if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) 1001 inst->streamon_out = 0; 1002 else 1003 inst->streamon_cap = 0; 1004 mutex_unlock(&inst->lock); 1005 return ret; 1006 } 1007 1008 static const struct vb2_ops venc_vb2_ops = { 1009 .queue_setup = venc_queue_setup, 1010 .buf_init = venus_helper_vb2_buf_init, 1011 .buf_prepare = venus_helper_vb2_buf_prepare, 1012 .start_streaming = venc_start_streaming, 1013 .stop_streaming = venus_helper_vb2_stop_streaming, 1014 .buf_queue = venus_helper_vb2_buf_queue, 1015 }; 1016 1017 static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type, 1018 u32 tag, u32 bytesused, u32 data_offset, u32 flags, 1019 u32 hfi_flags, u64 timestamp_us) 1020 { 1021 struct vb2_v4l2_buffer *vbuf; 1022 struct vb2_buffer *vb; 1023 unsigned int type; 1024 1025 if (buf_type == HFI_BUFFER_INPUT) 1026 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1027 else 1028 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1029 1030 vbuf = venus_helper_find_buf(inst, type, tag); 1031 if (!vbuf) 1032 return; 1033 1034 vbuf->flags = flags; 1035 1036 if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 1037 vb = &vbuf->vb2_buf; 1038 vb2_set_plane_payload(vb, 0, bytesused + data_offset); 1039 vb->planes[0].data_offset = data_offset; 1040 vb->timestamp = timestamp_us * NSEC_PER_USEC; 1041 vbuf->sequence = inst->sequence_cap++; 1042 } else { 1043 vbuf->sequence = inst->sequence_out++; 1044 } 1045 1046 v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE); 1047 } 1048 1049 static void venc_event_notify(struct venus_inst *inst, u32 event, 1050 struct hfi_event_data *data) 1051 { 1052 struct device *dev = inst->core->dev_enc; 1053 1054 if (event == EVT_SESSION_ERROR) { 1055 inst->session_error = true; 1056 dev_err(dev, "enc: event session error %x\n", inst->error); 1057 } 1058 } 1059 1060 static const struct hfi_inst_ops venc_hfi_ops = { 1061 .buf_done = venc_buf_done, 1062 .event_notify = venc_event_notify, 1063 }; 1064 1065 static const struct v4l2_m2m_ops venc_m2m_ops = { 1066 .device_run = venus_helper_m2m_device_run, 1067 .job_abort = venus_helper_m2m_job_abort, 1068 }; 1069 1070 static int m2m_queue_init(void *priv, struct vb2_queue *src_vq, 1071 struct vb2_queue *dst_vq) 1072 { 1073 struct venus_inst *inst = priv; 1074 int ret; 1075 1076 src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1077 src_vq->io_modes = VB2_MMAP | VB2_DMABUF; 1078 src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 1079 src_vq->ops = &venc_vb2_ops; 1080 src_vq->mem_ops = &vb2_dma_sg_memops; 1081 src_vq->drv_priv = inst; 1082 src_vq->buf_struct_size = sizeof(struct venus_buffer); 1083 src_vq->allow_zero_bytesused = 1; 1084 src_vq->min_buffers_needed = 1; 1085 src_vq->dev = inst->core->dev; 1086 if (inst->core->res->hfi_version == HFI_VERSION_1XX) 1087 src_vq->bidirectional = 1; 1088 ret = vb2_queue_init(src_vq); 1089 if (ret) 1090 return ret; 1091 1092 dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1093 dst_vq->io_modes = VB2_MMAP | VB2_DMABUF; 1094 dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY; 1095 dst_vq->ops = &venc_vb2_ops; 1096 dst_vq->mem_ops = &vb2_dma_sg_memops; 1097 dst_vq->drv_priv = inst; 1098 dst_vq->buf_struct_size = sizeof(struct venus_buffer); 1099 dst_vq->allow_zero_bytesused = 1; 1100 dst_vq->min_buffers_needed = 1; 1101 dst_vq->dev = inst->core->dev; 1102 ret = vb2_queue_init(dst_vq); 1103 if (ret) { 1104 vb2_queue_release(src_vq); 1105 return ret; 1106 } 1107 1108 return 0; 1109 } 1110 1111 static void venc_inst_init(struct venus_inst *inst) 1112 { 1113 inst->fmt_cap = &venc_formats[2]; 1114 inst->fmt_out = &venc_formats[0]; 1115 inst->width = 1280; 1116 inst->height = ALIGN(720, 32); 1117 inst->out_width = 1280; 1118 inst->out_height = 720; 1119 inst->fps = 15; 1120 inst->timeperframe.numerator = 1; 1121 inst->timeperframe.denominator = 15; 1122 inst->hfi_codec = HFI_VIDEO_CODEC_H264; 1123 } 1124 1125 static int venc_open(struct file *file) 1126 { 1127 struct venus_core *core = video_drvdata(file); 1128 struct venus_inst *inst; 1129 int ret; 1130 1131 inst = kzalloc(sizeof(*inst), GFP_KERNEL); 1132 if (!inst) 1133 return -ENOMEM; 1134 1135 INIT_LIST_HEAD(&inst->dpbbufs); 1136 INIT_LIST_HEAD(&inst->registeredbufs); 1137 INIT_LIST_HEAD(&inst->internalbufs); 1138 INIT_LIST_HEAD(&inst->list); 1139 mutex_init(&inst->lock); 1140 1141 inst->core = core; 1142 inst->session_type = VIDC_SESSION_TYPE_ENC; 1143 1144 venus_helper_init_instance(inst); 1145 1146 ret = pm_runtime_get_sync(core->dev_enc); 1147 if (ret < 0) 1148 goto err_free_inst; 1149 1150 ret = venc_ctrl_init(inst); 1151 if (ret) 1152 goto err_put_sync; 1153 1154 ret = hfi_session_create(inst, &venc_hfi_ops); 1155 if (ret) 1156 goto err_ctrl_deinit; 1157 1158 venc_inst_init(inst); 1159 1160 /* 1161 * create m2m device for every instance, the m2m context scheduling 1162 * is made by firmware side so we do not need to care about. 1163 */ 1164 inst->m2m_dev = v4l2_m2m_init(&venc_m2m_ops); 1165 if (IS_ERR(inst->m2m_dev)) { 1166 ret = PTR_ERR(inst->m2m_dev); 1167 goto err_session_destroy; 1168 } 1169 1170 inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init); 1171 if (IS_ERR(inst->m2m_ctx)) { 1172 ret = PTR_ERR(inst->m2m_ctx); 1173 goto err_m2m_release; 1174 } 1175 1176 v4l2_fh_init(&inst->fh, core->vdev_enc); 1177 1178 inst->fh.ctrl_handler = &inst->ctrl_handler; 1179 v4l2_fh_add(&inst->fh); 1180 inst->fh.m2m_ctx = inst->m2m_ctx; 1181 file->private_data = &inst->fh; 1182 1183 return 0; 1184 1185 err_m2m_release: 1186 v4l2_m2m_release(inst->m2m_dev); 1187 err_session_destroy: 1188 hfi_session_destroy(inst); 1189 err_ctrl_deinit: 1190 venc_ctrl_deinit(inst); 1191 err_put_sync: 1192 pm_runtime_put_sync(core->dev_enc); 1193 err_free_inst: 1194 kfree(inst); 1195 return ret; 1196 } 1197 1198 static int venc_close(struct file *file) 1199 { 1200 struct venus_inst *inst = to_inst(file); 1201 1202 v4l2_m2m_ctx_release(inst->m2m_ctx); 1203 v4l2_m2m_release(inst->m2m_dev); 1204 venc_ctrl_deinit(inst); 1205 hfi_session_destroy(inst); 1206 mutex_destroy(&inst->lock); 1207 v4l2_fh_del(&inst->fh); 1208 v4l2_fh_exit(&inst->fh); 1209 1210 pm_runtime_put_sync(inst->core->dev_enc); 1211 1212 kfree(inst); 1213 return 0; 1214 } 1215 1216 static const struct v4l2_file_operations venc_fops = { 1217 .owner = THIS_MODULE, 1218 .open = venc_open, 1219 .release = venc_close, 1220 .unlocked_ioctl = video_ioctl2, 1221 .poll = v4l2_m2m_fop_poll, 1222 .mmap = v4l2_m2m_fop_mmap, 1223 #ifdef CONFIG_COMPAT 1224 .compat_ioctl32 = v4l2_compat_ioctl32, 1225 #endif 1226 }; 1227 1228 static int venc_probe(struct platform_device *pdev) 1229 { 1230 struct device *dev = &pdev->dev; 1231 struct video_device *vdev; 1232 struct venus_core *core; 1233 int ret; 1234 1235 if (!dev->parent) 1236 return -EPROBE_DEFER; 1237 1238 core = dev_get_drvdata(dev->parent); 1239 if (!core) 1240 return -EPROBE_DEFER; 1241 1242 if (IS_V3(core) || IS_V4(core)) { 1243 core->core1_clk = devm_clk_get(dev, "core"); 1244 if (IS_ERR(core->core1_clk)) 1245 return PTR_ERR(core->core1_clk); 1246 } 1247 1248 if (IS_V4(core)) { 1249 core->core1_bus_clk = devm_clk_get(dev, "bus"); 1250 if (IS_ERR(core->core1_bus_clk)) 1251 return PTR_ERR(core->core1_bus_clk); 1252 } 1253 1254 platform_set_drvdata(pdev, core); 1255 1256 vdev = video_device_alloc(); 1257 if (!vdev) 1258 return -ENOMEM; 1259 1260 strlcpy(vdev->name, "qcom-venus-encoder", sizeof(vdev->name)); 1261 vdev->release = video_device_release; 1262 vdev->fops = &venc_fops; 1263 vdev->ioctl_ops = &venc_ioctl_ops; 1264 vdev->vfl_dir = VFL_DIR_M2M; 1265 vdev->v4l2_dev = &core->v4l2_dev; 1266 vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING; 1267 1268 ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); 1269 if (ret) 1270 goto err_vdev_release; 1271 1272 core->vdev_enc = vdev; 1273 core->dev_enc = dev; 1274 1275 video_set_drvdata(vdev, core); 1276 pm_runtime_enable(dev); 1277 1278 return 0; 1279 1280 err_vdev_release: 1281 video_device_release(vdev); 1282 return ret; 1283 } 1284 1285 static int venc_remove(struct platform_device *pdev) 1286 { 1287 struct venus_core *core = dev_get_drvdata(pdev->dev.parent); 1288 1289 video_unregister_device(core->vdev_enc); 1290 pm_runtime_disable(core->dev_enc); 1291 1292 return 0; 1293 } 1294 1295 static __maybe_unused int venc_runtime_suspend(struct device *dev) 1296 { 1297 struct venus_core *core = dev_get_drvdata(dev); 1298 int ret; 1299 1300 if (IS_V1(core)) 1301 return 0; 1302 1303 ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_ENC, true); 1304 if (ret) 1305 return ret; 1306 1307 if (IS_V4(core)) 1308 clk_disable_unprepare(core->core1_bus_clk); 1309 1310 clk_disable_unprepare(core->core1_clk); 1311 1312 return venus_helper_power_enable(core, VIDC_SESSION_TYPE_ENC, false); 1313 } 1314 1315 static __maybe_unused int venc_runtime_resume(struct device *dev) 1316 { 1317 struct venus_core *core = dev_get_drvdata(dev); 1318 int ret; 1319 1320 if (IS_V1(core)) 1321 return 0; 1322 1323 ret = venus_helper_power_enable(core, VIDC_SESSION_TYPE_ENC, true); 1324 if (ret) 1325 return ret; 1326 1327 ret = clk_prepare_enable(core->core1_clk); 1328 if (ret) 1329 goto err_power_disable; 1330 1331 if (IS_V4(core)) 1332 ret = clk_prepare_enable(core->core1_bus_clk); 1333 1334 if (ret) 1335 goto err_unprepare_core1; 1336 1337 return venus_helper_power_enable(core, VIDC_SESSION_TYPE_ENC, false); 1338 1339 err_unprepare_core1: 1340 clk_disable_unprepare(core->core1_clk); 1341 err_power_disable: 1342 venus_helper_power_enable(core, VIDC_SESSION_TYPE_ENC, false); 1343 return ret; 1344 } 1345 1346 static const struct dev_pm_ops venc_pm_ops = { 1347 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 1348 pm_runtime_force_resume) 1349 SET_RUNTIME_PM_OPS(venc_runtime_suspend, venc_runtime_resume, NULL) 1350 }; 1351 1352 static const struct of_device_id venc_dt_match[] = { 1353 { .compatible = "venus-encoder" }, 1354 { } 1355 }; 1356 MODULE_DEVICE_TABLE(of, venc_dt_match); 1357 1358 static struct platform_driver qcom_venus_enc_driver = { 1359 .probe = venc_probe, 1360 .remove = venc_remove, 1361 .driver = { 1362 .name = "qcom-venus-encoder", 1363 .of_match_table = venc_dt_match, 1364 .pm = &venc_pm_ops, 1365 }, 1366 }; 1367 module_platform_driver(qcom_venus_enc_driver); 1368 1369 MODULE_ALIAS("platform:qcom-venus-encoder"); 1370 MODULE_DESCRIPTION("Qualcomm Venus video encoder driver"); 1371 MODULE_LICENSE("GPL v2"); 1372