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