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