File Index
Files and directories
Sign in
FILE

iris_power.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/qcom/iris/iris_power.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  4 */
  5
  6#include <linux/pm_opp.h>
  7#include <linux/pm_runtime.h>
  8#include <media/v4l2-mem2mem.h>
  9
 10#include "iris_buffer.h"
 11#include "iris_instance.h"
 12#include "iris_power.h"
 13#include "iris_resources.h"
 14#include "iris_vpu_common.h"
 15
 16static u32 iris_calc_bw(struct iris_inst *inst, struct icc_vote_data *data)
 17{
 18	const struct bw_info *bw_tbl = NULL;
 19	struct iris_core *core = inst->core;
 20	u32 num_rows, i, mbs, mbps;
 21	u32 icc_bw = 0;
 22
 23	mbs = DIV_ROUND_UP(data->height, 16) * DIV_ROUND_UP(data->width, 16);
 24	mbps = mbs * data->fps;
 25	if (mbps == 0)
 26		goto exit;
 27
 28	bw_tbl = core->iris_platform_data->bw_tbl_dec;
 29	num_rows = core->iris_platform_data->bw_tbl_dec_size;
 30
 31	for (i = 0; i < num_rows; i++) {
 32		if (i != 0 && mbps > bw_tbl[i].mbs_per_sec)
 33			break;
 34
 35		icc_bw = bw_tbl[i].bw_ddr;
 36	}
 37
 38exit:
 39	return icc_bw;
 40}
 41
 42static int iris_set_interconnects(struct iris_inst *inst)
 43{
 44	struct iris_core *core = inst->core;
 45	struct iris_inst *instance;
 46	u64 total_bw_ddr = 0;
 47	int ret;
 48
 49	mutex_lock(&core->lock);
 50	list_for_each_entry(instance, &core->instances, list) {
 51		if (!instance->max_input_data_size)
 52			continue;
 53
 54		total_bw_ddr += instance->power.icc_bw;
 55	}
 56
 57	ret = iris_set_icc_bw(core, total_bw_ddr);
 58
 59	mutex_unlock(&core->lock);
 60
 61	return ret;
 62}
 63
 64static int iris_vote_interconnects(struct iris_inst *inst)
 65{
 66	struct icc_vote_data *vote_data = &inst->icc_data;
 67	struct v4l2_format *inp_f = inst->fmt_src;
 68
 69	vote_data->width = inp_f->fmt.pix_mp.width;
 70	vote_data->height = inp_f->fmt.pix_mp.height;
 71	vote_data->fps = DEFAULT_FPS;
 72
 73	inst->power.icc_bw = iris_calc_bw(inst, vote_data);
 74
 75	return iris_set_interconnects(inst);
 76}
 77
 78static int iris_set_clocks(struct iris_inst *inst)
 79{
 80	struct iris_core *core = inst->core;
 81	struct iris_inst *instance;
 82	u64 freq = 0;
 83	int ret;
 84
 85	mutex_lock(&core->lock);
 86	list_for_each_entry(instance, &core->instances, list) {
 87		if (!instance->max_input_data_size)
 88			continue;
 89
 90		freq += instance->power.min_freq;
 91	}
 92
 93	core->power.clk_freq = freq;
 94	ret = dev_pm_opp_set_rate(core->dev, freq);
 95	mutex_unlock(&core->lock);
 96
 97	return ret;
 98}
 99
100static int iris_scale_clocks(struct iris_inst *inst)
101{
102	const struct vpu_ops *vpu_ops = inst->core->iris_platform_data->vpu_ops;
103	struct v4l2_m2m_ctx *m2m_ctx = inst->m2m_ctx;
104	struct v4l2_m2m_buffer *buffer, *n;
105	struct iris_buffer *buf;
106	size_t data_size = 0;
107
108	v4l2_m2m_for_each_src_buf_safe(m2m_ctx, buffer, n) {
109		buf = to_iris_buffer(&buffer->vb);
110		data_size = max(data_size, buf->data_size);
111	}
112
113	inst->max_input_data_size = data_size;
114	if (!inst->max_input_data_size)
115		return 0;
116
117	inst->power.min_freq = vpu_ops->calc_freq(inst, inst->max_input_data_size);
118
119	return iris_set_clocks(inst);
120}
121
122int iris_scale_power(struct iris_inst *inst)
123{
124	struct iris_core *core = inst->core;
125	int ret;
126
127	if (pm_runtime_suspended(core->dev)) {
128		ret = pm_runtime_resume_and_get(core->dev);
129		if (ret < 0)
130			return ret;
131
132		pm_runtime_put_autosuspend(core->dev);
133	}
134
135	ret = iris_scale_clocks(inst);
136	if (ret)
137		return ret;
138
139	return iris_vote_interconnects(inst);
140}
~/ Read-only file preview.