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