Browse Source

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: Dhaval Patel <[email protected]>
Dhaval Patel 5 years ago
parent
commit
2843f86793

+ 26 - 42
msm/sde/sde_encoder_phys_wb.c

@@ -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);
 }
 
 /**

+ 149 - 184
msm/sde/sde_hw_catalog.c

@@ -213,25 +213,27 @@ 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,
+	QOS_CREQ_LUT_LINEAR,
+	QOS_CREQ_LUT_MACROTILE,
+	QOS_CREQ_LUT_NRT,
+	QOS_CREQ_LUT_CWB,
+	QOS_CREQ_LUT_MACROTILE_QSEED,
+	QOS_CREQ_LUT_LINEAR_QSEED,
+	QOS_PROP_MAX,
+};
+
 enum {
 	SSPP_OFF,
 	SSPP_SIZE,
@@ -562,37 +564,34 @@ 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,
-			PROP_TYPE_U32_ARRAY},
-	{PERF_SAFE_LUT_MACROTILE, "qcom,sde-safe-lut-macrotile", false,
-			PROP_TYPE_U32_ARRAY},
-	{PERF_SAFE_LUT_NRT, "qcom,sde-safe-lut-nrt", false,
-			PROP_TYPE_U32_ARRAY},
-	{PERF_SAFE_LUT_CWB, "qcom,sde-safe-lut-cwb", 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_QOS_LUT_LINEAR, "qcom,sde-qos-lut-linear", 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},
-	{PERF_QOS_LUT_MACROTILE, "qcom,sde-qos-lut-macrotile", false,
+	{QOS_DANGER_LUT, "qcom,sde-danger-lut", false, PROP_TYPE_U32_ARRAY},
+	{QOS_SAFE_LUT, "qcom,sde-safe-lut", 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",
+	{QOS_CREQ_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_LINEAR_QSEED, "qcom,sde-qos-lut-linear-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[] = {
@@ -3814,172 +3813,111 @@ 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[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;
 
-	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] =
+		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] = {
-			[SDE_QOS_LUT_USAGE_LINEAR] =
-					PERF_SAFE_LUT_LINEAR,
-			[SDE_QOS_LUT_USAGE_MACROTILE] =
-					PERF_SAFE_LUT_MACROTILE,
-			[SDE_QOS_LUT_USAGE_NRT] =
-					PERF_SAFE_LUT_NRT,
-			[SDE_QOS_LUT_USAGE_CWB] =
-					PERF_SAFE_LUT_CWB,
-			[SDE_QOS_LUT_USAGE_MACROTILE_QSEED] =
-					PERF_SAFE_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.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;
 
-		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;
+	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 (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);
+	if (prop_exists[QOS_SAFE_LUT] &&
+	    prop_count[QOS_SAFE_LUT] >= (SDE_QOS_LUT_USAGE_MAX * qos_count)) {
+		for (i = 0; i < prop_count[QOS_SAFE_LUT]; i++) {
+			cfg->perf.safe_lut[i] =
+				PROP_VALUE_ACCESS(prop_value,
+					QOS_SAFE_LUT, i);
+			SDE_DEBUG("safe usage:%d lut:0x%x\n",
+				i, cfg->perf.safe_lut[i]);
 		}
-		cfg->perf.sfe_lut_tbl[j].nentry = count;
 	}
 
-	for (j = 0; j < SDE_QOS_LUT_USAGE_MAX; j++) {
+	for (i = 0; i < SDE_QOS_LUT_USAGE_MAX; i++) {
 		static const u32 prop_key[SDE_QOS_LUT_USAGE_MAX] = {
 			[SDE_QOS_LUT_USAGE_LINEAR] =
-					PERF_QOS_LUT_LINEAR,
+					QOS_CREQ_LUT_LINEAR,
 			[SDE_QOS_LUT_USAGE_MACROTILE] =
-					PERF_QOS_LUT_MACROTILE,
+					QOS_CREQ_LUT_MACROTILE,
 			[SDE_QOS_LUT_USAGE_NRT] =
-					PERF_QOS_LUT_NRT,
+					QOS_CREQ_LUT_NRT,
 			[SDE_QOS_LUT_USAGE_CWB] =
-					PERF_QOS_LUT_CWB,
+					QOS_CREQ_LUT_CWB,
 			[SDE_QOS_LUT_USAGE_MACROTILE_QSEED] =
-					PERF_QOS_LUT_MACROTILE_QSEED,
+					QOS_CREQ_LUT_MACROTILE_QSEED,
+			[SDE_QOS_LUT_USAGE_LINEAR_QSEED] =
+					QOS_CREQ_LUT_LINEAR_QSEED,
 		};
-		const u32 entry_size = 3;
-		int m, count;
-		int key = prop_key[j];
+		int key = prop_key[i];
+		u64 lut_hi, lut_lo;
 
 		if (!prop_exists[key])
 			continue;
 
-		count = prop_count[key] / entry_size;
-
-		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 =
+		for (j = 0; j < qos_count; j++) {
+			lut_hi = PROP_VALUE_ACCESS(prop_value, key,
+				(j * 2) + 0);
+			lut_lo = PROP_VALUE_ACCESS(prop_value, key,
+				(j * 2) + 1);
+			index = (j * SDE_QOS_LUT_USAGE_MAX) + i;
+			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);
+			SDE_DEBUG("creq usage:%d lut:0x%llx\n",
+				index, cfg->perf.creq_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,
@@ -4088,11 +4026,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;
@@ -4163,6 +4096,43 @@ end:
 	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)
 {
@@ -4456,7 +4426,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;
 		sde_cfg->has_decimation = true;
 		sde_cfg->vbif_disable_inner_outer_shareable = true;
@@ -4483,7 +4452,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;
 		sde_cfg->has_hdr = true;
 		sde_cfg->has_vig_p010 = true;
@@ -4501,7 +4469,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;
 		sde_cfg->vbif_disable_inner_outer_shareable = true;
 	} else if (IS_KONA_TARGET(hw_rev)) {
@@ -4517,7 +4484,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;
 		sde_cfg->has_hdr = true;
 		sde_cfg->has_hdr_plus = true;
@@ -4539,7 +4505,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;
 		sde_cfg->has_hdr = true;
 		sde_cfg->has_hdr_plus = true;
@@ -4631,10 +4596,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;
@@ -4712,10 +4673,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);
@@ -4755,6 +4716,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;

+ 11 - 30
msm/sde/sde_hw_catalog.h

@@ -270,7 +270,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
@@ -281,7 +280,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
@@ -640,29 +638,10 @@ enum sde_qos_lut_usage {
 	SDE_QOS_LUT_USAGE_NRT,
 	SDE_QOS_LUT_USAGE_CWB,
 	SDE_QOS_LUT_USAGE_MACROTILE_QSEED,
+	SDE_QOS_LUT_USAGE_LINEAR_QSEED,
 	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)
@@ -1302,9 +1281,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: liner, linear_qseed, macrotile, etc. danger luts
+ * @sfe_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
@@ -1330,9 +1311,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;
@@ -1422,7 +1405,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
  * @has_mixer_combined_alpha     Mixer has single register for FG & BG alpha
  * @vbif_disable_inner_outer_shareable     VBIF requires disabling shareables
  * @inline_disable_const_clr     Disable constant color during inline rotate
@@ -1483,7 +1465,6 @@ struct sde_mdss_cfg {
 	bool has_qsync;
 	bool has_3d_merge_reset;
 	bool has_decimation;
-	bool has_qos_fl_nocalc;
 	bool has_mixer_combined_alpha;
 	bool vbif_disable_inner_outer_shareable;
 	bool inline_disable_const_clr;

+ 3 - 13
msm/sde/sde_hw_sspp.c

@@ -841,7 +841,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;
@@ -851,15 +851,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)) {
@@ -1230,9 +1221,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;
 	}
 

+ 3 - 12
msm/sde/sde_hw_sspp.h

@@ -1,6 +1,6 @@
 /* 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.
  */
 
 #ifndef _SDE_HW_SSPP_H
