diff options
author | Dave Airlie <airlied@redhat.com> | 2018-01-11 20:45:18 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-01-11 20:45:18 -0500 |
commit | 323b20c4af6e315e665b0ea85035fea7d738e0cc (patch) | |
tree | c5c59de32f20a0161e4c7d7e0269352b841eb4a2 /drivers | |
parent | fb8baefc7b2d7b93ad96abacbe63fa99e3d213d6 (diff) | |
parent | f91c14ab448af4d9d57350301dd9d6b6a7b6128a (diff) |
Merge tag 'drm-msm-next-2018-01-10' of git://people.freedesktop.org/~robclark/linux into drm-next
Updates for 4.16.. fairly small this time around, main thing is
devfreq support for the gpu.
* tag 'drm-msm-next-2018-01-10' of git://people.freedesktop.org/~robclark/linux:
drm/msm: Add devfreq support for the GPU
drm/msm/adreno: a5xx: Explicitly program the CP0 performance counter
drm/msm/adreno: Read the speed bins for a5xx targets
drm/msm/adreno: Move clock parsing to adreno_gpu_init()
drm/msm/adreno: Cleanup chipid parsing
drm/msm/gpu: Remove unused bus scaling code
drm/msm/adreno: Remove a useless call to dev_pm_opp_get_freq()
drm/msm/adreno: Call dev_pm_opp_put()
drm/msm: Fix NULL deref in adreno_load_gpu
drm/msm: gpu: Only sync fences on rings that exist
drm/msm: fix leak in failed get_pages
drm/msm: avoid false-positive -Wmaybe-uninitialized warning
drm/msm/mdp4: Deduplicate bus_find_device() by name matching
drm/msm: add missing MODULE_FIRMWARE declarations
drm/msm: update adreno firmware path in MODULE_FIRMWARE
drm/msm: free kstrdup'd cmdline
drm/msm: fix msm_rd_dump_submit prototype
drm/msm: fix spelling mistake: "ringubffer" -> "ringbuffer"
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 38 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/a5xx_power.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_device.c | 140 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.c | 85 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/adreno/adreno_gpu.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gem.c | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.c | 112 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_gpu.h | 14 |
11 files changed, 264 insertions, 170 deletions
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index a1f4eeeb73e2..7e09d44e4a15 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/dma-mapping.h> | 17 | #include <linux/dma-mapping.h> |
18 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
19 | #include <linux/soc/qcom/mdt_loader.h> | 19 | #include <linux/soc/qcom/mdt_loader.h> |
20 | #include <linux/pm_opp.h> | ||
21 | #include <linux/nvmem-consumer.h> | ||
20 | #include "msm_gem.h" | 22 | #include "msm_gem.h" |
21 | #include "msm_mmu.h" | 23 | #include "msm_mmu.h" |
22 | #include "a5xx_gpu.h" | 24 | #include "a5xx_gpu.h" |
@@ -595,6 +597,12 @@ static int a5xx_hw_init(struct msm_gpu *gpu) | |||
595 | /* Turn on performance counters */ | 597 | /* Turn on performance counters */ |
596 | gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_CNTL, 0x01); | 598 | gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_CNTL, 0x01); |
597 | 599 | ||
600 | /* Select CP0 to always count cycles */ | ||
601 | gpu_write(gpu, REG_A5XX_CP_PERFCTR_CP_SEL_0, PERF_CP_ALWAYS_COUNT); | ||
602 | |||
603 | /* Select RBBM0 to countable 6 to get the busy status for devfreq */ | ||
604 | gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_SEL_0, 6); | ||
605 | |||
598 | /* Increase VFD cache access so LRZ and other data gets evicted less */ | 606 | /* Increase VFD cache access so LRZ and other data gets evicted less */ |
599 | gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02); | 607 | gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02); |
600 | 608 | ||
@@ -1165,6 +1173,14 @@ static struct msm_ringbuffer *a5xx_active_ring(struct msm_gpu *gpu) | |||
1165 | return a5xx_gpu->cur_ring; | 1173 | return a5xx_gpu->cur_ring; |
1166 | } | 1174 | } |
1167 | 1175 | ||
1176 | static int a5xx_gpu_busy(struct msm_gpu *gpu, uint64_t *value) | ||
1177 | { | ||
1178 | *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO, | ||
1179 | REG_A5XX_RBBM_PERFCTR_RBBM_0_HI); | ||
1180 | |||
1181 | return 0; | ||
1182 | } | ||
1183 | |||
1168 | static const struct adreno_gpu_funcs funcs = { | 1184 | static const struct adreno_gpu_funcs funcs = { |
1169 | .base = { | 1185 | .base = { |
1170 | .get_param = adreno_get_param, | 1186 | .get_param = adreno_get_param, |
@@ -1180,10 +1196,30 @@ static const struct adreno_gpu_funcs funcs = { | |||
1180 | #ifdef CONFIG_DEBUG_FS | 1196 | #ifdef CONFIG_DEBUG_FS |
1181 | .show = a5xx_show, | 1197 | .show = a5xx_show, |
1182 | #endif | 1198 | #endif |
1199 | .gpu_busy = a5xx_gpu_busy, | ||
1183 | }, | 1200 | }, |
1184 | .get_timestamp = a5xx_get_timestamp, | 1201 | .get_timestamp = a5xx_get_timestamp, |
1185 | }; | 1202 | }; |
1186 | 1203 | ||
1204 | static void check_speed_bin(struct device *dev) | ||
1205 | { | ||
1206 | struct nvmem_cell *cell; | ||
1207 | u32 bin, val; | ||
1208 | |||
1209 | cell = nvmem_cell_get(dev, "speed_bin"); | ||
1210 | |||
1211 | /* If a nvmem cell isn't defined, nothing to do */ | ||
1212 | if (IS_ERR(cell)) | ||
1213 | return; | ||
1214 | |||
1215 | bin = *((u32 *) nvmem_cell_read(cell, NULL)); | ||
1216 | nvmem_cell_put(cell); | ||
1217 | |||
1218 | val = (1 << bin); | ||
1219 | |||
1220 | dev_pm_opp_set_supported_hw(dev, &val, 1); | ||
1221 | } | ||
1222 | |||
1187 | struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) | 1223 | struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) |
1188 | { | 1224 | { |
1189 | struct msm_drm_private *priv = dev->dev_private; | 1225 | struct msm_drm_private *priv = dev->dev_private; |
@@ -1210,6 +1246,8 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) | |||
1210 | 1246 | ||
1211 | a5xx_gpu->lm_leakage = 0x4E001A; | 1247 | a5xx_gpu->lm_leakage = 0x4E001A; |
1212 | 1248 | ||
1249 | check_speed_bin(&pdev->dev); | ||
1250 | |||
1213 | ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4); | 1251 | ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4); |
1214 | if (ret) { | 1252 | if (ret) { |
1215 | a5xx_destroy(&(a5xx_gpu->base.base)); | 1253 | a5xx_destroy(&(a5xx_gpu->base.base)); |
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c index e5700bbf09dd..4e4d965fd9ab 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c | |||
@@ -103,10 +103,16 @@ static inline uint32_t _get_mvolts(struct msm_gpu *gpu, uint32_t freq) | |||
103 | struct msm_drm_private *priv = dev->dev_private; | 103 | struct msm_drm_private *priv = dev->dev_private; |
104 | struct platform_device *pdev = priv->gpu_pdev; | 104 | struct platform_device *pdev = priv->gpu_pdev; |
105 | struct dev_pm_opp *opp; | 105 | struct dev_pm_opp *opp; |
106 | u32 ret = 0; | ||
106 | 107 | ||
107 | opp = dev_pm_opp_find_freq_exact(&pdev->dev, freq, true); | 108 | opp = dev_pm_opp_find_freq_exact(&pdev->dev, freq, true); |
108 | 109 | ||
109 | return (!IS_ERR(opp)) ? dev_pm_opp_get_voltage(opp) / 1000 : 0; | 110 | if (!IS_ERR(opp)) { |
111 | ret = dev_pm_opp_get_voltage(opp) / 1000; | ||
112 | dev_pm_opp_put(opp); | ||
113 | } | ||
114 | |||
115 | return ret; | ||
110 | } | 116 | } |
111 | 117 | ||
112 | /* Setup thermal limit management */ | 118 | /* Setup thermal limit management */ |
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 05022ea2a007..62bdb7316da1 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c | |||
@@ -17,7 +17,6 @@ | |||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | 17 | * this program. If not, see <http://www.gnu.org/licenses/>. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/pm_opp.h> | ||
21 | #include "adreno_gpu.h" | 20 | #include "adreno_gpu.h" |
22 | 21 | ||
23 | #define ANY_ID 0xff | 22 | #define ANY_ID 0xff |
@@ -90,14 +89,19 @@ static const struct adreno_info gpulist[] = { | |||
90 | }, | 89 | }, |
91 | }; | 90 | }; |
92 | 91 | ||
93 | MODULE_FIRMWARE("a300_pm4.fw"); | 92 | MODULE_FIRMWARE("qcom/a300_pm4.fw"); |
94 | MODULE_FIRMWARE("a300_pfp.fw"); | 93 | MODULE_FIRMWARE("qcom/a300_pfp.fw"); |
95 | MODULE_FIRMWARE("a330_pm4.fw"); | 94 | MODULE_FIRMWARE("qcom/a330_pm4.fw"); |
96 | MODULE_FIRMWARE("a330_pfp.fw"); | 95 | MODULE_FIRMWARE("qcom/a330_pfp.fw"); |
97 | MODULE_FIRMWARE("a420_pm4.fw"); | 96 | MODULE_FIRMWARE("qcom/a420_pm4.fw"); |
98 | MODULE_FIRMWARE("a420_pfp.fw"); | 97 | MODULE_FIRMWARE("qcom/a420_pfp.fw"); |
99 | MODULE_FIRMWARE("a530_fm4.fw"); | 98 | MODULE_FIRMWARE("qcom/a530_pm4.fw"); |
100 | MODULE_FIRMWARE("a530_pfp.fw"); | 99 | MODULE_FIRMWARE("qcom/a530_pfp.fw"); |
100 | MODULE_FIRMWARE("qcom/a530v3_gpmu.fw2"); | ||
101 | MODULE_FIRMWARE("qcom/a530_zap.mdt"); | ||
102 | MODULE_FIRMWARE("qcom/a530_zap.b00"); | ||
103 | MODULE_FIRMWARE("qcom/a530_zap.b01"); | ||
104 | MODULE_FIRMWARE("qcom/a530_zap.b02"); | ||
101 | 105 | ||
102 | static inline bool _rev_match(uint8_t entry, uint8_t id) | 106 | static inline bool _rev_match(uint8_t entry, uint8_t id) |
103 | { | 107 | { |
@@ -125,11 +129,14 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev) | |||
125 | { | 129 | { |
126 | struct msm_drm_private *priv = dev->dev_private; | 130 | struct msm_drm_private *priv = dev->dev_private; |
127 | struct platform_device *pdev = priv->gpu_pdev; | 131 | struct platform_device *pdev = priv->gpu_pdev; |
128 | struct msm_gpu *gpu = platform_get_drvdata(priv->gpu_pdev); | 132 | struct msm_gpu *gpu = NULL; |
129 | int ret; | 133 | int ret; |
130 | 134 | ||
135 | if (pdev) | ||
136 | gpu = platform_get_drvdata(pdev); | ||
137 | |||
131 | if (!gpu) { | 138 | if (!gpu) { |
132 | dev_err(dev->dev, "no adreno device\n"); | 139 | dev_err_once(dev->dev, "no GPU device was found\n"); |
133 | return NULL; | 140 | return NULL; |
134 | } | 141 | } |
135 | 142 | ||
@@ -153,101 +160,45 @@ static void set_gpu_pdev(struct drm_device *dev, | |||
153 | priv->gpu_pdev = pdev; | 160 | priv->gpu_pdev = pdev; |
154 | } | 161 | } |
155 | 162 | ||
156 | static int find_chipid(struct device *dev, u32 *chipid) | 163 | static int find_chipid(struct device *dev, struct adreno_rev *rev) |
157 | { | 164 | { |
158 | struct device_node *node = dev->of_node; | 165 | struct device_node *node = dev->of_node; |
159 | const char *compat; | 166 | const char *compat; |
160 | int ret; | 167 | int ret; |
168 | u32 chipid; | ||
161 | 169 | ||
162 | /* first search the compat strings for qcom,adreno-XYZ.W: */ | 170 | /* first search the compat strings for qcom,adreno-XYZ.W: */ |
163 | ret = of_property_read_string_index(node, "compatible", 0, &compat); | 171 | ret = of_property_read_string_index(node, "compatible", 0, &compat); |
164 | if (ret == 0) { | 172 | if (ret == 0) { |
165 | unsigned rev, patch; | 173 | unsigned int r, patch; |
166 | 174 | ||
167 | if (sscanf(compat, "qcom,adreno-%u.%u", &rev, &patch) == 2) { | 175 | if (sscanf(compat, "qcom,adreno-%u.%u", &r, &patch) == 2) { |
168 | *chipid = 0; | 176 | rev->core = r / 100; |
169 | *chipid |= (rev / 100) << 24; /* core */ | 177 | r %= 100; |
170 | rev %= 100; | 178 | rev->major = r / 10; |
171 | *chipid |= (rev / 10) << 16; /* major */ | 179 | r %= 10; |
172 | rev %= 10; | 180 | rev->minor = r; |
173 | *chipid |= rev << 8; /* minor */ | 181 | rev->patchid = patch; |
174 | *chipid |= patch; | ||
175 | 182 | ||
176 | return 0; | 183 | return 0; |
177 | } | 184 | } |
178 | } | 185 | } |
179 | 186 | ||
180 | /* and if that fails, fall back to legacy "qcom,chipid" property: */ | 187 | /* and if that fails, fall back to legacy "qcom,chipid" property: */ |
181 | ret = of_property_read_u32(node, "qcom,chipid", chipid); | 188 | ret = of_property_read_u32(node, "qcom,chipid", &chipid); |
182 | if (ret) | 189 | if (ret) { |
190 | dev_err(dev, "could not parse qcom,chipid: %d\n", ret); | ||
183 | return ret; | 191 | return ret; |
184 | |||
185 | dev_warn(dev, "Using legacy qcom,chipid binding!\n"); | ||
186 | dev_warn(dev, "Use compatible qcom,adreno-%u%u%u.%u instead.\n", | ||
187 | (*chipid >> 24) & 0xff, (*chipid >> 16) & 0xff, | ||
188 | (*chipid >> 8) & 0xff, *chipid & 0xff); | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | /* Get legacy powerlevels from qcom,gpu-pwrlevels and populate the opp table */ | ||
194 | static int adreno_get_legacy_pwrlevels(struct device *dev) | ||
195 | { | ||
196 | struct device_node *child, *node; | ||
197 | int ret; | ||
198 | |||
199 | node = of_find_compatible_node(dev->of_node, NULL, | ||
200 | "qcom,gpu-pwrlevels"); | ||
201 | if (!node) { | ||
202 | dev_err(dev, "Could not find the GPU powerlevels\n"); | ||
203 | return -ENXIO; | ||
204 | } | 192 | } |
205 | 193 | ||
206 | for_each_child_of_node(node, child) { | 194 | rev->core = (chipid >> 24) & 0xff; |
207 | unsigned int val; | 195 | rev->major = (chipid >> 16) & 0xff; |
208 | 196 | rev->minor = (chipid >> 8) & 0xff; | |
209 | ret = of_property_read_u32(child, "qcom,gpu-freq", &val); | 197 | rev->patchid = (chipid & 0xff); |
210 | if (ret) | ||
211 | continue; | ||
212 | 198 | ||
213 | /* | 199 | dev_warn(dev, "Using legacy qcom,chipid binding!\n"); |
214 | * Skip the intentionally bogus clock value found at the bottom | 200 | dev_warn(dev, "Use compatible qcom,adreno-%u%u%u.%u instead.\n", |
215 | * of most legacy frequency tables | 201 | rev->core, rev->major, rev->minor, rev->patchid); |
216 | */ | ||
217 | if (val != 27000000) | ||
218 | dev_pm_opp_add(dev, val, 0); | ||
219 | } | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int adreno_get_pwrlevels(struct device *dev, | ||
225 | struct adreno_platform_config *config) | ||
226 | { | ||
227 | unsigned long freq = ULONG_MAX; | ||
228 | struct dev_pm_opp *opp; | ||
229 | int ret; | ||
230 | |||
231 | /* You down with OPP? */ | ||
232 | if (!of_find_property(dev->of_node, "operating-points-v2", NULL)) | ||
233 | ret = adreno_get_legacy_pwrlevels(dev); | ||
234 | else | ||
235 | ret = dev_pm_opp_of_add_table(dev); | ||
236 | |||
237 | if (ret) | ||
238 | return ret; | ||
239 | |||
240 | /* Find the fastest defined rate */ | ||
241 | opp = dev_pm_opp_find_freq_floor(dev, &freq); | ||
242 | if (!IS_ERR(opp)) | ||
243 | config->fast_rate = dev_pm_opp_get_freq(opp); | ||
244 | |||
245 | if (!config->fast_rate) { | ||
246 | DRM_DEV_INFO(dev, | ||
247 | "Could not find clock rate. Using default\n"); | ||
248 | /* Pick a suitably safe clock speed for any target */ | ||
249 | config->fast_rate = 200000000; | ||
250 | } | ||
251 | 202 | ||
252 | return 0; | 203 | return 0; |
253 | } | 204 | } |
@@ -258,22 +209,9 @@ static int adreno_bind(struct device *dev, struct device *master, void *data) | |||
258 | const struct adreno_info *info; | 209 | const struct adreno_info *info; |
259 | struct drm_device *drm = dev_get_drvdata(master); | 210 | struct drm_device *drm = dev_get_drvdata(master); |
260 | struct msm_gpu *gpu; | 211 | struct msm_gpu *gpu; |
261 | u32 val; | ||
262 | int ret; | 212 | int ret; |
263 | 213 | ||
264 | ret = find_chipid(dev, &val); | 214 | ret = find_chipid(dev, &config.rev); |
265 | if (ret) { | ||
266 | dev_err(dev, "could not find chipid: %d\n", ret); | ||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | config.rev = ADRENO_REV((val >> 24) & 0xff, | ||
271 | (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff); | ||
272 | |||
273 | /* find clock rates: */ | ||
274 | config.fast_rate = 0; | ||
275 | |||
276 | ret = adreno_get_pwrlevels(dev, &config); | ||
277 | if (ret) | 215 | if (ret) |
278 | return ret; | 216 | return ret; |
279 | 217 | ||
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index e2ffecce59a3..de63ff26a062 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c | |||
@@ -17,11 +17,11 @@ | |||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | 17 | * this program. If not, see <http://www.gnu.org/licenses/>. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/pm_opp.h> | ||
20 | #include "adreno_gpu.h" | 21 | #include "adreno_gpu.h" |
21 | #include "msm_gem.h" | 22 | #include "msm_gem.h" |
22 | #include "msm_mmu.h" | 23 | #include "msm_mmu.h" |
23 | 24 | ||
24 | |||
25 | int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) | 25 | int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) |
26 | { | 26 | { |
27 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); | 27 | struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); |
@@ -461,10 +461,80 @@ void adreno_wait_ring(struct msm_ringbuffer *ring, uint32_t ndwords) | |||
461 | { | 461 | { |
462 | if (spin_until(ring_freewords(ring) >= ndwords)) | 462 | if (spin_until(ring_freewords(ring) >= ndwords)) |
463 | DRM_DEV_ERROR(ring->gpu->dev->dev, | 463 | DRM_DEV_ERROR(ring->gpu->dev->dev, |
464 | "timeout waiting for space in ringubffer %d\n", | 464 | "timeout waiting for space in ringbuffer %d\n", |
465 | ring->id); | 465 | ring->id); |
466 | } | 466 | } |
467 | 467 | ||
468 | /* Get legacy powerlevels from qcom,gpu-pwrlevels and populate the opp table */ | ||
469 | static int adreno_get_legacy_pwrlevels(struct device *dev) | ||
470 | { | ||
471 | struct device_node *child, *node; | ||
472 | int ret; | ||
473 | |||
474 | node = of_find_compatible_node(dev->of_node, NULL, | ||
475 | "qcom,gpu-pwrlevels"); | ||
476 | if (!node) { | ||
477 | dev_err(dev, "Could not find the GPU powerlevels\n"); | ||
478 | return -ENXIO; | ||
479 | } | ||
480 | |||
481 | for_each_child_of_node(node, child) { | ||
482 | unsigned int val; | ||
483 | |||
484 | ret = of_property_read_u32(child, "qcom,gpu-freq", &val); | ||
485 | if (ret) | ||
486 | continue; | ||
487 | |||
488 | /* | ||
489 | * Skip the intentionally bogus clock value found at the bottom | ||
490 | * of most legacy frequency tables | ||
491 | */ | ||
492 | if (val != 27000000) | ||
493 | dev_pm_opp_add(dev, val, 0); | ||
494 | } | ||
495 | |||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static int adreno_get_pwrlevels(struct device *dev, | ||
500 | struct msm_gpu *gpu) | ||
501 | { | ||
502 | unsigned long freq = ULONG_MAX; | ||
503 | struct dev_pm_opp *opp; | ||
504 | int ret; | ||
505 | |||
506 | gpu->fast_rate = 0; | ||
507 | |||
508 | /* You down with OPP? */ | ||
509 | if (!of_find_property(dev->of_node, "operating-points-v2", NULL)) | ||
510 | ret = adreno_get_legacy_pwrlevels(dev); | ||
511 | else { | ||
512 | ret = dev_pm_opp_of_add_table(dev); | ||
513 | if (ret) | ||
514 | dev_err(dev, "Unable to set the OPP table\n"); | ||
515 | } | ||
516 | |||
517 | if (!ret) { | ||
518 | /* Find the fastest defined rate */ | ||
519 | opp = dev_pm_opp_find_freq_floor(dev, &freq); | ||
520 | if (!IS_ERR(opp)) { | ||
521 | gpu->fast_rate = freq; | ||
522 | dev_pm_opp_put(opp); | ||
523 | } | ||
524 | } | ||
525 | |||
526 | if (!gpu->fast_rate) { | ||
527 | dev_warn(dev, | ||
528 | "Could not find a clock rate. Using a reasonable default\n"); | ||
529 | /* Pick a suitably safe clock speed for any target */ | ||
530 | gpu->fast_rate = 200000000; | ||
531 | } | ||
532 | |||
533 | DBG("fast_rate=%u, slow_rate=27000000", gpu->fast_rate); | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
468 | int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, | 538 | int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, |
469 | struct adreno_gpu *adreno_gpu, | 539 | struct adreno_gpu *adreno_gpu, |
470 | const struct adreno_gpu_funcs *funcs, int nr_rings) | 540 | const struct adreno_gpu_funcs *funcs, int nr_rings) |
@@ -479,15 +549,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, | |||
479 | adreno_gpu->revn = adreno_gpu->info->revn; | 549 | adreno_gpu->revn = adreno_gpu->info->revn; |
480 | adreno_gpu->rev = config->rev; | 550 | adreno_gpu->rev = config->rev; |
481 | 551 | ||
482 | gpu->fast_rate = config->fast_rate; | ||
483 | gpu->bus_freq = config->bus_freq; | ||
484 | #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING | ||
485 | gpu->bus_scale_table = config->bus_scale_table; | ||
486 | #endif | ||
487 | |||
488 | DBG("fast_rate=%u, slow_rate=27000000, bus_freq=%u", | ||
489 | gpu->fast_rate, gpu->bus_freq); | ||
490 | |||
491 | adreno_gpu_config.ioname = "kgsl_3d0_reg_memory"; | 552 | adreno_gpu_config.ioname = "kgsl_3d0_reg_memory"; |
492 | adreno_gpu_config.irqname = "kgsl_3d0_irq"; | 553 | adreno_gpu_config.irqname = "kgsl_3d0_irq"; |
493 | 554 | ||
@@ -496,6 +557,8 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, | |||
496 | 557 | ||
497 | adreno_gpu_config.nr_rings = nr_rings; | 558 | adreno_gpu_config.nr_rings = nr_rings; |
498 | 559 | ||
560 | adreno_get_pwrlevels(&pdev->dev, gpu); | ||
561 | |||
499 | pm_runtime_set_autosuspend_delay(&pdev->dev, DRM_MSM_INACTIVE_PERIOD); | 562 | pm_runtime_set_autosuspend_delay(&pdev->dev, DRM_MSM_INACTIVE_PERIOD); |
500 | pm_runtime_use_autosuspend(&pdev->dev); | 563 | pm_runtime_use_autosuspend(&pdev->dev); |
501 | pm_runtime_enable(&pdev->dev); | 564 | pm_runtime_enable(&pdev->dev); |
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 28e3de6e5f94..8d3d0a924908 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h | |||
@@ -129,10 +129,6 @@ struct adreno_gpu { | |||
129 | /* platform config data (ie. from DT, or pdata) */ | 129 | /* platform config data (ie. from DT, or pdata) */ |
130 | struct adreno_platform_config { | 130 | struct adreno_platform_config { |
131 | struct adreno_rev rev; | 131 | struct adreno_rev rev; |
132 | uint32_t fast_rate, bus_freq; | ||
133 | #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING | ||
134 | struct msm_bus_scale_pdata *bus_scale_table; | ||
135 | #endif | ||
136 | }; | 132 | }; |
137 | 133 | ||
138 | #define ADRENO_IDLE_TIMEOUT msecs_to_jiffies(1000) | 134 | #define ADRENO_IDLE_TIMEOUT msecs_to_jiffies(1000) |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h index 940de51ac5cd..a1b3e31e959e 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h | |||
@@ -234,10 +234,6 @@ static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev) | |||
234 | #endif | 234 | #endif |
235 | 235 | ||
236 | #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING | 236 | #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING |
237 | static inline int match_dev_name(struct device *dev, void *data) | ||
238 | { | ||
239 | return !strcmp(dev_name(dev), data); | ||
240 | } | ||
241 | /* bus scaling data is associated with extra pointless platform devices, | 237 | /* bus scaling data is associated with extra pointless platform devices, |
242 | * "dtv", etc.. this is a bit of a hack, but we need a way for encoders | 238 | * "dtv", etc.. this is a bit of a hack, but we need a way for encoders |
243 | * to find their pdata to make the bus-scaling stuff work. | 239 | * to find their pdata to make the bus-scaling stuff work. |
@@ -245,8 +241,7 @@ static inline int match_dev_name(struct device *dev, void *data) | |||
245 | static inline void *mdp4_find_pdata(const char *devname) | 241 | static inline void *mdp4_find_pdata(const char *devname) |
246 | { | 242 | { |
247 | struct device *dev; | 243 | struct device *dev; |
248 | dev = bus_find_device(&platform_bus_type, NULL, | 244 | dev = bus_find_device_by_name(&platform_bus_type, NULL, devname); |
249 | (void *)devname, match_dev_name); | ||
250 | return dev ? dev->platform_data : NULL; | 245 | return dev ? dev->platform_data : NULL; |
251 | } | 246 | } |
252 | #endif | 247 | #endif |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index ee41423baeb7..29678876fc09 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | |||
@@ -966,8 +966,6 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, | |||
966 | uint32_t src_x, src_y; | 966 | uint32_t src_x, src_y; |
967 | uint32_t src_w, src_h; | 967 | uint32_t src_w, src_h; |
968 | uint32_t src_img_w, src_img_h; | 968 | uint32_t src_img_w, src_img_h; |
969 | uint32_t src_x_r; | ||
970 | int crtc_x_r; | ||
971 | int ret; | 969 | int ret; |
972 | 970 | ||
973 | nplanes = fb->format->num_planes; | 971 | nplanes = fb->format->num_planes; |
@@ -1012,9 +1010,6 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, | |||
1012 | crtc_w /= 2; | 1010 | crtc_w /= 2; |
1013 | src_w /= 2; | 1011 | src_w /= 2; |
1014 | src_img_w /= 2; | 1012 | src_img_w /= 2; |
1015 | |||
1016 | crtc_x_r = crtc_x + crtc_w; | ||
1017 | src_x_r = src_x + src_w; | ||
1018 | } | 1013 | } |
1019 | 1014 | ||
1020 | ret = calc_scalex_steps(plane, pix_format, src_w, crtc_w, step.x); | 1015 | ret = calc_scalex_steps(plane, pix_format, src_w, crtc_w, step.x); |
@@ -1054,9 +1049,9 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, | |||
1054 | if (right_hwpipe) | 1049 | if (right_hwpipe) |
1055 | mdp5_hwpipe_mode_set(mdp5_kms, right_hwpipe, fb, &step, &pe, | 1050 | mdp5_hwpipe_mode_set(mdp5_kms, right_hwpipe, fb, &step, &pe, |
1056 | config, hdecm, vdecm, hflip, vflip, | 1051 | config, hdecm, vdecm, hflip, vflip, |
1057 | crtc_x_r, crtc_y, crtc_w, crtc_h, | 1052 | crtc_x + crtc_w, crtc_y, crtc_w, crtc_h, |
1058 | src_img_w, src_img_h, | 1053 | src_img_w, src_img_h, |
1059 | src_x_r, src_y, src_w, src_h); | 1054 | src_x + src_w, src_y, src_w, src_h); |
1060 | 1055 | ||
1061 | plane->fb = fb; | 1056 | plane->fb = fb; |
1062 | 1057 | ||
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index c646843d8822..0a653dd2e618 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h | |||
@@ -303,7 +303,8 @@ int msm_perf_debugfs_init(struct drm_minor *minor); | |||
303 | void msm_perf_debugfs_cleanup(struct msm_drm_private *priv); | 303 | void msm_perf_debugfs_cleanup(struct msm_drm_private *priv); |
304 | #else | 304 | #else |
305 | static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; } | 305 | static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; } |
306 | static inline void msm_rd_dump_submit(struct msm_gem_submit *submit) {} | 306 | static inline void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, |
307 | const char *fmt, ...) {} | ||
307 | static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {} | 308 | static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {} |
308 | static inline void msm_perf_debugfs_cleanup(struct msm_drm_private *priv) {} | 309 | static inline void msm_perf_debugfs_cleanup(struct msm_drm_private *priv) {} |
309 | #endif | 310 | #endif |
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 81fe6d6740ce..07376de9ff4c 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c | |||
@@ -93,14 +93,17 @@ static struct page **get_pages(struct drm_gem_object *obj) | |||
93 | return p; | 93 | return p; |
94 | } | 94 | } |
95 | 95 | ||
96 | msm_obj->pages = p; | ||
97 | |||
96 | msm_obj->sgt = drm_prime_pages_to_sg(p, npages); | 98 | msm_obj->sgt = drm_prime_pages_to_sg(p, npages); |
97 | if (IS_ERR(msm_obj->sgt)) { | 99 | if (IS_ERR(msm_obj->sgt)) { |
100 | void *ptr = ERR_CAST(msm_obj->sgt); | ||
101 | |||
98 | dev_err(dev->dev, "failed to allocate sgt\n"); | 102 | dev_err(dev->dev, "failed to allocate sgt\n"); |
99 | return ERR_CAST(msm_obj->sgt); | 103 | msm_obj->sgt = NULL; |
104 | return ptr; | ||
100 | } | 105 | } |
101 | 106 | ||
102 | msm_obj->pages = p; | ||
103 | |||
104 | /* For non-cached buffers, ensure the new pages are clean | 107 | /* For non-cached buffers, ensure the new pages are clean |
105 | * because display controller, GPU, etc. are not coherent: | 108 | * because display controller, GPU, etc. are not coherent: |
106 | */ | 109 | */ |
@@ -135,7 +138,10 @@ static void put_pages(struct drm_gem_object *obj) | |||
135 | if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) | 138 | if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) |
136 | dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, | 139 | dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, |
137 | msm_obj->sgt->nents, DMA_BIDIRECTIONAL); | 140 | msm_obj->sgt->nents, DMA_BIDIRECTIONAL); |
138 | sg_free_table(msm_obj->sgt); | 141 | |
142 | if (msm_obj->sgt) | ||
143 | sg_free_table(msm_obj->sgt); | ||
144 | |||
139 | kfree(msm_obj->sgt); | 145 | kfree(msm_obj->sgt); |
140 | 146 | ||
141 | if (use_pages(obj)) | 147 | if (use_pages(obj)) |
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 232201403439..bd376f9e18a7 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c | |||
@@ -21,42 +21,90 @@ | |||
21 | #include "msm_fence.h" | 21 | #include "msm_fence.h" |
22 | 22 | ||
23 | #include <linux/string_helpers.h> | 23 | #include <linux/string_helpers.h> |
24 | #include <linux/pm_opp.h> | ||
25 | #include <linux/devfreq.h> | ||
24 | 26 | ||
25 | 27 | ||
26 | /* | 28 | /* |
27 | * Power Management: | 29 | * Power Management: |
28 | */ | 30 | */ |
29 | 31 | ||
30 | #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING | 32 | static int msm_devfreq_target(struct device *dev, unsigned long *freq, |
31 | #include <mach/board.h> | 33 | u32 flags) |
32 | static void bs_init(struct msm_gpu *gpu) | ||
33 | { | 34 | { |
34 | if (gpu->bus_scale_table) { | 35 | struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev)); |
35 | gpu->bsc = msm_bus_scale_register_client(gpu->bus_scale_table); | 36 | struct dev_pm_opp *opp; |
36 | DBG("bus scale client: %08x", gpu->bsc); | 37 | |
37 | } | 38 | opp = devfreq_recommended_opp(dev, freq, flags); |
39 | |||
40 | if (IS_ERR(opp)) | ||
41 | return PTR_ERR(opp); | ||
42 | |||
43 | clk_set_rate(gpu->core_clk, *freq); | ||
44 | dev_pm_opp_put(opp); | ||
45 | |||
46 | return 0; | ||
38 | } | 47 | } |
39 | 48 | ||
40 | static void bs_fini(struct msm_gpu *gpu) | 49 | static int msm_devfreq_get_dev_status(struct device *dev, |
50 | struct devfreq_dev_status *status) | ||
41 | { | 51 | { |
42 | if (gpu->bsc) { | 52 | struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev)); |
43 | msm_bus_scale_unregister_client(gpu->bsc); | 53 | u64 cycles; |
44 | gpu->bsc = 0; | 54 | u32 freq = ((u32) status->current_frequency) / 1000000; |
45 | } | 55 | ktime_t time; |
56 | |||
57 | status->current_frequency = (unsigned long) clk_get_rate(gpu->core_clk); | ||
58 | gpu->funcs->gpu_busy(gpu, &cycles); | ||
59 | |||
60 | status->busy_time = ((u32) (cycles - gpu->devfreq.busy_cycles)) / freq; | ||
61 | |||
62 | gpu->devfreq.busy_cycles = cycles; | ||
63 | |||
64 | time = ktime_get(); | ||
65 | status->total_time = ktime_us_delta(time, gpu->devfreq.time); | ||
66 | gpu->devfreq.time = time; | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq) | ||
72 | { | ||
73 | struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev)); | ||
74 | |||
75 | *freq = (unsigned long) clk_get_rate(gpu->core_clk); | ||
76 | |||
77 | return 0; | ||
46 | } | 78 | } |
47 | 79 | ||
48 | static void bs_set(struct msm_gpu *gpu, int idx) | 80 | static struct devfreq_dev_profile msm_devfreq_profile = { |
81 | .polling_ms = 10, | ||
82 | .target = msm_devfreq_target, | ||
83 | .get_dev_status = msm_devfreq_get_dev_status, | ||
84 | .get_cur_freq = msm_devfreq_get_cur_freq, | ||
85 | }; | ||
86 | |||
87 | static void msm_devfreq_init(struct msm_gpu *gpu) | ||
49 | { | 88 | { |
50 | if (gpu->bsc) { | 89 | /* We need target support to do devfreq */ |
51 | DBG("set bus scaling: %d", idx); | 90 | if (!gpu->funcs->gpu_busy) |
52 | msm_bus_scale_client_update_request(gpu->bsc, idx); | 91 | return; |
92 | |||
93 | msm_devfreq_profile.initial_freq = gpu->fast_rate; | ||
94 | |||
95 | /* | ||
96 | * Don't set the freq_table or max_state and let devfreq build the table | ||
97 | * from OPP | ||
98 | */ | ||
99 | |||
100 | gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev, | ||
101 | &msm_devfreq_profile, "simple_ondemand", NULL); | ||
102 | |||
103 | if (IS_ERR(gpu->devfreq.devfreq)) { | ||
104 | dev_err(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n"); | ||
105 | gpu->devfreq.devfreq = NULL; | ||
53 | } | 106 | } |
54 | } | 107 | } |
55 | #else | ||
56 | static void bs_init(struct msm_gpu *gpu) {} | ||
57 | static void bs_fini(struct msm_gpu *gpu) {} | ||
58 | static void bs_set(struct msm_gpu *gpu, int idx) {} | ||
59 | #endif | ||
60 | 108 | ||
61 | static int enable_pwrrail(struct msm_gpu *gpu) | 109 | static int enable_pwrrail(struct msm_gpu *gpu) |
62 | { | 110 | { |
@@ -143,8 +191,6 @@ static int enable_axi(struct msm_gpu *gpu) | |||
143 | { | 191 | { |
144 | if (gpu->ebi1_clk) | 192 | if (gpu->ebi1_clk) |
145 | clk_prepare_enable(gpu->ebi1_clk); | 193 | clk_prepare_enable(gpu->ebi1_clk); |
146 | if (gpu->bus_freq) | ||
147 | bs_set(gpu, gpu->bus_freq); | ||
148 | return 0; | 194 | return 0; |
149 | } | 195 | } |
150 | 196 | ||
@@ -152,8 +198,6 @@ static int disable_axi(struct msm_gpu *gpu) | |||
152 | { | 198 | { |
153 | if (gpu->ebi1_clk) | 199 | if (gpu->ebi1_clk) |
154 | clk_disable_unprepare(gpu->ebi1_clk); | 200 | clk_disable_unprepare(gpu->ebi1_clk); |
155 | if (gpu->bus_freq) | ||
156 | bs_set(gpu, 0); | ||
157 | return 0; | 201 | return 0; |
158 | } | 202 | } |
159 | 203 | ||
@@ -175,6 +219,13 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu) | |||
175 | if (ret) | 219 | if (ret) |
176 | return ret; | 220 | return ret; |
177 | 221 | ||
222 | if (gpu->devfreq.devfreq) { | ||
223 | gpu->devfreq.busy_cycles = 0; | ||
224 | gpu->devfreq.time = ktime_get(); | ||
225 | |||
226 | devfreq_resume_device(gpu->devfreq.devfreq); | ||
227 | } | ||
228 | |||
178 | gpu->needs_hw_init = true; | 229 | gpu->needs_hw_init = true; |
179 | 230 | ||
180 | return 0; | 231 | return 0; |
@@ -186,6 +237,9 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu) | |||
186 | 237 | ||
187 | DBG("%s", gpu->name); | 238 | DBG("%s", gpu->name); |
188 | 239 | ||
240 | if (gpu->devfreq.devfreq) | ||
241 | devfreq_suspend_device(gpu->devfreq.devfreq); | ||
242 | |||
189 | ret = disable_axi(gpu); | 243 | ret = disable_axi(gpu); |
190 | if (ret) | 244 | if (ret) |
191 | return ret; | 245 | return ret; |
@@ -294,6 +348,8 @@ static void recover_worker(struct work_struct *work) | |||
294 | 348 | ||
295 | msm_rd_dump_submit(priv->hangrd, submit, | 349 | msm_rd_dump_submit(priv->hangrd, submit, |
296 | "offending task: %s (%s)", task->comm, cmd); | 350 | "offending task: %s (%s)", task->comm, cmd); |
351 | |||
352 | kfree(cmd); | ||
297 | } else { | 353 | } else { |
298 | msm_rd_dump_submit(priv->hangrd, submit, NULL); | 354 | msm_rd_dump_submit(priv->hangrd, submit, NULL); |
299 | } | 355 | } |
@@ -306,7 +362,7 @@ static void recover_worker(struct work_struct *work) | |||
306 | * needs to happen after msm_rd_dump_submit() to ensure that the | 362 | * needs to happen after msm_rd_dump_submit() to ensure that the |
307 | * bo's referenced by the offending submit are still around. | 363 | * bo's referenced by the offending submit are still around. |
308 | */ | 364 | */ |
309 | for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) { | 365 | for (i = 0; i < gpu->nr_rings; i++) { |
310 | struct msm_ringbuffer *ring = gpu->rb[i]; | 366 | struct msm_ringbuffer *ring = gpu->rb[i]; |
311 | 367 | ||
312 | uint32_t fence = ring->memptrs->fence; | 368 | uint32_t fence = ring->memptrs->fence; |
@@ -753,7 +809,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, | |||
753 | gpu->pdev = pdev; | 809 | gpu->pdev = pdev; |
754 | platform_set_drvdata(pdev, gpu); | 810 | platform_set_drvdata(pdev, gpu); |
755 | 811 | ||
756 | bs_init(gpu); | 812 | msm_devfreq_init(gpu); |
757 | 813 | ||
758 | gpu->aspace = msm_gpu_create_address_space(gpu, pdev, | 814 | gpu->aspace = msm_gpu_create_address_space(gpu, pdev, |
759 | config->va_start, config->va_end); | 815 | config->va_start, config->va_end); |
@@ -824,8 +880,6 @@ void msm_gpu_cleanup(struct msm_gpu *gpu) | |||
824 | 880 | ||
825 | WARN_ON(!list_empty(&gpu->active_list)); | 881 | WARN_ON(!list_empty(&gpu->active_list)); |
826 | 882 | ||
827 | bs_fini(gpu); | ||
828 | |||
829 | for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) { | 883 | for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) { |
830 | msm_ringbuffer_destroy(gpu->rb[i]); | 884 | msm_ringbuffer_destroy(gpu->rb[i]); |
831 | gpu->rb[i] = NULL; | 885 | gpu->rb[i] = NULL; |
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index e113d64574d3..fccfccd303af 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h | |||
@@ -66,6 +66,7 @@ struct msm_gpu_funcs { | |||
66 | /* show GPU status in debugfs: */ | 66 | /* show GPU status in debugfs: */ |
67 | void (*show)(struct msm_gpu *gpu, struct seq_file *m); | 67 | void (*show)(struct msm_gpu *gpu, struct seq_file *m); |
68 | #endif | 68 | #endif |
69 | int (*gpu_busy)(struct msm_gpu *gpu, uint64_t *value); | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | struct msm_gpu { | 72 | struct msm_gpu { |
@@ -108,12 +109,7 @@ struct msm_gpu { | |||
108 | struct clk **grp_clks; | 109 | struct clk **grp_clks; |
109 | int nr_clocks; | 110 | int nr_clocks; |
110 | struct clk *ebi1_clk, *core_clk, *rbbmtimer_clk; | 111 | struct clk *ebi1_clk, *core_clk, *rbbmtimer_clk; |
111 | uint32_t fast_rate, bus_freq; | 112 | uint32_t fast_rate; |
112 | |||
113 | #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING | ||
114 | struct msm_bus_scale_pdata *bus_scale_table; | ||
115 | uint32_t bsc; | ||
116 | #endif | ||
117 | 113 | ||
118 | /* Hang and Inactivity Detection: | 114 | /* Hang and Inactivity Detection: |
119 | */ | 115 | */ |
@@ -125,6 +121,12 @@ struct msm_gpu { | |||
125 | struct work_struct recover_work; | 121 | struct work_struct recover_work; |
126 | 122 | ||
127 | struct drm_gem_object *memptrs_bo; | 123 | struct drm_gem_object *memptrs_bo; |
124 | |||
125 | struct { | ||
126 | struct devfreq *devfreq; | ||
127 | u64 busy_cycles; | ||
128 | ktime_t time; | ||
129 | } devfreq; | ||
128 | }; | 130 | }; |
129 | 131 | ||
130 | /* It turns out that all targets use the same ringbuffer size */ | 132 | /* It turns out that all targets use the same ringbuffer size */ |