Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e41d4d0 authored by Srinu Gorle's avatar Srinu Gorle
Browse files

msm: vidc: fix for choosing clock frequency based on session type



In clock frequency table, codec config parameter first bit used to
identify codec type and second bit is used for session type.
If parallel encode and decode sessions are running for same codec, decoder
session is masking the encoder session type bit.
This is causing decoder codec clock frequency to get selected.
Propagate active sessions information separately while choosing clocks
frequency.

Change-Id: I259a9db1a4337cbc51cee2ff1724feba6e5aa952
Signed-off-by: default avatarSrinu Gorle <sgorle@codeaurora.org>
parent 87bcf4a6
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -2060,11 +2060,13 @@ int msm_comm_scale_clocks(struct msm_vidc_core *core)

int msm_comm_scale_clocks_load(struct msm_vidc_core *core, int num_mbs_per_sec)
{
	u32 codecs_enabled = 0;
	int rc = 0;
	struct hfi_device *hdev;
	struct msm_vidc_inst *inst = NULL;
	unsigned long instant_bitrate = 0;
	int num_sessions = 0;
	struct vidc_clk_scale_data clk_scale_data = { {0} };
	int codec = 0;

	if (!core) {
		dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, core);
@@ -2080,29 +2082,31 @@ int msm_comm_scale_clocks_load(struct msm_vidc_core *core, int num_mbs_per_sec)

	mutex_lock(&core->lock);
	list_for_each_entry(inst, &core->instances, list) {
		int codec = 0;

		codec = inst->session_type == MSM_VIDC_DECODER ?
			inst->fmts[OUTPUT_PORT]->fourcc :
			inst->fmts[CAPTURE_PORT]->fourcc;

		codecs_enabled |= VIDC_VOTE_DATA_SESSION_VAL(
		clk_scale_data.session[num_sessions] =
				VIDC_VOTE_DATA_SESSION_VAL(
				get_hal_codec(codec),
				get_hal_domain(inst->session_type));
		num_sessions++;

		if (inst->instant_bitrate > instant_bitrate)
			instant_bitrate = inst->instant_bitrate;

	}
	clk_scale_data.num_sessions = num_sessions;
	mutex_unlock(&core->lock);

	dprintk(VIDC_INFO, "num_mbs_per_sec = %d codecs_enabled %#x\n",
			num_mbs_per_sec, codecs_enabled);

	rc = call_hfi_op(hdev, scale_clocks,
		hdev->hfi_device_data, num_mbs_per_sec,
		codecs_enabled, instant_bitrate);
		&clk_scale_data, instant_bitrate);
	if (rc)
		dprintk(VIDC_ERR, "Failed to set clock rate: %d\n", rc);

	return rc;
}

+97 −47
Original line number Diff line number Diff line
@@ -86,7 +86,8 @@ static int __enable_regulators(struct venus_hfi_device *device);
static inline int __prepare_enable_clks(struct venus_hfi_device *device);
static inline void __disable_unprepare_clks(struct venus_hfi_device *device);
static int __scale_clocks(struct venus_hfi_device *device, int load,
		int codecs_enabled, unsigned long instant_bitrate);
		struct vidc_clk_scale_data *data,
		unsigned long instant_bitrate);
static void __flush_debug_queue(struct venus_hfi_device *device, u8 *packet);
static int __initialize_packetization(struct venus_hfi_device *device);
static struct hal_session *__get_session(struct venus_hfi_device *device,
@@ -711,7 +712,7 @@ static void __iommu_detach(struct venus_hfi_device *device)
}