@@ -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);
 
 	/**

+ 12 - 33
msm/sde/sde_hw_wb.c

@@ -81,13 +81,14 @@ static void _sde_hw_cwb_ctrl_init(struct sde_mdss_cfg *m,
 	u32 blk_off;
 	char name[64] = {0};
 
-	if (b) {
-		b->base_off = addr;
-		b->blk_off = m->cwb_blk_off;
-		b->length = 0x20;
-		b->hwversion = m->hwversion;
-		b->log_mask = SDE_DBG_MASK_WB;
-	}
+	if (!b)
+		return;
+
+	b->base_off = addr;
+	b->blk_off = m->cwb_blk_off;
+	b->length = 0x20;
+	b->hwversion = m->hwversion;
+	b->log_mask = SDE_DBG_MASK_WB;
 
 	for (i = 0; i < m->pingpong_count; i++) {
 		snprintf(name, sizeof(name), "cwb%d", i);
@@ -207,40 +208,22 @@ static void sde_hw_wb_roi(struct sde_hw_wb *ctx, struct sde_hw_wb_cfg *wb)
 	SDE_REG_WRITE(c, WB_OUT_SIZE, out_size);
 }
 
-static void sde_hw_wb_setup_danger_safe_lut(struct sde_hw_wb *ctx,
+static void sde_hw_wb_setup_qos_lut(struct sde_hw_wb *ctx,
 		struct sde_hw_wb_qos_cfg *cfg)
 {
 	struct sde_hw_blk_reg_map *c = &ctx->hw;
+	u32 qos_ctrl = 0;
 
 	if (!ctx || !cfg)
 		return;
 
 	SDE_REG_WRITE(c, WB_DANGER_LUT, cfg->danger_lut);
 	SDE_REG_WRITE(c, WB_SAFE_LUT, cfg->safe_lut);
-}
-
-static void sde_hw_wb_setup_creq_lut(struct sde_hw_wb *ctx,
-		struct sde_hw_wb_qos_cfg *cfg)
-{
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
-
-	if (!ctx || !cfg)
-		return;
 
 	if (ctx->caps && test_bit(SDE_WB_QOS_8LVL, &ctx->caps->features)) {
 		SDE_REG_WRITE(c, WB_CREQ_LUT_0, cfg->creq_lut);
 		SDE_REG_WRITE(c, WB_CREQ_LUT_1, cfg->creq_lut >> 32);
 	}
-}
-
-static void sde_hw_wb_setup_qos_ctrl(struct sde_hw_wb *ctx,
-		struct sde_hw_wb_qos_cfg *cfg)
-{
-	struct sde_hw_blk_reg_map *c = &ctx->hw;
-	u32 qos_ctrl = 0;
-
-	if (!ctx || !cfg)
-		return;
 
 	if (cfg->danger_safe_en)
 		qos_ctrl |= WB_QOS_CTRL_DANGER_SAFE_EN;
@@ -318,12 +301,8 @@ static void _setup_wb_ops(struct sde_hw_wb_ops *ops,
 	if (test_bit(SDE_WB_XY_ROI_OFFSET, &features))
 		ops->setup_roi = sde_hw_wb_roi;
 
-	if (test_bit(SDE_WB_QOS, &features)) {
-		ops->setup_danger_safe_lut =
-			sde_hw_wb_setup_danger_safe_lut;
-		ops->setup_creq_lut = sde_hw_wb_setup_creq_lut;
-		ops->setup_qos_ctrl = sde_hw_wb_setup_qos_ctrl;
-	}
+	if (test_bit(SDE_WB_QOS, &features))
+		ops->setup_qos_lut = sde_hw_wb_setup_qos_lut;
 
 	if (test_bit(SDE_WB_CDP, &features))
 		ops->setup_cdp = sde_hw_wb_setup_cdp;

+ 3 - 19
msm/sde/sde_hw_wb.h

@@ -1,6 +1,6 @@
 /* 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.
  */
 
 #ifndef _SDE_HW_WB_H
