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 return dev_pm_genpd_set_hwmode(core->pmdomains->pd_devs[coreid], !enable);
417 else if (coreid == VIDC_CORE_ID_1) {
418 ctrl = core->wrapper_base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL;
419 stat = core->wrapper_base + WRAPPER_VCODEC0_MMCC_POWER_STATUS;
420 } else {
421 ctrl = core->wrapper_base + WRAPPER_VCODEC1_MMCC_POWER_CONTROL;
422 stat = core->wrapper_base + WRAPPER_VCODEC1_MMCC_POWER_STATUS;
423 }
424
425 if (enable) {
426 writel(0, ctrl);
427
428 ret = readl_poll_timeout(stat, val, val & BIT(1), 1, 100);
429 if (ret)
430 return ret;
431 } else {
432 writel(1, ctrl);
433
434 ret = readl_poll_timeout(stat, val, !(val & BIT(1)), 1, 100);
435 if (ret)
436 return ret;
437 }
438
439 return 0;
440 }
441
poweroff_coreid(struct venus_core * core,unsigned int coreid_mask)442 static int poweroff_coreid(struct venus_core *core, unsigned int coreid_mask)
443 {
444 int ret;
445
446 if (coreid_mask & VIDC_CORE_ID_1) {
447 ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true);
448 if (ret)
449 return ret;
450
451 vcodec_clks_disable(core, core->vcodec0_clks);
452
453 if (!IS_V6(core)) {
454 ret = vcodec_control_v4(core, VIDC_CORE_ID_1, false);
455 if (ret)
456 return ret;
457 }
458
459 ret = pm_runtime_put_sync(core->pmdomains->pd_devs[1]);
460 if (ret < 0)
461 return ret;
462 }
463
464 if (coreid_mask & VIDC_CORE_ID_2) {
465 ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true);
466 if (ret)
467 return ret;
468
469 vcodec_clks_disable(core, core->vcodec1_clks);
470
471 if (!IS_V6(core)) {
472 ret = vcodec_control_v4(core, VIDC_CORE_ID_2, false);
473 if (ret)
474 return ret;
475 }
476
477 ret = pm_runtime_put_sync(core->pmdomains->pd_devs[2]);
478 if (ret < 0)
479 return ret;
480 }
481
482 return 0;
483 }
484
poweron_coreid(struct venus_core * core,unsigned int coreid_mask)485 static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask)
486 {
487 int ret;
488
489 if (coreid_mask & VIDC_CORE_ID_1) {
490 ret = pm_runtime_get_sync(core->pmdomains->pd_devs[1]);
491 if (ret < 0)
492 return ret;
493
494 if (!IS_V6(core)) {
495 ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true);
496 if (ret)
497 return ret;
498 }
499
500 ret = vcodec_clks_enable(core, core->vcodec0_clks);
501 if (ret)
502 return ret;
503
504 ret = vcodec_control_v4(core, VIDC_CORE_ID_1, false);
505 if (ret < 0)
506 return ret;
507 }
508
509 if (coreid_mask & VIDC_CORE_ID_2) {
510 ret = pm_runtime_get_sync(core->pmdomains->pd_devs[2]);
511 if (ret < 0)
512 return ret;
513
514 if (!IS_V6(core)) {
515 ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true);
516 if (ret)
517 return ret;
518 }
519
520 ret = vcodec_clks_enable(core, core->vcodec1_clks);
521 if (ret)
522 return ret;
523
524 ret = vcodec_control_v4(core, VIDC_CORE_ID_2, false);
525 if (ret < 0)
526 return ret;
527 }
528
529 return 0;
530 }
531
power_save_mode_enable(struct venus_inst * inst,bool enable)532 static inline int power_save_mode_enable(struct venus_inst *inst,
533 bool enable)
534 {
535 struct venc_controls *enc_ctr = &inst->controls.enc;
536 const u32 ptype = HFI_PROPERTY_CONFIG_VENC_PERF_MODE;
537 u32 venc_mode;
538 int ret = 0;
539
540 if (inst->session_type != VIDC_SESSION_TYPE_ENC)
541 return 0;
542
543 if (enc_ctr->bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
544 enable = false;
545
546 venc_mode = enable ? HFI_VENC_PERFMODE_POWER_SAVE :
547 HFI_VENC_PERFMODE_MAX_QUALITY;
548
549 ret = hfi_session_set_property(inst, ptype, &venc_mode);
550 if (ret)
551 return ret;
552
553 inst->flags = enable ? inst->flags | VENUS_LOW_POWER :
554 inst->flags & ~VENUS_LOW_POWER;
555
556 return ret;
557 }
558
move_core_to_power_save_mode(struct venus_core * core,u32 core_id)559 static int move_core_to_power_save_mode(struct venus_core *core,
560 u32 core_id)
561 {
562 struct venus_inst *inst = NULL;
563
564 mutex_lock(&core->lock);
565 list_for_each_entry(inst, &core->instances, list) {
566 if (inst->clk_data.core_id == core_id &&
567 inst->session_type == VIDC_SESSION_TYPE_ENC)
568 power_save_mode_enable(inst, true);
569 }
570 mutex_unlock(&core->lock);
571 return 0;
572 }
573
574 static void
min_loaded_core(struct venus_inst * inst,u32 * min_coreid,u32 * min_load,bool low_power)575 min_loaded_core(struct venus_inst *inst, u32 *min_coreid, u32 *min_load, bool low_power)
576 {
577 u32 mbs_per_sec, load, core1_load = 0, core2_load = 0;
578 u32 cores_max = core_num_max(inst);
579 struct venus_core *core = inst->core;
580 struct venus_inst *inst_pos;
581 unsigned long vpp_freq;
582 u32 coreid;
583
584 mutex_lock(&core->lock);
585
586 list_for_each_entry(inst_pos, &core->instances, list) {
587 if (inst_pos == inst)
588 continue;
589
590 if (inst_pos->state != INST_START)
591 continue;
592
593 if (inst->session_type == VIDC_SESSION_TYPE_DEC)
594 vpp_freq = inst_pos->clk_data.vpp_freq;
595 else if (inst->session_type == VIDC_SESSION_TYPE_ENC)
596 vpp_freq = low_power ? inst_pos->clk_data.low_power_freq :
597 inst_pos->clk_data.vpp_freq;
598 else
599 continue;
600
601 coreid = inst_pos->clk_data.core_id;
602
603 mbs_per_sec = load_per_instance(inst_pos);
604 load = mbs_per_sec * vpp_freq;
605
606 if ((coreid & VIDC_CORE_ID_3) == VIDC_CORE_ID_3) {
607 core1_load += load / 2;
608 core2_load += load / 2;
609 } else if (coreid & VIDC_CORE_ID_1) {
610 core1_load += load;
611 } else if (coreid & VIDC_CORE_ID_2) {
612 core2_load += load;
613 }
614 }
615
616 *min_coreid = core1_load <= core2_load ?
617 VIDC_CORE_ID_1 : VIDC_CORE_ID_2;
618 *min_load = min(core1_load, core2_load);
619
620 if (cores_max < VIDC_CORE_ID_2 || core->res->vcodec_num < 2) {
621 *min_coreid = VIDC_CORE_ID_1;
622 *min_load = core1_load;
623 }
624
625 mutex_unlock(&core->lock);
626 }
627
decide_core(struct venus_inst * inst)628 static int decide_core(struct venus_inst *inst)
629 {
630 const u32 ptype = HFI_PROPERTY_CONFIG_VIDEOCORES_USAGE;
631 struct venus_core *core = inst->core;
632 u32 min_coreid, min_load, cur_inst_load;
633 u32 min_lp_coreid, min_lp_load, cur_inst_lp_load;
634 struct hfi_videocores_usage_type cu;
635 unsigned long max_freq;
636 int ret = 0;
637
638 if (legacy_binding) {
639 if (inst->session_type == VIDC_SESSION_TYPE_DEC)
640 cu.video_core_enable_mask = VIDC_CORE_ID_1;
641 else
642 cu.video_core_enable_mask = VIDC_CORE_ID_2;
643
644 goto done;
645 }
646
647 if (inst->clk_data.core_id != VIDC_CORE_ID_DEFAULT)
648 return 0;
649
650 cur_inst_load = load_per_instance(inst);
651 cur_inst_load *= inst->clk_data.vpp_freq;
652 /*TODO : divide this inst->load by work_route */
653
654 cur_inst_lp_load = load_per_instance(inst);
655 cur_inst_lp_load *= inst->clk_data.low_power_freq;
656 /*TODO : divide this inst->load by work_route */
657
658 max_freq = core->res->freq_tbl[0].freq;
659
660 min_loaded_core(inst, &min_coreid, &min_load, false);
661 min_loaded_core(inst, &min_lp_coreid, &min_lp_load, true);
662
663 if (cur_inst_load + min_load <= max_freq) {
664 inst->clk_data.core_id = min_coreid;
665 cu.video_core_enable_mask = min_coreid;
666 } else if (cur_inst_lp_load + min_load <= max_freq) {
667 /* Move current instance to LP and return */
668 inst->clk_data.core_id = min_coreid;
669 cu.video_core_enable_mask = min_coreid;
670 power_save_mode_enable(inst, true);
671 } else if (cur_inst_lp_load + min_lp_load <= max_freq) {
672 /* Move all instances to LP mode and return */
673 inst->clk_data.core_id = min_lp_coreid;
674 cu.video_core_enable_mask = min_lp_coreid;
675 move_core_to_power_save_mode(core, min_lp_coreid);
676 } else {
677 dev_warn(core->dev, "HW can't support this load");
678 return -EINVAL;
679 }
680
681 done:
682 ret = hfi_session_set_property(inst, ptype, &cu);
683 if (ret)
684 return ret;
685
686 return ret;
687 }
688
acquire_core(struct venus_inst * inst)689 static int acquire_core(struct venus_inst *inst)
690 {
691 struct venus_core *core = inst->core;
692 unsigned int coreid_mask = 0;
693
694 if (inst->core_acquired)
695 return 0;
696
697 inst->core_acquired = true;
698
699 if (inst->clk_data.core_id & VIDC_CORE_ID_1) {
700 if (core->core0_usage_count++)
701 return 0;
702
703 coreid_mask = VIDC_CORE_ID_1;
704 }
705
706 if (inst->clk_data.core_id & VIDC_CORE_ID_2) {
707 if (core->core1_usage_count++)
708 return 0;
709
710 coreid_mask |= VIDC_CORE_ID_2;
711 }
712
713 return poweron_coreid(core, coreid_mask);
714 }
715
release_core(struct venus_inst * inst)716 static int release_core(struct venus_inst *inst)
717 {
718 struct venus_core *core = inst->core;
719 unsigned int coreid_mask = 0;
720 int ret;
721
722 if (!inst->core_acquired)
723 return 0;
724
725 if (inst->clk_data.core_id & VIDC_CORE_ID_1) {
726 if (--core->core0_usage_count)
727 goto done;
728
729 coreid_mask = VIDC_CORE_ID_1;
730 }
731
732 if (inst->clk_data.core_id & VIDC_CORE_ID_2) {
733 if (--core->core1_usage_count)
734 goto done;
735
736 coreid_mask |= VIDC_CORE_ID_2;
737 }
738
739 ret = poweroff_coreid(core, coreid_mask);
740 if (ret)
741 return ret;
742
743 done:
744 inst->clk_data.core_id = VIDC_CORE_ID_DEFAULT;
745 inst->core_acquired = false;
746 return 0;
747 }
748
coreid_power_v4(struct venus_inst * inst,int on)749 static int coreid_power_v4(struct venus_inst *inst, int on)
750 {
751 struct venus_core *core = inst->core;
752 int ret;
753
754 if (legacy_binding)
755 return 0;
756
757 if (on == POWER_ON) {
758 ret = decide_core(inst);
759 if (ret)
760 return ret;
761
762 mutex_lock(&core->lock);
763 ret = acquire_core(inst);
764 mutex_unlock(&core->lock);
765 } else {
766 mutex_lock(&core->lock);
767 ret = release_core(inst);
768 mutex_unlock(&core->lock);
769 }
770
771 return ret;
772 }
773
vdec_get_v4(struct device * dev)774 static int vdec_get_v4(struct device *dev)
775 {
776 struct venus_core *core = dev_get_drvdata(dev);
777
778 if (!legacy_binding)
779 return 0;
780
781 return vcodec_clks_get(core, dev, core->vcodec0_clks,
782 core->res->vcodec0_clks);
783 }
784
vdec_put_v4(struct device * dev)785 static void vdec_put_v4(struct device *dev)
786 {
787 struct venus_core *core = dev_get_drvdata(dev);
788 unsigned int i;
789
790 if (!legacy_binding)
791 return;
792
793 for (i = 0; i < core->res->vcodec_clks_num; i++)
794 core->vcodec0_clks[i] = NULL;
795 }
796
vdec_power_v4(struct device * dev,int on)797 static int vdec_power_v4(struct device *dev, int on)
798 {
799 struct venus_core *core = dev_get_drvdata(dev);
800 int ret;
801
802 if (!legacy_binding)
803 return 0;
804
805 ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true);
806 if (ret)
807 return ret;
808
809 if (on == POWER_ON)
810 ret = vcodec_clks_enable(core, core->vcodec0_clks);
811 else
812 vcodec_clks_disable(core, core->vcodec0_clks);
813
814 vcodec_control_v4(core, VIDC_CORE_ID_1, false);
815
816 return ret;
817 }
818
venc_get_v4(struct device * dev)819 static int venc_get_v4(struct device *dev)
820 {
821 struct venus_core *core = dev_get_drvdata(dev);
822
823 if (!legacy_binding)
824 return 0;
825
826 return vcodec_clks_get(core, dev, core->vcodec1_clks,
827 core->res->vcodec1_clks);
828 }
829
venc_put_v4(struct device * dev)830 static void venc_put_v4(struct device *dev)
831 {
832 struct venus_core *core = dev_get_drvdata(dev);
833 unsigned int i;
834
835 if (!legacy_binding)
836 return;
837
838 for (i = 0; i < core->res->vcodec_clks_num; i++)
839 core->vcodec1_clks[i] = NULL;
840 }
841
venc_power_v4(struct device * dev,int on)842 static int venc_power_v4(struct device *dev, int on)
843 {
844 struct venus_core *core = dev_get_drvdata(dev);
845 int ret;
846
847 if (!legacy_binding)
848 return 0;
849
850 ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true);
851 if (ret)
852 return ret;
853
854 if (on == POWER_ON)
855 ret = vcodec_clks_enable(core, core->vcodec1_clks);
856 else
857 vcodec_clks_disable(core, core->vcodec1_clks);
858
859 vcodec_control_v4(core, VIDC_CORE_ID_2, false);
860
861 return ret;
862 }
863
vcodec_domains_get(struct venus_core * core)864 static int vcodec_domains_get(struct venus_core *core)
865 {
866 int ret;
867 struct device *dev = core->dev;
868 const struct venus_resources *res = core->res;
869 struct dev_pm_domain_attach_data vcodec_data = {
870 .pd_names = res->vcodec_pmdomains,
871 .num_pd_names = res->vcodec_pmdomains_num,
872 .pd_flags = PD_FLAG_NO_DEV_LINK,
873 };
874 struct dev_pm_domain_attach_data opp_pd_data = {
875 .pd_names = res->opp_pmdomain,
876 .num_pd_names = 1,
877 .pd_flags = PD_FLAG_DEV_LINK_ON | PD_FLAG_REQUIRED_OPP,
878 };
879
880 if (!res->vcodec_pmdomains_num)
881 goto skip_pmdomains;
882
883 ret = devm_pm_domain_attach_list(dev, &vcodec_data, &core->pmdomains);
884 if (ret < 0)
885 return ret;
886
887 skip_pmdomains:
888 if (!res->opp_pmdomain)
889 return 0;
890
891 /* Attach the power domain for setting performance state */
892 ret = devm_pm_domain_attach_list(dev, &opp_pd_data, &core->opp_pmdomain);
893 if (ret < 0)
894 return ret;
895
896 return 0;
897 }
898
core_resets_reset(struct venus_core * core)899 static int core_resets_reset(struct venus_core *core)
900 {
901 const struct venus_resources *res = core->res;
902 unsigned int i;
903 int ret;
904
905 if (!res->resets_num)
906 return 0;
907
908 for (i = 0; i < res->resets_num; i++) {
909 ret = reset_control_assert(core->resets[i]);
910 if (ret)
911 goto err;
912
913 usleep_range(150, 250);
914 ret = reset_control_deassert(core->resets[i]);
915 if (ret)
916 goto err;
917 }
918
919 err:
920 return ret;
921 }
922
core_resets_get(struct venus_core * core)923 static int core_resets_get(struct venus_core *core)
924 {
925 struct device *dev = core->dev;
926 const struct venus_resources *res = core->res;
927 unsigned int i;
928 int ret;
929
930 if (!res->resets_num)
931 return 0;
932
933 for (i = 0; i < res->resets_num; i++) {
934 core->resets[i] =
935 devm_reset_control_get_exclusive(dev, res->resets[i]);
936 if (IS_ERR(core->resets[i])) {
937 ret = PTR_ERR(core->resets[i]);
938 return ret;
939 }
940 }
941
942 return 0;
943 }
944
core_get_v4(struct venus_core * core)945 static int core_get_v4(struct venus_core *core)
946 {
947 struct device *dev = core->dev;
948 const struct venus_resources *res = core->res;
949 int ret;
950
951 ret = core_clks_get(core);
952 if (ret)
953 return ret;
954
955 if (!res->vcodec_pmdomains_num)
956 legacy_binding = true;
957
958 dev_info(dev, "%s legacy binding\n", legacy_binding ? "" : "non");
959
960 ret = vcodec_clks_get(core, dev, core->vcodec0_clks, res->vcodec0_clks);
961 if (ret)
962 return ret;
963
964 ret = vcodec_clks_get(core, dev, core->vcodec1_clks, res->vcodec1_clks);
965 if (ret)
966 return ret;
967
968 ret = core_resets_get(core);
969 if (ret)
970 return ret;
971
972 if (legacy_binding)
973 return 0;
974
975 ret = devm_pm_opp_set_clkname(dev, "core");
976 if (ret)
977 return ret;
978
979 ret = vcodec_domains_get(core);
980 if (ret)
981 return ret;
982
983 if (core->res->opp_pmdomain) {
984 ret = devm_pm_opp_of_add_table(dev);
985 if (ret && ret != -ENODEV) {
986 dev_err(dev, "invalid OPP table in device tree\n");
987 return ret;
988 }
989 }
990
991 return 0;
992 }
993
core_put_v4(struct venus_core * core)994 static void core_put_v4(struct venus_core *core)
995 {
996 }
997
core_power_v4(struct venus_core * core,int on)998 static int core_power_v4(struct venus_core *core, int on)
999 {
1000 struct device *dev = core->dev;
1001 struct device *pmctrl = core->pmdomains ?
1002 core->pmdomains->pd_devs[0] : NULL;
1003 int ret = 0;
1004
1005 if (on == POWER_ON) {
1006 if (pmctrl) {
1007 ret = pm_runtime_resume_and_get(pmctrl);
1008 if (ret < 0) {
1009 return ret;
1010 }
1011 }
1012
1013 ret = core_resets_reset(core);
1014 if (ret) {
1015 if (pmctrl)
1016 pm_runtime_put_sync(pmctrl);
1017 return ret;
1018 }
1019
1020 ret = core_clks_enable(core);
1021 if (ret < 0 && pmctrl)
1022 pm_runtime_put_sync(pmctrl);
1023 } else {
1024 /* Drop the performance state vote */
1025 if (core->opp_pmdomain)
1026 dev_pm_opp_set_rate(dev, 0);
1027
1028 core_clks_disable(core);
1029
1030 ret = core_resets_reset(core);
1031
1032 if (pmctrl)
1033 pm_runtime_put_sync(pmctrl);
1034 }
1035
1036 return ret;
1037 }
1038
calculate_inst_freq(struct venus_inst * inst,unsigned long filled_len)1039 static unsigned long calculate_inst_freq(struct venus_inst *inst,
1040 unsigned long filled_len)
1041 {
1042 unsigned long vpp_freq_per_mb = 0, vpp_freq = 0, vsp_freq = 0;
1043 u32 fps = (u32)inst->fps;
1044 u32 mbs_per_sec;
1045
1046 mbs_per_sec = load_per_instance(inst);
1047
1048 if (inst->state != INST_START)
1049 return 0;
1050
1051 if (inst->session_type == VIDC_SESSION_TYPE_ENC) {
1052 vpp_freq_per_mb = inst->flags & VENUS_LOW_POWER ?
1053 inst->clk_data.low_power_freq :
1054 inst->clk_data.vpp_freq;
1055
1056 vpp_freq = mbs_per_sec * vpp_freq_per_mb;
1057 } else {
1058 vpp_freq = mbs_per_sec * inst->clk_data.vpp_freq;
1059 }
1060
1061 /* 21 / 20 is overhead factor */
1062 vpp_freq += vpp_freq / 20;
1063 vsp_freq = mbs_per_sec * inst->clk_data.vsp_freq;
1064
1065 /* 10 / 7 is overhead factor */
1066 if (inst->session_type == VIDC_SESSION_TYPE_ENC)
1067 vsp_freq += (inst->controls.enc.bitrate * 10) / 7;
1068 else
1069 vsp_freq += ((fps * filled_len * 8) * 10) / 7;
1070
1071 return max(vpp_freq, vsp_freq);
1072 }
1073
load_scale_v4(struct venus_inst * inst)1074 static int load_scale_v4(struct venus_inst *inst)
1075 {
1076 struct venus_core *core = inst->core;
1077 const struct freq_tbl *table = core->res->freq_tbl;
1078 unsigned int num_rows = core->res->freq_tbl_size;
1079 struct device *dev = core->dev;
1080 unsigned long freq = 0, freq_core1 = 0, freq_core2 = 0;
1081 unsigned long filled_len = 0;
1082 int i, ret = 0;
1083
1084 for (i = 0; i < inst->num_input_bufs; i++)
1085 filled_len = max(filled_len, inst->payloads[i]);
1086
1087 if (inst->session_type == VIDC_SESSION_TYPE_DEC && !filled_len)
1088 return ret;
1089
1090 freq = calculate_inst_freq(inst, filled_len);
1091 inst->clk_data.freq = freq;
1092
1093 mutex_lock(&core->lock);
1094 list_for_each_entry(inst, &core->instances, list) {
1095 if (inst->clk_data.core_id == VIDC_CORE_ID_1) {
1096 freq_core1 += inst->clk_data.freq;
1097 } else if (inst->clk_data.core_id == VIDC_CORE_ID_2) {
1098 freq_core2 += inst->clk_data.freq;
1099 } else if (inst->clk_data.core_id == VIDC_CORE_ID_3) {
1100 freq_core1 += inst->clk_data.freq;
1101 freq_core2 += inst->clk_data.freq;
1102 }
1103 }
1104
1105 freq = max(freq_core1, freq_core2);
1106
1107 if (freq > table[0].freq) {
1108 dev_dbg(dev, VDBGL "requested clock rate: %lu scaling clock rate : %lu\n",
1109 freq, table[0].freq);
1110
1111 freq = table[0].freq;
1112 goto set_freq;
1113 }
1114
1115 for (i = num_rows - 1 ; i >= 0; i--) {
1116 if (freq <= table[i].freq) {
1117 freq = table[i].freq;
1118 break;
1119 }
1120 }
1121
1122 set_freq:
1123
1124 ret = core_clks_set_rate(core, freq);
1125 if (ret) {
1126 dev_err(dev, "failed to set clock rate %lu (%d)\n",
1127 freq, ret);
1128 goto exit;
1129 }
1130
1131 ret = load_scale_bw(core);
1132 if (ret) {
1133 dev_err(dev, "failed to set bandwidth (%d)\n",
1134 ret);
1135 goto exit;
1136 }
1137
1138 exit:
1139 mutex_unlock(&core->lock);
1140 return ret;
1141 }
1142
1143 static const struct venus_pm_ops pm_ops_v4 = {
1144 .core_get = core_get_v4,
1145 .core_put = core_put_v4,
1146 .core_power = core_power_v4,
1147 .vdec_get = vdec_get_v4,
1148 .vdec_put = vdec_put_v4,
1149 .vdec_power = vdec_power_v4,
1150 .venc_get = venc_get_v4,
1151 .venc_put = venc_put_v4,
1152 .venc_power = venc_power_v4,
1153 .coreid_power = coreid_power_v4,
1154 .load_scale = load_scale_v4,
1155 };
1156
venus_pm_get(enum hfi_version version)1157 const struct venus_pm_ops *venus_pm_get(enum hfi_version version)
1158 {
1159 switch (version) {
1160 case HFI_VERSION_1XX:
1161 default:
1162 return &pm_ops_v1;
1163 case HFI_VERSION_3XX:
1164 return &pm_ops_v3;
1165 case HFI_VERSION_4XX:
1166 case HFI_VERSION_6XX:
1167 return &pm_ops_v4;
1168 }
1169
1170 return NULL;
1171 }
1172