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