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

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

Merge "ARM: dts: msm: add dt nodes for sde limits for atoll target"

parents 1f78cf85 4b6306bc
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -448,6 +448,15 @@ Optional properties:
- qcom,sde-axi-bus-width:	A u32 property to indicate the axi bus width value in bytes
- qcom,sde-mixer-stage-base-layer: A boolean property to indicate if a layer can be staged on base
				stage instead of border fill
- qcom,sde-limits:		A node that lists the limits for different properties. This node
				can have multiple child nodes. Each child node represents a
				specific usecase limit. The usecase can be defined for properties like
				sspp linewidth, bw limit etc.
				e.g. qcom,sde-limits
				-- qcom,sde-limit-name: name of the usecase
				-- qcom,sde-limit-cases: different usecases to be considered
				-- qcom,sde-limit-ids: respective ids for the above usecases
				-- qcom,sde-limit-values: usecase and value for different combinations

Bus Scaling Subnodes:
- qcom,sde-reg-bus:		Property to provide Bus scaling for register access for
@@ -771,6 +780,34 @@ Example:
        qcom,sde-dspp-vlut = <0x0 0x00010000>;
    };

   qcom,sde-limits {
	qcom,sde-linewidth-limits{
		qcom,sde-limit-cases = "vig", "dma", "scaling", "inline_rot";
		qcom,sde-limit-ids= <0x1 0x2 0x4 0x8>;
		/* the qcom,sde-limit-values property consist of two values:
		one for the usecase and the other for the value. The usecase can be
		any combination of the values mentioned in qcom,sde-limit-ids.
		For eg: <0x5 2560> means usecase is 0x5 and value is 2560.
		0x5 = (0x1 | 0x4) = vig + scaling. Thus the linewidth for usecase
		vig + scaling  = 2560 */
		qcom,sde-limit-values = <0x1 4096>,
					<0x5 2560>,
					<0xd 1088>,
					<0x2 4096>;
	};
       qcom,sde-bw-limits{
		qcom,sde-limit-cases = "per_pipe", "total_bw", "vfe_on", "cwb_on";
		qcom,sde-limit-ids = <0x1 0x2 0x4 0x8>;
		qcom,sde-limit-values = <0x1 2600000>,
					<0x9 2600000>,
					<0x5 2600000>,
					<0xd 2600000>,
					<0x2 5800000>,
					<0xa 5500000>,
					<0x6 4400000>,
					<0xe 3900000>;
	};
    };
    qcom,sde-mixer-blocks {
        qcom,sde-mixer-gc = <0x3c0 0x00010000>;
    };
