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