MALI: midgard: avoid GPU voltage domain keeping the initial voltage
authorFinley Xiao <finley.xiao@rock-chips.com>
Wed, 23 Nov 2016 02:23:01 +0000 (10:23 +0800)
committerFinley Xiao <finley.xiao@rock-chips.com>
Tue, 29 Nov 2016 06:17:41 +0000 (14:17 +0800)
If there is only one opp whose frequency is equal to the initial value
in opp table list, the GPU voltage domain will keep the initial voltage,
it may be too large.

Change-Id: I87a5fb82eaac8466123b61e39a5d7587da3066da
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
drivers/gpu/arm/midgard/backend/gpu/mali_kbase_devfreq.c

index 8f9a67e57ceaa3b97d9b93797d86e869a49c480f..fd3c1f58a7d409b35da10c8195802476d74376ff 100644 (file)
@@ -53,6 +53,7 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
        struct kbase_device *kbdev = dev_get_drvdata(dev);
        struct dev_pm_opp *opp;
        unsigned long freq = 0;
+       unsigned long old_freq = kbdev->current_freq;
        unsigned long voltage;
        int err = 0;
 
@@ -70,14 +71,24 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
        /*
         * Only update if there is a change of frequency
         */
-       if (kbdev->current_freq == freq) {
+       if (old_freq == freq) {
                *target_freq = freq;
+#ifdef CONFIG_REGULATOR
+               if (kbdev->current_voltage == voltage)
+                       return 0;
+               err = regulator_set_voltage(kbdev->regulator, voltage, voltage);
+               if (err) {
+                       dev_err(dev, "Failed to set voltage (%d)\n", err);
+                       return err;
+               }
+#else
                return 0;
+#endif
        }
 
 #ifdef CONFIG_REGULATOR
-       if (kbdev->regulator && kbdev->current_voltage != voltage
-                       && kbdev->current_freq < freq) {
+       if (kbdev->regulator && kbdev->current_voltage != voltage &&
+           old_freq < freq) {
                err = regulator_set_voltage(kbdev->regulator, voltage, voltage);
                if (err) {
                        dev_err(dev, "Failed to increase voltage (%d)\n", err);
@@ -96,10 +107,12 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
                                freq, *target_freq);
                return err;
        }
+       *target_freq = freq;
+       kbdev->current_freq = freq;
 
 #ifdef CONFIG_REGULATOR
-       if (kbdev->regulator && kbdev->current_voltage != voltage
-                       && kbdev->current_freq > freq) {
+       if (kbdev->regulator && kbdev->current_voltage != voltage &&
+           old_freq > freq) {
                err = regulator_set_voltage(kbdev->regulator, voltage, voltage);
                if (err) {
                        dev_err(dev, "Failed to decrease voltage (%d)\n", err);
@@ -108,9 +121,7 @@ kbase_devfreq_target(struct device *dev, unsigned long *target_freq, u32 flags)
        }
 #endif
 
-       *target_freq = freq;
        kbdev->current_voltage = voltage;
-       kbdev->current_freq = freq;
 
        kbase_pm_reset_dvfs_utilisation(kbdev);
 
@@ -213,6 +224,11 @@ int kbase_devfreq_init(struct kbase_device *kbdev)
                return -ENODEV;
 
        kbdev->current_freq = clk_get_rate(kbdev->clock);
+#ifdef CONFIG_REGULATOR
+       if (kbdev->regulator)
+               kbdev->current_voltage =
+                       regulator_get_voltage(kbdev->regulator);
+#endif
 
        dp = &kbdev->devfreq_profile;