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