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

Commit f2163420 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "disp: msm: sde: support fps based qos setting"

parents 83874a18 8c0376ae
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