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