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