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 core->sys_error = true; 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 hfi_core_deinit(core, true); 99 100 mutex_lock(&core->lock); 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 venus_shutdown(core); 109 110 venus_coredump(core); 111 112 pm_runtime_put_sync(core->dev); 113 114 for (i = 0; i < max_attempts; i++) { 115 if (!core->pmdomains[0] || !pm_runtime_active(core->pmdomains[0])) 116 break; 117 usleep_range(1000, 1500); 118 } 119 120 hfi_reinit(core); 121 122 ret = pm_runtime_get_sync(core->dev); 123 if (ret < 0) { 124 err_msg = "resume runtime PM"; 125 failed = true; 126 } 127 128 ret = venus_boot(core); 129 if (ret && !failed) { 130 err_msg = "boot Venus"; 131 failed = true; 132 } 133 134 ret = hfi_core_resume(core, true); 135 if (ret && !failed) { 136 err_msg = "resume HFI"; 137 failed = true; 138 } 139 140 enable_irq(core->irq); 141 142 mutex_unlock(&core->lock); 143 144 ret = hfi_core_init(core); 145 if (ret && !failed) { 146 err_msg = "init HFI"; 147 failed = true; 148 } 149 150 pm_runtime_put_sync(core->dev); 151 152 if (failed) { 153 disable_irq_nosync(core->irq); 154 dev_warn_ratelimited(core->dev, 155 "System error has occurred, recovery failed to %s\n", 156 err_msg); 157 schedule_delayed_work(&core->work, msecs_to_jiffies(10)); 158 return; 159 } 160 161 dev_warn(core->dev, "system error has occurred (recovered)\n"); 162 163 mutex_lock(&core->lock); 164 core->sys_error = false; 165 mutex_unlock(&core->lock); 166 } 167 168 static u32 to_v4l2_codec_type(u32 codec) 169 { 170 switch (codec) { 171 case HFI_VIDEO_CODEC_H264: 172 return V4L2_PIX_FMT_H264; 173 case HFI_VIDEO_CODEC_H263: 174 return V4L2_PIX_FMT_H263; 175 case HFI_VIDEO_CODEC_MPEG1: 176 return V4L2_PIX_FMT_MPEG1; 177 case HFI_VIDEO_CODEC_MPEG2: 178 return V4L2_PIX_FMT_MPEG2; 179 case HFI_VIDEO_CODEC_MPEG4: 180 return V4L2_PIX_FMT_MPEG4; 181 case HFI_VIDEO_CODEC_VC1: 182 return V4L2_PIX_FMT_VC1_ANNEX_G; 183 case HFI_VIDEO_CODEC_VP8: 184 return V4L2_PIX_FMT_VP8; 185 case HFI_VIDEO_CODEC_VP9: 186 return V4L2_PIX_FMT_VP9; 187 case HFI_VIDEO_CODEC_DIVX: 188 case HFI_VIDEO_CODEC_DIVX_311: 189 return V4L2_PIX_FMT_XVID; 190 default: 191 return 0; 192 } 193 } 194 195 static int venus_enumerate_codecs(struct venus_core *core, u32 type) 196 { 197 const struct hfi_inst_ops dummy_ops = {}; 198 struct venus_inst *inst; 199 u32 codec, codecs; 200 unsigned int i; 201 int ret; 202 203 if (core->res->hfi_version != HFI_VERSION_1XX) 204 return 0; 205 206 inst = kzalloc(sizeof(*inst), GFP_KERNEL); 207 if (!inst) 208 return -ENOMEM; 209 210 mutex_init(&inst->lock); 211 inst->core = core; 212 inst->session_type = type; 213 if (type == VIDC_SESSION_TYPE_DEC) 214 codecs = core->dec_codecs; 215 else 216 codecs = core->enc_codecs; 217 218 ret = hfi_session_create(inst, &dummy_ops); 219 if (ret) 220 goto err; 221 222 for (i = 0; i < MAX_CODEC_NUM; i++) { 223 codec = (1UL << i) & codecs; 224 if (!codec) 225 continue; 226 227 ret = hfi_session_init(inst, to_v4l2_codec_type(codec)); 228 if (ret) 229 goto done; 230 231 ret = hfi_session_deinit(inst); 232 if (ret) 233 goto done; 234 } 235 236 done: 237 hfi_session_destroy(inst); 238 err: 239 mutex_destroy(&inst->lock); 240 kfree(inst); 241 242 return ret; 243 } 244 245 static void venus_assign_register_offsets(struct venus_core *core) 246 { 247 if (IS_V6(core)) { 248 core->vbif_base = core->base + VBIF_BASE; 249 core->cpu_base = core->base + CPU_BASE_V6; 250 core->cpu_cs_base = core->base + CPU_CS_BASE_V6; 251 core->cpu_ic_base = core->base + CPU_IC_BASE_V6; 252 core->wrapper_base = core->base + WRAPPER_BASE_V6; 253 core->wrapper_tz_base = core->base + WRAPPER_TZ_BASE_V6; 254 core->aon_base = core->base + AON_BASE_V6; 255 } else { 256 core->vbif_base = core->base + VBIF_BASE; 257 core->cpu_base = core->base + CPU_BASE; 258 core->cpu_cs_base = core->base + CPU_CS_BASE; 259 core->cpu_ic_base = core->base + CPU_IC_BASE; 260 core->wrapper_base = core->base + WRAPPER_BASE; 261 core->wrapper_tz_base = NULL; 262 core->aon_base = NULL; 263 } 264 } 265 266 static int venus_probe(struct platform_device *pdev) 267 { 268 struct device *dev = &pdev->dev; 269 struct venus_core *core; 270 struct resource *r; 271 int ret; 272 273 core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL); 274 if (!core) 275 return -ENOMEM; 276 277 core->dev = dev; 278 279 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 280 core->base = devm_ioremap_resource(dev, r); 281 if (IS_ERR(core->base)) 282 return PTR_ERR(core->base); 283 284 core->video_path = devm_of_icc_get(dev, "video-mem"); 285 if (IS_ERR(core->video_path)) 286 return PTR_ERR(core->video_path); 287 288 core->cpucfg_path = devm_of_icc_get(dev, "cpu-cfg"); 289 if (IS_ERR(core->cpucfg_path)) 290 return PTR_ERR(core->cpucfg_path); 291 292 core->irq = platform_get_irq(pdev, 0); 293 if (core->irq < 0) 294 return core->irq; 295 296 core->res = of_device_get_match_data(dev); 297 if (!core->res) 298 return -ENODEV; 299 300 mutex_init(&core->pm_lock); 301 302 core->pm_ops = venus_pm_get(core->res->hfi_version); 303 if (!core->pm_ops) 304 return -ENODEV; 305 306 if (core->pm_ops->core_get) { 307 ret = core->pm_ops->core_get(core); 308 if (ret) 309 return ret; 310 } 311 312 ret = dma_set_mask_and_coherent(dev, core->res->dma_mask); 313 if (ret) 314 goto err_core_put; 315 316 dma_set_max_seg_size(dev, UINT_MAX); 317 318 INIT_LIST_HEAD(&core->instances); 319 mutex_init(&core->lock); 320 INIT_DELAYED_WORK(&core->work, venus_sys_error_handler); 321 322 ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, hfi_isr_thread, 323 IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 324 "venus", core); 325 if (ret) 326 goto err_core_put; 327 328 ret = hfi_create(core, &venus_core_ops); 329 if (ret) 330 goto err_core_put; 331 332 venus_assign_register_offsets(core); 333 334 ret = v4l2_device_register(dev, &core->v4l2_dev); 335 if (ret) 336 goto err_core_deinit; 337 338 platform_set_drvdata(pdev, core); 339 340 pm_runtime_enable(dev); 341 342 ret = pm_runtime_get_sync(dev); 343 if (ret < 0) 344 goto err_runtime_disable; 345 346 ret = of_platform_populate(dev->of_node, NULL, NULL, dev); 347 if (ret) 348 goto err_runtime_disable; 349 350 ret = venus_firmware_init(core); 351 if (ret) 352 goto err_runtime_disable; 353 354 ret = venus_boot(core); 355 if (ret) 356 goto err_runtime_disable; 357 358 ret = hfi_core_resume(core, true); 359 if (ret) 360 goto err_venus_shutdown; 361 362 ret = hfi_core_init(core); 363 if (ret) 364 goto err_venus_shutdown; 365 366 ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_DEC); 367 if (ret) 368 goto err_venus_shutdown; 369 370 ret = venus_enumerate_codecs(core, VIDC_SESSION_TYPE_ENC); 371 if (ret) 372 goto err_venus_shutdown; 373 374 ret = pm_runtime_put_sync(dev); 375 if (ret) { 376 pm_runtime_get_noresume(dev); 377 goto err_dev_unregister; 378 } 379 380 venus_dbgfs_init(core); 381 382 return 0; 383 384 err_dev_unregister: 385 v4l2_device_unregister(&core->v4l2_dev); 386 err_venus_shutdown: 387 venus_shutdown(core); 388 err_runtime_disable: 389 pm_runtime_put_noidle(dev); 390 pm_runtime_set_suspended(dev); 391 pm_runtime_disable(dev); 392 hfi_destroy(core); 393 err_core_deinit: 394 hfi_core_deinit(core, false); 395 err_core_put: 396 if (core->pm_ops->core_put) 397 core->pm_ops->core_put(core); 398 return ret; 399 } 400 401 static int venus_remove(struct platform_device *pdev) 402 { 403 struct venus_core *core = platform_get_drvdata(pdev); 404 const struct venus_pm_ops *pm_ops = core->pm_ops; 405 struct device *dev = core->dev; 406 int ret; 407 408 ret = pm_runtime_get_sync(dev); 409 WARN_ON(ret < 0); 410 411 ret = hfi_core_deinit(core, true); 412 WARN_ON(ret); 413 414 venus_shutdown(core); 415 of_platform_depopulate(dev); 416 417 venus_firmware_deinit(core); 418 419 pm_runtime_put_sync(dev); 420 pm_runtime_disable(dev); 421 422 if (pm_ops->core_put) 423 pm_ops->core_put(core); 424 425 v4l2_device_unregister(&core->v4l2_dev); 426 427 hfi_destroy(core); 428 429 mutex_destroy(&core->pm_lock); 430 mutex_destroy(&core->lock); 431 venus_dbgfs_deinit(core); 432 433 return ret; 434 } 435 436 static void venus_core_shutdown(struct platform_device *pdev) 437 { 438 struct venus_core *core = platform_get_drvdata(pdev); 439 440 pm_runtime_get_sync(core->dev); 441 venus_shutdown(core); 442 venus_firmware_deinit(core); 443 pm_runtime_put_sync(core->dev); 444 } 445 446 static __maybe_unused int venus_runtime_suspend(struct device *dev) 447 { 448 struct venus_core *core = dev_get_drvdata(dev); 449 const struct venus_pm_ops *pm_ops = core->pm_ops; 450 int ret; 451 452 ret = hfi_core_suspend(core); 453 if (ret) 454 return ret; 455 456 if (pm_ops->core_power) { 457 ret = pm_ops->core_power(core, POWER_OFF); 458 if (ret) 459 return ret; 460 } 461 462 ret = icc_set_bw(core->cpucfg_path, 0, 0); 463 if (ret) 464 goto err_cpucfg_path; 465 466 ret = icc_set_bw(core->video_path, 0, 0); 467 if (ret) 468 goto err_video_path; 469 470 return ret; 471 472 err_video_path: 473 icc_set_bw(core->cpucfg_path, kbps_to_icc(1000), 0); 474 err_cpucfg_path: 475 pm_ops->core_power(core, POWER_ON); 476 477 return ret; 478 } 479 480 static __maybe_unused int venus_runtime_resume(struct device *dev) 481 { 482 struct venus_core *core = dev_get_drvdata(dev); 483 const struct venus_pm_ops *pm_ops = core->pm_ops; 484 int ret; 485 486 ret = icc_set_bw(core->video_path, kbps_to_icc(20000), 0); 487 if (ret) 488 return ret; 489 490 ret = icc_set_bw(core->cpucfg_path, kbps_to_icc(1000), 0); 491 if (ret) 492 return ret; 493 494 if (pm_ops->core_power) { 495 ret = pm_ops->core_power(core, POWER_ON); 496 if (ret) 497 return ret; 498 } 499 500 return hfi_core_resume(core, false); 501 } 502 503 static const struct dev_pm_ops venus_pm_ops = { 504 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 505 pm_runtime_force_resume) 506 SET_RUNTIME_PM_OPS(venus_runtime_suspend, venus_runtime_resume, NULL) 507 }; 508 509 static const struct freq_tbl msm8916_freq_table[] = { 510 { 352800, 228570000 }, /* 1920x1088 @ 30 + 1280x720 @ 30 */ 511 { 244800, 160000000 }, /* 1920x1088 @ 30 */ 512 { 108000, 100000000 }, /* 1280x720 @ 30 */ 513 }; 514 515 static const struct reg_val msm8916_reg_preset[] = { 516 { 0xe0020, 0x05555556 }, 517 { 0xe0024, 0x05555556 }, 518 { 0x80124, 0x00000003 }, 519 }; 520 521 static const struct venus_resources msm8916_res = { 522 .freq_tbl = msm8916_freq_table, 523 .freq_tbl_size = ARRAY_SIZE(msm8916_freq_table), 524 .reg_tbl = msm8916_reg_preset, 525 .reg_tbl_size = ARRAY_SIZE(msm8916_reg_preset), 526 .clks = { "core", "iface", "bus", }, 527 .clks_num = 3, 528 .max_load = 352800, /* 720p@30 + 1080p@30 */ 529 .hfi_version = HFI_VERSION_1XX, 530 .vmem_id = VIDC_RESOURCE_NONE, 531 .vmem_size = 0, 532 .vmem_addr = 0, 533 .dma_mask = 0xddc00000 - 1, 534 .fwname = "qcom/venus-1.8/venus.mdt", 535 }; 536 537 static const struct freq_tbl msm8996_freq_table[] = { 538 { 1944000, 520000000 }, /* 4k UHD @ 60 (decode only) */ 539 { 972000, 520000000 }, /* 4k UHD @ 30 */ 540 { 489600, 346666667 }, /* 1080p @ 60 */ 541 { 244800, 150000000 }, /* 1080p @ 30 */ 542 { 108000, 75000000 }, /* 720p @ 30 */ 543 }; 544 545 static const struct reg_val msm8996_reg_preset[] = { 546 { 0x80010, 0xffffffff }, 547 { 0x80018, 0x00001556 }, 548 { 0x8001C, 0x00001556 }, 549 }; 550 551 static const struct venus_resources msm8996_res = { 552 .freq_tbl = msm8996_freq_table, 553 .freq_tbl_size = ARRAY_SIZE(msm8996_freq_table), 554 .reg_tbl = msm8996_reg_preset, 555 .reg_tbl_size = ARRAY_SIZE(msm8996_reg_preset), 556 .clks = {"core", "iface", "bus", "mbus" }, 557 .clks_num = 4, 558 .vcodec0_clks = { "core" }, 559 .vcodec1_clks = { "core" }, 560 .vcodec_clks_num = 1, 561 .max_load = 2563200, 562 .hfi_version = HFI_VERSION_3XX, 563 .vmem_id = VIDC_RESOURCE_NONE, 564 .vmem_size = 0, 565 .vmem_addr = 0, 566 .dma_mask = 0xddc00000 - 1, 567 .fwname = "qcom/venus-4.2/venus.mdt", 568 }; 569 570 static const struct freq_tbl sdm845_freq_table[] = { 571 { 3110400, 533000000 }, /* 4096x2160@90 */ 572 { 2073600, 444000000 }, /* 4096x2160@60 */ 573 { 1944000, 404000000 }, /* 3840x2160@60 */ 574 { 972000, 330000000 }, /* 3840x2160@30 */ 575 { 489600, 200000000 }, /* 1920x1080@60 */ 576 { 244800, 100000000 }, /* 1920x1080@30 */ 577 }; 578 579 static const struct bw_tbl sdm845_bw_table_enc[] = { 580 { 1944000, 1612000, 0, 2416000, 0 }, /* 3840x2160@60 */ 581 { 972000, 951000, 0, 1434000, 0 }, /* 3840x2160@30 */ 582 { 489600, 723000, 0, 973000, 0 }, /* 1920x1080@60 */ 583 { 244800, 370000, 0, 495000, 0 }, /* 1920x1080@30 */ 584 }; 585 586 static const struct bw_tbl sdm845_bw_table_dec[] = { 587 { 2073600, 3929000, 0, 5551000, 0 }, /* 4096x2160@60 */ 588 { 1036800, 1987000, 0, 2797000, 0 }, /* 4096x2160@30 */ 589 { 489600, 1040000, 0, 1298000, 0 }, /* 1920x1080@60 */ 590 { 244800, 530000, 0, 659000, 0 }, /* 1920x1080@30 */ 591 }; 592 593 static const struct venus_resources sdm845_res = { 594 .freq_tbl = sdm845_freq_table, 595 .freq_tbl_size = ARRAY_SIZE(sdm845_freq_table), 596 .bw_tbl_enc = sdm845_bw_table_enc, 597 .bw_tbl_enc_size = ARRAY_SIZE(sdm845_bw_table_enc), 598 .bw_tbl_dec = sdm845_bw_table_dec, 599 .bw_tbl_dec_size = ARRAY_SIZE(sdm845_bw_table_dec), 600 .clks = {"core", "iface", "bus" }, 601 .clks_num = 3, 602 .vcodec0_clks = { "core", "bus" }, 603 .vcodec1_clks = { "core", "bus" }, 604 .vcodec_clks_num = 2, 605 .max_load = 3110400, /* 4096x2160@90 */ 606 .hfi_version = HFI_VERSION_4XX, 607 .vmem_id = VIDC_RESOURCE_NONE, 608 .vmem_size = 0, 609 .vmem_addr = 0, 610 .dma_mask = 0xe0000000 - 1, 611 .fwname = "qcom/venus-5.2/venus.mdt", 612 }; 613 614 static const struct venus_resources sdm845_res_v2 = { 615 .freq_tbl = sdm845_freq_table, 616 .freq_tbl_size = ARRAY_SIZE(sdm845_freq_table), 617 .bw_tbl_enc = sdm845_bw_table_enc, 618 .bw_tbl_enc_size = ARRAY_SIZE(sdm845_bw_table_enc), 619 .bw_tbl_dec = sdm845_bw_table_dec, 620 .bw_tbl_dec_size = ARRAY_SIZE(sdm845_bw_table_dec), 621 .clks = {"core", "iface", "bus" }, 622 .clks_num = 3, 623 .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, 624 .vcodec1_clks = { "vcodec1_core", "vcodec1_bus" }, 625 .vcodec_clks_num = 2, 626 .vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" }, 627 .vcodec_pmdomains_num = 3, 628 .opp_pmdomain = (const char *[]) { "cx", NULL }, 629 .vcodec_num = 2, 630 .max_load = 3110400, /* 4096x2160@90 */ 631 .hfi_version = HFI_VERSION_4XX, 632 .vmem_id = VIDC_RESOURCE_NONE, 633 .vmem_size = 0, 634 .vmem_addr = 0, 635 .dma_mask = 0xe0000000 - 1, 636 .cp_start = 0, 637 .cp_size = 0x70800000, 638 .cp_nonpixel_start = 0x1000000, 639 .cp_nonpixel_size = 0x24800000, 640 .fwname = "qcom/venus-5.2/venus.mdt", 641 }; 642 643 static const struct freq_tbl sc7180_freq_table[] = { 644 { 0, 500000000 }, 645 { 0, 434000000 }, 646 { 0, 340000000 }, 647 { 0, 270000000 }, 648 { 0, 150000000 }, 649 }; 650 651 static const struct bw_tbl sc7180_bw_table_enc[] = { 652 { 972000, 750000, 0, 0, 0 }, /* 3840x2160@30 */ 653 { 489600, 451000, 0, 0, 0 }, /* 1920x1080@60 */ 654 { 244800, 234000, 0, 0, 0 }, /* 1920x1080@30 */ 655 }; 656 657 static const struct bw_tbl sc7180_bw_table_dec[] = { 658 { 1036800, 1386000, 0, 1875000, 0 }, /* 4096x2160@30 */ 659 { 489600, 865000, 0, 1146000, 0 }, /* 1920x1080@60 */ 660 { 244800, 530000, 0, 583000, 0 }, /* 1920x1080@30 */ 661 }; 662 663 static const struct venus_resources sc7180_res = { 664 .freq_tbl = sc7180_freq_table, 665 .freq_tbl_size = ARRAY_SIZE(sc7180_freq_table), 666 .bw_tbl_enc = sc7180_bw_table_enc, 667 .bw_tbl_enc_size = ARRAY_SIZE(sc7180_bw_table_enc), 668 .bw_tbl_dec = sc7180_bw_table_dec, 669 .bw_tbl_dec_size = ARRAY_SIZE(sc7180_bw_table_dec), 670 .clks = {"core", "iface", "bus" }, 671 .clks_num = 3, 672 .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, 673 .vcodec_clks_num = 2, 674 .vcodec_pmdomains = { "venus", "vcodec0" }, 675 .vcodec_pmdomains_num = 2, 676 .opp_pmdomain = (const char *[]) { "cx", NULL }, 677 .vcodec_num = 1, 678 .hfi_version = HFI_VERSION_4XX, 679 .vmem_id = VIDC_RESOURCE_NONE, 680 .vmem_size = 0, 681 .vmem_addr = 0, 682 .dma_mask = 0xe0000000 - 1, 683 .fwname = "qcom/venus-5.4/venus.mdt", 684 }; 685 686 static const struct freq_tbl sm8250_freq_table[] = { 687 { 0, 444000000 }, 688 { 0, 366000000 }, 689 { 0, 338000000 }, 690 { 0, 240000000 }, 691 }; 692 693 static const struct bw_tbl sm8250_bw_table_enc[] = { 694 { 1944000, 1954000, 0, 3711000, 0 }, /* 3840x2160@60 */ 695 { 972000, 996000, 0, 1905000, 0 }, /* 3840x2160@30 */ 696 { 489600, 645000, 0, 977000, 0 }, /* 1920x1080@60 */ 697 { 244800, 332000, 0, 498000, 0 }, /* 1920x1080@30 */ 698 }; 699 700 static const struct bw_tbl sm8250_bw_table_dec[] = { 701 { 2073600, 2403000, 0, 4113000, 0 }, /* 4096x2160@60 */ 702 { 1036800, 1224000, 0, 2079000, 0 }, /* 4096x2160@30 */ 703 { 489600, 812000, 0, 998000, 0 }, /* 1920x1080@60 */ 704 { 244800, 416000, 0, 509000, 0 }, /* 1920x1080@30 */ 705 }; 706 707 static const struct reg_val sm8250_reg_preset[] = { 708 { 0xb0088, 0 }, 709 }; 710 711 static const struct venus_resources sm8250_res = { 712 .freq_tbl = sm8250_freq_table, 713 .freq_tbl_size = ARRAY_SIZE(sm8250_freq_table), 714 .reg_tbl = sm8250_reg_preset, 715 .reg_tbl_size = ARRAY_SIZE(sm8250_reg_preset), 716 .bw_tbl_enc = sm8250_bw_table_enc, 717 .bw_tbl_enc_size = ARRAY_SIZE(sm8250_bw_table_enc), 718 .bw_tbl_dec = sm8250_bw_table_dec, 719 .bw_tbl_dec_size = ARRAY_SIZE(sm8250_bw_table_dec), 720 .clks = {"core", "iface"}, 721 .clks_num = 2, 722 .resets = { "bus", "core" }, 723 .resets_num = 2, 724 .vcodec0_clks = { "vcodec0_core" }, 725 .vcodec_clks_num = 1, 726 .vcodec_pmdomains = { "venus", "vcodec0" }, 727 .vcodec_pmdomains_num = 2, 728 .opp_pmdomain = (const char *[]) { "mx", NULL }, 729 .vcodec_num = 1, 730 .max_load = 7833600, 731 .hfi_version = HFI_VERSION_6XX, 732 .vmem_id = VIDC_RESOURCE_NONE, 733 .vmem_size = 0, 734 .vmem_addr = 0, 735 .dma_mask = 0xe0000000 - 1, 736 .fwname = "qcom/vpu-1.0/venus.mdt", 737 }; 738 739 static const struct of_device_id venus_dt_match[] = { 740 { .compatible = "qcom,msm8916-venus", .data = &msm8916_res, }, 741 { .compatible = "qcom,msm8996-venus", .data = &msm8996_res, }, 742 { .compatible = "qcom,sdm845-venus", .data = &sdm845_res, }, 743 { .compatible = "qcom,sdm845-venus-v2", .data = &sdm845_res_v2, }, 744 { .compatible = "qcom,sc7180-venus", .data = &sc7180_res, }, 745 { .compatible = "qcom,sm8250-venus", .data = &sm8250_res, }, 746 { } 747 }; 748 MODULE_DEVICE_TABLE(of, venus_dt_match); 749 750 static struct platform_driver qcom_venus_driver = { 751 .probe = venus_probe, 752 .remove = venus_remove, 753 .driver = { 754 .name = "qcom-venus", 755 .of_match_table = venus_dt_match, 756 .pm = &venus_pm_ops, 757 }, 758 .shutdown = venus_core_shutdown, 759 }; 760 module_platform_driver(qcom_venus_driver); 761 762 MODULE_ALIAS("platform:qcom-venus"); 763 MODULE_DESCRIPTION("Qualcomm Venus video encoder and decoder driver"); 764 MODULE_LICENSE("GPL v2"); 765