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