@@ -89,27 +89,11 @@ struct sde_hw_wb_ops {
 		struct sde_hw_wb_cfg *wb);
 
 	/**
-	 * setup_danger_safe_lut - setup danger safe LUTs
+	 * setup_qos_lut - setup danger, safe, creq, etc. LUTs
 	 * @ctx: Pointer to pipe context
 	 * @cfg: Pointer to pipe QoS configuration
 	 */
-	void (*setup_danger_safe_lut)(struct sde_hw_wb *ctx,
-			struct sde_hw_wb_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_wb *ctx,
-			struct sde_hw_wb_qos_cfg *cfg);
-
-	/**
-	 * setup_qos_ctrl - setup QoS control
-	 * @ctx: Pointer to pipe context
-	 * @cfg: Pointer to pipe QoS configuration
-	 */
-	void (*setup_qos_ctrl)(struct sde_hw_wb *ctx,
+	void (*setup_qos_lut)(struct sde_hw_wb *ctx,
 			struct sde_hw_wb_qos_cfg *cfg);
 
 	/**

+ 44 - 205
msm/sde/sde_plane.c

@@ -235,248 +235,88 @@ void sde_plane_setup_src_split_order(struct drm_plane *plane,
 }
 
 /**
- * _sde_plane_calc_fill_level - calculate fill level of the given source format
- * @plane:		Pointer to drm plane
- * @fmt:		Pointer to source buffer format
- * @src_wdith:		width of source buffer
- * Return: fill level corresponding to the source buffer/format or 0 if error
- */
-static inline int _sde_plane_calc_fill_level(struct drm_plane *plane,
-		const struct sde_format *fmt, u32 src_width)
-{
-	struct sde_plane *psde, *tmp;
-	struct sde_plane_state *pstate;
-	u32 fixed_buff_size;
-	u32 total_fl;
-	u32 hflip_bytes;
-	u32 unused_space;
-
-	if (!plane || !fmt || !plane->state || !src_width || !fmt->bpp) {
-		SDE_ERROR("invalid arguments\n");
-		return 0;
-	}
-
-	psde = to_sde_plane(plane);
-	if (psde->perf_features & BIT(SDE_PERF_SSPP_QOS_FL_NOCALC))
-		return 0;
-
-	pstate = to_sde_plane_state(plane->state);
-	fixed_buff_size = psde->pipe_sblk->pixel_ram_size;
-
-	list_for_each_entry(tmp, &psde->mplane_list, mplane_list) {
-		if (!sde_plane_enabled(tmp->base.state))
-			continue;
-		SDE_DEBUG("plane%d/%d src_width:%d/%d\n",
-				psde->base.base.id, tmp->base.base.id,
-				src_width, tmp->pipe_cfg.src_rect.w);
-		src_width = max_t(u32, src_width, tmp->pipe_cfg.src_rect.w);
-	}
-
-	if ((pstate->rotation & DRM_MODE_REFLECT_X) &&
-			SDE_FORMAT_IS_LINEAR(fmt))
-		hflip_bytes = (src_width + 32) * fmt->bpp;
-	else
-		hflip_bytes = 0;
-
-	if (fmt->fetch_planes == SDE_PLANE_PSEUDO_PLANAR) {
-
-		unused_space = 23 * 128;
-		if (fmt->chroma_sample == SDE_CHROMA_420) {
-			/* NV12 */
-			total_fl = (fixed_buff_size / 2 - hflip_bytes -
-				unused_space) / ((src_width + 32) * fmt->bpp);
-		} else {
-			/* non NV12 */
-			total_fl = (fixed_buff_size / 2 - hflip_bytes -
-				unused_space) * 2 / ((src_width + 32) *
-				fmt->bpp);
-		}
-	} else {
-
-		unused_space = 6 * 128;
-		if (pstate->multirect_mode == SDE_SSPP_MULTIRECT_PARALLEL) {
-			total_fl = (fixed_buff_size / 2 - hflip_bytes -
-				unused_space) * 2 / ((src_width + 32) *
-				fmt->bpp);
-		} else {
-			total_fl = (fixed_buff_size - hflip_bytes -
-				unused_space) * 2 / ((src_width + 32) *
-				fmt->bpp);
-		}
-	}
-
-	SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s w:%u hf:%d us:%d fl:%u\n",
-			plane->base.id, psde->pipe - SSPP_VIG0,
-			(char *)&fmt->base.pixel_format,
-			src_width, hflip_bytes, unused_space, total_fl);
-
-	return total_fl;
-}
-
-/**
- * _sde_plane_get_qos_lut - get LUT mapping based on fill level
- * @tbl:		Pointer to LUT table
- * @total_fl:		fill level
- * Return: LUT setting corresponding to the fill level
- */
-static u64 _sde_plane_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_plane_set_qos_lut - set QoS LUT of the given plane
+ * _sde_plane_set_qos_lut - set danger, safe and creq LUT of the given plane
  * @plane:		Pointer to drm plane
