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