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

Commit 8c0376ae authored by Dhaval Patel's avatar Dhaval Patel Committed by Jayaprakash
Browse files

disp: msm: sde: support fps based qos setting



Support different safe, danger and creq qos lut
configuration based on display fps. It also removes
the fill level calculations from sspp and wb block
because mdss hw supports simple configuration.

Change-Id: I203e4300c9eab27d3632c890bedd6383cca0e5a8
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
parent 64523147
Loading
Loading
Loading
Loading
+27 −43
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
 */

#define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
@@ -136,25 +136,6 @@ static void sde_encoder_phys_wb_set_qos_remap(
	sde_vbif_set_qos_remap(phys_enc->sde_kms, &qos_params);
}

static u64 _sde_encoder_phys_wb_get_qos_lut(const struct sde_qos_lut_tbl *tbl,
		u32 total_fl)
{
	int i;

	if (!tbl || !tbl->nentry || !tbl->entries)
		return 0;

	for (i = 0; i < tbl->nentry; i++)
		if (total_fl <= tbl->entries[i].fl)
			return tbl->entries[i].lut;

	/* if last fl is zero, use as default */
	if (!tbl->entries[i-1].fl)
		return tbl->entries[i-1].lut;

	return 0;
}

/**
 * sde_encoder_phys_wb_set_qos - set QoS/danger/safe LUTs for writeback
 * @phys_enc:	Pointer to physical encoder
@@ -163,14 +144,14 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc)
{
	struct sde_encoder_phys_wb *wb_enc;
	struct sde_hw_wb *hw_wb;
	struct sde_hw_wb_qos_cfg qos_cfg;
	struct sde_mdss_cfg *catalog;
	struct sde_hw_wb_qos_cfg qos_cfg = {0};
	struct sde_perf_cfg *perf;
	u32 fps_index = 0, lut_index, index, frame_rate, qos_count;

	if (!phys_enc || !phys_enc->sde_kms || !phys_enc->sde_kms->catalog) {
		SDE_ERROR("invalid parameter(s)\n");
		return;
	}
	catalog = phys_enc->sde_kms->catalog;

	wb_enc = to_sde_encoder_phys_wb(phys_enc);
	if (!wb_enc->hw_wb) {
@@ -178,35 +159,38 @@ static void sde_encoder_phys_wb_set_qos(struct sde_encoder_phys *phys_enc)
		return;
	}

	perf = &phys_enc->sde_kms->catalog->perf;
	frame_rate = phys_enc->cached_mode.vrefresh;

	hw_wb = wb_enc->hw_wb;
	qos_count = perf->qos_refresh_count;
	while (qos_count && perf->qos_refresh_rate) {
		if (frame_rate >= perf->qos_refresh_rate[qos_count - 1]) {
			fps_index = qos_count - 1;
			break;
		}
		qos_count--;
	}

	memset(&qos_cfg, 0, sizeof(struct sde_hw_wb_qos_cfg));
	qos_cfg.danger_safe_en = true;
	qos_cfg.danger_lut =
		catalog->perf.danger_lut_tbl[SDE_QOS_LUT_USAGE_NRT];

	if (phys_enc->in_clone_mode)
		qos_cfg.safe_lut = (u32) _sde_encoder_phys_wb_get_qos_lut(
			&catalog->perf.sfe_lut_tbl[SDE_QOS_LUT_USAGE_CWB], 0);
	else
		qos_cfg.safe_lut = (u32) _sde_encoder_phys_wb_get_qos_lut(
			&catalog->perf.sfe_lut_tbl[SDE_QOS_LUT_USAGE_NRT], 0);

	if (phys_enc->in_clone_mode)
		qos_cfg.creq_lut = _sde_encoder_phys_wb_get_qos_lut(
			&catalog->perf.qos_lut_tbl[SDE_QOS_LUT_USAGE_CWB], 0);
		lut_index = SDE_QOS_LUT_USAGE_CWB;
	else
		qos_cfg.creq_lut = _sde_encoder_phys_wb_get_qos_lut(
			&catalog->perf.qos_lut_tbl[SDE_QOS_LUT_USAGE_NRT], 0);
		lut_index = SDE_QOS_LUT_USAGE_NRT;
	index = (fps_index * SDE_QOS_LUT_USAGE_MAX) + lut_index;

	if (hw_wb->ops.setup_danger_safe_lut)
		hw_wb->ops.setup_danger_safe_lut(hw_wb, &qos_cfg);
	qos_cfg.danger_lut = perf->danger_lut[index];
	qos_cfg.safe_lut = (u32) perf->safe_lut[index];
	qos_cfg.creq_lut = perf->creq_lut[index];

	if (hw_wb->ops.setup_creq_lut)
		hw_wb->ops.setup_creq_lut(hw_wb, &qos_cfg);
	SDE_DEBUG("wb_enc:%d hw idx:%d fps:%d mode:%d luts[0x%x,0x%x 0x%llx]\n",
		DRMID(phys_enc->parent), hw_wb->idx - WB_0,
		frame_rate, phys_enc->in_clone_mode,
		qos_cfg.danger_lut, qos_cfg.safe_lut, qos_cfg.creq_lut);

	if (hw_wb->ops.setup_qos_ctrl)
		hw_wb->ops.setup_qos_ctrl(hw_wb, &qos_cfg);
	if (hw_wb->ops.setup_qos_lut)
		hw_wb->ops.setup_qos_lut(hw_wb, &qos_cfg);
}

/**
+162 −184
Original line number Diff line number Diff line
@@ -218,25 +218,30 @@ enum {
	PERF_DOWNSCALING_PREFILL_LINES,
	PERF_XTRA_PREFILL_LINES,
	PERF_AMORTIZABLE_THRESHOLD,
	PERF_DANGER_LUT,
	PERF_SAFE_LUT_LINEAR,
	PERF_SAFE_LUT_MACROTILE,
	PERF_SAFE_LUT_NRT,
	PERF_SAFE_LUT_CWB,
	PERF_QOS_LUT_LINEAR,
	PERF_QOS_LUT_MACROTILE,
	PERF_QOS_LUT_NRT,
	PERF_QOS_LUT_CWB,
	PERF_NUM_MNOC_PORTS,
	PERF_AXI_BUS_WIDTH,
	PERF_CDP_SETTING,
	PERF_CPU_MASK,
	PERF_CPU_DMA_LATENCY,
	PERF_QOS_LUT_MACROTILE_QSEED,
	PERF_SAFE_LUT_MACROTILE_QSEED,
	PERF_NUM_MNOC_PORTS,
	PERF_AXI_BUS_WIDTH,
	PERF_PROP_MAX,
};

enum {
	QOS_REFRESH_RATES,
	QOS_DANGER_LUT,
	QOS_SAFE_LUT_LINEAR,
	QOS_SAFE_LUT_MACROTILE,
	QOS_SAFE_LUT_NRT,
	QOS_SAFE_LUT_CWB,
	QOS_SAFE_LUT_MACROTILE_QSEED,
	QOS_CREQ_LUT_LINEAR,
	QOS_CREQ_LUT_MACROTILE,
	QOS_CREQ_LUT_NRT,
	QOS_CREQ_LUT_CWB,
	QOS_CREQ_LUT_MACROTILE_QSEED,
	QOS_PROP_MAX,
};

enum {
	SSPP_OFF,
	SSPP_SIZE,
@@ -532,37 +537,41 @@ static struct sde_prop_type sde_perf_prop[] = {
			false, PROP_TYPE_U32},
	{PERF_AMORTIZABLE_THRESHOLD, "qcom,sde-amortizable-threshold",
			false, PROP_TYPE_U32},
	{PERF_DANGER_LUT, "qcom,sde-danger-lut", false, PROP_TYPE_U32_ARRAY},
	{PERF_SAFE_LUT_LINEAR, "qcom,sde-safe-lut-linear", false,
	{PERF_NUM_MNOC_PORTS, "qcom,sde-num-mnoc-ports",
			false, PROP_TYPE_U32},
	{PERF_AXI_BUS_WIDTH, "qcom,sde-axi-bus-width",
			false, PROP_TYPE_U32},
	{PERF_CDP_SETTING, "qcom,sde-cdp-setting", false,
			PROP_TYPE_U32_ARRAY},
	{PERF_SAFE_LUT_MACROTILE, "qcom,sde-safe-lut-macrotile", false,
	{PERF_CPU_MASK, "qcom,sde-qos-cpu-mask", false, PROP_TYPE_U32},
	{PERF_CPU_DMA_LATENCY, "qcom,sde-qos-cpu-dma-latency", false,
			PROP_TYPE_U32},
};

static struct sde_prop_type sde_qos_prop[] = {
	{QOS_REFRESH_RATES, "qcom,sde-qos-refresh-rates",
				false, PROP_TYPE_U32_ARRAY},
	{QOS_DANGER_LUT, "qcom,sde-danger-lut", false, PROP_TYPE_U32_ARRAY},
	{QOS_SAFE_LUT_LINEAR, "qcom,sde-safe-lut-linear", false,
			PROP_TYPE_U32_ARRAY},
	{PERF_SAFE_LUT_NRT, "qcom,sde-safe-lut-nrt", false,
	{QOS_SAFE_LUT_MACROTILE, "qcom,sde-safe-lut-macrotile", false,
			PROP_TYPE_U32_ARRAY},
	{PERF_SAFE_LUT_CWB, "qcom,sde-safe-lut-cwb", false,
	{QOS_SAFE_LUT_NRT, "qcom,sde-safe-lut-nrt", false,
			PROP_TYPE_U32_ARRAY},
	{PERF_QOS_LUT_LINEAR, "qcom,sde-qos-lut-linear", false,
	{QOS_SAFE_LUT_CWB, "qcom,sde-safe-lut-cwb", false,
			PROP_TYPE_U32_ARRAY},
	{PERF_QOS_LUT_MACROTILE, "qcom,sde-qos-lut-macrotile", false,
	{QOS_SAFE_LUT_MACROTILE_QSEED, "qcom,sde-safe-lut-macrotile-qseed",
			false, PROP_TYPE_U32_ARRAY},
	{QOS_CREQ_LUT_LINEAR, "qcom,sde-qos-lut-linear", false,
			PROP_TYPE_U32_ARRAY},
	{PERF_QOS_LUT_NRT, "qcom,sde-qos-lut-nrt", false,
	{QOS_CREQ_LUT_MACROTILE, "qcom,sde-qos-lut-macrotile", false,
			PROP_TYPE_U32_ARRAY},
	{PERF_QOS_LUT_CWB, "qcom,sde-qos-lut-cwb", false,
	{QOS_CREQ_LUT_NRT, "qcom,sde-qos-lut-nrt", false,
			PROP_TYPE_U32_ARRAY},

	{PERF_CDP_SETTING, "qcom,sde-cdp-setting", false,
	{QOS_CREQ_LUT_CWB, "qcom,sde-qos-lut-cwb", false,
			PROP_TYPE_U32_ARRAY},
	{PERF_CPU_MASK, "qcom,sde-qos-cpu-mask", false, PROP_TYPE_U32},
	{PERF_CPU_DMA_LATENCY, "qcom,sde-qos-cpu-dma-latency", false,
			PROP_TYPE_U32},
	{PERF_QOS_LUT_MACROTILE_QSEED, "qcom,sde-qos-lut-macrotile-qseed",
			false, PROP_TYPE_U32_ARRAY},
	{PERF_SAFE_LUT_MACROTILE_QSEED, "qcom,sde-safe-lut-macrotile-qseed",
	{QOS_CREQ_LUT_MACROTILE_QSEED, "qcom,sde-qos-lut-macrotile-qseed",
			false, PROP_TYPE_U32_ARRAY},
	{PERF_NUM_MNOC_PORTS, "qcom,sde-num-mnoc-ports",
			false, PROP_TYPE_U32},
	{PERF_AXI_BUS_WIDTH, "qcom,sde-axi-bus-width",
			false, PROP_TYPE_U32},
};

static struct sde_prop_type sspp_prop[] = {
@@ -3580,172 +3589,116 @@ static int _sde_perf_parse_dt_validate(struct device_node *np, int *prop_count)
	if (rc)
		return rc;

	rc = _validate_dt_entry(np, &sde_perf_prop[PERF_DANGER_LUT], 1,
			&prop_count[PERF_DANGER_LUT], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_LINEAR], 1,
			&prop_count[PERF_SAFE_LUT_LINEAR], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_MACROTILE], 1,
			&prop_count[PERF_SAFE_LUT_MACROTILE], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_NRT], 1,
			&prop_count[PERF_SAFE_LUT_NRT], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np, &sde_perf_prop[PERF_SAFE_LUT_CWB], 1,
			&prop_count[PERF_SAFE_LUT_CWB], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_LINEAR], 1,
			&prop_count[PERF_QOS_LUT_LINEAR], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_MACROTILE], 1,
			&prop_count[PERF_QOS_LUT_MACROTILE], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_NRT], 1,
			&prop_count[PERF_QOS_LUT_NRT], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np, &sde_perf_prop[PERF_QOS_LUT_CWB], 1,
			&prop_count[PERF_QOS_LUT_CWB], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np, &sde_perf_prop[PERF_CDP_SETTING], 1,
			&prop_count[PERF_CDP_SETTING], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np,
			&sde_perf_prop[PERF_QOS_LUT_MACROTILE_QSEED], 1,
			&prop_count[PERF_QOS_LUT_MACROTILE_QSEED], NULL);
	if (rc)
		return rc;

	rc = _validate_dt_entry(np,
			&sde_perf_prop[PERF_SAFE_LUT_MACROTILE_QSEED], 1,
			&prop_count[PERF_SAFE_LUT_MACROTILE_QSEED], NULL);

	return rc;
}

static int _sde_perf_parse_dt_cfg_qos(struct sde_mdss_cfg *cfg, int *prop_count,
static int _sde_qos_parse_dt_cfg(struct sde_mdss_cfg *cfg, int *prop_count,
	struct sde_prop_value *prop_value, bool *prop_exists)
{
	int j, k;
	int i, j;
	u32 qos_count = 1, index;

	if (prop_exists[PERF_DANGER_LUT] && prop_count[PERF_DANGER_LUT] <=
			SDE_QOS_LUT_USAGE_MAX) {
		for (j = 0; j < prop_count[PERF_DANGER_LUT]; j++) {
			cfg->perf.danger_lut_tbl[j] =
	if (prop_exists[QOS_REFRESH_RATES]) {
		qos_count = prop_count[QOS_REFRESH_RATES];
		cfg->perf.qos_refresh_rate = kcalloc(qos_count,
			sizeof(u32), GFP_KERNEL);
		if (!cfg->perf.qos_refresh_rate)
			goto end;

		for (j = 0; j < qos_count; j++) {
			cfg->perf.qos_refresh_rate[j] =
					PROP_VALUE_ACCESS(prop_value,
						PERF_DANGER_LUT, j);
			SDE_DEBUG("danger usage:%d lut:0x%x\n",
					j, cfg->perf.danger_lut_tbl[j]);
						QOS_REFRESH_RATES, j);
			SDE_DEBUG("qos usage:%d refresh rate:0x%x\n",
					j, cfg->perf.qos_refresh_rate[j]);
		}
	}
	cfg->perf.qos_refresh_count = qos_count;

	for (j = 0; j < SDE_QOS_LUT_USAGE_MAX; j++) {
		static const u32 safe_key[SDE_QOS_LUT_USAGE_MAX] = {
	cfg->perf.danger_lut = kcalloc(qos_count,
		sizeof(u64) * SDE_QOS_LUT_USAGE_MAX, GFP_KERNEL);
	cfg->perf.safe_lut = kcalloc(qos_count,
		sizeof(u64) * SDE_QOS_LUT_USAGE_MAX, GFP_KERNEL);
	cfg->perf.creq_lut = kcalloc(qos_count,
		sizeof(u64) * SDE_QOS_LUT_USAGE_MAX, GFP_KERNEL);
	if (!cfg->perf.creq_lut || !cfg->perf.safe_lut || !cfg->perf.danger_lut)
		goto end;

	if (prop_exists[QOS_DANGER_LUT] &&
	    prop_count[QOS_DANGER_LUT] >= (SDE_QOS_LUT_USAGE_MAX * qos_count)) {
		for (i = 0; i < prop_count[QOS_DANGER_LUT]; i++) {
			cfg->perf.danger_lut[i] =
				PROP_VALUE_ACCESS(prop_value,
						QOS_DANGER_LUT, i);
			SDE_DEBUG("danger usage:%i lut:0x%x\n",
					i, cfg->perf.danger_lut[i]);
		}
	}

	for (i = 0; i < SDE_QOS_LUT_USAGE_MAX; i++) {
		static const u32 prop_creq_key[SDE_QOS_LUT_USAGE_MAX] = {
			[SDE_QOS_LUT_USAGE_LINEAR] =
					PERF_SAFE_LUT_LINEAR,
					QOS_CREQ_LUT_LINEAR,
			[SDE_QOS_LUT_USAGE_MACROTILE] =
					PERF_SAFE_LUT_MACROTILE,
					QOS_CREQ_LUT_MACROTILE,
			[SDE_QOS_LUT_USAGE_NRT] =
					PERF_SAFE_LUT_NRT,
					QOS_CREQ_LUT_NRT,
			[SDE_QOS_LUT_USAGE_CWB] =
					PERF_SAFE_LUT_CWB,
					QOS_CREQ_LUT_CWB,
			[SDE_QOS_LUT_USAGE_MACROTILE_QSEED] =
					PERF_SAFE_LUT_MACROTILE_QSEED,
					QOS_CREQ_LUT_MACROTILE_QSEED,
		};
		const u32 entry_size = 2;
		int m, count;
		int key = safe_key[j];

		if (!prop_exists[key])
			continue;

		count = prop_count[key] / entry_size;

		cfg->perf.sfe_lut_tbl[j].entries = kcalloc(count,
			sizeof(struct sde_qos_lut_entry), GFP_KERNEL);
		if (!cfg->perf.sfe_lut_tbl[j].entries)
			return -ENOMEM;

		for (k = 0, m = 0; k < count; k++, m += entry_size) {
			u64 lut_lo;

			cfg->perf.sfe_lut_tbl[j].entries[k].fl =
					PROP_VALUE_ACCESS(prop_value, key, m);
			lut_lo = PROP_VALUE_ACCESS(prop_value, key, m + 1);
			cfg->perf.sfe_lut_tbl[j].entries[k].lut = lut_lo;
			SDE_DEBUG("safe usage:%d.%d fl:%d lut:0x%llx\n",
				j, k,
				cfg->perf.sfe_lut_tbl[j].entries[k].fl,
				cfg->perf.sfe_lut_tbl[j].entries[k].lut);
		}
		cfg->perf.sfe_lut_tbl[j].nentry = count;
	}

	for (j = 0; j < SDE_QOS_LUT_USAGE_MAX; j++) {
		static const u32 prop_key[SDE_QOS_LUT_USAGE_MAX] = {
		static const u32 prop_safe_key[SDE_QOS_LUT_USAGE_MAX] = {
			[SDE_QOS_LUT_USAGE_LINEAR] =
					PERF_QOS_LUT_LINEAR,
					QOS_SAFE_LUT_LINEAR,
			[SDE_QOS_LUT_USAGE_MACROTILE] =
					PERF_QOS_LUT_MACROTILE,
					QOS_SAFE_LUT_MACROTILE,
			[SDE_QOS_LUT_USAGE_NRT] =
					PERF_QOS_LUT_NRT,
					QOS_SAFE_LUT_NRT,
			[SDE_QOS_LUT_USAGE_CWB] =
					PERF_QOS_LUT_CWB,
					QOS_SAFE_LUT_CWB,
			[SDE_QOS_LUT_USAGE_MACROTILE_QSEED] =
					PERF_QOS_LUT_MACROTILE_QSEED,
					QOS_SAFE_LUT_MACROTILE_QSEED,
		};
		const u32 entry_size = 3;
		int m, count;
		int key = prop_key[j];
		int creq_key = prop_creq_key[i];
		int safe_key = prop_safe_key[i];
		u64 lut_hi, lut_lo;

		if (!prop_exists[key])
		if (!prop_exists[creq_key] || !prop_exists[safe_key])
			continue;

		count = prop_count[key] / entry_size;
		for (j = 0; j < qos_count; j++) {
			lut_hi = PROP_VALUE_ACCESS(prop_value, creq_key,
					(j * 3) + 1);
			lut_lo = PROP_VALUE_ACCESS(prop_value, creq_key,
					(j * 3) + 2);
			index = (j * SDE_QOS_LUT_USAGE_MAX) + i;

		cfg->perf.qos_lut_tbl[j].entries = kcalloc(count,
			sizeof(struct sde_qos_lut_entry), GFP_KERNEL);
		if (!cfg->perf.qos_lut_tbl[j].entries)
			return -ENOMEM;

		for (k = 0, m = 0; k < count; k++, m += entry_size) {
			u64 lut_hi, lut_lo;

			cfg->perf.qos_lut_tbl[j].entries[k].fl =
					PROP_VALUE_ACCESS(prop_value, key, m);
			lut_hi = PROP_VALUE_ACCESS(prop_value, key, m + 1);
			lut_lo = PROP_VALUE_ACCESS(prop_value, key, m + 2);
			cfg->perf.qos_lut_tbl[j].entries[k].lut =
			cfg->perf.creq_lut[index] =
					(lut_hi << 32) | lut_lo;
			SDE_DEBUG("usage:%d.%d fl:%d lut:0x%llx\n",
				j, k,
				cfg->perf.qos_lut_tbl[j].entries[k].fl,
				cfg->perf.qos_lut_tbl[j].entries[k].lut);
			cfg->perf.safe_lut[index] =
				PROP_VALUE_ACCESS(prop_value, safe_key,
					(j * 2) + 1);
			SDE_DEBUG("usage:%d creq lut:0x%llx safe:0x%x\n",
				index, cfg->perf.creq_lut[index],
				cfg->perf.safe_lut[index]);
		}
		cfg->perf.qos_lut_tbl[j].nentry = count;
	}

	return 0;

end:
	kfree(cfg->perf.qos_refresh_rate);
	kfree(cfg->perf.creq_lut);
	kfree(cfg->perf.danger_lut);
	kfree(cfg->perf.safe_lut);

	return -ENOMEM;
}

static void _sde_perf_parse_dt_cfg_populate(struct sde_mdss_cfg *cfg,
@@ -3854,11 +3807,6 @@ static int _sde_perf_parse_dt_cfg(struct device_node *np,
	_sde_perf_parse_dt_cfg_populate(cfg, prop_count, prop_value,
			prop_exists);

	rc = _sde_perf_parse_dt_cfg_qos(cfg, prop_count, prop_value,
			prop_exists);
	if (rc)
		return rc;

	if (prop_exists[PERF_CDP_SETTING]) {
		const u32 prop_size = 2;
		u32 count = prop_count[PERF_CDP_SETTING] / prop_size;
@@ -3929,6 +3877,43 @@ static int sde_perf_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
	return rc;
}

static int sde_qos_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
{
	int rc, prop_count[QOS_PROP_MAX];
	struct sde_prop_value *prop_value = NULL;
	bool prop_exists[QOS_PROP_MAX];

	if (!cfg) {
		SDE_ERROR("invalid argument\n");
		rc = -EINVAL;
		goto end;
	}

	prop_value = kzalloc(QOS_PROP_MAX *
			sizeof(struct sde_prop_value), GFP_KERNEL);
	if (!prop_value) {
		rc = -ENOMEM;
		goto end;
	}

	rc = _validate_dt_entry(np, sde_qos_prop, ARRAY_SIZE(sde_qos_prop),
			prop_count, NULL);
	if (rc)
		goto freeprop;

	rc = _read_dt_entry(np, sde_qos_prop, ARRAY_SIZE(sde_qos_prop),
			prop_count, prop_exists, prop_value);
	if (rc)
		goto freeprop;

	rc = _sde_qos_parse_dt_cfg(cfg, prop_count, prop_value, prop_exists);

freeprop:
	kfree(prop_value);
end:
	return rc;
}

static int sde_parse_merge_3d_dt(struct device_node *np,
		struct sde_mdss_cfg *sde_cfg)
{
@@ -4225,7 +4210,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->sui_misr_supported = true;
		sde_cfg->sui_block_xin_mask = 0x3F71;
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		sde_cfg->has_3d_merge_reset = true;
		clear_bit(MDSS_INTR_LTM_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(MDSS_INTR_LTM_1_INTR, sde_cfg->mdss_irqs);
@@ -4255,7 +4239,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->has_decimation = true;
		sde_cfg->sui_block_xin_mask = 0x2EE1;
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		sde_cfg->has_3d_merge_reset = true;
		clear_bit(MDSS_INTR_LTM_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(MDSS_INTR_LTM_1_INTR, sde_cfg->mdss_irqs);
@@ -4274,7 +4257,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->sui_misr_supported = true;
		sde_cfg->sui_block_xin_mask = 0xE71;
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		sde_cfg->has_3d_merge_reset = true;
	} else if (IS_KONA_TARGET(hw_rev)) {
		sde_cfg->has_cwb_support = true;
@@ -4289,7 +4271,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->sui_misr_supported = true;
		sde_cfg->sui_block_xin_mask = 0x3F71;
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		sde_cfg->has_3d_merge_reset = true;
		clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
@@ -4312,7 +4293,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->sui_misr_supported = true;
		sde_cfg->sui_block_xin_mask = 0xE71;
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		sde_cfg->has_3d_merge_reset = true;
		clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
@@ -4348,7 +4328,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->sui_block_xin_mask = 0xC01;
		sde_cfg->has_hdr = false;
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
	} else if (IS_LAGOON_TARGET(hw_rev)) {
@@ -4363,7 +4342,6 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
		sde_cfg->sui_misr_supported = true;
		sde_cfg->sui_block_xin_mask = 0x261;
		sde_cfg->has_sui_blendstage = true;
		sde_cfg->has_qos_fl_nocalc = true;
		clear_bit(MDSS_INTR_AD4_0_INTR, sde_cfg->mdss_irqs);
		clear_bit(MDSS_INTR_AD4_1_INTR, sde_cfg->mdss_irqs);
		sde_cfg->has_hdr = true;
@@ -4403,10 +4381,6 @@ static int _sde_hardware_post_caps(struct sde_mdss_cfg *sde_cfg,
				sde_cfg->sspp[i].sblk->maxvdeciexp);
		}

		if (sde_cfg->has_qos_fl_nocalc)
			set_bit(SDE_PERF_SSPP_QOS_FL_NOCALC,
				&sde_cfg->sspp[i].perf_features);

		/*
		 * set sec-ui blocked SSPP feature flag based on blocked
		 * xin-mask if sec-ui-misr feature is enabled;
@@ -4489,10 +4463,10 @@ void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
		kfree(sde_cfg->limit_cfg[i].value_cfg);
	}

	for (i = 0; i < SDE_QOS_LUT_USAGE_MAX; i++) {
		kfree(sde_cfg->perf.sfe_lut_tbl[i].entries);
		kfree(sde_cfg->perf.qos_lut_tbl[i].entries);
	}
	kfree(sde_cfg->perf.qos_refresh_rate);
	kfree(sde_cfg->perf.danger_lut);
	kfree(sde_cfg->perf.safe_lut);
	kfree(sde_cfg->perf.creq_lut);

	kfree(sde_cfg->dma_formats);
	kfree(sde_cfg->cursor_formats);
@@ -4531,6 +4505,10 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 hw_rev)
	if (rc)
		goto end;

	rc = sde_qos_parse_dt(np, sde_cfg);
	if (rc)
		goto end;

	rc = sde_rot_parse_dt(np, sde_cfg);
	if (rc)
		goto end;
+10 −30
Original line number Diff line number Diff line
@@ -260,7 +260,6 @@ enum {
 * @SDE_PERF_SSPP_TS_PREFILL      Supports prefill with traffic shaper
 * @SDE_PERF_SSPP_TS_PREFILL_REC1 Supports prefill with traffic shaper multirec
 * @SDE_PERF_SSPP_CDP             Supports client driven prefetch
 * @SDE_PERF_SSPP_QOS_FL_NOCALC   Avoid fill level calc for QoS/danger/safe
 * @SDE_PERF_SSPP_SYS_CACHE,      SSPP supports system cache
 * @SDE_PERF_SSPP_UIDLE,          sspp supports uidle
 * @SDE_PERF_SSPP_MAX             Maximum value
@@ -271,7 +270,6 @@ enum {
	SDE_PERF_SSPP_TS_PREFILL,
	SDE_PERF_SSPP_TS_PREFILL_REC1,
	SDE_PERF_SSPP_CDP,
	SDE_PERF_SSPP_QOS_FL_NOCALC,
	SDE_PERF_SSPP_SYS_CACHE,
	SDE_PERF_SSPP_UIDLE,
	SDE_PERF_SSPP_MAX
@@ -568,26 +566,6 @@ enum sde_qos_lut_usage {
	SDE_QOS_LUT_USAGE_MAX,
};

/**
 * struct sde_qos_lut_entry - define QoS LUT table entry
 * @fl: fill level, or zero on last entry to indicate default lut
 * @lut: lut to use if equal to or less than fill level
 */