+ * @crtc:		Pointer to drm crtc to find refresh rate on mode
  * @fb:			Pointer to framebuffer associated with the given plane
  */
 static void _sde_plane_set_qos_lut(struct drm_plane *plane,
+		struct drm_crtc *crtc,
 		struct drm_framebuffer *fb)
 {
 	struct sde_plane *psde;
 	const struct sde_format *fmt = NULL;
-	u64 qos_lut;
-	u32 total_fl = 0, lut_usage;
+	u32 frame_rate, qos_count, fps_index = 0, lut_index, index;
+	struct sde_perf_cfg *perf;
+	struct sde_plane_state *pstate;
 
 	if (!plane || !fb) {
-		SDE_ERROR("invalid arguments plane %d fb %d\n",
-				!plane, !fb);
+		SDE_ERROR("invalid arguments\n");
 		return;
 	}
 
 	psde = to_sde_plane(plane);
+	pstate = to_sde_plane_state(plane->state);
 
 	if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
 		SDE_ERROR("invalid arguments\n");
 		return;
-	} else if (!psde->pipe_hw->ops.setup_creq_lut) {
+	} else if (!psde->pipe_hw->ops.setup_qos_lut) {
 		return;
 	}
 
-	if (!psde->is_rt_pipe) {
-		lut_usage = SDE_QOS_LUT_USAGE_NRT;
-	} else {
-		fmt = sde_get_sde_format_ext(
-				fb->format->format,
-				fb->modifier);
-		total_fl = _sde_plane_calc_fill_level(plane, fmt,
-				psde->pipe_cfg.src_rect.w);
-
-		if (fmt && SDE_FORMAT_IS_LINEAR(fmt))
-			lut_usage = SDE_QOS_LUT_USAGE_LINEAR;
-		else if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3) ||
-			psde->features & BIT(SDE_SSPP_SCALER_QSEED3LITE))
-			lut_usage = SDE_QOS_LUT_USAGE_MACROTILE_QSEED;
-		else
-			lut_usage = SDE_QOS_LUT_USAGE_MACROTILE;
-	}
-
-	qos_lut = _sde_plane_get_qos_lut(
-			&psde->catalog->perf.qos_lut_tbl[lut_usage], total_fl);
-
-	psde->pipe_qos_cfg.creq_lut = qos_lut;
-
-	trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
-			(fmt) ? fmt->base.pixel_format : 0,
-			psde->is_rt_pipe, total_fl, qos_lut, lut_usage);
-
-	SDE_DEBUG("plane%u: pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",
-			plane->base.id,
-			psde->pipe - SSPP_VIG0,
-			fmt ? (char *)&fmt->base.pixel_format : NULL,
-			psde->is_rt_pipe, total_fl, qos_lut);
-
-	psde->pipe_hw->ops.setup_creq_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
-}
-
-/**
- * _sde_plane_set_panic_lut - set danger/safe LUT of the given plane
- * @plane:		Pointer to drm plane
- * @fb:			Pointer to framebuffer associated with the given plane
- */
-static void _sde_plane_set_danger_lut(struct drm_plane *plane,
-		struct drm_framebuffer *fb)
-{
-	struct sde_plane *psde;
-	const struct sde_format *fmt = NULL;
-	u32 danger_lut, safe_lut;
-	u32 total_fl = 0, lut_usage;
-
-	if (!plane || !fb) {
-		SDE_ERROR("invalid arguments\n");
-		return;
-	}
-
-	psde = to_sde_plane(plane);
-
-	if (!psde->pipe_hw || !psde->pipe_sblk || !psde->catalog) {
-		SDE_ERROR("invalid arguments\n");
-		return;
-	} else if (!psde->pipe_hw->ops.setup_danger_safe_lut) {
-		return;
+	frame_rate = crtc->mode.vrefresh;
+	perf = &psde->catalog->perf;
+	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--;
 	}
 
 	if (!psde->is_rt_pipe) {
-		danger_lut = psde->catalog->perf.danger_lut_tbl
-				[SDE_QOS_LUT_USAGE_NRT];
-		lut_usage = SDE_QOS_LUT_USAGE_NRT;
+		lut_index = SDE_QOS_LUT_USAGE_NRT;
 	} else {
 		fmt = sde_get_sde_format_ext(
 				fb->format->format,
 				fb->modifier);
-		total_fl = _sde_plane_calc_fill_level(plane, fmt,
-				psde->pipe_cfg.src_rect.w);
-
-		if (fmt && SDE_FORMAT_IS_LINEAR(fmt)) {
-			danger_lut = psde->catalog->perf.danger_lut_tbl
-					[SDE_QOS_LUT_USAGE_LINEAR];
-			lut_usage = SDE_QOS_LUT_USAGE_LINEAR;
-		} else if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
-			danger_lut = psde->catalog->perf.danger_lut_tbl
-					[SDE_QOS_LUT_USAGE_MACROTILE_QSEED];
-			lut_usage = SDE_QOS_LUT_USAGE_MACROTILE_QSEED;
-		} else {
-			danger_lut = psde->catalog->perf.danger_lut_tbl
-					[SDE_QOS_LUT_USAGE_MACROTILE];
-			lut_usage = SDE_QOS_LUT_USAGE_MACROTILE;
-		}
-	}
 
