diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fbdev.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_fbdev.c | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index fb5bb5b32a60..4ee16b264dbe 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c | |||
| @@ -336,8 +336,8 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, | |||
| 336 | bool *enabled, int width, int height) | 336 | bool *enabled, int width, int height) |
| 337 | { | 337 | { |
| 338 | struct drm_i915_private *dev_priv = to_i915(fb_helper->dev); | 338 | struct drm_i915_private *dev_priv = to_i915(fb_helper->dev); |
| 339 | unsigned long conn_configured, conn_seq, mask; | ||
| 340 | unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG); | 339 | unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG); |
| 340 | unsigned long conn_configured, conn_seq; | ||
| 341 | int i, j; | 341 | int i, j; |
| 342 | bool *save_enabled; | 342 | bool *save_enabled; |
| 343 | bool fallback = true, ret = true; | 343 | bool fallback = true, ret = true; |
| @@ -355,10 +355,9 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, | |||
| 355 | drm_modeset_backoff(&ctx); | 355 | drm_modeset_backoff(&ctx); |
| 356 | 356 | ||
| 357 | memcpy(save_enabled, enabled, count); | 357 | memcpy(save_enabled, enabled, count); |
| 358 | mask = GENMASK(count - 1, 0); | 358 | conn_seq = GENMASK(count - 1, 0); |
| 359 | conn_configured = 0; | 359 | conn_configured = 0; |
| 360 | retry: | 360 | retry: |
| 361 | conn_seq = conn_configured; | ||
| 362 | for (i = 0; i < count; i++) { | 361 | for (i = 0; i < count; i++) { |
| 363 | struct drm_fb_helper_connector *fb_conn; | 362 | struct drm_fb_helper_connector *fb_conn; |
| 364 | struct drm_connector *connector; | 363 | struct drm_connector *connector; |
| @@ -371,7 +370,8 @@ retry: | |||
| 371 | if (conn_configured & BIT(i)) | 370 | if (conn_configured & BIT(i)) |
| 372 | continue; | 371 | continue; |
| 373 | 372 | ||
| 374 | if (conn_seq == 0 && !connector->has_tile) | 373 | /* First pass, only consider tiled connectors */ |
| 374 | if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile) | ||
| 375 | continue; | 375 | continue; |
| 376 | 376 | ||
| 377 | if (connector->status == connector_status_connected) | 377 | if (connector->status == connector_status_connected) |
| @@ -475,8 +475,10 @@ retry: | |||
| 475 | conn_configured |= BIT(i); | 475 | conn_configured |= BIT(i); |
| 476 | } | 476 | } |
| 477 | 477 | ||
| 478 | if ((conn_configured & mask) != mask && conn_configured != conn_seq) | 478 | if (conn_configured != conn_seq) { /* repeat until no more are found */ |
| 479 | conn_seq = conn_configured; | ||
| 479 | goto retry; | 480 | goto retry; |
| 481 | } | ||
| 480 | 482 | ||
| 481 | /* | 483 | /* |
| 482 | * If the BIOS didn't enable everything it could, fall back to have the | 484 | * If the BIOS didn't enable everything it could, fall back to have the |
| @@ -679,6 +681,7 @@ int intel_fbdev_init(struct drm_device *dev) | |||
| 679 | if (ifbdev == NULL) | 681 | if (ifbdev == NULL) |
| 680 | return -ENOMEM; | 682 | return -ENOMEM; |
| 681 | 683 | ||
| 684 | mutex_init(&ifbdev->hpd_lock); | ||
| 682 | drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs); | 685 | drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs); |
| 683 | 686 | ||
| 684 | if (!intel_fbdev_init_bios(dev, ifbdev)) | 687 | if (!intel_fbdev_init_bios(dev, ifbdev)) |
| @@ -752,6 +755,26 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv) | |||
| 752 | intel_fbdev_destroy(ifbdev); | 755 | intel_fbdev_destroy(ifbdev); |
| 753 | } | 756 | } |
| 754 | 757 | ||
| 758 | /* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD | ||
| 759 | * processing, fbdev will perform a full connector reprobe if a hotplug event | ||
| 760 | * was received while HPD was suspended. | ||
| 761 | */ | ||
| 762 | static void intel_fbdev_hpd_set_suspend(struct intel_fbdev *ifbdev, int state) | ||
| 763 | { | ||
| 764 | bool send_hpd = false; | ||
| 765 | |||
| 766 | mutex_lock(&ifbdev->hpd_lock); | ||
| 767 | ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED; | ||
| 768 | send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting; | ||
| 769 | ifbdev->hpd_waiting = false; | ||
| 770 | mutex_unlock(&ifbdev->hpd_lock); | ||
| 771 | |||
| 772 | if (send_hpd) { | ||
| 773 | DRM_DEBUG_KMS("Handling delayed fbcon HPD event\n"); | ||
| 774 | drm_fb_helper_hotplug_event(&ifbdev->helper); | ||
| 775 | } | ||
| 776 | } | ||
| 777 | |||
| 755 | void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) | 778 | void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous) |
| 756 | { | 779 | { |
| 757 | struct drm_i915_private *dev_priv = to_i915(dev); | 780 | struct drm_i915_private *dev_priv = to_i915(dev); |
| @@ -773,6 +796,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous | |||
| 773 | */ | 796 | */ |
| 774 | if (state != FBINFO_STATE_RUNNING) | 797 | if (state != FBINFO_STATE_RUNNING) |
| 775 | flush_work(&dev_priv->fbdev_suspend_work); | 798 | flush_work(&dev_priv->fbdev_suspend_work); |
| 799 | |||
| 776 | console_lock(); | 800 | console_lock(); |
| 777 | } else { | 801 | } else { |
| 778 | /* | 802 | /* |
| @@ -800,17 +824,26 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous | |||
| 800 | 824 | ||
| 801 | drm_fb_helper_set_suspend(&ifbdev->helper, state); | 825 | drm_fb_helper_set_suspend(&ifbdev->helper, state); |
| 802 | console_unlock(); | 826 | console_unlock(); |
| 827 | |||
| 828 | intel_fbdev_hpd_set_suspend(ifbdev, state); | ||
| 803 | } | 829 | } |
| 804 | 830 | ||
| 805 | void intel_fbdev_output_poll_changed(struct drm_device *dev) | 831 | void intel_fbdev_output_poll_changed(struct drm_device *dev) |
| 806 | { | 832 | { |
| 807 | struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; | 833 | struct intel_fbdev *ifbdev = to_i915(dev)->fbdev; |
| 834 | bool send_hpd; | ||
| 808 | 835 | ||
| 809 | if (!ifbdev) | 836 | if (!ifbdev) |
| 810 | return; | 837 | return; |
| 811 | 838 | ||
| 812 | intel_fbdev_sync(ifbdev); | 839 | intel_fbdev_sync(ifbdev); |
| 813 | if (ifbdev->vma || ifbdev->helper.deferred_setup) | 840 | |
| 841 | mutex_lock(&ifbdev->hpd_lock); | ||
| 842 | send_hpd = !ifbdev->hpd_suspended; | ||
| 843 | ifbdev->hpd_waiting = true; | ||
| 844 | mutex_unlock(&ifbdev->hpd_lock); | ||
| 845 | |||
| 846 | if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup)) | ||
| 814 | drm_fb_helper_hotplug_event(&ifbdev->helper); | 847 | drm_fb_helper_hotplug_event(&ifbdev->helper); |
| 815 | } | 848 | } |
| 816 | 849 | ||
