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