-	safe_lut = (u32) _sde_plane_get_qos_lut(
-			&psde->catalog->perf.sfe_lut_tbl[lut_usage], total_fl);
+		if (fmt && SDE_FORMAT_IS_LINEAR(fmt) &&
+		    pstate->scaler3_cfg.enable)
+			lut_index = SDE_QOS_LUT_USAGE_LINEAR_QSEED;
+		else if (fmt && SDE_FORMAT_IS_LINEAR(fmt))
+			lut_index = SDE_QOS_LUT_USAGE_LINEAR;
+		else if (pstate->scaler3_cfg.enable)
+			lut_index = SDE_QOS_LUT_USAGE_MACROTILE_QSEED;
+		else
+			lut_index = SDE_QOS_LUT_USAGE_MACROTILE;
+	}
 
-	psde->pipe_qos_cfg.danger_lut = danger_lut;
-	psde->pipe_qos_cfg.safe_lut = safe_lut;
+	index = (fps_index * SDE_QOS_LUT_USAGE_MAX) + lut_index;
+	psde->pipe_qos_cfg.danger_lut = perf->danger_lut[index];
+	psde->pipe_qos_cfg.safe_lut = perf->safe_lut[index];
+	psde->pipe_qos_cfg.creq_lut = perf->creq_lut[index];
 
