diff options
| -rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 10 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_fbdev.c | 33 |
2 files changed, 42 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f94a04b4ad87..e9ddeaf05a14 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -209,6 +209,16 @@ struct intel_fbdev { | |||
| 209 | unsigned long vma_flags; | 209 | unsigned long vma_flags; |
| 210 | async_cookie_t cookie; | 210 | async_cookie_t cookie; |
| 211 | int preferred_bpp; | 211 | int preferred_bpp; |
| 212 | |||
| 213 | /* Whether or not fbdev hpd processing is temporarily suspended */ | ||
| 214 | bool hpd_suspended : 1; | ||
| 215 | /* Set when a hotplug was received while HPD processing was | ||
| 216 | * suspended | ||
| 217 | */ | ||
| 218 | bool hpd_waiting : 1; | ||
| 219 | |||
| 220 | /* Protects hpd_suspended */ | ||
| 221 | struct mutex hpd_lock; | ||
| 212 | }; | 222 | }; |
| 213 | 223 | ||
| 214 | struct intel_encoder { | 224 | struct intel_encoder { |
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 | */ | ||
| 760 | static 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 | |||
| 755 | void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) | 776 | void 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 | ||
| 805 | void intel_fbdev_output_poll_changed(struct drm_device *dev) | 829 | void 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 | ||
