diff mbox

[5/6] drm/msm: gpu: Use OPP tables if we can

Message ID 1488906176-10720-6-git-send-email-jcrouse@codeaurora.org (mailing list archive)
State New, archived
Headers show

Commit Message

Jordan Crouse March 7, 2017, 5:02 p.m. UTC
If a OPP table is defined for the GPU device in the device tree use
that in lieu of the downstream style GPU frequency table. If we do
use the downstream table convert it to a OPP table so that we can
take advantage of the OPP lookup facilities later.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
---
 drivers/gpu/drm/msm/adreno/adreno_device.c | 85 +++++++++++++++++++++++-------
 1 file changed, 66 insertions(+), 19 deletions(-)

Comments

Rob Clark March 13, 2017, 5:35 p.m. UTC | #1
On Tue, Mar 7, 2017 at 12:02 PM, Jordan Crouse <jcrouse@codeaurora.org> wrote:
> If a OPP table is defined for the GPU device in the device tree use
> that in lieu of the downstream style GPU frequency table. If we do
> use the downstream table convert it to a OPP table so that we can
> take advantage of the OPP lookup facilities later.

so this one should probably be accompanied by an update to
Documentation/devicetree/bindings/display/msm/gpu.txt (and cc'd to
devicetree list, although I think it should not be controversial to
use the proper bindings for this ;-))

otherwise, looks good.. 1/6 looks like fixes material so I'll pull
that one in immediately..

BR,
-R

> Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
> ---
>  drivers/gpu/drm/msm/adreno/adreno_device.c | 85 +++++++++++++++++++++++-------
>  1 file changed, 66 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
> index 8374e9a..24da7f6 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> @@ -17,6 +17,7 @@
>   * this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>
> +#include <linux/pm_opp.h>
>  #include "adreno_gpu.h"
>
>  #define ANY_ID 0xff
> @@ -220,10 +221,71 @@ static int find_chipid(struct device *dev, u32 *chipid)
>         return 0;
>  }
>
> +/* Get legacy powerlevels from qcom,gpu-pwrlevels and populate the opp table */
> +static int adreno_get_legacy_pwrlevels(struct device *dev)
> +{
> +       struct device_node *child, *node;
> +       int ret;
> +
> +       node = of_find_compatible_node(dev->of_node, NULL,
> +               "qcom,gpu-pwrlevels");
> +       if (!node) {
> +               dev_err(dev, "Could not find the GPU powerlevels\n");
> +               return -ENXIO;
> +       }
> +
> +       for_each_child_of_node(node, child) {
> +               unsigned int val;
> +
> +               ret = of_property_read_u32(child, "qcom,gpu-freq", &val);
> +               if (ret)
> +                       continue;
> +
> +               /*
> +                * Skip the intentionally bogus clock value found at the bottom
> +                * of most legacy frequency tables
> +                */
> +               if (val != 27000000)
> +                       dev_pm_opp_add(dev, val, 0);
> +       }
> +
> +       return 0;
> +}
> +
> +static int adreno_get_pwrlevels(struct device *dev,
> +               struct adreno_platform_config *config)
> +{
> +       unsigned long freq = ULONG_MAX;
> +       struct dev_pm_opp *opp;
> +       int ret;
> +
> +       /* You down with OPP? */
> +       if (!of_find_property(dev->of_node, "operating-points-v2", NULL))
> +               ret = adreno_get_legacy_pwrlevels(dev);
> +       else
> +               ret = dev_pm_opp_of_add_table(dev);
> +
> +       if (ret)
> +               return ret;
> +
> +       /* Find the fastest defined rate */
> +       opp = dev_pm_opp_find_freq_floor(dev, &freq);
> +       if (!IS_ERR(opp))
> +               config->fast_rate = dev_pm_opp_get_freq(opp);
> +
> +       if (!config->fast_rate) {
> +               DRM_DEV_INFO(dev,
> +                       "Could not find clock rate. Using default\n");
> +               /* Pick a suitably safe clock speed for any target */
> +               config->fast_rate = 200000000;
> +       }
> +
> +       return 0;
> +}
> +
>  static int adreno_bind(struct device *dev, struct device *master, void *data)
>  {
>         static struct adreno_platform_config config = {};
> -       struct device_node *child, *node = dev->of_node;
>         u32 val;
>         int ret;
>
> @@ -238,25 +300,10 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
>
>         /* find clock rates: */
>         config.fast_rate = 0;
> -       for_each_child_of_node(node, child) {
> -               if (of_device_is_compatible(child, "qcom,gpu-pwrlevels")) {
> -                       struct device_node *pwrlvl;
> -                       for_each_child_of_node(child, pwrlvl) {
> -                               ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
> -                               if (ret) {
> -                                       dev_err(dev, "could not find gpu-freq: %d\n", ret);
> -                                       return ret;
> -                               }
> -                               config.fast_rate = max(config.fast_rate, val);
> -                       }
> -               }
> -       }
>
> -       if (!config.fast_rate) {
> -               dev_warn(dev, "could not find clk rates\n");
> -               /* This is a safe low speed for all devices: */
> -               config.fast_rate = 200000000;
> -       }
> +       ret = adreno_get_pwrlevels(dev, &config);
> +       if (ret)
> +               return ret;
>
>         dev->platform_data = &config;
>         set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev));
> --
> 1.9.1
>
> _______________________________________________
> Freedreno mailing list
> Freedreno@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/freedreno
diff mbox