-	trace_sde_perf_set_danger_luts(psde->pipe - SSPP_VIG0,
+	trace_sde_perf_set_qos_luts(psde->pipe - SSPP_VIG0,
 			(fmt) ? fmt->base.pixel_format : 0,
 			(fmt) ? fmt->fetch_mode : 0,
 			psde->pipe_qos_cfg.danger_lut,
-			psde->pipe_qos_cfg.safe_lut);
+			psde->pipe_qos_cfg.safe_lut,
+			psde->pipe_qos_cfg.creq_lut);
 
-	SDE_DEBUG("plane%u: pnum:%d fmt:%4.4s mode:%d fl:%d luts[0x%x,0x%x]\n",
+	SDE_DEBUG(
+		"plane%u: pnum:%d fmt:%4.4s fps:%d mode:%d luts[0x%x,0x%x 0x%llx]\n",
 		plane->base.id,
 		psde->pipe - SSPP_VIG0,
-		fmt ? (char *)&fmt->base.pixel_format : NULL,
-		fmt ? fmt->fetch_mode : -1, total_fl,
+		fmt ? (char *)&fmt->base.pixel_format : NULL, frame_rate,
+		fmt ? fmt->fetch_mode : -1,
 		psde->pipe_qos_cfg.danger_lut,
-		psde->pipe_qos_cfg.safe_lut);
+		psde->pipe_qos_cfg.safe_lut,
+		psde->pipe_qos_cfg.creq_lut);
 
