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