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