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