aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-03 11:31:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-03 11:31:14 -0400
commit80ad99da8bd213e12b925407f1c97a303aa8f87f (patch)
treef31f9409e2018154f1ceb2aa44194c6dd017e284 /drivers/gpu
parent58586869599f6bb38aeca71a847cd77bfea74808 (diff)
parenteee0815dabbdd7d584bea8275f5758d25c97cb9b (diff)
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull drm fixes from Dave Airlie: "Nothing too major or scary. One i915 regression fix, nouveau has a tmds regression fix, along with a regression fix for the runtime pm code for optimus laptops not restoring the display hw correctly" * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: drm/nouveau: make sure display hardware is reinitialised on runtime resume drm/nouveau: punt fbcon resume out to a workqueue drm/nouveau: fix regression on original nv50 board drm/nv50/disp: fix dpms regression on certain boards drm/i915: Flush the PTEs after updating them before suspend
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c23
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c51
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c23
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.h1
8 files changed, 65 insertions, 62 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 1411613f2174..e42925f76b4b 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -1310,6 +1310,16 @@ void i915_check_and_clear_faults(struct drm_device *dev)
1310 POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS])); 1310 POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS]));
1311} 1311}
1312 1312
1313static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
1314{
1315 if (INTEL_INFO(dev_priv->dev)->gen < 6) {
1316 intel_gtt_chipset_flush();
1317 } else {
1318 I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
1319 POSTING_READ(GFX_FLSH_CNTL_GEN6);
1320 }
1321}
1322
1313void i915_gem_suspend_gtt_mappings(struct drm_device *dev) 1323void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
1314{ 1324{
1315 struct drm_i915_private *dev_priv = dev->dev_private; 1325 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1326,6 +1336,8 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
1326 dev_priv->gtt.base.start, 1336 dev_priv->gtt.base.start,
1327 dev_priv->gtt.base.total, 1337 dev_priv->gtt.base.total,
1328 true); 1338 true);
1339
1340 i915_ggtt_flush(dev_priv);
1329} 1341}
1330 1342
1331void i915_gem_restore_gtt_mappings(struct drm_device *dev) 1343void i915_gem_restore_gtt_mappings(struct drm_device *dev)
@@ -1378,7 +1390,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
1378 gen6_write_pdes(container_of(vm, struct i915_hw_ppgtt, base)); 1390 gen6_write_pdes(container_of(vm, struct i915_hw_ppgtt, base));
1379 } 1391 }
1380 1392
1381 i915_gem_chipset_flush(dev); 1393 i915_ggtt_flush(dev_priv);
1382} 1394}
1383 1395
1384int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj) 1396int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 4b5bb5d58a54..f8cbb512132f 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -1763,9 +1763,10 @@ nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp
1763 const int or = ffs(outp->or) - 1; 1763 const int or = ffs(outp->or) - 1;
1764 const u32 loff = (or * 0x800) + (link * 0x80); 1764 const u32 loff = (or * 0x800) + (link * 0x80);
1765 const u16 mask = (outp->sorconf.link << 6) | outp->or; 1765 const u16 mask = (outp->sorconf.link << 6) | outp->or;
1766 struct dcb_output match;
1766 u8 ver, hdr; 1767 u8 ver, hdr;
1767 1768
1768 if (dcb_outp_match(bios, DCB_OUTPUT_DP, mask, &ver, &hdr, outp)) 1769 if (dcb_outp_match(bios, DCB_OUTPUT_DP, mask, &ver, &hdr, &match))
1769 nv_mask(priv, 0x61c10c + loff, 0x00000001, 0x00000000); 1770 nv_mask(priv, 0x61c10c + loff, 0x00000001, 0x00000000);
1770} 1771}
1771 1772
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index 99cd9e4a2aa6..3440fc999f2f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -285,6 +285,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
285 struct nouveau_software_chan *swch; 285 struct nouveau_software_chan *swch;
286 struct nv_dma_v0 args = {}; 286 struct nv_dma_v0 args = {};
287 int ret, i; 287 int ret, i;
288 bool save;
288 289
289 nvif_object_map(chan->object); 290 nvif_object_map(chan->object);
290 291
@@ -386,7 +387,11 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
386 } 387 }
387 388
388 /* initialise synchronisation */ 389 /* initialise synchronisation */
389 return nouveau_fence(chan->drm)->context_new(chan); 390 save = cli->base.super;
391 cli->base.super = true; /* hack until fencenv50 fixed */
392 ret = nouveau_fence(chan->drm)->context_new(chan);
393 cli->base.super = save;
394 return ret;
390} 395}
391 396
392int 397int
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 65b4fd53dd4e..4a21b2b06ce2 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -550,14 +550,12 @@ nouveau_display_destroy(struct drm_device *dev)
550} 550}
551 551
552int 552int
553nouveau_display_suspend(struct drm_device *dev) 553nouveau_display_suspend(struct drm_device *dev, bool runtime)
554{ 554{
555 struct nouveau_drm *drm = nouveau_drm(dev);
556 struct drm_crtc *crtc; 555 struct drm_crtc *crtc;
557 556
558 nouveau_display_fini(dev); 557 nouveau_display_fini(dev);
559 558
560 NV_INFO(drm, "unpinning framebuffer(s)...\n");
561 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 559 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
562 struct nouveau_framebuffer *nouveau_fb; 560 struct nouveau_framebuffer *nouveau_fb;
563 561
@@ -579,12 +577,13 @@ nouveau_display_suspend(struct drm_device *dev)
579} 577}
580 578
581void 579void
582nouveau_display_repin(struct drm_device *dev) 580nouveau_display_resume(struct drm_device *dev, bool runtime)
583{ 581{
584 struct nouveau_drm *drm = nouveau_drm(dev); 582 struct nouveau_drm *drm = nouveau_drm(dev);
585 struct drm_crtc *crtc; 583 struct drm_crtc *crtc;
586 int ret; 584 int ret, head;
587 585
586 /* re-pin fb/cursors */
588 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 587 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
589 struct nouveau_framebuffer *nouveau_fb; 588 struct nouveau_framebuffer *nouveau_fb;
590 589
@@ -606,13 +605,6 @@ nouveau_display_repin(struct drm_device *dev)
606 if (ret) 605 if (ret)
607 NV_ERROR(drm, "Could not pin/map cursor.\n"); 606 NV_ERROR(drm, "Could not pin/map cursor.\n");
608 } 607 }
609}
610
611void
612nouveau_display_resume(struct drm_device *dev)
613{
614 struct drm_crtc *crtc;
615 int head;
616 608
617 nouveau_display_init(dev); 609 nouveau_display_init(dev);
618 610
@@ -627,6 +619,13 @@ nouveau_display_resume(struct drm_device *dev)
627 for (head = 0; head < dev->mode_config.num_crtc; head++) 619 for (head = 0; head < dev->mode_config.num_crtc; head++)
628 drm_vblank_on(dev, head); 620 drm_vblank_on(dev, head);
629 621
622 /* This should ensure we don't hit a locking problem when someone
623 * wakes us up via a connector. We should never go into suspend
624 * while the display is on anyways.
625 */
626 if (runtime)
627 return;
628
630 drm_helper_resume_force_mode(dev); 629 drm_helper_resume_force_mode(dev);
631 630
632 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 631 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 88ca177cb1c7..be3d5947c6be 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -63,9 +63,8 @@ int nouveau_display_create(struct drm_device *dev);
63void nouveau_display_destroy(struct drm_device *dev); 63void nouveau_display_destroy(struct drm_device *dev);
64int nouveau_display_init(struct drm_device *dev); 64int nouveau_display_init(struct drm_device *dev);
65void nouveau_display_fini(struct drm_device *dev); 65void nouveau_display_fini(struct drm_device *dev);
66int nouveau_display_suspend(struct drm_device *dev); 66int nouveau_display_suspend(struct drm_device *dev, bool runtime);
67void nouveau_display_repin(struct drm_device *dev); 67void nouveau_display_resume(struct drm_device *dev, bool runtime);
68void nouveau_display_resume(struct drm_device *dev);
69int nouveau_display_vblank_enable(struct drm_device *, int); 68int nouveau_display_vblank_enable(struct drm_device *, int);
70void nouveau_display_vblank_disable(struct drm_device *, int); 69void nouveau_display_vblank_disable(struct drm_device *, int);
71int nouveau_display_scanoutpos(struct drm_device *, int, unsigned int, 70int nouveau_display_scanoutpos(struct drm_device *, int, unsigned int,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 9c3af96a7153..3ed32dd90303 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -547,9 +547,11 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
547 struct nouveau_cli *cli; 547 struct nouveau_cli *cli;
548 int ret; 548 int ret;
549 549
550 if (dev->mode_config.num_crtc && !runtime) { 550 if (dev->mode_config.num_crtc) {
551 NV_INFO(drm, "suspending console...\n");
552 nouveau_fbcon_set_suspend(dev, 1);
551 NV_INFO(drm, "suspending display...\n"); 553 NV_INFO(drm, "suspending display...\n");
552 ret = nouveau_display_suspend(dev); 554 ret = nouveau_display_suspend(dev, runtime);
553 if (ret) 555 if (ret)
554 return ret; 556 return ret;
555 } 557 }
@@ -603,7 +605,7 @@ fail_client:
603fail_display: 605fail_display:
604 if (dev->mode_config.num_crtc) { 606 if (dev->mode_config.num_crtc) {
605 NV_INFO(drm, "resuming display...\n"); 607 NV_INFO(drm, "resuming display...\n");
606 nouveau_display_resume(dev); 608 nouveau_display_resume(dev, runtime);
607 } 609 }
608 return ret; 610 return ret;
609} 611}
@@ -618,9 +620,6 @@ int nouveau_pmops_suspend(struct device *dev)
618 drm_dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF) 620 drm_dev->switch_power_state == DRM_SWITCH_POWER_DYNAMIC_OFF)
619 return 0; 621 return 0;
620 622
621 if (drm_dev->mode_config.num_crtc)
622 nouveau_fbcon_set_suspend(drm_dev, 1);
623
624 ret = nouveau_do_suspend(drm_dev, false); 623 ret = nouveau_do_suspend(drm_dev, false);
625 if (ret) 624 if (ret)
626 return ret; 625 return ret;
@@ -633,7 +632,7 @@ int nouveau_pmops_suspend(struct device *dev)
633} 632}
634 633
635static int 634static int
636nouveau_do_resume(struct drm_device *dev) 635nouveau_do_resume(struct drm_device *dev, bool runtime)
637{ 636{
638 struct nouveau_drm *drm = nouveau_drm(dev); 637 struct nouveau_drm *drm = nouveau_drm(dev);
639 struct nouveau_cli *cli; 638 struct nouveau_cli *cli;
@@ -658,7 +657,9 @@ nouveau_do_resume(struct drm_device *dev)
658 657
659 if (dev->mode_config.num_crtc) { 658 if (dev->mode_config.num_crtc) {
660 NV_INFO(drm, "resuming display...\n"); 659 NV_INFO(drm, "resuming display...\n");
661 nouveau_display_repin(dev); 660 nouveau_display_resume(dev, runtime);
661 NV_INFO(drm, "resuming console...\n");
662 nouveau_fbcon_set_suspend(dev, 0);
662 } 663 }
663 664
664 return 0; 665 return 0;
@@ -681,47 +682,21 @@ int nouveau_pmops_resume(struct device *dev)
681 return ret; 682 return ret;
682 pci_set_master(pdev); 683 pci_set_master(pdev);
683 684
684 ret = nouveau_do_resume(drm_dev); 685 return nouveau_do_resume(drm_dev, false);
685 if (ret)
686 return ret;
687
688 if (drm_dev->mode_config.num_crtc) {
689 nouveau_display_resume(drm_dev);
690 nouveau_fbcon_set_suspend(drm_dev, 0);
691 }
692
693 return 0;
694} 686}
695 687
696static int nouveau_pmops_freeze(struct device *dev) 688static int nouveau_pmops_freeze(struct device *dev)
697{ 689{
698 struct pci_dev *pdev = to_pci_dev(dev); 690 struct pci_dev *pdev = to_pci_dev(dev);
699 struct drm_device *drm_dev = pci_get_drvdata(pdev); 691 struct drm_device *drm_dev = pci_get_drvdata(pdev);
700 int ret; 692 return nouveau_do_suspend(drm_dev, false);
701
702 if (drm_dev->mode_config.num_crtc)
703 nouveau_fbcon_set_suspend(drm_dev, 1);
704
705 ret = nouveau_do_suspend(drm_dev, false);
706 return ret;
707} 693}
708 694
709static int nouveau_pmops_thaw(struct device *dev) 695static int nouveau_pmops_thaw(struct device *dev)
710{ 696{
711 struct pci_dev *pdev = to_pci_dev(dev); 697 struct pci_dev *pdev = to_pci_dev(dev);
712 struct drm_device *drm_dev = pci_get_drvdata(pdev); 698 struct drm_device *drm_dev = pci_get_drvdata(pdev);
713 int ret; 699 return nouveau_do_resume(drm_dev, false);
714
715 ret = nouveau_do_resume(drm_dev);
716 if (ret)
717 return ret;
718
719 if (drm_dev->mode_config.num_crtc) {
720 nouveau_display_resume(drm_dev);
721 nouveau_fbcon_set_suspend(drm_dev, 0);
722 }
723
724 return 0;
725} 700}
726 701
727 702
@@ -977,7 +952,7 @@ static int nouveau_pmops_runtime_resume(struct device *dev)
977 return ret; 952 return ret;
978 pci_set_master(pdev); 953 pci_set_master(pdev);
979 954
980 ret = nouveau_do_resume(drm_dev); 955 ret = nouveau_do_resume(drm_dev, true);
981 drm_kms_helper_poll_enable(drm_dev); 956 drm_kms_helper_poll_enable(drm_dev);
982 /* do magic */ 957 /* do magic */
983 nvif_mask(device, 0x88488, (1 << 25), (1 << 25)); 958 nvif_mask(device, 0x88488, (1 << 25), (1 << 25));
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 8bdd27091db8..49fe6075cc7c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -486,6 +486,16 @@ static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
486 .fb_probe = nouveau_fbcon_create, 486 .fb_probe = nouveau_fbcon_create,
487}; 487};
488 488
489static void
490nouveau_fbcon_set_suspend_work(struct work_struct *work)
491{
492 struct nouveau_fbdev *fbcon = container_of(work, typeof(*fbcon), work);
493 console_lock();
494 nouveau_fbcon_accel_restore(fbcon->dev);
495 nouveau_fbcon_zfill(fbcon->dev, fbcon);
496 fb_set_suspend(fbcon->helper.fbdev, FBINFO_STATE_RUNNING);
497 console_unlock();
498}
489 499
490int 500int
491nouveau_fbcon_init(struct drm_device *dev) 501nouveau_fbcon_init(struct drm_device *dev)
@@ -503,6 +513,7 @@ nouveau_fbcon_init(struct drm_device *dev)
503 if (!fbcon) 513 if (!fbcon)
504 return -ENOMEM; 514 return -ENOMEM;
505 515
516 INIT_WORK(&fbcon->work, nouveau_fbcon_set_suspend_work);
506 fbcon->dev = dev; 517 fbcon->dev = dev;
507 drm->fbcon = fbcon; 518 drm->fbcon = fbcon;
508 519
@@ -551,14 +562,14 @@ nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
551{ 562{
552 struct nouveau_drm *drm = nouveau_drm(dev); 563 struct nouveau_drm *drm = nouveau_drm(dev);
553 if (drm->fbcon) { 564 if (drm->fbcon) {
554 console_lock(); 565 if (state == FBINFO_STATE_RUNNING) {
555 if (state == 0) { 566 schedule_work(&drm->fbcon->work);
556 nouveau_fbcon_accel_restore(dev); 567 return;
557 nouveau_fbcon_zfill(dev, drm->fbcon);
558 } 568 }
569 flush_work(&drm->fbcon->work);
570 console_lock();
559 fb_set_suspend(drm->fbcon->helper.fbdev, state); 571 fb_set_suspend(drm->fbcon->helper.fbdev, state);
560 if (state == 1) 572 nouveau_fbcon_accel_save_disable(dev);
561 nouveau_fbcon_accel_save_disable(dev);
562 console_unlock(); 573 console_unlock();
563 } 574 }
564} 575}
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
index 34658cfa8f5d..0b465c7d3907 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
@@ -36,6 +36,7 @@ struct nouveau_fbdev {
36 struct nouveau_framebuffer nouveau_fb; 36 struct nouveau_framebuffer nouveau_fb;
37 struct list_head fbdev_list; 37 struct list_head fbdev_list;
38 struct drm_device *dev; 38 struct drm_device *dev;
39 struct work_struct work;
39 unsigned int saved_flags; 40 unsigned int saved_flags;
40 struct nvif_object surf2d; 41 struct nvif_object surf2d;
41 struct nvif_object clip; 42 struct nvif_object clip;