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

Commit 3a2f09f3 authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Dynamically create an OPP table at runtime



The other reason why we define a OPP table for each target is for devfreq.
This is equally as silly as the first reason because we already have a
frequency table and forcing the developer to define it twice only invites
a mistake.  Remove the need for the static OPP table and create it
dynamically, at run time, from the information we already have.

Change-Id: Ic0dedbada16ec0832c0d531f39460f14aadc1bdd
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 2cb2a114
Loading
Loading
Loading
Loading
+35 −11
Original line number Diff line number Diff line
@@ -885,6 +885,40 @@ static void adreno_of_get_ca_aware_properties(struct adreno_device *adreno_dev,
	}
}

/* Dynamically build the OPP table for the GPU device */
static void adreno_build_opp_table(struct device *dev, struct kgsl_pwrctrl *pwr)
{
	unsigned long freq = 0;
	int i;

	/*
	 * First an annoying step: Some targets have clock drivers that
	 * "helpfully" builds a OPP table for us but usually it is wrong.
	 * Go through and filter out unsupported frequencies
	 */

	for (;;) {
		struct dev_pm_opp *opp = dev_pm_opp_find_freq_ceil(dev, &freq);

		if (IS_ERR(opp))
			break;

		for (i = 0; i < pwr->num_pwrlevels; i++) {
			if (freq == pwr->pwrlevels[i].gpu_freq)
				break;
		}

		if (i == pwr->num_pwrlevels)
			dev_pm_opp_remove(dev, freq);

		freq++;
	}

	/* Now add all of our supported frequencies into the tree */
	for (i = 0; i < pwr->num_pwrlevels; i++)
		dev_pm_opp_add(dev, pwr->pwrlevels[i].gpu_freq, 0);
}

static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
		struct device_node *node)
{
@@ -893,17 +927,6 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
	struct device_node *child;
	int ret;

	/* ADD the GPU OPP table if we define it */
	if (of_find_property(device->pdev->dev.of_node,
			"operating-points-v2", NULL)) {
		ret = dev_pm_opp_of_add_table(&device->pdev->dev);
		if (ret) {
			dev_err(device->dev,
				"Unable to set the GPU OPP table: %d\n", ret);
			return ret;
		}
	}

	pwr->num_pwrlevels = 0;

	for_each_child_of_node(node, child) {
@@ -971,6 +994,7 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
			"qcom,bus-max", &level->bus_max);
	}

	adreno_build_opp_table(&device->pdev->dev, pwr);
	return 0;
out:
	of_node_put(child);
+0 −39
Original line number Diff line number Diff line
@@ -1584,43 +1584,6 @@ static int kgsl_pwrctrl_clk_set_rate(struct clk *grp_clk, unsigned int freq,
	return ret;
}

static bool _gpu_freq_supported(struct kgsl_pwrctrl *pwr, unsigned int freq)
{
	int i;

	for (i = pwr->num_pwrlevels - 1; i >= 0; i--) {
		if (pwr->pwrlevels[i].gpu_freq == freq)
			return true;
	}

	return false;
}

void kgsl_pwrctrl_disable_unused_opp(struct kgsl_device *device,
		struct device *dev)
{
	struct dev_pm_opp *opp;
	unsigned long freq = 0;
	int ret;

	ret = dev_pm_opp_get_opp_count(dev);
	/* Return early, If no OPP table or OPP count is zero */
	if (ret <= 0)
		return;

	while (1) {
		opp = dev_pm_opp_find_freq_ceil(dev, &freq);
		if (IS_ERR(opp))
			break;

		if (!_gpu_freq_supported(&device->pwrctrl, freq))
			dev_pm_opp_disable(dev, freq);

		dev_pm_opp_put(opp);
		freq++;
	}
}

static u32 *kgsl_bus_get_table(struct platform_device *pdev, int *count)
{
	u32 *levels;
@@ -1702,8 +1665,6 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
			pwr->pwrlevels[i].gpu_freq = freq;
	}

	kgsl_pwrctrl_disable_unused_opp(device, &pdev->dev);

	kgsl_clk_set_rate(device, pwr->num_pwrlevels - 1);

	freq = clk_round_rate(pwr->grp_clks[6], KGSL_RBBMTIMER_CLK_FREQ);
+0 −2
Original line number Diff line number Diff line
@@ -198,7 +198,5 @@ void kgsl_pwrctrl_busy_time(struct kgsl_device *device, u64 time, u64 busy);
void kgsl_pwrctrl_set_constraint(struct kgsl_device *device,
			struct kgsl_pwr_constraint *pwrc, uint32_t id);
int kgsl_pwrctrl_set_default_gpu_pwrlevel(struct kgsl_device *device);
void kgsl_pwrctrl_disable_unused_opp(struct kgsl_device *device,
		struct device *dev);

#endif /* __KGSL_PWRCTRL_H */