struct sde_qos_lut_entry {
	u32 fl;
	u64 lut;
};

/**
 * struct sde_qos_lut_tbl - define QoS LUT table
 * @nentry: number of entry in this table
 * @entries: Pointer to table entries
 */
struct sde_qos_lut_tbl {
	u32 nentry;
	struct sde_qos_lut_entry *entries;
};

/**
 * struct sde_sspp_sub_blks : SSPP sub-blocks
 * @maxdwnscale: max downscale ratio supported(without DECIMATION)
@@ -1154,9 +1132,11 @@ struct sde_sc_cfg {
 * @downscaling_prefill_lines  downscaling latency in lines
 * @amortizable_theshold minimum y position for traffic shaping prefill
 * @min_prefill_lines  minimum pipeline latency in lines
 * @danger_lut_tbl: LUT tables for danger signals
 * @sfe_lut_tbl: LUT tables for safe signals
 * @qos_lut_tbl: LUT tables for QoS signals
 * @danger_lut:		linear, macrotile, etc. danger luts
 * @safe_lut: linear, macrotile, macrotile_qseed, etc. safe luts
 * @creq_lut: linear, macrotile, non_realtime, cwb, etc. creq luts
 * @qos_refresh_count: total refresh count for possible different luts
 * @qos_refresh_rate: different refresh rates for luts
 * @cdp_cfg            cdp use case configurations
 * @cpu_mask:          pm_qos cpu mask value
 * @cpu_dma_latency:   pm_qos cpu dma latency value
@@ -1182,9 +1162,11 @@ struct sde_perf_cfg {
	u32 downscaling_prefill_lines;
	u32 amortizable_threshold;
	u32 min_prefill_lines;
	u32 danger_lut_tbl[SDE_QOS_LUT_USAGE_MAX];
	struct sde_qos_lut_tbl sfe_lut_tbl[SDE_QOS_LUT_USAGE_MAX];
	struct sde_qos_lut_tbl qos_lut_tbl[SDE_QOS_LUT_USAGE_MAX];
	u64 *danger_lut;
	u64 *safe_lut;
	u64 *creq_lut;
	u32 qos_refresh_count;
	u32 *qos_refresh_rate;
	struct sde_perf_cdp_cfg cdp_cfg[SDE_PERF_CDP_USAGE_MAX];
	u32 cpu_mask;
	u32 cpu_dma_latency;
@@ -1276,7 +1258,6 @@ struct sde_limit_cfg {
 * @has_qsync	       Supports qsync feature
 * @has_3d_merge_reset Supports 3D merge reset
 * @has_decimation     Supports decimation
 * @has_qos_fl_nocalc  flag to indicate QoS fill level needs no calculation
 * @update_tcsr_disp_glitch  flag to enable HW workaround to avoid spurious
 *                            transactions during suspend
 * @has_base_layer     Supports staging layer as base layer
@@ -1335,7 +1316,6 @@ struct sde_mdss_cfg {
	bool has_qsync;
	bool has_3d_merge_reset;
	bool has_decimation;
	bool has_qos_fl_nocalc;
	bool update_tcsr_disp_glitch;
	bool has_base_layer;

+3 −13
Original line number Diff line number Diff line
@@ -844,7 +844,7 @@ static void sde_hw_sspp_setup_solidfill(struct sde_hw_pipe *ctx, u32 color, enum
				color);
}

static void sde_hw_sspp_setup_danger_safe_lut(struct sde_hw_pipe *ctx,
static void sde_hw_sspp_setup_qos_lut(struct sde_hw_pipe *ctx,
		struct sde_hw_pipe_qos_cfg *cfg)
{
	u32 idx;
@@ -854,15 +854,6 @@ static void sde_hw_sspp_setup_danger_safe_lut(struct sde_hw_pipe *ctx,

	SDE_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT + idx, cfg->danger_lut);
	SDE_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT + idx, cfg->safe_lut);
}

static void sde_hw_sspp_setup_creq_lut(struct sde_hw_pipe *ctx,
		struct sde_hw_pipe_qos_cfg *cfg)
{
	u32 idx;

	if (_sspp_subblk_offset(ctx, SDE_SSPP_SRC, &idx))
		return;

	if (ctx->cap && test_bit(SDE_PERF_SSPP_QOS_8LVL,
				&ctx->cap->perf_features)) {
@@ -1224,9 +1215,8 @@ static void _setup_layer_ops(struct sde_hw_pipe *c,
		c->ops.setup_excl_rect = _sde_hw_sspp_setup_excl_rect;

	if (test_bit(SDE_PERF_SSPP_QOS, &features)) {
		c->ops.setup_danger_safe_lut =
			sde_hw_sspp_setup_danger_safe_lut;
		c->ops.setup_creq_lut = sde_hw_sspp_setup_creq_lut;
		c->ops.setup_qos_lut =
			sde_hw_sspp_setup_qos_lut;
		c->ops.setup_qos_ctrl = sde_hw_sspp_setup_qos_ctrl;
	}

+2 −11
Original line number Diff line number Diff line
@@ -460,21 +460,12 @@ struct sde_hw_sspp_ops {
				enum sde_sspp_multirect_index idx);

	/**
	 * setup_danger_safe_lut - setup danger safe LUTs
	 * setup_qos_lut - setup danger, safe, creq LUTs
	 * @ctx: Pointer to pipe context
	 * @cfg: Pointer to pipe QoS configuration
	 *
	 */
	void (*setup_danger_safe_lut)(struct sde_hw_pipe *ctx,
			struct sde_hw_pipe_qos_cfg *cfg);

	/**
	 * setup_creq_lut - setup CREQ LUT
	 * @ctx: Pointer to pipe context
	 * @cfg: Pointer to pipe QoS configuration
	 *
	 */
	void (*setup_creq_lut)(struct sde_hw_pipe *ctx,
	void (*setup_qos_lut)(struct sde_hw_pipe *ctx,
			struct sde_hw_pipe_qos_cfg *cfg);

	/**
Loading