aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-06-18 02:28:00 -0400
committerBen Skeggs <bskeggs@redhat.com>2011-09-20 02:02:53 -0400
commitd0f67a48f47a1874622418ba6bc2c45935b01b36 (patch)
tree085fa2e87f4dedcd54206947a718693a67cb4170 /drivers/gpu/drm/nouveau
parent78e2933d07124ea28593a1bdadc546294f77a504 (diff)
drm/nva3/pm: idle graphics engine before changing clocks
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r--drivers/gpu/drm/nouveau/nva3_pm.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c
index 98ea3aa0bb65..8541d5215e0d 100644
--- a/drivers/gpu/drm/nouveau/nva3_pm.c
+++ b/drivers/gpu/drm/nouveau/nva3_pm.c
@@ -264,10 +264,40 @@ out:
264 return info; 264 return info;
265} 265}
266 266
267static bool
268nva3_pm_grcp_idle(void *data)
269{
270 struct drm_device *dev = data;
271
272 if (!(nv_rd32(dev, 0x400304) & 0x00000001))
273 return true;
274 if (nv_rd32(dev, 0x400308) == 0x0050001c)
275 return true;
276 return false;
277}
278
267void 279void
268nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) 280nva3_pm_clocks_set(struct drm_device *dev, void *pre_state)
269{ 281{
282 struct drm_nouveau_private *dev_priv = dev->dev_private;
270 struct nva3_pm_state *info = pre_state; 283 struct nva3_pm_state *info = pre_state;
284 unsigned long flags;
285
286 /* prevent any new grctx switches from starting */
287 spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
288 nv_wr32(dev, 0x400324, 0x00000000);
289 nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */
290 /* wait for any pending grctx switches to complete */
291 if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) {
292 NV_ERROR(dev, "pm: ctxprog didn't go idle\n");
293 goto cleanup;
294 }
295 /* freeze PFIFO */
296 nv_mask(dev, 0x002504, 0x00000001, 0x00000001);
297 if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) {
298 NV_ERROR(dev, "pm: fifo didn't go idle\n");
299 goto cleanup;
300 }
271 301
272 prog_pll(dev, 0x00, 0x004200, &info->nclk); 302 prog_pll(dev, 0x00, 0x004200, &info->nclk);
273 prog_pll(dev, 0x01, 0x004220, &info->sclk); 303 prog_pll(dev, 0x01, 0x004220, &info->sclk);
@@ -285,5 +315,15 @@ nva3_pm_clocks_set(struct drm_device *dev, void *pre_state)
285 nv_wr32(dev, 0x1002dc, 0); 315 nv_wr32(dev, 0x1002dc, 0);
286 nv_wr32(dev, 0x100210, 0x80000000); 316 nv_wr32(dev, 0x100210, 0x80000000);
287 317
318cleanup:
319 /* unfreeze PFIFO */
320 nv_mask(dev, 0x002504, 0x00000001, 0x00000000);
321 /* restore ctxprog to normal */
322 nv_wr32(dev, 0x400324, 0x00000000);
323 nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */
324 /* unblock it if necessary */
325 if (nv_rd32(dev, 0x400308) == 0x0050001c)
326 nv_mask(dev, 0x400824, 0x10000000, 0x10000000);
327 spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
288 kfree(info); 328 kfree(info);
289} 329}