aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2014-04-01 12:55:22 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-04-04 03:30:10 -0400
commit76c4b250080fff6e4befaa3619942422fd0ea380 (patch)
treea6f7a01f06504a98e3a0691f0eac1afb4a533a76
parentbc104d1f10eb6001f1b1003a5a92066a1b03f080 (diff)
drm/i915: move power domain init earlier during system resume
During resume the intel hda audio driver depends on the i915 driver reinitializing the audio power domain. Since the order of calling the i915 resume handler wrt. that of the audio driver is not guaranteed, move the power domain reinitialization step to the resume_early handler. This is guaranteed to run before the resume handler of any other driver. The power domain initialization in turn requires us to enable the i915 pci device first, so move that part earlier too. Accordingly disabling of the i915 pci device should happen after the audio suspend handler ran. So move the disabling later from the i915 resume handler to the resume_late handler. v2: - move intel_uncore_sanitize/early_sanitize earlier too, so they don't get reordered wrt. intel_power_domains_init_hw() Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76152 Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Takashi Iwai <tiwai@suse.de> Cc: stable@vger.kernel.org [danvet: Add cc: stable and loud comments that this is just a hack.] [danvet: Fix "Should it be static?" sparse warning reported by Wu Fengguang's kbuilder.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c90
1 files changed, 76 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 11f77a8e4c4d..82f4d1f47d3b 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -537,14 +537,21 @@ static void intel_resume_hotplug(struct drm_device *dev)
537 drm_helper_hpd_irq_event(dev); 537 drm_helper_hpd_irq_event(dev);
538} 538}
539 539
540static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) 540static int i915_drm_thaw_early(struct drm_device *dev)
541{ 541{
542 struct drm_i915_private *dev_priv = dev->dev_private; 542 struct drm_i915_private *dev_priv = dev->dev_private;
543 int error = 0;
544 543
545 intel_uncore_early_sanitize(dev); 544 intel_uncore_early_sanitize(dev);
546
547 intel_uncore_sanitize(dev); 545 intel_uncore_sanitize(dev);
546 intel_power_domains_init_hw(dev_priv);
547
548 return 0;
549}
550
551static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
552{
553 struct drm_i915_private *dev_priv = dev->dev_private;
554 int error = 0;
548 555
549 if (drm_core_check_feature(dev, DRIVER_MODESET) && 556 if (drm_core_check_feature(dev, DRIVER_MODESET) &&
550 restore_gtt_mappings) { 557 restore_gtt_mappings) {
@@ -553,8 +560,6 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
553 mutex_unlock(&dev->struct_mutex); 560 mutex_unlock(&dev->struct_mutex);
554 } 561 }
555 562
556 intel_power_domains_init_hw(dev_priv);
557
558 i915_restore_state(dev); 563 i915_restore_state(dev);
559 intel_opregion_setup(dev); 564 intel_opregion_setup(dev);
560 565
@@ -619,19 +624,33 @@ static int i915_drm_thaw(struct drm_device *dev)
619 return __i915_drm_thaw(dev, true); 624 return __i915_drm_thaw(dev, true);
620} 625}
621 626
622int i915_resume(struct drm_device *dev) 627static int i915_resume_early(struct drm_device *dev)
623{ 628{
624 struct drm_i915_private *dev_priv = dev->dev_private;
625 int ret;
626
627 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) 629 if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
628 return 0; 630 return 0;
629 631
632 /*
633 * We have a resume ordering issue with the snd-hda driver also
634 * requiring our device to be power up. Due to the lack of a
635 * parent/child relationship we currently solve this with an early
636 * resume hook.
637 *
638 * FIXME: This should be solved with a special hdmi sink device or
639 * similar so that power domains can be employed.
640 */
630 if (pci_enable_device(dev->pdev)) 641 if (pci_enable_device(dev->pdev))
631 return -EIO; 642 return -EIO;
632 643
633 pci_set_master(dev->pdev); 644 pci_set_master(dev->pdev);
634 645
646 return i915_drm_thaw_early(dev);
647}
648
649int i915_resume(struct drm_device *dev)
650{
651 struct drm_i915_private *dev_priv = dev->dev_private;
652 int ret;
653
635 /* 654 /*
636 * Platforms with opregion should have sane BIOS, older ones (gen3 and 655 * Platforms with opregion should have sane BIOS, older ones (gen3 and
637 * earlier) need to restore the GTT mappings since the BIOS might clear 656 * earlier) need to restore the GTT mappings since the BIOS might clear
@@ -645,6 +664,14 @@ int i915_resume(struct drm_device *dev)
645 return 0; 664 return 0;
646} 665}
647 666
667static int i915_resume_legacy(struct drm_device *dev)
668{
669 i915_resume_early(dev);
670 i915_resume(dev);
671
672 return 0;
673}
674
648/** 675/**
649 * i915_reset - reset chip after a hang 676 * i915_reset - reset chip after a hang
650 * @dev: drm device to reset 677 * @dev: drm device to reset
@@ -776,7 +803,6 @@ static int i915_pm_suspend(struct device *dev)
776{ 803{
777 struct pci_dev *pdev = to_pci_dev(dev); 804 struct pci_dev *pdev = to_pci_dev(dev);
778 struct drm_device *drm_dev = pci_get_drvdata(pdev); 805 struct drm_device *drm_dev = pci_get_drvdata(pdev);
779 int error;
780 806
781 if (!drm_dev || !drm_dev->dev_private) { 807 if (!drm_dev || !drm_dev->dev_private) {
782 dev_err(dev, "DRM not initialized, aborting suspend.\n"); 808 dev_err(dev, "DRM not initialized, aborting suspend.\n");
@@ -786,9 +812,25 @@ static int i915_pm_suspend(struct device *dev)
786 if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) 812 if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
787 return 0; 813 return 0;
788 814
789 error = i915_drm_freeze(drm_dev); 815 return i915_drm_freeze(drm_dev);
790 if (error) 816}
791 return error; 817
818static int i915_pm_suspend_late(struct device *dev)
819{
820 struct pci_dev *pdev = to_pci_dev(dev);
821 struct drm_device *drm_dev = pci_get_drvdata(pdev);
822
823 /*
824 * We have a suspedn ordering issue with the snd-hda driver also
825 * requiring our device to be power up. Due to the lack of a
826 * parent/child relationship we currently solve this with an late
827 * suspend hook.
828 *
829 * FIXME: This should be solved with a special hdmi sink device or
830 * similar so that power domains can be employed.
831 */
832 if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
833 return 0;
792 834
793 pci_disable_device(pdev); 835 pci_disable_device(pdev);
794 pci_set_power_state(pdev, PCI_D3hot); 836 pci_set_power_state(pdev, PCI_D3hot);
@@ -796,6 +838,14 @@ static int i915_pm_suspend(struct device *dev)
796 return 0; 838 return 0;
797} 839}
798 840
841static int i915_pm_resume_early(struct device *dev)
842{
843 struct pci_dev *pdev = to_pci_dev(dev);
844 struct drm_device *drm_dev = pci_get_drvdata(pdev);
845
846 return i915_resume_early(drm_dev);
847}
848
799static int i915_pm_resume(struct device *dev) 849static int i915_pm_resume(struct device *dev)
800{ 850{
801 struct pci_dev *pdev = to_pci_dev(dev); 851 struct pci_dev *pdev = to_pci_dev(dev);
@@ -817,6 +867,14 @@ static int i915_pm_freeze(struct device *dev)
817 return i915_drm_freeze(drm_dev); 867 return i915_drm_freeze(drm_dev);
818} 868}
819 869
870static int i915_pm_thaw_early(struct device *dev)
871{
872 struct pci_dev *pdev = to_pci_dev(dev);
873 struct drm_device *drm_dev = pci_get_drvdata(pdev);
874
875 return i915_drm_thaw_early(drm_dev);
876}
877
820static int i915_pm_thaw(struct device *dev) 878static int i915_pm_thaw(struct device *dev)
821{ 879{
822 struct pci_dev *pdev = to_pci_dev(dev); 880 struct pci_dev *pdev = to_pci_dev(dev);
@@ -887,10 +945,14 @@ static int i915_runtime_resume(struct device *device)
887 945
888static const struct dev_pm_ops i915_pm_ops = { 946static const struct dev_pm_ops i915_pm_ops = {
889 .suspend = i915_pm_suspend, 947 .suspend = i915_pm_suspend,
948 .suspend_late = i915_pm_suspend_late,
949 .resume_early = i915_pm_resume_early,
890 .resume = i915_pm_resume, 950 .resume = i915_pm_resume,
891 .freeze = i915_pm_freeze, 951 .freeze = i915_pm_freeze,
952 .thaw_early = i915_pm_thaw_early,
892 .thaw = i915_pm_thaw, 953 .thaw = i915_pm_thaw,
893 .poweroff = i915_pm_poweroff, 954 .poweroff = i915_pm_poweroff,
955 .restore_early = i915_pm_resume_early,
894 .restore = i915_pm_resume, 956 .restore = i915_pm_resume,
895 .runtime_suspend = i915_runtime_suspend, 957 .runtime_suspend = i915_runtime_suspend,
896 .runtime_resume = i915_runtime_resume, 958 .runtime_resume = i915_runtime_resume,
@@ -933,7 +995,7 @@ static struct drm_driver driver = {
933 995
934 /* Used in place of i915_pm_ops for non-DRIVER_MODESET */ 996 /* Used in place of i915_pm_ops for non-DRIVER_MODESET */
935 .suspend = i915_suspend, 997 .suspend = i915_suspend,
936 .resume = i915_resume, 998 .resume = i915_resume_legacy,
937 999
938 .device_is_agp = i915_driver_device_is_agp, 1000 .device_is_agp = i915_driver_device_is_agp,
939 .master_create = i915_master_create, 1001 .master_create = i915_master_create,