aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-01-11 20:45:18 -0500
committerDave Airlie <airlied@redhat.com>2018-01-11 20:45:18 -0500
commit323b20c4af6e315e665b0ea85035fea7d738e0cc (patch)
treec5c59de32f20a0161e4c7d7e0269352b841eb4a2 /drivers
parentfb8baefc7b2d7b93ad96abacbe63fa99e3d213d6 (diff)
parentf91c14ab448af4d9d57350301dd9d6b6a7b6128a (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.c38
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_power.c8
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c140
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c85
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h4
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h7
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c9
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h3
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c14
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c112
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h14
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
1176static 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
1168static const struct adreno_gpu_funcs funcs = { 1184static 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
1204static 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
1187struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) 1223struct 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
93MODULE_FIRMWARE("a300_pm4.fw"); 92MODULE_FIRMWARE("qcom/a300_pm4.fw");
94MODULE_FIRMWARE("a300_pfp.fw"); 93MODULE_FIRMWARE("qcom/a300_pfp.fw");
95MODULE_FIRMWARE("a330_pm4.fw"); 94MODULE_FIRMWARE("qcom/a330_pm4.fw");
96MODULE_FIRMWARE("a330_pfp.fw"); 95MODULE_FIRMWARE("qcom/a330_pfp.fw");
97MODULE_FIRMWARE("a420_pm4.fw"); 96MODULE_FIRMWARE("qcom/a420_pm4.fw");
98MODULE_FIRMWARE("a420_pfp.fw"); 97MODULE_FIRMWARE("qcom/a420_pfp.fw");
99MODULE_FIRMWARE("a530_fm4.fw"); 98MODULE_FIRMWARE("qcom/a530_pm4.fw");
100MODULE_FIRMWARE("a530_pfp.fw"); 99MODULE_FIRMWARE("qcom/a530_pfp.fw");
100MODULE_FIRMWARE("qcom/a530v3_gpmu.fw2");
101MODULE_FIRMWARE("qcom/a530_zap.mdt");
102MODULE_FIRMWARE("qcom/a530_zap.b00");
103MODULE_FIRMWARE("qcom/a530_zap.b01");
104MODULE_FIRMWARE("qcom/a530_zap.b02");
101 105
102static inline bool _rev_match(uint8_t entry, uint8_t id) 106static 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
156static int find_chipid(struct device *dev, u32 *chipid) 163static 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 */
194static 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
224static 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
25int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) 25int 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 */
469static 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
499static 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
468int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, 538int 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) */
130struct adreno_platform_config { 130struct 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
237static 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)
245static inline void *mdp4_find_pdata(const char *devname) 241static 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);
303void msm_perf_debugfs_cleanup(struct msm_drm_private *priv); 303void msm_perf_debugfs_cleanup(struct msm_drm_private *priv);
304#else 304#else
305static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; } 305static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; }
306static inline void msm_rd_dump_submit(struct msm_gem_submit *submit) {} 306static inline void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
307 const char *fmt, ...) {}
307static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {} 308static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {}
308static inline void msm_perf_debugfs_cleanup(struct msm_drm_private *priv) {} 309static 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 32static int msm_devfreq_target(struct device *dev, unsigned long *freq,
31#include <mach/board.h> 33 u32 flags)
32static 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
40static void bs_fini(struct msm_gpu *gpu) 49static 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
71static 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
48static void bs_set(struct msm_gpu *gpu, int idx) 80static 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
87static 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
56static void bs_init(struct msm_gpu *gpu) {}
57static void bs_fini(struct msm_gpu *gpu) {}
58static void bs_set(struct msm_gpu *gpu, int idx) {}
59#endif
60 108
61static int enable_pwrrail(struct msm_gpu *gpu) 109static 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
71struct msm_gpu { 72struct 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 */