aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_fbdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fbdev.c')
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index fb5bb5b32a60..7f365ac0b549 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -679,6 +679,7 @@ int intel_fbdev_init(struct drm_device *dev)
679 if (ifbdev == NULL) 679 if (ifbdev == NULL)
680 return -ENOMEM; 680 return -ENOMEM;
681 681
682 mutex_init(&ifbdev->hpd_lock);
682 drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs); 683 drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
683 684
684 if (!intel_fbdev_init_bios(dev, ifbdev)) 685 if (!intel_fbdev_init_bios(dev, ifbdev))
@@ -752,6 +753,26 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv)
752 intel_fbdev_destroy(ifbdev); 753 intel_fbdev_destroy(ifbdev);
753} 754}
754 755
756/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD
757 * processing, fbdev will perform a full connector reprobe if a hotplug event
758 * was received while HPD was suspended.
759 */
760static void intel_fbdev_hpd_set_suspend(struct intel_fbdev *ifbdev, int state)
761{
762 bool send_hpd = false;
763
764 mutex_lock(&ifbdev->hpd_lock);
765 ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED;
766 send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting;
767 ifbdev->hpd_waiting = false;
768 mutex_unlock(&ifbdev->hpd_lock);
769
770 if (send_hpd) {
771 DRM_DEBUG_KMS("Handling delayed fbcon HPD event\n");
772 drm_fb_helper_hotplug_event(&ifbdev->helper);
773 }
774}
775
755void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) 776void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
756{ 777{
757 struct drm_i915_private *dev_priv = to_i915(dev); 778 struct drm_i915_private *dev_priv = to_i915(dev);
@@ -773,6 +794,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
773 */ 794 */
774 if (state != FBINFO_STATE_RUNNING) 795 if (state != FBINFO_STATE_RUNNING)
775 flush_work(&dev_priv->fbdev_suspend_work); 796 flush_work(&dev_priv->fbdev_suspend_work);
797
776 console_lock(); 798 console_lock();
777 } else { 799 } else {
778 /* 800 /*
@@ -800,17 +822,26 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
800 822
801 drm_fb_helper_set_suspend(&ifbdev->helper, state); 823 drm_fb_helper_set_suspend(&ifbdev->helper, state);
802 console_unlock(); 824 console_unlock();
825
826 intel_fbdev_hpd_set_suspend(ifbdev, state);
803} 827}
804 828
805void intel_fbdev_output_poll_changed(struct drm_device *dev) 829void intel_fbdev_output_poll_changed(struct drm_device *dev)
806{ 830{
807 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; 831 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
832 bool send_hpd;
808 833
809 if (!ifbdev) 834 if (!ifbdev)
810 return; 835 return;
811 836
812 intel_fbdev_sync(ifbdev); 837 intel_fbdev_sync(ifbdev);
813 if (ifbdev->vma || ifbdev->helper.deferred_setup) 838
839 mutex_lock(&ifbdev->hpd_lock);
840 send_hpd = !ifbdev->hpd_suspended;
841 ifbdev->hpd_waiting = true;
842 mutex_unlock(&ifbdev->hpd_lock);
843
844 if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))
814 drm_fb_helper_hotplug_event(&ifbdev->helper); 845 drm_fb_helper_hotplug_event(&ifbdev->helper);
815} 846}
816 847