diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a6xx_gpu.h | 3 |
4 files changed, 67 insertions, 5 deletions
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 613d639833c0..d4e98e5876bc 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c | |||
@@ -61,8 +61,10 @@ static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu) | |||
61 | A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF)); | 61 | A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF)); |
62 | } | 62 | } |
63 | 63 | ||
64 | static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) | 64 | static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) |
65 | { | 65 | { |
66 | int ret; | ||
67 | |||
66 | gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0); | 68 | gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0); |
67 | 69 | ||
68 | gmu_write(gmu, REG_A6XX_GMU_DCVS_PERF_SETTING, | 70 | gmu_write(gmu, REG_A6XX_GMU_DCVS_PERF_SETTING, |
@@ -78,7 +80,37 @@ static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index) | |||
78 | a6xx_gmu_set_oob(gmu, GMU_OOB_DCVS_SET); | 80 | a6xx_gmu_set_oob(gmu, GMU_OOB_DCVS_SET); |
79 | a6xx_gmu_clear_oob(gmu, GMU_OOB_DCVS_SET); | 81 | a6xx_gmu_clear_oob(gmu, GMU_OOB_DCVS_SET); |
80 | 82 | ||
81 | return gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN); | 83 | ret = gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN); |
84 | if (ret) | ||
85 | dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret); | ||
86 | |||
87 | gmu->freq = gmu->gpu_freqs[index]; | ||
88 | } | ||
89 | |||
90 | void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq) | ||
91 | { | ||
92 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); | ||
93 | struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); | ||
94 | struct a6xx_gmu *gmu = &a6xx_gpu->gmu; | ||
95 | u32 perf_index = 0; | ||
96 | |||
97 | if (freq == gmu->freq) | ||
98 | return; | ||
99 | |||
100 | for (perf_index = 0; perf_index < gmu->nr_gpu_freqs - 1; perf_index++) | ||
101 | if (freq == gmu->gpu_freqs[perf_index]) | ||
102 | break; | ||
103 | |||
104 | __a6xx_gmu_set_freq(gmu, perf_index); | ||
105 | } | ||
106 | |||
107 | unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu) | ||
108 | { | ||
109 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); | ||
110 | struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); | ||
111 | struct a6xx_gmu *gmu = &a6xx_gpu->gmu; | ||
112 | |||
113 | return gmu->freq; | ||
82 | } | 114 | } |
83 | 115 | ||
84 | static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu) | 116 | static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu) |
@@ -637,7 +669,7 @@ int a6xx_gmu_reset(struct a6xx_gpu *a6xx_gpu) | |||
637 | ret = a6xx_hfi_start(gmu, GMU_COLD_BOOT); | 669 | ret = a6xx_hfi_start(gmu, GMU_COLD_BOOT); |
638 | 670 | ||
639 | /* Set the GPU back to the highest power frequency */ | 671 | /* Set the GPU back to the highest power frequency */ |
640 | a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1); | 672 | __a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1); |
641 | 673 | ||
642 | out: | 674 | out: |
643 | if (ret) | 675 | if (ret) |
@@ -676,7 +708,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) | |||
676 | ret = a6xx_hfi_start(gmu, status); | 708 | ret = a6xx_hfi_start(gmu, status); |
677 | 709 | ||
678 | /* Set the GPU to the highest power frequency */ | 710 | /* Set the GPU to the highest power frequency */ |
679 | a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1); | 711 | __a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1); |
680 | 712 | ||
681 | out: | 713 | out: |
682 | /* Make sure to turn off the boot OOB request on error */ | 714 | /* Make sure to turn off the boot OOB request on error */ |
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index f34630c72c4d..35f765afae45 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h | |||
@@ -74,6 +74,8 @@ struct a6xx_gmu { | |||
74 | unsigned long gmu_freqs[4]; | 74 | unsigned long gmu_freqs[4]; |
75 | u32 cx_arc_votes[4]; | 75 | u32 cx_arc_votes[4]; |
76 | 76 | ||
77 | unsigned long freq; | ||
78 | |||
77 | struct a6xx_hfi_queue queues[2]; | 79 | struct a6xx_hfi_queue queues[2]; |
78 | 80 | ||
79 | struct tasklet_struct hfi_tasklet; | 81 | struct tasklet_struct hfi_tasklet; |
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 5f36b8d88240..e4ac95f20ca7 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c | |||
@@ -7,6 +7,8 @@ | |||
7 | #include "a6xx_gpu.h" | 7 | #include "a6xx_gpu.h" |
8 | #include "a6xx_gmu.xml.h" | 8 | #include "a6xx_gmu.xml.h" |
9 | 9 | ||
10 | #include <linux/devfreq.h> | ||
11 | |||
10 | static inline bool _a6xx_check_idle(struct msm_gpu *gpu) | 12 | static inline bool _a6xx_check_idle(struct msm_gpu *gpu) |
11 | { | 13 | { |
12 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); | 14 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
@@ -682,6 +684,8 @@ static int a6xx_pm_resume(struct msm_gpu *gpu) | |||
682 | 684 | ||
683 | gpu->needs_hw_init = true; | 685 | gpu->needs_hw_init = true; |
684 | 686 | ||
687 | msm_gpu_resume_devfreq(gpu); | ||
688 | |||
685 | return ret; | 689 | return ret; |
686 | } | 690 | } |
687 | 691 | ||
@@ -690,6 +694,8 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu) | |||
690 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); | 694 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
691 | struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); | 695 | struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); |
692 | 696 | ||
697 | devfreq_suspend_device(gpu->devfreq.devfreq); | ||
698 | |||
693 | /* | 699 | /* |
694 | * Make sure the GMU is idle before continuing (because some transitions | 700 | * Make sure the GMU is idle before continuing (because some transitions |
695 | * may use VBIF | 701 | * may use VBIF |
@@ -753,6 +759,24 @@ static void a6xx_destroy(struct msm_gpu *gpu) | |||
753 | kfree(a6xx_gpu); | 759 | kfree(a6xx_gpu); |
754 | } | 760 | } |
755 | 761 | ||
762 | static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) | ||
763 | { | ||
764 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); | ||
765 | struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); | ||
766 | u64 busy_cycles; | ||
767 | unsigned long busy_time; | ||
768 | |||
769 | busy_cycles = gmu_read64(&a6xx_gpu->gmu, | ||
770 | REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L, | ||
771 | REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H); | ||
772 | |||
773 | busy_time = ((busy_cycles - gpu->devfreq.busy_cycles) * 10) / 192; | ||
774 | |||
775 | gpu->devfreq.busy_cycles = busy_cycles; | ||
776 | |||
777 | return busy_time; | ||
778 | } | ||
779 | |||
756 | static const struct adreno_gpu_funcs funcs = { | 780 | static const struct adreno_gpu_funcs funcs = { |
757 | .base = { | 781 | .base = { |
758 | .get_param = adreno_get_param, | 782 | .get_param = adreno_get_param, |
@@ -768,6 +792,9 @@ static const struct adreno_gpu_funcs funcs = { | |||
768 | #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) | 792 | #if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP) |
769 | .show = a6xx_show, | 793 | .show = a6xx_show, |
770 | #endif | 794 | #endif |
795 | .gpu_busy = a6xx_gpu_busy, | ||
796 | .gpu_get_freq = a6xx_gmu_get_freq, | ||
797 | .gpu_set_freq = a6xx_gmu_set_freq, | ||
771 | }, | 798 | }, |
772 | .get_timestamp = a6xx_get_timestamp, | 799 | .get_timestamp = a6xx_get_timestamp, |
773 | }; | 800 | }; |
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h index dd69e5b0e692..4127dcebc202 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h | |||
@@ -56,5 +56,6 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state); | |||
56 | 56 | ||
57 | int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node); | 57 | int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node); |
58 | void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu); | 58 | void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu); |
59 | 59 | void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq); | |
60 | unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu); | ||
60 | #endif /* __A6XX_GPU_H__ */ | 61 | #endif /* __A6XX_GPU_H__ */ |