-	psde->pipe_hw->ops.setup_danger_safe_lut(psde->pipe_hw,
-			&psde->pipe_qos_cfg);
+	psde->pipe_hw->ops.setup_qos_lut(psde->pipe_hw, &psde->pipe_qos_cfg);
 }
 
 /**
@@ -3202,8 +3042,7 @@ static void _sde_plane_update_properties(struct drm_plane *plane,
 		psde->pipe_hw->ops.setup_sharpening)
 		_sde_plane_update_sharpening(psde);
 
-	_sde_plane_set_qos_lut(plane, fb);
-	_sde_plane_set_danger_lut(plane, fb);
+	_sde_plane_set_qos_lut(plane, crtc, fb);
 
 	if (plane->type != DRM_PLANE_TYPE_CURSOR) {
 		_sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);

+ 7 - 31
msm/sde/sde_trace.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2014-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
  */
 
 #if !defined(_SDE_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
@@ -16,41 +16,16 @@
 #define TRACE_INCLUDE_FILE sde_trace
 
 TRACE_EVENT(sde_perf_set_qos_luts,
-	TP_PROTO(u32 pnum, u32 fmt, bool rt, u32 fl,
-		u32 lut, u32 lut_usage),
-	TP_ARGS(pnum, fmt, rt, fl, lut, lut_usage),
-	TP_STRUCT__entry(
-			__field(u32, pnum)
-			__field(u32, fmt)
-			__field(bool, rt)
-			__field(u32, fl)
-			__field(u64, lut)
-			__field(u32, lut_usage)
-	),
-	TP_fast_assign(
-			__entry->pnum = pnum;
-			__entry->fmt = fmt;
-			__entry->rt = rt;
-			__entry->fl = fl;
-			__entry->lut = lut;
-			__entry->lut_usage = lut_usage;
-	),
-	TP_printk("pnum=%d fmt=0x%x rt=%d fl=%d lut=0x%llx lut_usage=%d",
-			__entry->pnum, __entry->fmt,
-			__entry->rt, __entry->fl,
-			__entry->lut, __entry->lut_usage)
-);
-
-TRACE_EVENT(sde_perf_set_danger_luts,
 	TP_PROTO(u32 pnum, u32 fmt, u32 mode, u32 danger_lut,
-		u32 safe_lut),
-	TP_ARGS(pnum, fmt, mode, danger_lut, safe_lut),
+		u32 safe_lut, u64 creq_lut),
+	TP_ARGS(pnum, fmt, mode, danger_lut, safe_lut, creq_lut),
 	TP_STRUCT__entry(
 			__field(u32, pnum)
 			__field(u32, fmt)
 			__field(u32, mode)
 			__field(u32, danger_lut)
 			__field(u32, safe_lut)
+			__field(u64, creq_lut)
 	),
 	TP_fast_assign(
 			__entry->pnum = pnum;
@@ -58,11 +33,12 @@ TRACE_EVENT(sde_perf_set_danger_luts,
 			__entry->mode = mode;
 			__entry->danger_lut = danger_lut;
 			__entry->safe_lut = safe_lut;
+			__entry->creq_lut = creq_lut;
 	),
-	TP_printk("pnum=%d fmt=0x%x mode=%d luts[0x%x, 0x%x]",
+	TP_printk("pnum=%d fmt=0x%x mode=%d luts[0x%x, 0x%x 0x%llx]",
 			__entry->pnum, __entry->fmt,
 			__entry->mode, __entry->danger_lut,
-			__entry->safe_lut)
+			__entry->safe_lut, __entry->creq_lut)
 );
 
 TRACE_EVENT(sde_perf_set_ot,