static bool __is_session_supported(unsigned long sessions_supported,
		enum vidc_bus_vote_data_session session_type)
		enum vidc_vote_data_session session_type)
{
	bool same_codec, same_session_type;
	int codec_bit, session_type_bit;
@@ -1155,74 +1156,112 @@ static struct regulator_info *__get_regulator(struct venus_hfi_device *device,
}

static unsigned long __get_clock_rate(struct clock_info *clock,
	int num_mbs_per_sec, int codecs_enabled)
	int num_mbs_per_sec, struct vidc_clk_scale_data *data)
{
	int num_rows = clock->count;
	struct load_freq_table *table = clock->load_freq_tbl;
	unsigned long freq = table[0].freq;
	int i;
	unsigned long freq = table[0].freq, max_freq = 0;
	int i = 0, j = 0;
	unsigned long instance_freq[VIDC_MAX_SESSIONS] = {0};

	if (!num_mbs_per_sec && num_rows > 1)
		return table[num_rows - 1].freq;
	if (!data && !num_rows) {
		freq = 0;
		goto print_clk;
	}

	for (i = 0; i < num_rows; i++) {
		bool matches = __is_session_supported(
			table[i].supported_codecs, codecs_enabled);
		if (!matches)
			continue;
	if ((!num_mbs_per_sec || !data) && num_rows) {
		freq = table[num_rows - 1].freq;
		goto print_clk;
	}

	for (i = 0; i < num_rows; i++) {
		if (num_mbs_per_sec > table[i].load)
			break;
		for (j = 0; j < data->num_sessions; j++) {
			bool matches = __is_session_supported(
				table[i].supported_codecs, data->session[j]);

		freq = table[i].freq;
			if (!matches)
				continue;
			instance_freq[j] = table[i].freq;
		}
	}
	for (i = 0; i < data->num_sessions; i++)
		max_freq = max(instance_freq[i], max_freq);

	freq = max_freq ? : freq;
print_clk:
	dprintk(VIDC_PROF, "Required clock rate = %lu num_mbs_per_sec %d\n",
					freq, num_mbs_per_sec);
	return freq;
}

static unsigned long __get_clock_rate_with_bitrate(struct clock_info *clock,
		int num_mbs_per_sec, int codecs_enabled,
		int num_mbs_per_sec, struct vidc_clk_scale_data *data,
		unsigned long instant_bitrate)
{
	int num_rows = clock->count;
	struct load_freq_table *table = clock->load_freq_tbl;
	unsigned long freq = table[0].freq;
	unsigned long base_freq;
	int i;
	unsigned long freq = table[0].freq, max_freq = 0;
	unsigned long base_freq, supported_clk[VIDC_MAX_SESSIONS] = {0};
	int i, j;

	if (!num_mbs_per_sec && num_rows > 1)
		return table[num_rows - 1].freq;
	if (!data && !num_rows) {
		freq = 0;
		goto print_clk;
	}
	if ((!num_mbs_per_sec || !data) && num_rows) {
		freq = table[num_rows - 1].freq;
		goto print_clk;
	}

	/* Get clock rate based on current load only */
	base_freq = __get_clock_rate(clock, num_mbs_per_sec, codecs_enabled);
	base_freq = __get_clock_rate(clock, num_mbs_per_sec, data);

	/*
	 * Supported bitrate = 40% of clock frequency
	 * Check if the instant bitrate is supported by the base frequency.
	 * If not, move on to the next frequency which supports the bitrate.
	 */

	for (j = 0; j < data->num_sessions; j++) {
		unsigned long supported_bitrate = 0;

		for (i = num_rows - 1; i >= 0; i--) {
		unsigned long supported_bitrate;
			bool matches = __is_session_supported(
		   table[i].supported_codecs, codecs_enabled);
				table[i].supported_codecs, data->session[j]);

			if (!matches)
				continue;

			freq = table[i].freq;
		supported_bitrate = freq * 40/100;

		if (table[i].freq >= base_freq &&
			supported_bitrate >= instant_bitrate)
			supported_bitrate = freq * 40/100;
			/*
			 * Store this frequency for each instance, we need
			 * to select the maximum freq among all the instances.
			 */
			if (freq >= base_freq &&
				supported_bitrate >= instant_bitrate) {
				supported_clk[j] = freq;
				break;
			}
		}
	}

	for (i = 0; i < data->num_sessions; i++)
		max_freq = max(supported_clk[i], max_freq);

	freq = max_freq ? : base_freq;

	if (base_freq == freq)
		dprintk(VIDC_DBG, "Stay at base freq: %lu bitrate = %lu\n",
			freq, instant_bitrate);
	else
		dprintk(VIDC_DBG, "Move up clock freq: %lu bitrate = %lu\n",
			freq, instant_bitrate);

print_clk:
	dprintk(VIDC_PROF, "Required clock rate = %lu num_mbs_per_sec %d\n",
					freq, num_mbs_per_sec);
	return freq;
}

@@ -1330,25 +1369,35 @@ static int __halt_axi(struct venus_hfi_device *device)
}

static int __scale_clocks(struct venus_hfi_device *device, int load,
		int codecs_enabled, unsigned long instant_bitrate)
		struct vidc_clk_scale_data *data, unsigned long instant_bitrate)
{
	struct clock_info *cl;

	device->clk_load = load;
	device->codecs_enabled = codecs_enabled;
	device->clk_bitrate = instant_bitrate;

