ソースを参照

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

qctecmdr 5 年 前
コミット
8a690a0b80

+ 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,
@@ -566,37 +568,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[] = {
@@ -3830,172 +3829,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,
@@ -4104,11 +4042,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;
@@ -4179,6 +4112,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)
 {
@@ -4472,7 +4442,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;
@@ -4499,7 +4468,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;
@@ -4517,7 +4485,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)) {
@@ -4533,7 +4500,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;
@@ -4555,7 +4521,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;
@@ -4647,10 +4612,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;
@@ -4728,10 +4689,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);
@@ -4771,6 +4732,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,