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