1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. 4 * Copyright (C) 2017 Linaro Ltd. 5 */ 6 #include <linux/init.h> 7 #include <linux/interconnect.h> 8 #include <linux/io.h> 9 #include <linux/ioctl.h> 10 #include <linux/delay.h> 11 #include <linux/devcoredump.h> 12 #include <linux/list.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/of_platform.h> 16 #include <linux/platform_device.h> 17 #include <linux/slab.h> 18 #include <linux/types.h> 19 #include <linux/pm_domain.h> 20 #include <linux/pm_runtime.h> 21 #include <media/videobuf2-v4l2.h> 22 #include <media/v4l2-ctrls.h> 23 #include <media/v4l2-mem2mem.h> 24 #include <media/v4l2-ioctl.h> 25 26 #include "core.h" 27 #include "firmware.h" 28 #include "pm_helpers.h" 29 #include "hfi_venus_io.h" 30 31 static void venus_coredump(struct venus_core *core) 32 { 33 struct device *dev; 34 phys_addr_t mem_phys; 35 size_t mem_size; 36 void *mem_va; 37 void *data; 38 39 dev = core->dev; 40 mem_phys = core->fw.mem_phys; 41 mem_size = core->fw.mem_size; 42 43 mem_va = memremap(mem_phys, mem_size, MEMREMAP_WC); 44 if (!mem_va) 45 return; 46 47 data = vmalloc(mem_size); 48 if (!data) { 49 memunmap(mem_va); 50 return; 51 } 52 53 memcpy(data, mem_va, mem_size); 54 memunmap(mem_va); 55 dev_coredumpv(dev, data, mem_size, GFP_KERNEL); 56 } 57 58 static void venus_event_notify(struct venus_core *core, u32 event) 59 { 60 struct venus_inst *inst; 61 62 switch (event) { 63 case EVT_SYS_WATCHDOG_TIMEOUT: 64 case EVT_SYS_ERROR: 65 break; 66 default: 67 return; 68 } 69 70 mutex_lock(&core->lock); 71 set_bit(0, &core->sys_error); 72 set_bit(0, &core->dump_core); 73 list_for_each_entry(inst, &core->instances, list) 74 inst->ops->event_notify(inst, EVT_SESSION_ERROR, NULL); 75 mutex_unlock(&core->lock); 76 77 disable_irq_nosync(core->irq); 78 schedule_delayed_work(&core->work, msecs_to_jiffies(10)); 79 } 80 81 static const struct hfi_core_ops venus_core_ops = { 82 .event_notify = venus_event_notify, 83 }; 84 85 #define RPM_WAIT_FOR_IDLE_MAX_ATTEMPTS 10 86 87 static void venus_sys_error_handler(struct work_struct *work) 88 { 89 struct venus_core *core = 90 container_of(work, struct venus_core, work.work); 91 int ret, i, max_attempts = RPM_WAIT_FOR_IDLE_MAX_ATTEMPTS; 92 const char *err_msg = ""; 93 bool failed = false; 94 95 ret = pm_runtime_get_sync(core->dev); 96 if (ret < 0) { 97 err_msg = "resume runtime PM"; 98 max_attempts = 0; 99 failed = true; 100 } 101 102 core->ops->core_deinit(core); 103 core->state = CORE_UNINIT; 104 105 for (i = 0; i < max_attempts; i++) { 106 if (!pm_runtime_active(core->dev_dec) && !pm_runtime_active(core->dev_enc)) 107 break; 108 msleep(10); 109 } 110 111 mutex_lock(&core->lock); 112 113 venus_shutdown(core); 114 115 if (test_bit(0, &core->dump_core)) { 116 venus_coredump(core); 117 clear_bit(0, &core->dump_core); 118 } 119 120 pm_runtime_put_sync(core->dev); 121 122 for (i = 0; i < max_attempts; i++) { 123 if (!core->pmdomains || 124 !pm_runtime_active(core->pmdomains->pd_devs[0])) 125 break; 126 usleep_range(1000, 1500); 127 } 128 129 hfi_reinit(core); 130 131 ret = pm_runtime_get_sync(core->dev); 132 if (ret < 0) { 133 err_msg = "resume runtime PM"; 134 failed = true; 135 } 136 137 ret = venus_boot(core); 138 if (ret && !failed) { 139 err_msg = "boot Venus"; 140 failed = true; 141 } 142 143 ret = hfi_core_resume(core, true); 144 if (ret && !failed) { 145 err_msg = "resume HFI"; 146 failed = true; 147 } 148 149 enable_irq(core->irq); 150 151 mutex_unlock(&core->lock); 152 153 ret = hfi_core_init(core); 154 if (ret && !failed) { 155 err_msg = "init HFI"; 156 failed = true; 157 } 158 159 pm_runtime_put_sync(core->dev); 160 161 if (failed) { 162 disable_irq_nosync(core->irq); 163 dev_warn_ratelimited(core->dev, 164 "System error has occurred, recovery failed to %s\n", 165 err_msg); 166 schedule_delayed_work(&core->work, msecs_to_jiffies(10)); 167 return; 168 } 169 170 dev_warn(core->dev, "system error has occurred (recovered)\n"); 171 172 mutex_lock(&core->lock); 173 clear_bit(0, &core->sys_error); 174 wake_up_all(&core->sys_err_done); 175 mutex_unlock(&core->lock); 176 } 177 178 static u32 to_v4l2_codec_type(u32 codec) 179 { 180 switch (codec) { 181 case HFI_VIDEO_CODEC_H264: 182 return V4L2_PIX_FMT_H264; 183 case HFI_VIDEO_CODEC_H263: 184 return V4L2_PIX_FMT_H263; 185 case HFI_VIDEO_CODEC_MPEG1: 186 return V4L2_PIX_FMT_MPEG1; 187 case HFI_VIDEO_CODEC_MPEG2: 188 return V4L2_PIX_FMT_MPEG2; 189 case HFI_VIDEO_CODEC_MPEG4: 190 return V4L2_PIX_FMT_MPEG4; 191 case HFI_VIDEO_CODEC_VC1: 192 return V4L2_PIX_FMT_VC1_ANNEX_G; 193 case HFI_VIDEO_CODEC_VP8: 194 return V4L2_PIX_FMT_VP8; 195 case HFI_VIDEO_CODEC_VP9: 196 return V4L2_PIX_FMT_VP9; 197 case HFI_VIDEO_CODEC_DIVX: 198 case HFI_VIDEO_CODEC_DIVX_311: 199 return V4L2_PIX_FMT_XVID; 200 default: 201 return 0; 202 } 203 } 204 205 static int venus_enumerate_codecs(struct venus_core *core, u32 type) 206 { 207 const struct hfi_inst_ops dummy_ops = {}; 208 struct venus_inst *inst; 209 u32 codec, codecs; 210 unsigned int i; 211 int ret; 212 213 if (core->res->hfi_version != HFI_VERSION_1XX) 214 return 0; 215 216 inst = kzalloc(sizeof(*inst), GFP_KERNEL); 217 if (!inst) 218 return -ENOMEM; 219 220 mutex_init(&inst->lock); 221 inst->core = core; 222 inst->session_type = type; 223 if (type == VIDC_SESSION_TYPE_DEC) 224 codecs = core->dec_codecs; 225 else 226 codecs = core->enc_codecs; 227 228 ret = hfi_session_create(inst, &dummy_ops); 229 if (ret) 230 goto err; 231 232 for (i = 0; i < MAX_CODEC_NUM; i++) { 233 codec = (1UL << i) & codecs; 234 if (!codec) 235 continue; 236 237 ret = hfi_session_init(inst, to_v4l2_codec_type(codec)); 238 if (ret) 239 goto done; 240 241 ret = hfi_session_deinit(inst); 242 if (ret) 243 goto done; 244 } 245 246 done: 247 hfi_session_destroy(inst); 248 err: 249 mutex_destroy(&inst->lock); 250 kfree(inst); 251 252 return ret; 253 } 254 255 static void venus_assign_register_offsets(struct venus_core *core) 256 { 257 if (IS_IRIS2(core) || IS_IRIS2_1(core)) { 258 core->vbif_base = core->base + VBIF_BASE; 259 core->cpu_base = core->base + CPU_BASE_V6; 260 core->cpu_cs_base = core->base + CPU_CS_BASE_V6; 261 core->cpu_ic_base = core->base + CPU_IC_BASE_V6; 262 core->wrapper_base = core->base + WRAPPER_BASE_V6; 263 core->wrapper_tz_base = core->base + WRAPPER_TZ_BASE_V6; 264 core->aon_base = core->base + AON_BASE_V6; 265 } else { 266 core->vbif_base = core->base + VBIF_BASE; 267 core->cpu_base = core->base + CPU_BASE; 268 core->cpu_cs_base = core->base + CPU_CS_BASE; 269 core->cpu_ic_base = core->base + CPU_IC_BASE; 270 core->wrapper_base = core->base + WRAPPER_BASE; 271 core->wrapper_tz_base = NULL; 272 core->aon_base = NULL; 273 } 274 } 275 276 static irqreturn_t venus_isr_thread(int irq, void *dev_id) 277 { 278 struct venus_core *core = dev_id; 279 irqreturn_t ret; 280 281 ret = hfi_isr_thread(irq, dev_id); 282 283 if (ret == IRQ_HANDLED && venus_fault_inject_ssr()) 284 hfi_core_trigger_ssr(core, HFI_TEST_SSR_SW_ERR_FATAL); 285 286 return ret; 287 } 288 289 #if defined(CONFIG_OF_DYNAMIC) 290 static int venus_add_video_core(struct venus_core *core, const char *node_name, 291 const char *compat) 292 { 293 struct of_changeset *ocs = core->ocs; 294 struct device *dev = core->dev; 295 struct device_node *np, *enp; 296 int ret; 297 298 if (!node_name) 299 return 0; 300 301 enp = of_find_node_by_name(dev->of_node, node_name); 302 if (enp) { 303 of_node_put(enp); 304 return 0; 305 } 306 307 np = of_changeset_create_node(ocs, dev->of_node, node_name); 308 if (!np) { 309 dev_err(dev, "Unable to create new node\n"); 310 return -ENODEV; 311 } 312 313 ret = of_changeset_add_prop_string(ocs, np, "compatible", compat); 314 if (ret) 315 dev_err(dev, "unable to add %s\n", compat); 316 317 of_node_put(np); 318 319 return ret; 320 } 321 322 static int venus_add_dynamic_nodes(struct venus_core *core) 323 { 324 struct device *dev = core->dev; 325 int ret; 326 327 core->ocs = kmalloc(sizeof(*core->ocs), GFP_KERNEL); 328 if (!core->ocs) 329 return -ENOMEM; 330 331 of_changeset_init(core->ocs); 332 333 ret = venus_add_video_core(core, core->res->dec_nodename, "venus-decoder"); 334 if (ret) 335 goto err; 336 337 ret = venus_add_video_core(core, core->res->enc_nodename, "venus-encoder"); 338 if (ret) 339 goto err; 340 341 ret = of_changeset_apply(core->ocs); 342 if (ret) { 343 dev_err(dev, "applying changeset fail ret %d\n", ret); 344 goto err; 345 } 346 347 return 0; 348 err: 349 of_changeset_destroy(core->ocs); 350 kfree(core->ocs); 351 core->ocs = NULL; 352 return ret; 353 } 354 355 static void venus_remove_dynamic_nodes(struct venus_core *core) 356 { 357 if (core->ocs) { 358 of_changeset_revert(core->ocs); 359 of_changeset_destroy(core->ocs); 360 kfree(core->ocs); 361 } 362 } 363 #else 364 static int venus_add_dynamic_nodes(struct venus_core *core) 365 { 366 return 0; 367 } 368 369 static void venus_remove_dynamic_nodes(struct venus_core *core) {} 370 #endif 371 372 static int venus_probe(struct platform_device *pdev) 373 { 374 struct device *dev = &pdev->dev; 375 struct venus_core *core; 376 int ret; 377 378 core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL); 379 if (!core) 380 return -ENOMEM; 381 382 core->dev = dev; 383 384 core->base = devm_platform_ioremap_resource(pdev, 0); 385 if (IS_ERR(core->base)) 386 return PTR_ERR(core->base); 387 388 core->video_path = devm_of_icc_get(dev, "video-mem"); 389 if (IS_ERR(core->video_path)) 390 return PTR_ERR(core->video_path); 391 392 core->cpucfg_path = devm_of_icc_get(dev, "cpu-cfg"); 393 if (IS_ERR(core->cpucfg_path)) 394 return PTR_ERR(core->cpucfg_path); 395 396 core->irq = platform_get_irq(pdev, 0); 397 if (core->irq < 0) 398 return core->irq; 399 400 core->res = of_device_get_match_data(dev); 401 if (!core->res) 402 return -ENODEV; 403 404 mutex_init(&core->pm_lock); 405 406 core->pm_ops = venus_pm_get(core->res->hfi_version); 407 if (!core->pm_ops) 408 return -ENODEV; 409 410 if (core->pm_ops->core_get) { 411 ret = core->pm_ops->core_get(core); 412 if (ret) 413 return ret; 414 } 415 416 ret = dma_set_mask_and_coherent(dev, core->res->dma_mask); 417 if (ret) 418 goto err_core_put; 419 420 dma_set_max_seg_size(dev, UINT_MAX); 421 422 INIT_LIST_HEAD(&core->instances); 423 mutex_init(&core->lock); 424 INIT_DELAYED_WORK(&core->work, venus_sys_error_handler); 425 init_waitqueue_head(&core->sys_err_done); 426 427 ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, venus_isr_thread, 428 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 429 "venus", core); 430 if (ret) 431 goto err_core_put; 432 433 ret = hfi_create(core, &venus_core_ops); 434 if (ret) 435 goto err_core_put; 436 437 venus_assign_register_offsets(core); 438 439 ret = v4l2_device_register(dev, &core->v4l2_dev); 440 if (ret) 441 goto err_hfi_destroy; 442 443 platform_set_drvdata(pdev, core); 444 445 pm_runtime_enable(dev); 446 447 ret = pm_runtime_get_sync(dev); 448 if (ret < 0) 449 goto err_runtime_disable; 450 451 if (core->res->dec_nodename || core->res->enc_nodename) { 452 ret = venus_add_dynamic_nodes(core); 453 if (ret) 454 goto err_runtime_disable; 455 } 456 457 ret = of_platform_populate(dev->of_node, NULL, NULL, dev); 458 if (ret) 459 goto err_remove_dynamic_nodes; 460 461 ret = venus_firmware_init(core); 462 if (ret) 463 goto err_of_depopulate; 464 465 ret = venus_boot(core); 466 if (ret) 467 goto err_firmware_deinit; 468 469 ret = hfi_core_resume(core, true); 470 if (ret) 471 goto err_venus_shutdown; 472 473 ret = hfi_core_init(core); 474 if (ret) 475 goto err_venus_shutdown; 476 477 ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_DEC); 478 if (ret) 479 goto err_core_deinit; 480 481 ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_ENC); 482 if (ret) 483 goto err_core_deinit; 484 485 ret = pm_runtime_put_sync(dev); 486 if (ret) { 487 pm_runtime_get_noresume(dev); 488 goto err_core_deinit; 489 } 490 491 venus_dbgfs_init(core); 492 493 return 0; 494 495 err_core_deinit: 496 hfi_core_deinit(core, false); 497 err_venus_shutdown: 498 venus_shutdown(core); 499 err_firmware_deinit: 500 venus_firmware_deinit(core); 501 err_of_depopulate: 502 of_platform_depopulate(dev); 503 err_remove_dynamic_nodes: 504 venus_remove_dynamic_nodes(core); 505 err_runtime_disable: 506 pm_runtime_put_noidle(dev); 507 pm_runtime_disable(dev); 508 pm_runtime_set_suspended(dev); 509 v4l2_device_unregister(&core->v4l2_dev); 510 err_hfi_destroy: 511 hfi_destroy(core); 512 err_core_put: 513 if (core->pm_ops->core_put) 514 core->pm_ops->core_put(core); 515 return ret; 516 } 517 518 static void venus_remove(struct platform_device *pdev) 519 { 520 struct venus_core *core = platform_get_drvdata(pdev); 521 const struct venus_pm_ops *pm_ops = core->pm_ops; 522 struct device *dev = core->dev; 523 int ret; 524 525 cancel_delayed_work_sync(&core->work); 526 ret = pm_runtime_get_sync(dev); 527 WARN_ON(ret < 0); 528 529 ret = hfi_core_deinit(core, true); 530 WARN_ON(ret); 531 532 venus_shutdown(core); 533 of_platform_depopulate(dev); 534 535 venus_firmware_deinit(core); 536 537 venus_remove_dynamic_nodes(core); 538 539 pm_runtime_put_sync(dev); 540 pm_runtime_disable(dev); 541 542 if (pm_ops->core_put) 543 pm_ops->core_put(core); 544 545 v4l2_device_unregister(&core->v4l2_dev); 546 547 hfi_destroy(core); 548 549 mutex_destroy(&core->pm_lock); 550 mutex_destroy(&core->lock); 551 venus_dbgfs_deinit(core); 552 } 553 554 static void venus_core_shutdown(struct platform_device *pdev) 555 { 556 struct venus_core *core = platform_get_drvdata(pdev); 557 558 pm_runtime_get_sync(core->dev); 559 venus_shutdown(core); 560 venus_firmware_deinit(core); 561 pm_runtime_put_sync(core->dev); 562 } 563 564 static __maybe_unused int venus_runtime_suspend(struct device *dev) 565 { 566 struct venus_core *core = dev_get_drvdata(dev); 567 const struct venus_pm_ops *pm_ops = core->pm_ops; 568 int ret; 569 570 ret = hfi_core_suspend(core); 571 if (ret) 572 return ret; 573 574 if (pm_ops->core_power) { 575 ret = pm_ops->core_power(core, POWER_OFF); 576 if (ret) 577 return ret; 578 } 579 580 ret = icc_set_bw(core->cpucfg_path, 0, 0); 581 if (ret) 582 goto err_cpucfg_path; 583 584 ret = icc_set_bw(core->video_path, 0, 0); 585 if (ret) 586 goto err_video_path; 587 588 return ret; 589 590 err_video_path: 591 icc_set_bw(core->cpucfg_path, kbps_to_icc(1000), 0); 592 err_cpucfg_path: 593 if (pm_ops->core_power) 594 pm_ops->core_power(core, POWER_ON); 595 596 return ret; 597 } 598 599 void venus_close_common(struct venus_inst *inst) 600 { 601 /* 602 * Make sure we don't have IRQ/IRQ-thread currently running 603 * or pending execution, which would race with the inst destruction. 604 */ 605 synchronize_irq(inst->core->irq); 606 607 v4l2_m2m_ctx_release(inst->m2m_ctx); 608 v4l2_m2m_release(inst->m2m_dev); 609 hfi_session_destroy(inst); 610 v4l2_fh_del(&inst->fh); 611 v4l2_fh_exit(&inst->fh); 612 v4l2_ctrl_handler_free(&inst->ctrl_handler); 613 614 mutex_destroy(&inst->lock); 615 mutex_destroy(&inst->ctx_q_lock); 616 } 617 EXPORT_SYMBOL_GPL(venus_close_common); 618 619 static __maybe_unused int venus_runtime_resume(struct device *dev) 620 { 621 struct venus_core *core = dev_get_drvdata(dev); 622 const struct venus_pm_ops *pm_ops = core->pm_ops; 623 int ret; 624 625 ret = icc_set_bw(core->video_path, kbps_to_icc(20000), 0); 626 if (ret) 627 return ret; 628 629 ret = icc_set_bw(core->cpucfg_path, kbps_to_icc(1000), 0); 630 if (ret) 631 return ret; 632 633 if (pm_ops->core_power) { 634 ret = pm_ops->core_power(core, POWER_ON); 635 if (ret) 636 return ret; 637 } 638 639 return hfi_core_resume(core, false); 640 } 641 642 static const struct dev_pm_ops venus_pm_ops = { 643 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 644 pm_runtime_force_resume) 645 SET_RUNTIME_PM_OPS(venus_runtime_suspend, venus_runtime_resume, NULL) 646 }; 647 648 static const struct freq_tbl msm8916_freq_table[] = { 649 { 352800, 228570000 }, /* 1920x1088 @ 30 + 1280x720 @ 30 */ 650 { 244800, 160000000 }, /* 1920x1088 @ 30 */ 651 { 108000, 100000000 }, /* 1280x720 @ 30 */ 652 }; 653 654 static const struct reg_val msm8916_reg_preset[] = { 655 { 0xe0020, 0x05555556 }, 656 { 0xe0024, 0x05555556 }, 657 { 0x80124, 0x00000003 }, 658 }; 659 660 static const struct venus_resources msm8916_res = { 661 .freq_tbl = msm8916_freq_table, 662 .freq_tbl_size = ARRAY_SIZE(msm8916_freq_table), 663 .reg_tbl = msm8916_reg_preset, 664 .reg_tbl_size = ARRAY_SIZE(msm8916_reg_preset), 665 .clks = { "core", "iface", "bus", }, 666 .clks_num = 3, 667 .max_load = 352800, /* 720p@30 + 1080p@30 */ 668 .hfi_version = HFI_VERSION_1XX, 669 .vmem_id = VIDC_RESOURCE_NONE, 670 .vmem_size = 0, 671 .vmem_addr = 0, 672 .dma_mask = 0xddc00000 - 1, 673 .fwname = "qcom/venus-1.8/venus.mbn", 674 .dec_nodename = "video-decoder", 675 .enc_nodename = "video-encoder", 676 }; 677 678 static const struct freq_tbl msm8996_freq_table[] = { 679 { 1944000, 520000000 }, /* 4k UHD @ 60 (decode only) */ 680 { 972000, 520000000 }, /* 4k UHD @ 30 */ 681 { 489600, 346666667 }, /* 1080p @ 60 */ 682 { 244800, 150000000 }, /* 1080p @ 30 */ 683 { 108000, 75000000 }, /* 720p @ 30 */ 684 }; 685 686 static const struct reg_val msm8996_reg_preset[] = { 687 { 0x80010, 0xffffffff }, 688 { 0x80018, 0x00001556 }, 689 { 0x8001C, 0x00001556 }, 690 }; 691 692 static const struct venus_resources msm8996_res = { 693 .freq_tbl = msm8996_freq_table, 694 .freq_tbl_size = ARRAY_SIZE(msm8996_freq_table), 695 .reg_tbl = msm8996_reg_preset, 696 .reg_tbl_size = ARRAY_SIZE(msm8996_reg_preset), 697 .clks = {"core", "iface", "bus", "mbus" }, 698 .clks_num = 4, 699 .vcodec0_clks = { "core" }, 700 .vcodec1_clks = { "core" }, 701 .vcodec_clks_num = 1, 702 .max_load = 2563200, 703 .hfi_version = HFI_VERSION_3XX, 704 .vmem_id = VIDC_RESOURCE_NONE, 705 .vmem_size = 0, 706 .vmem_addr = 0, 707 .dma_mask = 0xddc00000 - 1, 708 .fwname = "qcom/venus-4.2/venus.mbn", 709 }; 710 711 static const struct freq_tbl msm8998_freq_table[] = { 712 { 1944000, 465000000 }, /* 4k UHD @ 60 (decode only) */ 713 { 972000, 465000000 }, /* 4k UHD @ 30 */ 714 { 489600, 360000000 }, /* 1080p @ 60 */ 715 { 244800, 186000000 }, /* 1080p @ 30 */ 716 { 108000, 100000000 }, /* 720p @ 30 */ 717 }; 718 719 static const struct reg_val msm8998_reg_preset[] = { 720 { 0x80124, 0x00000003 }, 721 { 0x80550, 0x01111111 }, 722 { 0x80560, 0x01111111 }, 723 { 0x80568, 0x01111111 }, 724 { 0x80570, 0x01111111 }, 725 { 0x80580, 0x01111111 }, 726 { 0x80588, 0x01111111 }, 727 { 0xe2010, 0x00000000 }, 728 }; 729 730 static const struct venus_resources msm8998_res = { 731 .freq_tbl = msm8998_freq_table, 732 .freq_tbl_size = ARRAY_SIZE(msm8998_freq_table), 733 .reg_tbl = msm8998_reg_preset, 734 .reg_tbl_size = ARRAY_SIZE(msm8998_reg_preset), 735 .clks = { "core", "iface", "bus", "mbus" }, 736 .clks_num = 4, 737 .vcodec0_clks = { "core" }, 738 .vcodec1_clks = { "core" }, 739 .vcodec_clks_num = 1, 740 .max_load = 2563200, 741 .hfi_version = HFI_VERSION_3XX, 742 .vmem_id = VIDC_RESOURCE_NONE, 743 .vmem_size = 0, 744 .vmem_addr = 0, 745 .dma_mask = 0xddc00000 - 1, 746 .fwname = "qcom/venus-4.4/venus.mbn", 747 }; 748 749 static const struct freq_tbl sdm660_freq_table[] = { 750 { 979200, 518400000 }, 751 { 489600, 441600000 }, 752 { 432000, 404000000 }, 753 { 244800, 320000000 }, 754 { 216000, 269330000 }, 755 { 108000, 133330000 }, 756 }; 757 758 static const struct reg_val sdm660_reg_preset[] = { 759 { 0x80010, 0x001f001f }, 760 { 0x80018, 0x00000156 }, 761 { 0x8001c, 0x00000156 }, 762 }; 763 764 static const struct bw_tbl sdm660_bw_table_enc[] = { 765 { 979200, 1044000, 0, 2446336, 0 }, /* 4k UHD @ 30 */ 766 { 864000, 887000, 0, 2108416, 0 }, /* 720p @ 240 */ 767 { 489600, 666000, 0, 1207296, 0 }, /* 1080p @ 60 */ 768 { 432000, 578000, 0, 1058816, 0 }, /* 720p @ 120 */ 769 { 244800, 346000, 0, 616448, 0 }, /* 1080p @ 30 */ 770 { 216000, 293000, 0, 534528, 0 }, /* 720p @ 60 */ 771 { 108000, 151000, 0, 271360, 0 }, /* 720p @ 30 */ 772 }; 773 774 static const struct bw_tbl sdm660_bw_table_dec[] = { 775 { 979200, 2365000, 0, 1892000, 0 }, /* 4k UHD @ 30 */ 776 { 864000, 1978000, 0, 1554000, 0 }, /* 720p @ 240 */ 777 { 489600, 1133000, 0, 895000, 0 }, /* 1080p @ 60 */ 778 { 432000, 994000, 0, 781000, 0 }, /* 720p @ 120 */ 779 { 244800, 580000, 0, 460000, 0 }, /* 1080p @ 30 */ 780 { 216000, 501000, 0, 301000, 0 }, /* 720p @ 60 */ 781 { 108000, 255000, 0, 202000, 0 }, /* 720p @ 30 */ 782 }; 783 784 static const struct venus_resources sdm660_res = { 785 .freq_tbl = sdm660_freq_table, 786 .freq_tbl_size = ARRAY_SIZE(sdm660_freq_table), 787 .reg_tbl = sdm660_reg_preset, 788 .reg_tbl_size = ARRAY_SIZE(sdm660_reg_preset), 789 .bw_tbl_enc = sdm660_bw_table_enc, 790 .bw_tbl_enc_size = ARRAY_SIZE(sdm660_bw_table_enc), 791 .bw_tbl_dec = sdm660_bw_table_dec, 792 .bw_tbl_dec_size = ARRAY_SIZE(sdm660_bw_table_dec), 793 .clks = {"core", "iface", "bus", "bus_throttle" }, 794 .clks_num = 4, 795 .vcodec0_clks = { "vcodec0_core" }, 796 .vcodec1_clks = { "vcodec0_core" }, 797 .vcodec_clks_num = 1, 798 .vcodec_num = 1, 799 .max_load = 1036800, 800 .hfi_version = HFI_VERSION_3XX, 801 .vmem_id = VIDC_RESOURCE_NONE, 802 .vmem_size = 0, 803 .vmem_addr = 0, 804 .cp_start = 0, 805 .cp_size = 0x79000000, 806 .cp_nonpixel_start = 0x1000000, 807 .cp_nonpixel_size = 0x28000000, 808 .dma_mask = 0xd9000000 - 1, 809 .fwname = "qcom/venus-4.4/venus.mdt", 810 }; 811 812 static const struct freq_tbl sdm845_freq_table[] = { 813 { 3110400, 533000000 }, /* 4096x2160@90 */ 814 { 2073600, 444000000 }, /* 4096x2160@60 */ 815 { 1944000, 404000000 }, /* 3840x2160@60 */ 816 { 972000, 330000000 }, /* 3840x2160@30 */ 817 { 489600, 200000000 }, /* 1920x1080@60 */ 818 { 244800, 100000000 }, /* 1920x1080@30 */ 819 }; 820 821 static const struct bw_tbl sdm845_bw_table_enc[] = { 822 { 1944000, 1612000, 0, 2416000, 0 }, /* 3840x2160@60 */ 823 { 972000, 951000, 0, 1434000, 0 }, /* 3840x2160@30 */ 824 { 489600, 723000, 0, 973000, 0 }, /* 1920x1080@60 */ 825 { 244800, 370000, 0, 495000, 0 }, /* 1920x1080@30 */ 826 }; 827 828 static const struct bw_tbl sdm845_bw_table_dec[] = { 829 { 2073600, 3929000, 0, 5551000, 0 }, /* 4096x2160@60 */ 830 { 1036800, 1987000, 0, 2797000, 0 }, /* 4096x2160@30 */ 831 { 489600, 1040000, 0, 1298000, 0 }, /* 1920x1080@60 */ 832 { 244800, 530000, 0, 659000, 0 }, /* 1920x1080@30 */ 833 }; 834 835 static const struct venus_resources sdm845_res = { 836 .freq_tbl = sdm845_freq_table, 837 .freq_tbl_size = ARRAY_SIZE(sdm845_freq_table), 838 .bw_tbl_enc = sdm845_bw_table_enc, 839 .bw_tbl_enc_size = ARRAY_SIZE(sdm845_bw_table_enc), 840 .bw_tbl_dec = sdm845_bw_table_dec, 841 .bw_tbl_dec_size = ARRAY_SIZE(sdm845_bw_table_dec), 842 .clks = {"core", "iface", "bus" }, 843 .clks_num = 3, 844 .vcodec0_clks = { "core", "bus" }, 845 .vcodec1_clks = { "core", "bus" }, 846 .vcodec_clks_num = 2, 847 .max_load = 3110400, /* 4096x2160@90 */ 848 .hfi_version = HFI_VERSION_4XX, 849 .vpu_version = VPU_VERSION_AR50, 850 .vmem_id = VIDC_RESOURCE_NONE, 851 .vmem_size = 0, 852 .vmem_addr = 0, 853 .dma_mask = 0xe0000000 - 1, 854 .fwname = "qcom/venus-5.2/venus.mbn", 855 }; 856 857 static const struct venus_resources sdm845_res_v2 = { 858 .freq_tbl = sdm845_freq_table, 859 .freq_tbl_size = ARRAY_SIZE(sdm845_freq_table), 860 .bw_tbl_enc = sdm845_bw_table_enc, 861 .bw_tbl_enc_size = ARRAY_SIZE(sdm845_bw_table_enc), 862 .bw_tbl_dec = sdm845_bw_table_dec, 863 .bw_tbl_dec_size = ARRAY_SIZE(sdm845_bw_table_dec), 864 .clks = {"core", "iface", "bus" }, 865 .clks_num = 3, 866 .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, 867 .vcodec1_clks = { "vcodec1_core", "vcodec1_bus" }, 868 .vcodec_clks_num = 2, 869 .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0", "vcodec1" }, 870 .vcodec_pmdomains_num = 3, 871 .opp_pmdomain = (const char *[]) { "cx" }, 872 .vcodec_num = 2, 873 .max_load = 3110400, /* 4096x2160@90 */ 874 .hfi_version = HFI_VERSION_4XX, 875 .vpu_version = VPU_VERSION_AR50, 876 .vmem_id = VIDC_RESOURCE_NONE, 877 .vmem_size = 0, 878 .vmem_addr = 0, 879 .dma_mask = 0xe0000000 - 1, 880 .cp_start = 0, 881 .cp_size = 0x70800000, 882 .cp_nonpixel_start = 0x1000000, 883 .cp_nonpixel_size = 0x24800000, 884 .fwname = "qcom/venus-5.2/venus.mbn", 885 .dec_nodename = "video-core0", 886 .enc_nodename = "video-core1", 887 }; 888 889 static const struct freq_tbl sc7180_freq_table[] = { 890 { 0, 500000000 }, 891 { 0, 434000000 }, 892 { 0, 340000000 }, 893 { 0, 270000000 }, 894 { 0, 150000000 }, 895 }; 896 897 static const struct bw_tbl sc7180_bw_table_enc[] = { 898 { 972000, 750000, 0, 0, 0 }, /* 3840x2160@30 */ 899 { 489600, 451000, 0, 0, 0 }, /* 1920x1080@60 */ 900 { 244800, 234000, 0, 0, 0 }, /* 1920x1080@30 */ 901 }; 902 903 static const struct bw_tbl sc7180_bw_table_dec[] = { 904 { 1036800, 1386000, 0, 1875000, 0 }, /* 4096x2160@30 */ 905 { 489600, 865000, 0, 1146000, 0 }, /* 1920x1080@60 */ 906 { 244800, 530000, 0, 583000, 0 }, /* 1920x1080@30 */ 907 }; 908 909 static const struct venus_resources sc7180_res = { 910 .freq_tbl = sc7180_freq_table, 911 .freq_tbl_size = ARRAY_SIZE(sc7180_freq_table), 912 .bw_tbl_enc = sc7180_bw_table_enc, 913 .bw_tbl_enc_size = ARRAY_SIZE(sc7180_bw_table_enc), 914 .bw_tbl_dec = sc7180_bw_table_dec, 915 .bw_tbl_dec_size = ARRAY_SIZE(sc7180_bw_table_dec), 916 .clks = {"core", "iface", "bus" }, 917 .clks_num = 3, 918 .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, 919 .vcodec_clks_num = 2, 920 .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" }, 921 .vcodec_pmdomains_num = 2, 922 .opp_pmdomain = (const char *[]) { "cx" }, 923 .vcodec_num = 1, 924 .hfi_version = HFI_VERSION_4XX, 925 .vpu_version = VPU_VERSION_AR50, 926 .vmem_id = VIDC_RESOURCE_NONE, 927 .vmem_size = 0, 928 .vmem_addr = 0, 929 .dma_mask = 0xe0000000 - 1, 930 .cp_start = 0, 931 .cp_size = 0x70800000, 932 .cp_nonpixel_start = 0x1000000, 933 .cp_nonpixel_size = 0x24800000, 934 .fwname = "qcom/venus-5.4/venus.mbn", 935 .dec_nodename = "video-decoder", 936 .enc_nodename = "video-encoder", 937 }; 938 939 static const struct freq_tbl sm8250_freq_table[] = { 940 { 0, 444000000 }, 941 { 0, 366000000 }, 942 { 0, 338000000 }, 943 { 0, 240000000 }, 944 }; 945 946 static const struct bw_tbl sm8250_bw_table_enc[] = { 947 { 1944000, 1954000, 0, 3711000, 0 }, /* 3840x2160@60 */ 948 { 972000, 996000, 0, 1905000, 0 }, /* 3840x2160@30 */ 949 { 489600, 645000, 0, 977000, 0 }, /* 1920x1080@60 */ 950 { 244800, 332000, 0, 498000, 0 }, /* 1920x1080@30 */ 951 }; 952 953 static const struct bw_tbl sm8250_bw_table_dec[] = { 954 { 2073600, 2403000, 0, 4113000, 0 }, /* 4096x2160@60 */ 955 { 1036800, 1224000, 0, 2079000, 0 }, /* 4096x2160@30 */ 956 { 489600, 812000, 0, 998000, 0 }, /* 1920x1080@60 */ 957 { 244800, 416000, 0, 509000, 0 }, /* 1920x1080@30 */ 958 }; 959 960 static const struct reg_val sm8250_reg_preset[] = { 961 { 0xb0088, 0 }, 962 }; 963 964 static const struct venus_resources sm8250_res = { 965 .freq_tbl = sm8250_freq_table, 966 .freq_tbl_size = ARRAY_SIZE(sm8250_freq_table), 967 .reg_tbl = sm8250_reg_preset, 968 .reg_tbl_size = ARRAY_SIZE(sm8250_reg_preset), 969 .bw_tbl_enc = sm8250_bw_table_enc, 970 .bw_tbl_enc_size = ARRAY_SIZE(sm8250_bw_table_enc), 971 .bw_tbl_dec = sm8250_bw_table_dec, 972 .bw_tbl_dec_size = ARRAY_SIZE(sm8250_bw_table_dec), 973 .clks = {"core", "iface"}, 974 .clks_num = 2, 975 .resets = { "bus", "core" }, 976 .resets_num = 2, 977 .vcodec0_clks = { "vcodec0_core" }, 978 .vcodec_clks_num = 1, 979 .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" }, 980 .vcodec_pmdomains_num = 2, 981 .opp_pmdomain = (const char *[]) { "mx" }, 982 .vcodec_num = 1, 983 .max_load = 7833600, 984 .hfi_version = HFI_VERSION_6XX, 985 .vpu_version = VPU_VERSION_IRIS2, 986 .num_vpp_pipes = 4, 987 .vmem_id = VIDC_RESOURCE_NONE, 988 .vmem_size = 0, 989 .vmem_addr = 0, 990 .dma_mask = 0xe0000000 - 1, 991 .fwname = "qcom/vpu-1.0/venus.mbn", 992 .dec_nodename = "video-decoder", 993 .enc_nodename = "video-encoder", 994 }; 995 996 static const struct freq_tbl sc7280_freq_table[] = { 997 { 0, 460000000 }, 998 { 0, 424000000 }, 999 { 0, 335000000 }, 1000 { 0, 240000000 }, 1001 { 0, 133333333 }, 1002 }; 1003 1004 static const struct bw_tbl sc7280_bw_table_enc[] = { 1005 { 1944000, 1896000, 0, 3657000, 0 }, /* 3840x2160@60 */ 1006 { 972000, 968000, 0, 1848000, 0 }, /* 3840x2160@30 */ 1007 { 489600, 618000, 0, 941000, 0 }, /* 1920x1080@60 */ 1008 { 244800, 318000, 0, 480000, 0 }, /* 1920x1080@30 */ 1009 }; 1010 1011 static const struct bw_tbl sc7280_bw_table_dec[] = { 1012 { 2073600, 2128000, 0, 3831000, 0 }, /* 4096x2160@60 */ 1013 { 1036800, 1085000, 0, 1937000, 0 }, /* 4096x2160@30 */ 1014 { 489600, 779000, 0, 998000, 0 }, /* 1920x1080@60 */ 1015 { 244800, 400000, 0, 509000, 0 }, /* 1920x1080@30 */ 1016 }; 1017 1018 static const struct reg_val sm7280_reg_preset[] = { 1019 { 0xb0088, 0 }, 1020 }; 1021 1022 static const struct hfi_ubwc_config sc7280_ubwc_config = { 1023 0, 0, {1, 1, 1, 0, 0, 0}, 8, 32, 14, 0, 0, {0, 0} 1024 }; 1025 1026 static const struct venus_resources sc7280_res = { 1027 .freq_tbl = sc7280_freq_table, 1028 .freq_tbl_size = ARRAY_SIZE(sc7280_freq_table), 1029 .reg_tbl = sm7280_reg_preset, 1030 .reg_tbl_size = ARRAY_SIZE(sm7280_reg_preset), 1031 .bw_tbl_enc = sc7280_bw_table_enc, 1032 .bw_tbl_enc_size = ARRAY_SIZE(sc7280_bw_table_enc), 1033 .bw_tbl_dec = sc7280_bw_table_dec, 1034 .bw_tbl_dec_size = ARRAY_SIZE(sc7280_bw_table_dec), 1035 .ubwc_conf = &sc7280_ubwc_config, 1036 .clks = {"core", "bus", "iface"}, 1037 .clks_num = 3, 1038 .vcodec0_clks = {"vcodec_core", "vcodec_bus"}, 1039 .vcodec_clks_num = 2, 1040 .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" }, 1041 .vcodec_pmdomains_num = 2, 1042 .opp_pmdomain = (const char *[]) { "cx" }, 1043 .vcodec_num = 1, 1044 .hfi_version = HFI_VERSION_6XX, 1045 .vpu_version = VPU_VERSION_IRIS2_1, 1046 .num_vpp_pipes = 1, 1047 .vmem_id = VIDC_RESOURCE_NONE, 1048 .vmem_size = 0, 1049 .vmem_addr = 0, 1050 .dma_mask = 0xe0000000 - 1, 1051 .cp_start = 0, 1052 .cp_size = 0x25800000, 1053 .cp_nonpixel_start = 0x1000000, 1054 .cp_nonpixel_size = 0x24800000, 1055 .fwname = "qcom/vpu-2.0/venus.mbn", 1056 .dec_nodename = "video-decoder", 1057 .enc_nodename = "video-encoder", 1058 }; 1059 1060 static const struct of_device_id venus_dt_match[] = { 1061 { .compatible = "qcom,msm8916-venus", .data = &msm8916_res, }, 1062 { .compatible = "qcom,msm8996-venus", .data = &msm8996_res, }, 1063 { .compatible = "qcom,msm8998-venus", .data = &msm8998_res, }, 1064 { .compatible = "qcom,sdm660-venus", .data = &sdm660_res, }, 1065 { .compatible = "qcom,sdm845-venus", .data = &sdm845_res, }, 1066 { .compatible = "qcom,sdm845-venus-v2", .data = &sdm845_res_v2, }, 1067 { .compatible = "qcom,sc7180-venus", .data = &sc7180_res, }, 1068 { .compatible = "qcom,sc7280-venus", .data = &sc7280_res, }, 1069 { .compatible = "qcom,sm8250-venus", .data = &sm8250_res, }, 1070 { } 1071 }; 1072 MODULE_DEVICE_TABLE(of, venus_dt_match); 1073 1074 static struct platform_driver qcom_venus_driver = { 1075 .probe = venus_probe, 1076 .remove = venus_remove, 1077 .driver = { 1078 .name = "qcom-venus", 1079 .of_match_table = venus_dt_match, 1080 .pm = &venus_pm_ops, 1081 }, 1082 .shutdown = venus_core_shutdown, 1083 }; 1084 module_platform_driver(qcom_venus_driver); 1085 1086 MODULE_ALIAS("platform:qcom-venus"); 1087 MODULE_DESCRIPTION("Qualcomm Venus video encoder and decoder driver"); 1088 MODULE_LICENSE("GPL v2"); 1089