	venus_hfi_for_each_clock(device, cl) {
		if (cl->count) {/* has_scaling */
			unsigned long rate;

			unsigned long rate = 0;
			int rc;
			/*
			 * load_fw and power_on needs to be addressed.
			 * differently. Below check enforces the same.
			 */
			if (!device->clk_bitrate && !data && !load &&
				device->clk_freq)
				rate = device->clk_freq;

			if (!rate) {
				if (!device->clk_bitrate)
					rate = __get_clock_rate(cl, load,
					codecs_enabled);
							data);
				else
				rate = __get_clock_rate_with_bitrate(cl, load,
					codecs_enabled, instant_bitrate);
					rate = __get_clock_rate_with_bitrate(cl,
							load, data,
							instant_bitrate);
			}
			device->clk_freq = rate;
			rc = clk_set_rate(cl->clk, rate);
			if (rc) {
				dprintk(VIDC_ERR,
@@ -1368,7 +1417,8 @@ static int __scale_clocks(struct venus_hfi_device *device, int load,
	return 0;
}

static int venus_hfi_scale_clocks(void *dev, int load, int codecs_enabled,
static int venus_hfi_scale_clocks(void *dev, int load,
					struct vidc_clk_scale_data *data,
					unsigned long instant_bitrate)
{
	int rc = 0;
@@ -1380,7 +1430,7 @@ static int venus_hfi_scale_clocks(void *dev, int load, int codecs_enabled,
	}

	mutex_lock(&device->lock);
	rc = __scale_clocks(device, load, codecs_enabled, instant_bitrate);
	rc = __scale_clocks(device, load, data, instant_bitrate);
	mutex_unlock(&device->lock);

	return rc;
@@ -3492,6 +3542,7 @@ static inline void __deinit_clocks(struct venus_hfi_device *device)
{
	struct clock_info *cl;

	device->clk_freq = 0;
	venus_hfi_for_each_clock_reverse(device, cl) {
		if (cl->clk) {
			clk_put(cl->clk);
@@ -3536,7 +3587,7 @@ static inline int __init_clocks(struct venus_hfi_device *device)
			}
		}
	}

	device->clk_freq = 0;
	return 0;

err_clk_get:
@@ -4019,8 +4070,7 @@ static int __venus_power_on(struct venus_hfi_device *device)
		goto fail_enable_clks;
	}

	rc = __scale_clocks(device, device->clk_load, device->codecs_enabled,
			device->clk_bitrate);
	rc = __scale_clocks(device, 0, NULL, 0);
	if (rc) {
		dprintk(VIDC_WARN,
				"Failed to scale clocks, performance might be affected\n");
+1 −2
Original line number Diff line number Diff line
@@ -222,8 +222,7 @@ struct venus_hfi_device {
	struct list_head sess_head;
	u32 intr_status;
	u32 device_id;
	u32 clk_load;
	u32 codecs_enabled;
	u32 clk_freq;
	u32 last_packet_type;
	unsigned long clk_bitrate;
	unsigned long scaled_rate;
+13 −4
Original line number Diff line number Diff line
@@ -64,6 +64,9 @@
#define HAL_MAX_LIMIT_COEFFS 6
#define VENUS_VERSION_LENGTH 128

/* 32 encoder and 32 decoder sessions */
#define VIDC_MAX_SESSIONS               64

enum vidc_status {
	VIDC_ERR_NONE = 0x0,
	VIDC_ERR_FAIL = 0x80000000,
@@ -1343,7 +1346,7 @@ enum msm_vidc_thermal_level {
	VIDC_THERMAL_CRITICAL
};

enum vidc_bus_vote_data_session {
enum vidc_vote_data_session {
	VIDC_BUS_VOTE_DATA_SESSION_INVALID = 0,
	/* No declarations exist. Values generated by VIDC_VOTE_DATA_SESSION_VAL
	 * describe the enumerations e.g.:
@@ -1358,7 +1361,7 @@ enum vidc_bus_vote_data_session {
 *
 * This macro assigns two bits to each codec: the lower bit denoting the codec
 * type, and the higher bit denoting session type. */
static inline enum vidc_bus_vote_data_session VIDC_VOTE_DATA_SESSION_VAL(
static inline enum vidc_vote_data_session VIDC_VOTE_DATA_SESSION_VAL(
		enum hal_video_codec c, enum hal_domain d) {
	if (d != HAL_VIDEO_DOMAIN_ENCODER && d != HAL_VIDEO_DOMAIN_DECODER)
		return VIDC_BUS_VOTE_DATA_SESSION_INVALID;
@@ -1390,6 +1393,11 @@ struct vidc_bus_vote_data {
	unsigned long core_freq;
};

struct vidc_clk_scale_data {
	enum vidc_vote_data_session session[VIDC_MAX_SESSIONS];
	int num_sessions;
};

struct hal_index_extradata_input_crop_payload {
	u32 size;
	u32 version;
@@ -1446,7 +1454,8 @@ struct hfi_device {
	int (*session_set_property)(void *sess, enum hal_property ptype,
			void *pdata);
	int (*session_get_property)(void *sess, enum hal_property ptype);
	int (*scale_clocks)(void *dev, int load, int codecs_enabled,
	int (*scale_clocks)(void *dev, int load,
			struct vidc_clk_scale_data *data,
			unsigned long instant_bitrate);
	int (*vote_bus)(void *dev, struct vidc_bus_vote_data *data,
			int num_data);