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

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

Merge "disp: msm: add split-vote support with interconnect"

parents a4d36867 85c0c75d
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -63,22 +63,25 @@ TRACE_EVENT(sde_perf_set_ot,

TRACE_EVENT(sde_perf_update_bus,
	TP_PROTO(u32 bus_id, unsigned long long ab_quota,
	unsigned long long ib_quota),
	TP_ARGS(bus_id, ab_quota, ib_quota),
	unsigned long long ib_quota, u32 paths),
	TP_ARGS(bus_id, ab_quota, ib_quota, paths),
	TP_STRUCT__entry(
			__field(u32, bus_id);
			__field(u64, ab_quota)
			__field(u64, ib_quota)
			__field(u32, paths)
	),
	TP_fast_assign(
			__entry->bus_id = bus_id;
			__entry->ab_quota = ab_quota;
			__entry->ib_quota = ib_quota;
			__entry->paths = paths;
	),
	TP_printk("Request bus_id:%d ab=%llu ib=%llu",
	TP_printk("Request bus_id:%d ab=%llu ib=%llu paths=%d",
			__entry->bus_id,
			__entry->ab_quota,
			__entry->ib_quota)
			__entry->ib_quota,
			__entry->paths)
)


+126 −107
Original line number Diff line number Diff line
@@ -290,22 +290,21 @@ static int _sde_power_data_bus_set_quota(
	struct sde_power_data_bus_handle *pdbus,
	u64 in_ab_quota, u64 in_ib_quota)
{
	int rc = 0, i = 0, j = 0;
	int rc = 0, i = 0;
	u32 paths = pdbus->data_paths_cnt;

	if (!pdbus->data_paths_cnt) {
		pr_err("invalid data bus handle\n");
	if (!paths || paths > DATA_BUS_PATH_MAX) {
		pr_err("invalid data bus handle, paths %d\n", paths);
		return -EINVAL;
	}

	pr_debug("ab=%llu ib=%llu\n", in_ab_quota, in_ib_quota);

	in_ab_quota = div_u64(in_ab_quota, pdbus->data_paths_cnt);
	in_ab_quota = div_u64(in_ab_quota, paths);

	SDE_ATRACE_BEGIN("msm_bus_scale_req");
	for (i = 0; i < pdbus->data_paths_cnt; i++) {
	for (i = 0; i < paths; i++) {
		if (pdbus->data_bus_hdl[i]) {
			rc = icc_set_bw(pdbus->data_bus_hdl[i],
				in_ab_quota, in_ib_quota);
			rc = icc_set_bw(pdbus->data_bus_hdl[i], in_ab_quota,
					in_ib_quota);
			if (rc)
				goto err;
		}
@@ -318,9 +317,9 @@ static int _sde_power_data_bus_set_quota(

	return rc;
err:
	for (j = 0; j < i; j++)
		if (pdbus->data_bus_hdl[j])
			icc_set_bw(pdbus->data_bus_hdl[j],
	for (; i >= 0; --i)
		if (pdbus->data_bus_hdl[i])
			icc_set_bw(pdbus->data_bus_hdl[i],
				   pdbus->curr_val.ab,
				   pdbus->curr_val.ib);

@@ -335,116 +334,154 @@ int sde_power_data_bus_set_quota(struct sde_power_handle *phandle,
	u32 bus_id, u64 ab_quota, u64 ib_quota)
{
	int rc = 0;
	u32 paths;

	if (!phandle || bus_id >= SDE_POWER_HANDLE_DBUS_ID_MAX) {
		pr_err("invalid parameters\n");
		return -EINVAL;
	}

	mutex_lock(&phandle->phandle_lock);

	trace_sde_perf_update_bus(bus_id, ab_quota, ib_quota);
	paths = phandle->data_bus_handle[bus_id].data_paths_cnt;
	if (!paths)
		goto skip_vote;

	if (phandle->data_bus_handle[bus_id].data_paths_cnt > 0)
		rc = _sde_power_data_bus_set_quota(
			&phandle->data_bus_handle[bus_id], ab_quota, ib_quota);
	trace_sde_perf_update_bus(bus_id, ab_quota, ib_quota, paths);

	mutex_lock(&phandle->phandle_lock);
	rc = _sde_power_data_bus_set_quota(&phandle->data_bus_handle[bus_id],
			ab_quota, ib_quota);
	mutex_unlock(&phandle->phandle_lock);

skip_vote:
	pr_debug("bus=%d, ab=%llu, ib=%llu, paths=%d\n", bus_id, ab_quota,
			ib_quota, paths);

	return rc;
}

static void sde_power_data_bus_unregister(
		struct sde_power_data_bus_handle *pdbus)
/**
 * sde_power_icc_get - get the interconnect path for the given bus_name
 * @pdev - platform device
 * @bus_name - bus name for the corresponding interconnect
 * @path - the icc_path object we want to obtain for this @bus_name (output)
 * @count - if given, incremented only if the path was successfully retrieved
 **/
static int sde_power_icc_get(struct platform_device *pdev,
	const char *bus_name, struct icc_path **path, u32 *count)
{
	int i = 0;
	int rc = of_property_match_string(pdev->dev.of_node,
			"interconnect-names", bus_name);

	for (i = 0; i < pdbus->data_paths_cnt; i++) {
		if (pdbus->data_bus_hdl[i]) {
			icc_put(pdbus->data_bus_hdl[i]);
			pdbus->data_bus_hdl[i] = NULL;
		}
	/* bus_names are optional for any given device node, skip if missing */
	if (rc < 0)
		goto end;

	*path = of_icc_get(&pdev->dev, bus_name);
	if (IS_ERR_OR_NULL(*path)) {
		rc = PTR_ERR(*path);
		pr_err("bus %s parsing failed, rc:%d\n", bus_name, rc);
		*path = NULL;
		return rc;
	}

	if (count)
		(*count)++;

end:
	pr_debug("bus %s dt node %s(%d), icc_path is %s, count:%d\n",
			bus_name, rc < 0 ? "missing" : "found", rc,
			*path ? "valid" : "NULL", count ? *count : -1);
	return 0;
}

static int sde_power_data_bus_parse(struct platform_device *pdev,
static int sde_power_mnoc_bus_parse(struct platform_device *pdev,
	struct sde_power_data_bus_handle *pdbus, const char *name)
{
	int i, rc = 0;
	char bus_name[32];
	int i = 0, ret = 0;

	for (i = 0; i < DATA_BUS_PATH_MAX; i++) {
	for (i = 0; i < DATA_BUS_PATH_MAX; ++i) {
		snprintf(bus_name, sizeof(bus_name), "%s%d", name, i);
		ret = of_property_match_string(pdev->dev.of_node,
			"interconnect-names", bus_name);
		if (ret < 0) {
			if (!pdbus->data_paths_cnt) {
				pr_debug("sde: bus %s dt node missing\n", bus_name);
				return 0;
			} else
				goto end;
		} else
			pdbus->data_bus_hdl[i] = of_icc_get(&pdev->dev, bus_name);

		if (IS_ERR_OR_NULL(pdbus->data_bus_hdl[i])) {
			pr_debug("icc get path failed for %s\n", bus_name);
		rc = sde_power_icc_get(pdev, bus_name, &pdbus->data_bus_hdl[i],
				&pdbus->data_paths_cnt);
		if (rc)
			break;
	}
		pdbus->data_paths_cnt++;
	}

	/* at least one databus path is required */
	if (!pdbus->data_paths_cnt) {
		pr_err("get none data bus path for %s\n", name);
		pr_err("missing required interconnect:%s, rc:%d\n", name, rc);
		return -EINVAL;
	} else if (rc) {
		pr_info("ignoring error %d for non-primary data path\n", rc);
		rc = 0;
	}

end:
	if (of_find_property(pdev->dev.of_node,
			     "qcom,msm-bus,active-only", NULL)) {
		pdbus->bus_active_only = true;
		for (i = 0; i < pdbus->data_paths_cnt; i++) {
			icc_set_tag(pdbus->data_bus_hdl[i],
				    QCOM_ICC_TAG_ACTIVE_ONLY);
		}
	}

	pr_debug("register %s data_bus success, path number=%d\n",
		name, pdbus->data_paths_cnt);

	return 0;
	return rc;
}

static int sde_power_reg_bus_parse(struct platform_device *pdev,
static int sde_power_bus_parse(struct platform_device *pdev,
	struct sde_power_handle *phandle)
{
	int rc = 0;
	int i, j, rc = 0;
	bool active_only = false;
	const char *bus_name = "qcom,sde-reg-bus";
	struct sde_power_data_bus_handle *pdbus = phandle->data_bus_handle;

	/* not all clients need reg-bus, skip if not referenced for this node */
	rc = of_property_match_string(pdev->dev.of_node,
			"interconnect-names", bus_name);
	if (rc < 0)
		goto end;

	phandle->reg_bus_hdl = of_icc_get(&pdev->dev, bus_name);
	if (IS_ERR_OR_NULL(phandle->reg_bus_hdl)) {
		rc = PTR_ERR(phandle->reg_bus_hdl);
		pr_err("bus %s parsing failed, rc:%d\n", bus_name, rc);
		phandle->reg_bus_hdl = NULL;
	/* reg bus */
	rc = sde_power_icc_get(pdev, bus_name, &phandle->reg_bus_hdl, NULL);
	if (rc)
		return rc;

	/* data buses */
	if (of_find_property(pdev->dev.of_node,
			"qcom,msm-bus,active-only", NULL))
		active_only = true;

	for (i = SDE_POWER_HANDLE_DBUS_ID_MNOC;
			i < SDE_POWER_HANDLE_DBUS_ID_MAX; ++i) {
		if (i == SDE_POWER_HANDLE_DBUS_ID_MNOC)
			rc = sde_power_mnoc_bus_parse(pdev, &pdbus[i],
					data_bus_name[i]);
		else
			rc = sde_power_icc_get(pdev, data_bus_name[i],
					&pdbus[i].data_bus_hdl[0],
					&pdbus[i].data_paths_cnt);

		if (rc)
			break;

		if (active_only) {
			pdbus[i].bus_active_only = true;
			for (j = 0; j < pdbus[i].data_paths_cnt; ++j)
				icc_set_tag(pdbus[i].data_bus_hdl[j],
						QCOM_ICC_TAG_ACTIVE_ONLY);
		}

end:
	pr_debug("bus %s dt node %s(%d), hdl is %s\n",
			bus_name, rc < 0 ? "missing" : "found", rc,
			phandle->reg_bus_hdl ? "valid" : "NULL");
	return 0;
		pr_debug("found %d paths for %s\n", pdbus[i].data_paths_cnt,
				data_bus_name[i]);
	}

	return rc;
}

static void sde_power_reg_bus_unregister(struct icc_path *reg_bus_hdl)
static void sde_power_bus_unregister(struct sde_power_handle *phandle)
{
	if (reg_bus_hdl)
		icc_put(reg_bus_hdl);
	int i, j;
	struct sde_power_data_bus_handle *pdbus = phandle->data_bus_handle;

	icc_put(phandle->reg_bus_hdl);
	phandle->reg_bus_hdl = NULL;

	for (i = SDE_POWER_HANDLE_DBUS_ID_MAX - 1;
			i >= SDE_POWER_HANDLE_DBUS_ID_MNOC; i--) {
		for (j = 0; j < pdbus[i].data_paths_cnt; j++) {
			if (pdbus[i].data_bus_hdl[j]) {
				icc_put(pdbus[i].data_bus_hdl[j]);
				pdbus[i].data_bus_hdl[j] = NULL;
			}
		}
	}
}

static int sde_power_reg_bus_update(struct icc_path *reg_bus_hdl,
@@ -469,7 +506,7 @@ static int sde_power_reg_bus_update(struct icc_path *reg_bus_hdl,
int sde_power_resource_init(struct platform_device *pdev,
	struct sde_power_handle *phandle)
{
	int rc = 0, i;
	int rc = 0;
	struct dss_module_power *mp;

	if (!phandle || !pdev) {
@@ -502,33 +539,21 @@ int sde_power_resource_init(struct platform_device *pdev,
	rc = msm_dss_get_clk(&pdev->dev, mp->clk_config, mp->num_clk);
	if (rc) {
		pr_err("clock get failed rc=%d\n", rc);
		goto clk_err;
		goto clkget_err;
	}

	rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
	if (rc) {
		pr_err("clock set rate failed rc=%d\n", rc);
		goto bus_err;
		goto clkset_err;
	}

	rc = sde_power_reg_bus_parse(pdev, phandle);
	rc = sde_power_bus_parse(pdev, phandle);
	if (rc) {
		pr_err("register bus parse failed rc=%d\n", rc);
		pr_err("bus parse failed rc=%d\n", rc);
		goto bus_err;
	}

	for (i = SDE_POWER_HANDLE_DBUS_ID_MNOC;
			i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
		rc = sde_power_data_bus_parse(pdev,
				&phandle->data_bus_handle[i],
				data_bus_name[i]);
		if (rc) {
			pr_err("register data bus parse failed id=%d rc=%d\n",
					i, rc);
			goto data_bus_err;
		}
	}

	INIT_LIST_HEAD(&phandle->event_list);

	phandle->rsc_client = NULL;
@@ -538,13 +563,11 @@ int sde_power_resource_init(struct platform_device *pdev,

	return rc;

data_bus_err:
	for (i--; i >= 0; i--)
		sde_power_data_bus_unregister(&phandle->data_bus_handle[i]);
	sde_power_reg_bus_unregister(phandle->reg_bus_hdl);
bus_err:
	sde_power_bus_unregister(phandle);
clkset_err:
	msm_dss_put_clk(mp->clk_config, mp->num_clk);
clk_err:
clkget_err:
	msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, 0);
vreg_err:
	if (mp->vreg_config)
@@ -563,7 +586,6 @@ void sde_power_resource_deinit(struct platform_device *pdev,
{
	struct dss_module_power *mp;
	struct sde_power_event *curr_event, *next_event;
	int i;

	if (!phandle || !pdev) {
		pr_err("invalid input param\n");
@@ -582,10 +604,7 @@ void sde_power_resource_deinit(struct platform_device *pdev,
	}
	mutex_unlock(&phandle->phandle_lock);

	for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
		sde_power_data_bus_unregister(&phandle->data_bus_handle[i]);

	sde_power_reg_bus_unregister(phandle->reg_bus_hdl);
	sde_power_bus_unregister(phandle);

	msm_dss_put_clk(mp->clk_config, mp->num_clk);