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
core_clks_get(struct venus_core * core)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
core_clks_enable(struct venus_core * core)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
core_clks_disable(struct venus_core * core)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
core_clks_set_rate(struct venus_core * core,unsigned long freq)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
vcodec_clks_get(struct venus_core * core,struct device * dev,struct clk ** clks,const char * const * id)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
vcodec_clks_enable(struct venus_core * core,struct clk ** clks)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
vcodec_clks_disable(struct venus_core * core,struct clk ** clks)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
load_per_instance(struct venus_inst * inst)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
load_per_type(struct venus_core * core,u32 session_type)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
mbs_to_bw(struct venus_inst * inst,u32 mbs,u32 * avg,u32 * peak)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
load_scale_bw(struct venus_core * core)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
load_scale_v1(struct venus_inst * inst)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
core_get_v1(struct venus_core * core)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
core_put_v1(struct venus_core * core)308 static void core_put_v1(struct venus_core *core)
309 {
310 }
311
core_power_v1(struct venus_core * core,int on)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
vcodec_control_v3(struct venus_core * core,u32 session_type,bool enable)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
vdec_get_v3(struct device * dev)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
vdec_power_v3(struct device * dev,int on)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
venc_get_v3(struct device * dev)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
venc_power_v3(struct device * dev,int on)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
vcodec_control_v4(struct venus_core * core,u32 coreid,bool enable)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
poweroff_coreid(struct venus_core * core,unsigned int coreid_mask)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
poweron_coreid(struct venus_core * core,unsigned int coreid_mask)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
power_save_mode_enable(struct venus_inst * inst,bool enable)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
move_core_to_power_save_mode(struct venus_core * core,u32 core_id)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
min_loaded_core(struct venus_inst * inst,u32 * min_coreid,u32 * min_load,bool low_power)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
decide_core(struct venus_inst * inst)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
acquire_core(struct venus_inst * inst)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
release_core(struct venus_inst * inst)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
coreid_power_v4(struct venus_inst * inst,int on)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
vdec_get_v4(struct device * dev)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
vdec_put_v4(struct device * dev)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
vdec_power_v4(struct device * dev,int on)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
venc_get_v4(struct device * dev)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
venc_put_v4(struct device * dev)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
venc_power_v4(struct device * dev,int on)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
vcodec_domains_get(struct venus_core * core)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
core_resets_reset(struct venus_core * core)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
core_resets_get(struct venus_core * core)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
core_get_v4(struct venus_core * core)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
core_put_v4(struct venus_core * core)1012 static void core_put_v4(struct venus_core *core)
1013 {
1014 }
1015
core_power_v4(struct venus_core * core,int on)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
calculate_inst_freq(struct venus_inst * inst,unsigned long filled_len)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
load_scale_v4(struct venus_inst * inst)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
venus_pm_get(enum hfi_version version)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