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