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