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