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