Patch

diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 8374e9a..24da7f6 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -17,6 +17,7 @@ 
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/pm_opp.h>
 #include "adreno_gpu.h"
 
 #define ANY_ID 0xff
@@ -220,10 +221,71 @@  static int find_chipid(struct device *dev, u32 *chipid)
 	return 0;
 }
 
+/* Get legacy powerlevels from qcom,gpu-pwrlevels and populate the opp table */
+static int adreno_get_legacy_pwrlevels(struct device *dev)
+{
+	struct device_node *child, *node;
+	int ret;
+
+	node = of_find_compatible_node(dev->of_node, NULL,
+		"qcom,gpu-pwrlevels");
+	if (!node) {
+		dev_err(dev, "Could not find the GPU powerlevels\n");
+		return -ENXIO;
+	}
+
+	for_each_child_of_node(node, child) {
+		unsigned int val;
+
+		ret = of_property_read_u32(child, "qcom,gpu-freq", &val);
+		if (ret)
+			continue;
+
+		/*
+		 * Skip the intentionally bogus clock value found at the bottom
+		 * of most legacy frequency tables
+		 */
+		if (val != 27000000)
+			dev_pm_opp_add(dev, val, 0);
+	}
+
+	return 0;
+}
+
+static int adreno_get_pwrlevels(struct device *dev,
+		struct adreno_platform_config *config)
+{
+	unsigned long freq = ULONG_MAX;
+	struct dev_pm_opp *opp;
+	int ret;
+
+	/* You down with OPP? */
+	if (!of_find_property(dev->of_node, "operating-points-v2", NULL))
+		ret = adreno_get_legacy_pwrlevels(dev);
+	else
+		ret = dev_pm_opp_of_add_table(dev);
+
+	if (ret)
+		return ret;
+
+	/* Find the fastest defined rate */
+	opp = dev_pm_opp_find_freq_floor(dev, &freq);
+	if (!IS_ERR(opp))
+		config->fast_rate = dev_pm_opp_get_freq(opp);
+
+	if (!config->fast_rate) {
+		DRM_DEV_INFO(dev,
+			"Could not find clock rate. Using default\n");
+		/* Pick a suitably safe clock speed for any target */
+		config->fast_rate = 200000000;
+	}
+
+	return 0;
+}
+
 static int adreno_bind(struct device *dev, struct device *master, void *data)
 {
 	static struct adreno_platform_config config = {};
-	struct device_node *child, *node = dev->of_node;
 	u32 val;
 	int ret;
 
@@ -238,25 +300,10 @@  static int adreno_bind(struct device *dev, struct device *master, void *data)
 
 	/* find clock rates: */
 	config.fast_rate = 0;
-	for_each_child_of_node(node, child) {
-		if (of_device_is_compatible(child, "qcom,gpu-pwrlevels")) {
-			struct device_node *pwrlvl;
-			for_each_child_of_node(child, pwrlvl) {
-				ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
-				if (ret) {
-					dev_err(dev, "could not find gpu-freq: %d\n", ret);
-					return ret;
-				}
-				config.fast_rate = max(config.fast_rate, val);
-			}
-		}
-	}
 
-	if (!config.fast_rate) {
-		dev_warn(dev, "could not find clk rates\n");
-		/* This is a safe low speed for all devices: */
-		config.fast_rate = 200000000;
-	}
+	ret = adreno_get_pwrlevels(dev, &config);
+	if (ret)
+		return ret;
 
 	dev->platform_data = &config;
 	set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev));