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