1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2019 Linaro Ltd. 4 * 5 * Author: Stanimir Varbanov <stanimir.varbanov@linaro.org> 6 */ 7 #include <linux/clk.h> 8 #include <linux/interconnect.h> 9 #include <linux/iopoll.h> 10 #include <linux/kernel.h> 11 #include <linux/pm_domain.h> 12 #include <linux/pm_opp.h> 13 #include <linux/pm_runtime.h> 14 #include <linux/types.h> 15 #include <media/v4l2-mem2mem.h> 16 17 #include "core.h" 18 #include "hfi_parser.h" 19 #include "hfi_venus_io.h" 20 #include "pm_helpers.h" 21 #include "hfi_platform.h" 22 23 static bool legacy_binding; 24 25 static int core_clks_get(struct venus_core *core) 26 { 27 const struct venus_resources *res = core->res; 28 struct device *dev = core->dev; 29 unsigned int i; 30 31 for (i = 0; i < res->clks_num; i++) { 32 core->clks[i] = devm_clk_get(dev, res->clks[i]); 33 if (IS_ERR(core->clks[i])) 34 return PTR_ERR(core->clks[i]); 35 } 36 37 return 0; 38 } 39 40 static int core_clks_enable(struct venus_core *core) 41 { 42 const struct venus_resources *res = core->res; 43 unsigned int i; 44 int ret; 45 46 for (i = 0; i < res->clks_num; i++) { 47 ret = clk_prepare_enable(core->clks[i]); 48 if (ret) 49 goto err; 50 } 51 52 return 0; 53 err: 54 while (i--) 55 clk_disable_unprepare(core->clks[i]); 56 57 return ret; 58 } 59 60 static void core_clks_disable(struct venus_core *core) 61 { 62 const struct venus_resources *res = core->res; 63 unsigned int i = res->clks_num; 64 65 while (i--) 66 clk_disable_unprepare(core->clks[i]); 67 } 68 69 static int core_clks_set_rate(struct venus_core *core, unsigned long freq) 70 { 71 int ret; 72 73 ret = dev_pm_opp_set_rate(core->dev, freq); 74 if (ret) 75 return ret; 76 77 ret = clk_set_rate(core->vcodec0_clks[0], freq); 78 if (ret) 79 return ret; 80 81 ret = clk_set_rate(core->vcodec1_clks[0], freq); 82 if (ret) 83 return ret; 84 85 return 0; 86 } 87 88 static int vcodec_clks_get(struct venus_core *core, struct device *dev, 89 struct clk **clks, const char * const *id) 90 { 91 const struct venus_resources *res = core->res; 92 unsigned int i; 93 94 for (i = 0; i < res->vcodec_clks_num; i++) { 95 if (!id[i]) 96 continue; 97 clks[i] = devm_clk_get(dev, id[i]); 98 if (IS_ERR(clks[i])) 99 return PTR_ERR(clks[i]); 100 } 101 102 return 0; 103 } 104 105 static int vcodec_clks_enable(struct venus_core *core, struct clk **clks) 106 { 107 const struct venus_resources *res = core->res; 108 unsigned int i; 109 int ret; 110 111 for (i = 0; i < res->vcodec_clks_num; i++) { 112 ret = clk_prepare_enable(clks[i]); 113 if (ret) 114 goto err; 115 } 116 117 return 0; 118 err: 119 while (i--) 120 clk_disable_unprepare(clks[i]); 121 122 return ret; 123 } 124 125 static void vcodec_clks_disable(struct venus_core *core, struct clk **clks) 126 { 127 const struct venus_resources *res = core->res; 128 unsigned int i = res->vcodec_clks_num; 129 130 while (i--) 131 clk_disable_unprepare(clks[i]); 132 } 133 134 static u32 load_per_instance(struct venus_inst *inst) 135 { 136 u32 mbs; 137 138 if (!inst || !(inst->state >= INST_INIT && inst->state < INST_STOP)) 139 return 0; 140 141 mbs = (ALIGN(inst->width, 16) / 16) * (ALIGN(inst->height, 16) / 16); 142 143 return mbs * inst->fps; 144 } 145 146 static u32 load_per_type(struct venus_core *core, u32 session_type) 147 { 148 struct venus_inst *inst = NULL; 149 u32 mbs_per_sec = 0; 150 151 mutex_lock(&core->lock); 152 list_for_each_entry(inst, &core->instances, list) { 153 if (inst->session_type != session_type) 154 continue; 155 156 mbs_per_sec += load_per_instance(inst); 157 } 158 mutex_unlock(&core->lock); 159 160 return mbs_per_sec; 161 } 162 163 static void mbs_to_bw(struct venus_inst *inst, u32 mbs, u32 *avg, u32 *peak) 164 { 165 const struct venus_resources *res = inst->core->res; 166 const struct bw_tbl *bw_tbl; 167 unsigned int num_rows, i; 168 169 *avg = 0; 170 *peak = 0; 171 172 if (mbs == 0) 173 return; 174 175 if (inst->session_type == VIDC_SESSION_TYPE_ENC) { 176 num_rows = res->bw_tbl_enc_size; 177 bw_tbl = res->bw_tbl_enc; 178 } else if (inst->session_type == VIDC_SESSION_TYPE_DEC) { 179 num_rows = res->bw_tbl_dec_size; 180 bw_tbl = res->bw_tbl_dec; 181 } else { 182 return; 183 } 184 185 if (!bw_tbl || num_rows == 0) 186 return; 187 188 for (i = 0; i < num_rows; i++) { 189 if (mbs > bw_tbl[i].mbs_per_sec) 190 break; 191 192 if (inst->dpb_fmt & HFI_COLOR_FORMAT_10_BIT_BASE) { 193 *avg = bw_tbl[i].avg_10bit; 194 *peak = bw_tbl[i].peak_10bit; 195 } else { 196 *avg = bw_tbl[i].avg; 197 *peak = bw_tbl[i].peak; 198 } 199 } 200 } 201 202 static int load_scale_bw(struct venus_core *core) 203 { 204 struct venus_inst *inst = NULL; 205 u32 mbs_per_sec, avg, peak, total_avg = 0, total_peak = 0; 206 207 mutex_lock(&core->lock); 208 list_for_each_entry(inst, &core->instances, list) { 209 mbs_per_sec = load_per_instance(inst); 210 mbs_to_bw(inst, mbs_per_sec, &avg, &peak); 211 total_avg += avg; 212 total_peak += peak; 213 } 214 mutex_unlock(&core->lock); 215 216 /* 217 * keep minimum bandwidth vote for "video-mem" path, 218 * so that clks can be disabled during vdec_session_release(). 219 * Actual bandwidth drop will be done during device supend 220 * so that device can power down without any warnings. 221 */ 222 223 if (!total_avg && !total_peak) 224 total_avg = kbps_to_icc(1000); 225 226 dev_dbg(core->dev, VDBGL "total: avg_bw: %u, peak_bw: %u\n", 227 total_avg, total_peak); 228 229 return icc_set_bw(core->video_path, total_avg, total_peak); 230 } 231 232 static int load_scale_v1(struct venus_inst *inst) 233 { 234 struct venus_core *core = inst->core; 235 const struct freq_tbl *table = core->res->freq_tbl; 236 unsigned int num_rows = core->res->freq_tbl_size; 237 unsigned long freq = table[0].freq; 238 struct device *dev = core->dev; 239 u32 mbs_per_sec; 240 unsigned int i; 241 int ret; 242 243 mbs_per_sec = load_per_type(core, VIDC_SESSION_TYPE_ENC) + 244 load_per_type(core, VIDC_SESSION_TYPE_DEC); 245 246 if (mbs_per_sec > core->res->max_load) 247 dev_warn(dev, "HW is overloaded, needed: %d max: %d\n", 248 mbs_per_sec, core->res->max_load); 249 250 if (!mbs_per_sec && num_rows > 1) { 251 freq = table[num_rows - 1].freq; 252 goto set_freq; 253 } 254 255 for (i = 0; i < num_rows; i++) { 256 if (mbs_per_sec > table[i].load) 257 break; 258 freq = table[i].freq; 259 } 260 261 set_freq: 262 263 ret = core_clks_set_rate(core, freq); 264 if (ret) { 265 dev_err(dev, "failed to set clock rate %lu (%d)\n", 266 freq, ret); 267 return ret; 268 } 269 270 ret = load_scale_bw(core); 271 if (ret) { 272 dev_err(dev, "failed to set bandwidth (%d)\n", 273 ret); 274 return ret; 275 } 276 277 return 0; 278 } 279 280 static int core_get_v1(struct device *dev) 281 { 282 struct venus_core *core = dev_get_drvdata(dev); 283 284 return core_clks_get(core); 285 } 286 287 static int core_power_v1(struct device *dev, int on) 288 { 289 struct venus_core *core = dev_get_drvdata(dev); 290 int ret = 0; 291 292 if (on == POWER_ON) 293 ret = core_clks_enable(core); 294 else 295 core_clks_disable(core); 296 297 return ret; 298 } 299 300 static const struct venus_pm_ops pm_ops_v1 = { 301 .core_get = core_get_v1, 302 .core_power = core_power_v1, 303 .load_scale = load_scale_v1, 304 }; 305 306 static void 307 vcodec_control_v3(struct venus_core *core, u32 session_type, bool enable) 308 { 309 void __iomem *ctrl; 310 311 if (session_type == VIDC_SESSION_TYPE_DEC) 312 ctrl = core->base + WRAPPER_VDEC_VCODEC_POWER_CONTROL; 313 else 314 ctrl = core->base + WRAPPER_VENC_VCODEC_POWER_CONTROL; 315 316 if (enable) 317 writel(0, ctrl); 318 else 319 writel(1, ctrl); 320 } 321 322 static int vdec_get_v3(struct device *dev) 323 { 324 struct venus_core *core = dev_get_drvdata(dev); 325 326 return vcodec_clks_get(core, dev, core->vcodec0_clks, 327 core->res->vcodec0_clks); 328 } 329 330 static int vdec_power_v3(struct device *dev, int on) 331 { 332 struct venus_core *core = dev_get_drvdata(dev); 333 int ret = 0; 334 335 vcodec_control_v3(core, VIDC_SESSION_TYPE_DEC, true); 336 337 if (on == POWER_ON) 338 ret = vcodec_clks_enable(core, core->vcodec0_clks); 339 else 340 vcodec_clks_disable(core, core->vcodec0_clks); 341 342 vcodec_control_v3(core, VIDC_SESSION_TYPE_DEC, false); 343 344 return ret; 345 } 346 347 static int venc_get_v3(struct device *dev) 348 { 349 struct venus_core *core = dev_get_drvdata(dev); 350 351 return vcodec_clks_get(core, dev, core->vcodec1_clks, 352 core->res->vcodec1_clks); 353 } 354 355 static int venc_power_v3(struct device *dev, int on) 356 { 357 struct venus_core *core = dev_get_drvdata(dev); 358 int ret = 0; 359 360 vcodec_control_v3(core, VIDC_SESSION_TYPE_ENC, true); 361 362 if (on == POWER_ON) 363 ret = vcodec_clks_enable(core, core->vcodec1_clks); 364 else 365 vcodec_clks_disable(core, core->vcodec1_clks); 366 367 vcodec_control_v3(core, VIDC_SESSION_TYPE_ENC, false); 368 369 return ret; 370 } 371 372 static const struct venus_pm_ops pm_ops_v3 = { 373 .core_get = core_get_v1, 374 .core_power = core_power_v1, 375 .vdec_get = vdec_get_v3, 376 .vdec_power = vdec_power_v3, 377 .venc_get = venc_get_v3, 378 .venc_power = venc_power_v3, 379 .load_scale = load_scale_v1, 380 }; 381 382 static int vcodec_control_v4(struct venus_core *core, u32 coreid, bool enable) 383 { 384 void __iomem *ctrl, *stat; 385 u32 val; 386 int ret; 387 388 if (coreid == VIDC_CORE_ID_1) { 389 ctrl = core->base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL; 390 stat = core->base + WRAPPER_VCODEC0_MMCC_POWER_STATUS; 391 } else { 392 ctrl = core->base + WRAPPER_VCODEC1_MMCC_POWER_CONTROL; 393 stat = core->base + WRAPPER_VCODEC1_MMCC_POWER_STATUS; 394 } 395 396 if (enable) { 397 writel(0, ctrl); 398 399 ret = readl_poll_timeout(stat, val, val & BIT(1), 1, 100); 400 if (ret) 401 return ret; 402 } else { 403 writel(1, ctrl); 404 405 ret = readl_poll_timeout(stat, val, !(val & BIT(1)), 1, 100); 406 if (ret) 407 return ret; 408 } 409 410 return 0; 411 } 412 413 static int poweroff_coreid(struct venus_core *core, unsigned int coreid_mask) 414 { 415 int ret; 416 417 if (coreid_mask & VIDC_CORE_ID_1) { 418 ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true); 419 if (ret) 420 return ret; 421 422 vcodec_clks_disable(core, core->vcodec0_clks); 423 424 ret = vcodec_control_v4(core, VIDC_CORE_ID_1, false); 425 if (ret) 426 return ret; 427 428 ret = pm_runtime_put_sync(core->pmdomains[1]); 429 if (ret < 0) 430 return ret; 431 } 432 433 if (coreid_mask & VIDC_CORE_ID_2) { 434 ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true); 435 if (ret) 436 return ret; 437 438 vcodec_clks_disable(core, core->vcodec1_clks); 439 440 ret = vcodec_control_v4(core, VIDC_CORE_ID_2, false); 441 if (ret) 442 return ret; 443 444 ret = pm_runtime_put_sync(core->pmdomains[2]); 445 if (ret < 0) 446 return ret; 447 } 448 449 return 0; 450 } 451 452 static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask) 453 { 454 int ret; 455 456 if (coreid_mask & VIDC_CORE_ID_1) { 457 ret = pm_runtime_get_sync(core->pmdomains[1]); 458 if (ret < 0) 459 return ret; 460 461 ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true); 462 if (ret) 463 return ret; 464 465 ret = vcodec_clks_enable(core, core->vcodec0_clks); 466 if (ret) 467 return ret; 468 469 ret = vcodec_control_v4(core, VIDC_CORE_ID_1, false); 470 if (ret < 0) 471 return ret; 472 } 473 474 if (coreid_mask & VIDC_CORE_ID_2) { 475 ret = pm_runtime_get_sync(core->pmdomains[2]); 476 if (ret < 0) 477 return ret; 478 479 ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true); 480 if (ret) 481 return ret; 482 483 ret = vcodec_clks_enable(core, core->vcodec1_clks); 484 if (ret) 485 return ret; 486 487 ret = vcodec_control_v4(core, VIDC_CORE_ID_2, false); 488 if (ret < 0) 489 return ret; 490 } 491 492 return 0; 493 } 494 495 static void 496 min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load) 497 { 498 u32 mbs_per_sec, load, core1_load = 0, core2_load = 0; 499 u32 cores_max = core_num_max(inst); 500 struct venus_core *core = inst->core; 501 struct venus_inst *inst_pos; 502 unsigned long vpp_freq; 503 u32 coreid; 504 505 mutex_lock(&core->lock); 506 507 list_for_each_entry(inst_pos, &core->instances, list) { 508 if (inst_pos == inst) 509 continue; 510 511 if (inst_pos->state != INST_START) 512 continue; 513 514 vpp_freq = inst_pos->clk_data.vpp_freq; 515 coreid = inst_pos->clk_data.core_id; 516 517 mbs_per_sec = load_per_instance(inst_pos); 518 load = mbs_per_sec * vpp_freq; 519 520 if ((coreid & VIDC_CORE_ID_3) == VIDC_CORE_ID_3) { 521 core1_load += load / 2; 522 core2_load += load / 2; 523 } else if (coreid & VIDC_CORE_ID_1) { 524 core1_load += load; 525 } else if (coreid & VIDC_CORE_ID_2) { 526 core2_load += load; 527 } 528 } 529 530 *min_coreid = core1_load <= core2_load ? 531 VIDC_CORE_ID_1 : VIDC_CORE_ID_2; 532 *min_load = min(core1_load, core2_load); 533 534 if (cores_max < VIDC_CORE_ID_2 || core->res->vcodec_num < 2) { 535 *min_coreid = VIDC_CORE_ID_1; 536 *min_load = core1_load; 537 } 538 539 mutex_unlock(&core->lock); 540 } 541 542 static int decide_core(struct venus_inst *inst) 543 { 544 const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE; 545 struct venus_core *core = inst->core; 546 u32 min_coreid, min_load, inst_load; 547 struct hfi_videocores_usage_type cu; 548 unsigned long max_freq; 549 550 if (legacy_binding) { 551 if (inst->session_type == VIDC_SESSION_TYPE_DEC) 552 cu.video_core_enable_mask = VIDC_CORE_ID_1; 553 else 554 cu.video_core_enable_mask = VIDC_CORE_ID_2; 555 556 goto done; 557 } 558 559 if (inst->clk_data.core_id != VIDC_CORE_ID_DEFAULT) 560 return 0; 561 562 inst_load = load_per_instance(inst); 563 inst_load *= inst->clk_data.vpp_freq; 564 max_freq = core->res->freq_tbl[0].freq; 565 566 min_loaded_core(inst, &min_coreid, &min_load); 567 568 if ((inst_load + min_load) > max_freq) { 569 dev_warn(core->dev, "HW is overloaded, needed: %u max: %lu\n", 570 inst_load, max_freq); 571 return -EINVAL; 572 } 573 574 inst->clk_data.core_id = min_coreid; 575 cu.video_core_enable_mask = min_coreid; 576 577 done: 578 return hfi_session_set_property(inst, ptype, &cu); 579 } 580 581 static int acquire_core(struct venus_inst *inst) 582 { 583 struct venus_core *core = inst->core; 584 unsigned int coreid_mask = 0; 585 586 if (inst->core_acquired) 587 return 0; 588 589 inst->core_acquired = true; 590 591 if (inst->clk_data.core_id & VIDC_CORE_ID_1) { 592 if (core->core0_usage_count++) 593 return 0; 594 595 coreid_mask = VIDC_CORE_ID_1; 596 } 597 598 if (inst->clk_data.core_id & VIDC_CORE_ID_2) { 599 if (core->core1_usage_count++) 600 return 0; 601 602 coreid_mask |= VIDC_CORE_ID_2; 603 } 604 605 return poweron_coreid(core, coreid_mask); 606 } 607 608 static int release_core(struct venus_inst *inst) 609 { 610 struct venus_core *core = inst->core; 611 unsigned int coreid_mask = 0; 612 int ret; 613 614 if (!inst->core_acquired) 615 return 0; 616 617 if (inst->clk_data.core_id & VIDC_CORE_ID_1) { 618 if (--core->core0_usage_count) 619 goto done; 620 621 coreid_mask = VIDC_CORE_ID_1; 622 } 623 624 if (inst->clk_data.core_id & VIDC_CORE_ID_2) { 625 if (--core->core1_usage_count) 626 goto done; 627 628 coreid_mask |= VIDC_CORE_ID_2; 629 } 630 631 ret = poweroff_coreid(core, coreid_mask); 632 if (ret) 633 return ret; 634 635 done: 636 inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT; 637 inst->core_acquired = false; 638 return 0; 639 } 640 641 static int coreid_power_v4(struct venus_inst *inst, int on) 642 { 643 struct venus_core *core = inst->core; 644 int ret; 645 646 if (legacy_binding) 647 return 0; 648 649 if (on == POWER_ON) { 650 ret = decide_core(inst); 651 if (ret) 652 return ret; 653 654 mutex_lock(&core->lock); 655 ret = acquire_core(inst); 656 mutex_unlock(&core->lock); 657 } else { 658 mutex_lock(&core->lock); 659 ret = release_core(inst); 660 mutex_unlock(&core->lock); 661 } 662 663 return ret; 664 } 665 666 static int vdec_get_v4(struct device *dev) 667 { 668 struct venus_core *core = dev_get_drvdata(dev); 669 670 if (!legacy_binding) 671 return 0; 672 673 return vcodec_clks_get(core, dev, core->vcodec0_clks, 674 core->res->vcodec0_clks); 675 } 676 677 static void vdec_put_v4(struct device *dev) 678 { 679 struct venus_core *core = dev_get_drvdata(dev); 680 unsigned int i; 681 682 if (!legacy_binding) 683 return; 684 685 for (i = 0; i < core->res->vcodec_clks_num; i++) 686 core->vcodec0_clks[i] = NULL; 687 } 688 689 static int vdec_power_v4(struct device *dev, int on) 690 { 691 struct venus_core *core = dev_get_drvdata(dev); 692 int ret; 693 694 if (!legacy_binding) 695 return 0; 696 697 ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true); 698 if (ret) 699 return ret; 700 701 if (on == POWER_ON) 702 ret = vcodec_clks_enable(core, core->vcodec0_clks); 703 else 704 vcodec_clks_disable(core, core->vcodec0_clks); 705 706 vcodec_control_v4(core, VIDC_CORE_ID_1, false); 707 708 return ret; 709 } 710 711 static int venc_get_v4(struct device *dev) 712 { 713 struct venus_core *core = dev_get_drvdata(dev); 714 715 if (!legacy_binding) 716 return 0; 717 718 return vcodec_clks_get(core, dev, core->vcodec1_clks, 719 core->res->vcodec1_clks); 720 } 721 722 static void venc_put_v4(struct device *dev) 723 { 724 struct venus_core *core = dev_get_drvdata(dev); 725 unsigned int i; 726 727 if (!legacy_binding) 728 return; 729 730 for (i = 0; i < core->res->vcodec_clks_num; i++) 731 core->vcodec1_clks[i] = NULL; 732 } 733 734 static int venc_power_v4(struct device *dev, int on) 735 { 736 struct venus_core *core = dev_get_drvdata(dev); 737 int ret; 738 739 if (!legacy_binding) 740 return 0; 741 742 ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true); 743 if (ret) 744 return ret; 745 746 if (on == POWER_ON) 747 ret = vcodec_clks_enable(core, core->vcodec1_clks); 748 else 749 vcodec_clks_disable(core, core->vcodec1_clks); 750 751 vcodec_control_v4(core, VIDC_CORE_ID_2, false); 752 753 return ret; 754 } 755 756 static int vcodec_domains_get(struct device *dev) 757 { 758 int ret; 759 struct opp_table *opp_table; 760 struct device **opp_virt_dev; 761 struct venus_core *core = dev_get_drvdata(dev); 762 const struct venus_resources *res = core->res; 763 struct device *pd; 764 unsigned int i; 765 766 if (!res->vcodec_pmdomains_num) 767 goto skip_pmdomains; 768 769 for (i = 0; i < res->vcodec_pmdomains_num; i++) { 770 pd = dev_pm_domain_attach_by_name(dev, 771 res->vcodec_pmdomains[i]); 772 if (IS_ERR(pd)) 773 return PTR_ERR(pd); 774 core->pmdomains[i] = pd; 775 } 776 777 core->pd_dl_venus = device_link_add(dev, core->pmdomains[0], 778 DL_FLAG_PM_RUNTIME | 779 DL_FLAG_STATELESS | 780 DL_FLAG_RPM_ACTIVE); 781 if (!core->pd_dl_venus) 782 return -ENODEV; 783 784 skip_pmdomains: 785 if (!core->has_opp_table) 786 return 0; 787 788 /* Attach the power domain for setting performance state */ 789 opp_table = dev_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev); 790 if (IS_ERR(opp_table)) { 791 ret = PTR_ERR(opp_table); 792 goto opp_attach_err; 793 } 794 795 core->opp_pmdomain = *opp_virt_dev; 796 core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain, 797 DL_FLAG_RPM_ACTIVE | 798 DL_FLAG_PM_RUNTIME | 799 DL_FLAG_STATELESS); 800 if (!core->opp_dl_venus) { 801 ret = -ENODEV; 802 goto opp_dl_add_err; 803 } 804 805 return 0; 806 807 opp_dl_add_err: 808 dev_pm_opp_detach_genpd(core->opp_table); 809 opp_attach_err: 810 if (core->pd_dl_venus) { 811 device_link_del(core->pd_dl_venus); 812 for (i = 0; i < res->vcodec_pmdomains_num; i++) { 813 if (IS_ERR_OR_NULL(core->pmdomains[i])) 814 continue; 815 dev_pm_domain_detach(core->pmdomains[i], true); 816 } 817 } 818 return ret; 819 } 820 821 static void vcodec_domains_put(struct device *dev) 822 { 823 struct venus_core *core = dev_get_drvdata(dev); 824 const struct venus_resources *res = core->res; 825 unsigned int i; 826 827 if (!res->vcodec_pmdomains_num) 828 goto skip_pmdomains; 829 830 if (core->pd_dl_venus) 831 device_link_del(core->pd_dl_venus); 832 833 for (i = 0; i < res->vcodec_pmdomains_num; i++) { 834 if (IS_ERR_OR_NULL(core->pmdomains[i])) 835 continue; 836 dev_pm_domain_detach(core->pmdomains[i], true); 837 } 838 839 skip_pmdomains: 840 if (!core->has_opp_table) 841 return; 842 843 if (core->opp_dl_venus) 844 device_link_del(core->opp_dl_venus); 845 846 dev_pm_opp_detach_genpd(core->opp_table); 847 } 848 849 static int core_get_v4(struct device *dev) 850 { 851 struct venus_core *core = dev_get_drvdata(dev); 852 const struct venus_resources *res = core->res; 853 int ret; 854 855 ret = core_clks_get(core); 856 if (ret) 857 return ret; 858 859 if (!res->vcodec_pmdomains_num) 860 legacy_binding = true; 861 862 dev_info(dev, "%s legacy binding\n", legacy_binding ? "" : "non"); 863 864 ret = vcodec_clks_get(core, dev, core->vcodec0_clks, res->vcodec0_clks); 865 if (ret) 866 return ret; 867 868 ret = vcodec_clks_get(core, dev, core->vcodec1_clks, res->vcodec1_clks); 869 if (ret) 870 return ret; 871 872 if (legacy_binding) 873 return 0; 874 875 core->opp_table = dev_pm_opp_set_clkname(dev, "core"); 876 if (IS_ERR(core->opp_table)) 877 return PTR_ERR(core->opp_table); 878 879 if (core->res->opp_pmdomain) { 880 ret = dev_pm_opp_of_add_table(dev); 881 if (!ret) { 882 core->has_opp_table = true; 883 } else if (ret != -ENODEV) { 884 dev_err(dev, "invalid OPP table in device tree\n"); 885 dev_pm_opp_put_clkname(core->opp_table); 886 return ret; 887 } 888 } 889 890 ret = vcodec_domains_get(dev); 891 if (ret) { 892 if (core->has_opp_table) 893 dev_pm_opp_of_remove_table(dev); 894 dev_pm_opp_put_clkname(core->opp_table); 895 return ret; 896 } 897 898 return 0; 899 } 900 901 static void core_put_v4(struct device *dev) 902 { 903 struct venus_core *core = dev_get_drvdata(dev); 904 905 if (legacy_binding) 906 return; 907 908 vcodec_domains_put(dev); 909 910 if (core->has_opp_table) 911 dev_pm_opp_of_remove_table(dev); 912 dev_pm_opp_put_clkname(core->opp_table); 913 914 } 915 916 static int core_power_v4(struct device *dev, int on) 917 { 918 struct venus_core *core = dev_get_drvdata(dev); 919 int ret = 0; 920 921 if (on == POWER_ON) { 922 ret = core_clks_enable(core); 923 } else { 924 /* Drop the performance state vote */ 925 if (core->opp_pmdomain) 926 dev_pm_opp_set_rate(dev, 0); 927 928 core_clks_disable(core); 929 } 930 931 return ret; 932 } 933 934 static unsigned long calculate_inst_freq(struct venus_inst *inst, 935 unsigned long filled_len) 936 { 937 unsigned long vpp_freq = 0, vsp_freq = 0; 938 u32 fps = (u32)inst->fps; 939 u32 mbs_per_sec; 940 941 mbs_per_sec = load_per_instance(inst); 942 943 if (inst->state != INST_START) 944 return 0; 945 946 vpp_freq = mbs_per_sec * inst->clk_data.vpp_freq; 947 /* 21 / 20 is overhead factor */ 948 vpp_freq += vpp_freq / 20; 949 vsp_freq = mbs_per_sec * inst->clk_data.vsp_freq; 950 951 /* 10 / 7 is overhead factor */ 952 if (inst->session_type == VIDC_SESSION_TYPE_ENC) 953 vsp_freq += (inst->controls.enc.bitrate * 10) / 7; 954 else 955 vsp_freq += ((fps * filled_len * 8) * 10) / 7; 956 957 return max(vpp_freq, vsp_freq); 958 } 959 960 static int load_scale_v4(struct venus_inst *inst) 961 { 962 struct venus_core *core = inst->core; 963 const struct freq_tbl *table = core->res->freq_tbl; 964 unsigned int num_rows = core->res->freq_tbl_size; 965 struct device *dev = core->dev; 966 unsigned long freq = 0, freq_core1 = 0, freq_core2 = 0; 967 unsigned long filled_len = 0; 968 int i, ret; 969 970 for (i = 0; i < inst->num_input_bufs; i++) 971 filled_len = max(filled_len, inst->payloads[i]); 972 973 if (inst->session_type == VIDC_SESSION_TYPE_DEC && !filled_len) 974 return 0; 975 976 freq = calculate_inst_freq(inst, filled_len); 977 inst->clk_data.freq = freq; 978 979 mutex_lock(&core->lock); 980 list_for_each_entry(inst, &core->instances, list) { 981 if (inst->clk_data.core_id == VIDC_CORE_ID_1) { 982 freq_core1 += inst->clk_data.freq; 983 } else if (inst->clk_data.core_id == VIDC_CORE_ID_2) { 984 freq_core2 += inst->clk_data.freq; 985 } else if (inst->clk_data.core_id == VIDC_CORE_ID_3) { 986 freq_core1 += inst->clk_data.freq; 987 freq_core2 += inst->clk_data.freq; 988 } 989 } 990 mutex_unlock(&core->lock); 991 992 freq = max(freq_core1, freq_core2); 993 994 if (freq >= table[0].freq) { 995 freq = table[0].freq; 996 dev_warn(dev, "HW is overloaded, needed: %lu max: %lu\n", 997 freq, table[0].freq); 998 goto set_freq; 999 } 1000 1001 for (i = num_rows - 1 ; i >= 0; i--) { 1002 if (freq <= table[i].freq) { 1003 freq = table[i].freq; 1004 break; 1005 } 1006 } 1007 1008 set_freq: 1009 1010 ret = core_clks_set_rate(core, freq); 1011 if (ret) { 1012 dev_err(dev, "failed to set clock rate %lu (%d)\n", 1013 freq, ret); 1014 return ret; 1015 } 1016 1017 ret = load_scale_bw(core); 1018 if (ret) { 1019 dev_err(dev, "failed to set bandwidth (%d)\n", 1020 ret); 1021 return ret; 1022 } 1023 1024 return 0; 1025 } 1026 1027 static const struct venus_pm_ops pm_ops_v4 = { 1028 .core_get = core_get_v4, 1029 .core_put = core_put_v4, 1030 .core_power = core_power_v4, 1031 .vdec_get = vdec_get_v4, 1032 .vdec_put = vdec_put_v4, 1033 .vdec_power = vdec_power_v4, 1034 .venc_get = venc_get_v4, 1035 .venc_put = venc_put_v4, 1036 .venc_power = venc_power_v4, 1037 .coreid_power = coreid_power_v4, 1038 .load_scale = load_scale_v4, 1039 }; 1040 1041 const struct venus_pm_ops *venus_pm_get(enum hfi_version version) 1042 { 1043 switch (version) { 1044 case HFI_VERSION_1XX: 1045 default: 1046 return &pm_ops_v1; 1047 case HFI_VERSION_3XX: 1048 return &pm_ops_v3; 1049 case HFI_VERSION_4XX: 1050 return &pm_ops_v4; 1051 } 1052 1053 return NULL; 1054 } 1055