+32 −0
Original line number Diff line number Diff line
@@ -274,6 +274,38 @@
				<1 590 0 150000>,
				<1 590 0 300000>;
		};

		qcom,sde-limits {
			qcom,sde-linewidth-limits{
				qcom,sde-limit-name = "sspp_linewidth_usecases";
				qcom,sde-limit-cases = "vig", "dma", "scale";
				qcom,sde-limit-ids= <0x1 0x2 0x4>;
				qcom,sde-limit-values = <0x1 4096>,
							<0x5 2560>,
							<0x2 2160>;
			};
			qcom,sde-bw-limits{
				qcom,sde-limit-name = "sde_bwlimit_usecases";
				qcom,sde-limit-cases = "per_vig_pipe",
							"per_dma_pipe",
							"total_max_bw",
							"camera_concurrency",
							"cwb_concurrency";
				qcom,sde-limit-ids = <0x1 0x2 0x4 0x8 0x10>;
				qcom,sde-limit-values = <0x1 2600000>,
							<0x11 2600000>,
							<0x9 2600000>,
							<0x19 2600000>,
							<0x2 2600000>,
							<0x12 2600000>,
							<0xa 2600000>,
							<0x1a 2600000>,
							<0x4 5800000>,
							<0x14 5500000>,
							<0xc 4400000>,
							<0x1c 3900000>;
			};
		};
	};

	sde_rscc: qcom,sde_rscc@af20000 {
+33 −0
Original line number Diff line number Diff line
@@ -5589,6 +5589,8 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
	struct drm_device *dev;
	struct sde_kms_info *info;
	struct sde_kms *sde_kms;
	int i, j;

	static const struct drm_prop_enum_list e_secure_level[] = {
		{SDE_DRM_SEC_NON_SEC, "sec_and_non_sec"},
		{SDE_DRM_SEC_ONLY, "sec_only"},
@@ -5800,6 +5802,37 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc,
	if (sde_kms->perf.max_core_clk_rate)
		sde_kms_info_add_keyint(info, "max_mdp_clk",
				sde_kms->perf.max_core_clk_rate);

	for (i = 0; i < catalog->limit_count; i++) {
		sde_kms_info_add_keyint(info,
			catalog->limit_cfg[i].name,
			catalog->limit_cfg[i].lmt_case_cnt);

		for (j = 0; j < catalog->limit_cfg[i].lmt_case_cnt; j++) {
			sde_kms_info_add_keyint(info,
				catalog->limit_cfg[i].vector_cfg[j].usecase,
				catalog->limit_cfg[i].vector_cfg[j].value);
		}

		if (!strcmp(catalog->limit_cfg[i].name,
			"sspp_linewidth_usecases"))
			sde_kms_info_add_keyint(info,
				"sspp_linewidth_values",
				catalog->limit_cfg[i].lmt_vec_cnt);
		else if (!strcmp(catalog->limit_cfg[i].name,
				"sde_bwlimit_usecases"))
			sde_kms_info_add_keyint(info,
				"sde_bwlimit_values",
				catalog->limit_cfg[i].lmt_vec_cnt);

		for (j = 0; j < catalog->limit_cfg[i].lmt_vec_cnt; j++) {
			sde_kms_info_add_keyint(info, "limit_usecase",
				catalog->limit_cfg[i].value_cfg[j].use_concur);
			sde_kms_info_add_keyint(info, "limit_value",
				catalog->limit_cfg[i].value_cfg[j].value);
		}
	}

	sde_kms_info_add_keystr(info, "core_ib_ff",
			catalog->perf.core_ib_ff);
	sde_kms_info_add_keystr(info, "core_clk_ff",
+169 −0
Original line number Diff line number Diff line
@@ -173,6 +173,7 @@ enum sde_prop {
	SEC_SID_MASK,
	LINE_INSERTION,
	BASE_LAYER,
	SDE_LIMITS,
	SDE_PROP_MAX,
};

@@ -267,6 +268,14 @@ enum {
	INTF_PROP_MAX,
};

enum {
	LIMIT_NAME,
	LIMIT_USECASE,
	LIMIT_ID,
	LIMIT_VALUE,
	LIMIT_PROP_MAX,
};

enum {
	PP_OFF,
	PP_LEN,
@@ -463,6 +472,7 @@ static struct sde_prop_type sde_prop[] = {
	{SEC_SID_MASK, "qcom,sde-secure-sid-mask", false, PROP_TYPE_U32_ARRAY},
	{LINE_INSERTION, "qcom,sde-has-line-insertion", false, PROP_TYPE_BOOL},
	{BASE_LAYER, "qcom,sde-mixer-stage-base-layer", false, PROP_TYPE_BOOL},
	{SDE_LIMITS, "qcom,sde-limits", false, PROP_TYPE_NODE},
};

static struct sde_prop_type sde_perf_prop[] = {
@@ -745,6 +755,14 @@ static struct sde_prop_type inline_rot_prop[INLINE_ROT_PROP_MAX] = {
						PROP_TYPE_BIT_OFFSET_ARRAY},
};

static struct sde_prop_type limit_usecase_prop[] = {
	{LIMIT_NAME, "qcom,sde-limit-name", false, PROP_TYPE_STRING},
	{LIMIT_USECASE, "qcom,sde-limit-cases", false, PROP_TYPE_STRING_ARRAY},
	{LIMIT_ID, "qcom,sde-limit-ids", false, PROP_TYPE_U32_ARRAY},
	{LIMIT_VALUE, "qcom,sde-limit-values", false,
				PROP_TYPE_BIT_OFFSET_ARRAY},
};

/*************************************************************
 * static API list
 *************************************************************/
@@ -2935,6 +2953,148 @@ static int sde_pp_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg)
	return rc;
}

static int sde_read_limit_node(struct device_node *snp,
	struct sde_prop_value *lmt_val, struct sde_mdss_cfg *cfg)
{
	int j, i = 0, rc = 0;
	const char *type = NULL;
	struct device_node *node = NULL;

	for_each_child_of_node(snp, node) {
		cfg->limit_cfg[i].vector_cfg =
			kcalloc(cfg->limit_cfg[i].lmt_case_cnt,
				sizeof(struct limit_vector_cfg), GFP_KERNEL);
		if (!cfg->limit_cfg[i].vector_cfg) {
			rc = -ENOMEM;
			goto error;
		}

		for (j = 0; j < cfg->limit_cfg[i].lmt_case_cnt; j++) {
			of_property_read_string_index(node,
				limit_usecase_prop[LIMIT_USECASE].prop_name,
				j, &type);
			cfg->limit_cfg[i].vector_cfg[j].usecase = type;
			cfg->limit_cfg[i].vector_cfg[j].value =
				PROP_VALUE_ACCESS(&lmt_val[i * LIMIT_PROP_MAX],
				LIMIT_ID, j);
		}

		cfg->limit_cfg[i].value_cfg =
				kcalloc(cfg->limit_cfg[i].lmt_vec_cnt,
				sizeof(struct limit_value_cfg), GFP_KERNEL);

		if (!cfg->limit_cfg[i].value_cfg) {
			rc = -ENOMEM;
			goto error;
		}

		for (j = 0; j < cfg->limit_cfg[i].lmt_vec_cnt; j++) {
			cfg->limit_cfg[i].value_cfg[j].use_concur =
				PROP_BITVALUE_ACCESS(
					&lmt_val[i * LIMIT_PROP_MAX],
					LIMIT_VALUE, j, 0);
			cfg->limit_cfg[i].value_cfg[j].value =
				PROP_BITVALUE_ACCESS(
					&lmt_val[i * LIMIT_PROP_MAX],
					LIMIT_VALUE, j, 1);
		}
		i++;
	}

	return 0;
error:
	for (j = 0; j < cfg->limit_count; j++) {
		kfree(cfg->limit_cfg[j].vector_cfg);
		kfree(cfg->limit_cfg[j].value_cfg);
	}

	cfg->limit_count = 0;
	return rc;
}

static int sde_validate_limit_node(struct device_node *snp,
	struct sde_prop_value *sde_limit_value, struct sde_mdss_cfg *cfg)
{
	int i = 0, rc = 0;
	struct device_node *node = NULL;
	int limit_value_count[LIMIT_PROP_MAX];
	bool limit_value_exists[LIMIT_SUBBLK_COUNT_MAX][LIMIT_PROP_MAX];
	const char *type = NULL;

	for_each_child_of_node(snp, node) {
		rc = _validate_dt_entry(node, limit_usecase_prop,
			ARRAY_SIZE(limit_usecase_prop),
			limit_value_count, NULL);
		if (rc)
			goto end;

		rc = _read_dt_entry(node, limit_usecase_prop,
			ARRAY_SIZE(limit_usecase_prop), limit_value_count,
			&limit_value_exists[i][0],
			&sde_limit_value[i * LIMIT_PROP_MAX]);
		if (rc)
			goto end;

		cfg->limit_cfg[i].lmt_case_cnt =
				limit_value_count[LIMIT_ID];

		cfg->limit_cfg[i].lmt_vec_cnt =
				limit_value_count[LIMIT_VALUE];
		of_property_read_string(node,
			limit_usecase_prop[LIMIT_NAME].prop_name, &type);
		cfg->limit_cfg[i].name = type;

		if (!limit_value_count[LIMIT_ID] ||
				!limit_value_count[LIMIT_VALUE]) {
			rc = -EINVAL;
			goto end;
		}
		i++;
	}
	return 0;
end:
	cfg->limit_count = 0;
	return rc;
}

static int sde_limit_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
{
	struct device_node *snp = NULL;
	struct sde_prop_value  *sde_limit_value = NULL;
	int rc = 0;

	snp = of_get_child_by_name(np, sde_prop[SDE_LIMITS].prop_name);
	if (!snp)
		goto end;

	cfg->limit_count = of_get_child_count(snp);
	if (cfg->limit_count < 0) {
		rc = -EINVAL;
		goto end;
	}

	sde_limit_value = kzalloc(cfg->limit_count * LIMIT_PROP_MAX *
			sizeof(struct sde_prop_value), GFP_KERNEL);
	if (!sde_limit_value) {
		rc = -ENOMEM;
		goto end;
	}

	rc = sde_validate_limit_node(snp, sde_limit_value, cfg);
	if (rc) {
		SDE_ERROR("validating limit node failed\n");
		goto end;
	}

	rc = sde_read_limit_node(snp, sde_limit_value, cfg);
	if (rc)
		SDE_ERROR("reading limit node failed\n");

end:
	kfree(sde_limit_value);
	return rc;
}

static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
{
	int rc, i, dma_rc, len, prop_count[SDE_PROP_MAX];
@@ -3103,6 +3263,10 @@ static int sde_parse_dt(struct device_node *np, struct sde_mdss_cfg *cfg)
	cfg->has_line_insertion = PROP_VALUE_ACCESS(prop_value,
		LINE_INSERTION, 0);
	cfg->has_base_layer = PROP_VALUE_ACCESS(prop_value, BASE_LAYER, 0);

	rc = sde_limit_parse_dt(np, cfg);
	if (rc)
		SDE_DEBUG("parsing of sde limit failed\n");
end:
	kfree(prop_value);
	return rc;
@@ -3919,6 +4083,11 @@ void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
			kfree(sde_cfg->vbif[i].qos_tbl[j].priority_lvl);
	}

	for (i = 0; i < sde_cfg->limit_count; i++) {
		kfree(sde_cfg->limit_cfg[i].vector_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);
+39 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@

#define MAX_XIN_COUNT 16
#define SSPP_SUBBLK_COUNT_MAX 2
#define LIMIT_SUBBLK_COUNT_MAX 10

#define SDE_CTL_CFG_VERSION_1_0_0       0x100
#define MAX_INTF_PER_CTL_V1                 2
@@ -1088,6 +1089,42 @@ struct sde_perf_cfg {
	u32 num_mnoc_ports;
};

/**
 * struct limit_vector_cfg - information on the usecase for each limit
 * @usecase: usecase for each limit
 * @value: id corresponding to each usecase
 */
struct limit_vector_cfg {
	const char *usecase;
	u32 value;
};

/**
 * struct limit_value_cfg - information on the value of usecase
 * @use_concur: usecase for each limit
 * @value: value corresponding to usecase for each limit
 */
struct limit_value_cfg {
	u32 use_concur;
	u32 value;
};

/**
 * struct sde_limit_cfg - information om different mdp limits
 * @name: name of the limit property
 * @lmt_vec_cnt: number of vector values for each limit
 * @lmt_case_cnt: number of usecases for each limit
 * @vector_cfg: pointer to the vector entries containing info on usecase
 * @value_cfg: pointer to the value of each vector entry
 */
struct sde_limit_cfg {
	const char *name;
	u32 lmt_vec_cnt;
	u32 lmt_case_cnt;
	struct limit_vector_cfg *vector_cfg;
	struct limit_value_cfg *value_cfg;
};

/**
 * struct sde_mdss_cfg - information of MDSS HW
 * This is the main catalog data structure representing
@@ -1253,6 +1290,8 @@ struct sde_mdss_cfg {
	u32 qdss_count;
	struct sde_qdss_cfg qdss[MAX_BLOCKS];

	u32 limit_count;
	struct sde_limit_cfg limit_cfg[LIMIT_SUBBLK_COUNT_MAX];
	/* Add additional block data structures here */

	struct sde_perf_cfg perf;