diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 9e6b0907268c..4f866925e423 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -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); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index b35b9c49d0aa..1468bbabc570 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -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); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index d3d10b7aad02..7d2ca5d45195 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -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 */