diff options
Diffstat (limited to 'drivers/gpu')
84 files changed, 799 insertions, 491 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index 57afad79f55d..8fa850a070e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | |||
@@ -540,6 +540,9 @@ int amdgpu_acpi_pcie_performance_request(struct amdgpu_device *adev, | |||
540 | size_t size; | 540 | size_t size; |
541 | u32 retry = 3; | 541 | u32 retry = 3; |
542 | 542 | ||
543 | if (amdgpu_acpi_pcie_notify_device_ready(adev)) | ||
544 | return -EINVAL; | ||
545 | |||
543 | /* Get the device handle */ | 546 | /* Get the device handle */ |
544 | handle = ACPI_HANDLE(&adev->pdev->dev); | 547 | handle = ACPI_HANDLE(&adev->pdev->dev); |
545 | if (!handle) | 548 | if (!handle) |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 74d2efaec52f..7a073ac5f9c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | |||
@@ -69,25 +69,18 @@ void amdgpu_connector_hotplug(struct drm_connector *connector) | |||
69 | /* don't do anything if sink is not display port, i.e., | 69 | /* don't do anything if sink is not display port, i.e., |
70 | * passive dp->(dvi|hdmi) adaptor | 70 | * passive dp->(dvi|hdmi) adaptor |
71 | */ | 71 | */ |
72 | if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { | 72 | if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT && |
73 | int saved_dpms = connector->dpms; | 73 | amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd) && |
74 | /* Only turn off the display if it's physically disconnected */ | 74 | amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) { |
75 | if (!amdgpu_display_hpd_sense(adev, amdgpu_connector->hpd.hpd)) { | 75 | /* Don't start link training before we have the DPCD */ |
76 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | 76 | if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector)) |
77 | } else if (amdgpu_atombios_dp_needs_link_train(amdgpu_connector)) { | 77 | return; |
78 | /* Don't try to start link training before we | 78 | |
79 | * have the dpcd */ | 79 | /* Turn the connector off and back on immediately, which |
80 | if (amdgpu_atombios_dp_get_dpcd(amdgpu_connector)) | 80 | * will trigger link training |
81 | return; | 81 | */ |
82 | 82 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | |
83 | /* set it to OFF so that drm_helper_connector_dpms() | 83 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); |
84 | * won't return immediately since the current state | ||
85 | * is ON at this point. | ||
86 | */ | ||
87 | connector->dpms = DRM_MODE_DPMS_OFF; | ||
88 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); | ||
89 | } | ||
90 | connector->dpms = saved_dpms; | ||
91 | } | 84 | } |
92 | } | 85 | } |
93 | } | 86 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index af1b879a9ee9..66cb10cdc7c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
@@ -2063,9 +2063,12 @@ void amdgpu_device_fini(struct amdgpu_device *adev) | |||
2063 | 2063 | ||
2064 | DRM_INFO("amdgpu: finishing device.\n"); | 2064 | DRM_INFO("amdgpu: finishing device.\n"); |
2065 | adev->shutdown = true; | 2065 | adev->shutdown = true; |
2066 | if (adev->mode_info.mode_config_initialized) | 2066 | if (adev->mode_info.mode_config_initialized){ |
2067 | drm_crtc_force_disable_all(adev->ddev); | 2067 | if (!amdgpu_device_has_dc_support(adev)) |
2068 | 2068 | drm_crtc_force_disable_all(adev->ddev); | |
2069 | else | ||
2070 | drm_atomic_helper_shutdown(adev->ddev); | ||
2071 | } | ||
2069 | amdgpu_ib_pool_fini(adev); | 2072 | amdgpu_ib_pool_fini(adev); |
2070 | amdgpu_fence_driver_fini(adev); | 2073 | amdgpu_fence_driver_fini(adev); |
2071 | amdgpu_fbdev_fini(adev); | 2074 | amdgpu_fbdev_fini(adev); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index e48b4ec88c8c..ca6c931dabfa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | |||
@@ -36,8 +36,6 @@ void amdgpu_gem_object_free(struct drm_gem_object *gobj) | |||
36 | struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj); | 36 | struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj); |
37 | 37 | ||
38 | if (robj) { | 38 | if (robj) { |
39 | if (robj->gem_base.import_attach) | ||
40 | drm_prime_gem_destroy(&robj->gem_base, robj->tbo.sg); | ||
41 | amdgpu_mn_unregister(robj); | 39 | amdgpu_mn_unregister(robj); |
42 | amdgpu_bo_unref(&robj); | 40 | amdgpu_bo_unref(&robj); |
43 | } | 41 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 54f06c959340..2264c5c97009 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | |||
@@ -352,6 +352,7 @@ struct amdgpu_mode_info { | |||
352 | u16 firmware_flags; | 352 | u16 firmware_flags; |
353 | /* pointer to backlight encoder */ | 353 | /* pointer to backlight encoder */ |
354 | struct amdgpu_encoder *bl_encoder; | 354 | struct amdgpu_encoder *bl_encoder; |
355 | u8 bl_level; /* saved backlight level */ | ||
355 | struct amdgpu_audio audio; /* audio stuff */ | 356 | struct amdgpu_audio audio; /* audio stuff */ |
356 | int num_crtc; /* number of crtcs */ | 357 | int num_crtc; /* number of crtcs */ |
357 | int num_hpd; /* number of hpd pins */ | 358 | int num_hpd; /* number of hpd pins */ |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 5c4c3e0d527b..1220322c1680 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | |||
@@ -56,6 +56,8 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo) | |||
56 | 56 | ||
57 | amdgpu_bo_kunmap(bo); | 57 | amdgpu_bo_kunmap(bo); |
58 | 58 | ||
59 | if (bo->gem_base.import_attach) | ||
60 | drm_prime_gem_destroy(&bo->gem_base, bo->tbo.sg); | ||
59 | drm_gem_object_release(&bo->gem_base); | 61 | drm_gem_object_release(&bo->gem_base); |
60 | amdgpu_bo_unref(&bo->parent); | 62 | amdgpu_bo_unref(&bo->parent); |
61 | if (!list_empty(&bo->shadow_list)) { | 63 | if (!list_empty(&bo->shadow_list)) { |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 13044e66dcaf..561d3312af32 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | |||
@@ -481,7 +481,7 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf, | |||
481 | result = 0; | 481 | result = 0; |
482 | 482 | ||
483 | if (*pos < 12) { | 483 | if (*pos < 12) { |
484 | early[0] = amdgpu_ring_get_rptr(ring); | 484 | early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask; |
485 | early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask; | 485 | early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask; |
486 | early[2] = ring->wptr & ring->buf_mask; | 486 | early[2] = ring->wptr & ring->buf_mask; |
487 | for (i = *pos / 4; i < 3 && size; i++) { | 487 | for (i = *pos / 4; i < 3 && size; i++) { |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index b2eae86bf906..5c26a8e806b9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | |||
@@ -299,12 +299,15 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev) | |||
299 | 299 | ||
300 | cancel_delayed_work_sync(&adev->uvd.idle_work); | 300 | cancel_delayed_work_sync(&adev->uvd.idle_work); |
301 | 301 | ||
302 | for (i = 0; i < adev->uvd.max_handles; ++i) | 302 | /* only valid for physical mode */ |
303 | if (atomic_read(&adev->uvd.handles[i])) | 303 | if (adev->asic_type < CHIP_POLARIS10) { |
304 | break; | 304 | for (i = 0; i < adev->uvd.max_handles; ++i) |
305 | if (atomic_read(&adev->uvd.handles[i])) | ||
306 | break; | ||
305 | 307 | ||
306 | if (i == AMDGPU_MAX_UVD_HANDLES) | 308 | if (i == adev->uvd.max_handles) |
307 | return 0; | 309 | return 0; |
310 | } | ||
308 | 311 | ||
309 | size = amdgpu_bo_size(adev->uvd.vcpu_bo); | 312 | size = amdgpu_bo_size(adev->uvd.vcpu_bo); |
310 | ptr = adev->uvd.cpu_addr; | 313 | ptr = adev->uvd.cpu_addr; |
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index 2af26d2da127..d702fb8e3427 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include <linux/backlight.h> | 34 | #include <linux/backlight.h> |
35 | #include "bif/bif_4_1_d.h" | 35 | #include "bif/bif_4_1_d.h" |
36 | 36 | ||
37 | static u8 | 37 | u8 |
38 | amdgpu_atombios_encoder_get_backlight_level_from_reg(struct amdgpu_device *adev) | 38 | amdgpu_atombios_encoder_get_backlight_level_from_reg(struct amdgpu_device *adev) |
39 | { | 39 | { |
40 | u8 backlight_level; | 40 | u8 backlight_level; |
@@ -48,7 +48,7 @@ amdgpu_atombios_encoder_get_backlight_level_from_reg(struct amdgpu_device *adev) | |||
48 | return backlight_level; | 48 | return backlight_level; |
49 | } | 49 | } |
50 | 50 | ||
51 | static void | 51 | void |
52 | amdgpu_atombios_encoder_set_backlight_level_to_reg(struct amdgpu_device *adev, | 52 | amdgpu_atombios_encoder_set_backlight_level_to_reg(struct amdgpu_device *adev, |
53 | u8 backlight_level) | 53 | u8 backlight_level) |
54 | { | 54 | { |
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.h b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.h index 2bdec40515ce..f77cbdef679e 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.h +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.h | |||
@@ -25,6 +25,11 @@ | |||
25 | #define __ATOMBIOS_ENCODER_H__ | 25 | #define __ATOMBIOS_ENCODER_H__ |
26 | 26 | ||
27 | u8 | 27 | u8 |
28 | amdgpu_atombios_encoder_get_backlight_level_from_reg(struct amdgpu_device *adev); | ||
29 | void | ||
30 | amdgpu_atombios_encoder_set_backlight_level_to_reg(struct amdgpu_device *adev, | ||
31 | u8 backlight_level); | ||
32 | u8 | ||
28 | amdgpu_atombios_encoder_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder); | 33 | amdgpu_atombios_encoder_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder); |
29 | void | 34 | void |
30 | amdgpu_atombios_encoder_set_backlight_level(struct amdgpu_encoder *amdgpu_encoder, | 35 | amdgpu_atombios_encoder_set_backlight_level(struct amdgpu_encoder *amdgpu_encoder, |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index f34bc68aadfb..022f303463fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | |||
@@ -2921,6 +2921,11 @@ static int dce_v10_0_hw_fini(void *handle) | |||
2921 | 2921 | ||
2922 | static int dce_v10_0_suspend(void *handle) | 2922 | static int dce_v10_0_suspend(void *handle) |
2923 | { | 2923 | { |
2924 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | ||
2925 | |||
2926 | adev->mode_info.bl_level = | ||
2927 | amdgpu_atombios_encoder_get_backlight_level_from_reg(adev); | ||
2928 | |||
2924 | return dce_v10_0_hw_fini(handle); | 2929 | return dce_v10_0_hw_fini(handle); |
2925 | } | 2930 | } |
2926 | 2931 | ||
@@ -2929,6 +2934,9 @@ static int dce_v10_0_resume(void *handle) | |||
2929 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 2934 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
2930 | int ret; | 2935 | int ret; |
2931 | 2936 | ||
2937 | amdgpu_atombios_encoder_set_backlight_level_to_reg(adev, | ||
2938 | adev->mode_info.bl_level); | ||
2939 | |||
2932 | ret = dce_v10_0_hw_init(handle); | 2940 | ret = dce_v10_0_hw_init(handle); |
2933 | 2941 | ||
2934 | /* turn on the BL */ | 2942 | /* turn on the BL */ |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 26378bd6aba4..800a9f36ab4f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | |||
@@ -3047,6 +3047,11 @@ static int dce_v11_0_hw_fini(void *handle) | |||
3047 | 3047 | ||
3048 | static int dce_v11_0_suspend(void *handle) | 3048 | static int dce_v11_0_suspend(void *handle) |
3049 | { | 3049 | { |
3050 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | ||
3051 | |||
3052 | adev->mode_info.bl_level = | ||
3053 | amdgpu_atombios_encoder_get_backlight_level_from_reg(adev); | ||
3054 | |||
3050 | return dce_v11_0_hw_fini(handle); | 3055 | return dce_v11_0_hw_fini(handle); |
3051 | } | 3056 | } |
3052 | 3057 | ||
@@ -3055,6 +3060,9 @@ static int dce_v11_0_resume(void *handle) | |||
3055 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 3060 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
3056 | int ret; | 3061 | int ret; |
3057 | 3062 | ||
3063 | amdgpu_atombios_encoder_set_backlight_level_to_reg(adev, | ||
3064 | adev->mode_info.bl_level); | ||
3065 | |||
3058 | ret = dce_v11_0_hw_init(handle); | 3066 | ret = dce_v11_0_hw_init(handle); |
3059 | 3067 | ||
3060 | /* turn on the BL */ | 3068 | /* turn on the BL */ |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index bd2c4f727df6..b8368f69ce1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | |||
@@ -2787,6 +2787,11 @@ static int dce_v6_0_hw_fini(void *handle) | |||
2787 | 2787 | ||
2788 | static int dce_v6_0_suspend(void *handle) | 2788 | static int dce_v6_0_suspend(void *handle) |
2789 | { | 2789 | { |
2790 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | ||
2791 | |||
2792 | adev->mode_info.bl_level = | ||
2793 | amdgpu_atombios_encoder_get_backlight_level_from_reg(adev); | ||
2794 | |||
2790 | return dce_v6_0_hw_fini(handle); | 2795 | return dce_v6_0_hw_fini(handle); |
2791 | } | 2796 | } |
2792 | 2797 | ||
@@ -2795,6 +2800,9 @@ static int dce_v6_0_resume(void *handle) | |||
2795 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 2800 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
2796 | int ret; | 2801 | int ret; |
2797 | 2802 | ||
2803 | amdgpu_atombios_encoder_set_backlight_level_to_reg(adev, | ||
2804 | adev->mode_info.bl_level); | ||
2805 | |||
2798 | ret = dce_v6_0_hw_init(handle); | 2806 | ret = dce_v6_0_hw_init(handle); |
2799 | 2807 | ||
2800 | /* turn on the BL */ | 2808 | /* turn on the BL */ |
@@ -3093,7 +3101,7 @@ static int dce_v6_0_hpd_irq(struct amdgpu_device *adev, | |||
3093 | tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK; | 3101 | tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK; |
3094 | WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp); | 3102 | WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp); |
3095 | schedule_work(&adev->hotplug_work); | 3103 | schedule_work(&adev->hotplug_work); |
3096 | DRM_INFO("IH: HPD%d\n", hpd + 1); | 3104 | DRM_DEBUG("IH: HPD%d\n", hpd + 1); |
3097 | } | 3105 | } |
3098 | 3106 | ||
3099 | return 0; | 3107 | return 0; |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index c008dc030687..012e0a9ae0ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | |||
@@ -2819,6 +2819,11 @@ static int dce_v8_0_hw_fini(void *handle) | |||
2819 | 2819 | ||
2820 | static int dce_v8_0_suspend(void *handle) | 2820 | static int dce_v8_0_suspend(void *handle) |
2821 | { | 2821 | { |
2822 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | ||
2823 | |||
2824 | adev->mode_info.bl_level = | ||
2825 | amdgpu_atombios_encoder_get_backlight_level_from_reg(adev); | ||
2826 | |||
2822 | return dce_v8_0_hw_fini(handle); | 2827 | return dce_v8_0_hw_fini(handle); |
2823 | } | 2828 | } |
2824 | 2829 | ||
@@ -2827,6 +2832,9 @@ static int dce_v8_0_resume(void *handle) | |||
2827 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 2832 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
2828 | int ret; | 2833 | int ret; |
2829 | 2834 | ||
2835 | amdgpu_atombios_encoder_set_backlight_level_to_reg(adev, | ||
2836 | adev->mode_info.bl_level); | ||
2837 | |||
2830 | ret = dce_v8_0_hw_init(handle); | 2838 | ret = dce_v8_0_hw_init(handle); |
2831 | 2839 | ||
2832 | /* turn on the BL */ | 2840 | /* turn on the BL */ |
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index a066c5eda135..a4309698e76c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | |||
@@ -4384,34 +4384,8 @@ static void gfx_v7_0_gpu_early_init(struct amdgpu_device *adev) | |||
4384 | case CHIP_KAVERI: | 4384 | case CHIP_KAVERI: |
4385 | adev->gfx.config.max_shader_engines = 1; | 4385 | adev->gfx.config.max_shader_engines = 1; |
4386 | adev->gfx.config.max_tile_pipes = 4; | 4386 | adev->gfx.config.max_tile_pipes = 4; |
4387 | if ((adev->pdev->device == 0x1304) || | 4387 | adev->gfx.config.max_cu_per_sh = 8; |
4388 | (adev->pdev->device == 0x1305) || | 4388 | adev->gfx.config.max_backends_per_se = 2; |
4389 | (adev->pdev->device == 0x130C) || | ||
4390 | (adev->pdev->device == 0x130F) || | ||
4391 | (adev->pdev->device == 0x1310) || | ||
4392 | (adev->pdev->device == 0x1311) || | ||
4393 | (adev->pdev->device == 0x131C)) { | ||
4394 | adev->gfx.config.max_cu_per_sh = 8; | ||
4395 | adev->gfx.config.max_backends_per_se = 2; | ||
4396 | } else if ((adev->pdev->device == 0x1309) || | ||
4397 | (adev->pdev->device == 0x130A) || | ||
4398 | (adev->pdev->device == 0x130D) || | ||
4399 | (adev->pdev->device == 0x1313) || | ||
4400 | (adev->pdev->device == 0x131D)) { | ||
4401 | adev->gfx.config.max_cu_per_sh = 6; | ||
4402 | adev->gfx.config.max_backends_per_se = 2; | ||
4403 | } else if ((adev->pdev->device == 0x1306) || | ||
4404 | (adev->pdev->device == 0x1307) || | ||
4405 | (adev->pdev->device == 0x130B) || | ||
4406 | (adev->pdev->device == 0x130E) || | ||
4407 | (adev->pdev->device == 0x1315) || | ||
4408 | (adev->pdev->device == 0x131B)) { | ||
4409 | adev->gfx.config.max_cu_per_sh = 4; | ||
4410 | adev->gfx.config.max_backends_per_se = 1; | ||
4411 | } else { | ||
4412 | adev->gfx.config.max_cu_per_sh = 3; | ||
4413 | adev->gfx.config.max_backends_per_se = 1; | ||
4414 | } | ||
4415 | adev->gfx.config.max_sh_per_se = 1; | 4389 | adev->gfx.config.max_sh_per_se = 1; |
4416 | adev->gfx.config.max_texture_channel_caches = 4; | 4390 | adev->gfx.config.max_texture_channel_caches = 4; |
4417 | adev->gfx.config.max_gprs = 256; | 4391 | adev->gfx.config.max_gprs = 256; |
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 543101d5a5ed..2095173aaabf 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "amdgpu_uvd.h" | 31 | #include "amdgpu_uvd.h" |
32 | #include "amdgpu_vce.h" | 32 | #include "amdgpu_vce.h" |
33 | #include "atom.h" | 33 | #include "atom.h" |
34 | #include "amd_pcie.h" | ||
34 | #include "amdgpu_powerplay.h" | 35 | #include "amdgpu_powerplay.h" |
35 | #include "sid.h" | 36 | #include "sid.h" |
36 | #include "si_ih.h" | 37 | #include "si_ih.h" |
@@ -1461,8 +1462,8 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev) | |||
1461 | { | 1462 | { |
1462 | struct pci_dev *root = adev->pdev->bus->self; | 1463 | struct pci_dev *root = adev->pdev->bus->self; |
1463 | int bridge_pos, gpu_pos; | 1464 | int bridge_pos, gpu_pos; |
1464 | u32 speed_cntl, mask, current_data_rate; | 1465 | u32 speed_cntl, current_data_rate; |
1465 | int ret, i; | 1466 | int i; |
1466 | u16 tmp16; | 1467 | u16 tmp16; |
1467 | 1468 | ||
1468 | if (pci_is_root_bus(adev->pdev->bus)) | 1469 | if (pci_is_root_bus(adev->pdev->bus)) |
@@ -1474,23 +1475,20 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev) | |||
1474 | if (adev->flags & AMD_IS_APU) | 1475 | if (adev->flags & AMD_IS_APU) |
1475 | return; | 1476 | return; |
1476 | 1477 | ||
1477 | ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); | 1478 | if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | |
1478 | if (ret != 0) | 1479 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3))) |
1479 | return; | ||
1480 | |||
1481 | if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80))) | ||
1482 | return; | 1480 | return; |
1483 | 1481 | ||
1484 | speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); | 1482 | speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); |
1485 | current_data_rate = (speed_cntl & LC_CURRENT_DATA_RATE_MASK) >> | 1483 | current_data_rate = (speed_cntl & LC_CURRENT_DATA_RATE_MASK) >> |
1486 | LC_CURRENT_DATA_RATE_SHIFT; | 1484 | LC_CURRENT_DATA_RATE_SHIFT; |
1487 | if (mask & DRM_PCIE_SPEED_80) { | 1485 | if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) { |
1488 | if (current_data_rate == 2) { | 1486 | if (current_data_rate == 2) { |
1489 | DRM_INFO("PCIE gen 3 link speeds already enabled\n"); | 1487 | DRM_INFO("PCIE gen 3 link speeds already enabled\n"); |
1490 | return; | 1488 | return; |
1491 | } | 1489 | } |
1492 | DRM_INFO("enabling PCIE gen 3 link speeds, disable with amdgpu.pcie_gen2=0\n"); | 1490 | DRM_INFO("enabling PCIE gen 3 link speeds, disable with amdgpu.pcie_gen2=0\n"); |
1493 | } else if (mask & DRM_PCIE_SPEED_50) { | 1491 | } else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) { |
1494 | if (current_data_rate == 1) { | 1492 | if (current_data_rate == 1) { |
1495 | DRM_INFO("PCIE gen 2 link speeds already enabled\n"); | 1493 | DRM_INFO("PCIE gen 2 link speeds already enabled\n"); |
1496 | return; | 1494 | return; |
@@ -1506,7 +1504,7 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev) | |||
1506 | if (!gpu_pos) | 1504 | if (!gpu_pos) |
1507 | return; | 1505 | return; |
1508 | 1506 | ||
1509 | if (mask & DRM_PCIE_SPEED_80) { | 1507 | if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) { |
1510 | if (current_data_rate != 2) { | 1508 | if (current_data_rate != 2) { |
1511 | u16 bridge_cfg, gpu_cfg; | 1509 | u16 bridge_cfg, gpu_cfg; |
1512 | u16 bridge_cfg2, gpu_cfg2; | 1510 | u16 bridge_cfg2, gpu_cfg2; |
@@ -1589,9 +1587,9 @@ static void si_pcie_gen3_enable(struct amdgpu_device *adev) | |||
1589 | 1587 | ||
1590 | pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16); | 1588 | pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16); |
1591 | tmp16 &= ~0xf; | 1589 | tmp16 &= ~0xf; |
1592 | if (mask & DRM_PCIE_SPEED_80) | 1590 | if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) |
1593 | tmp16 |= 3; | 1591 | tmp16 |= 3; |
1594 | else if (mask & DRM_PCIE_SPEED_50) | 1592 | else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) |
1595 | tmp16 |= 2; | 1593 | tmp16 |= 2; |
1596 | else | 1594 | else |
1597 | tmp16 |= 1; | 1595 | tmp16 |= 1; |
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index ce675a7f179a..22f0b7ff3ac9 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "amdgpu_pm.h" | 26 | #include "amdgpu_pm.h" |
27 | #include "amdgpu_dpm.h" | 27 | #include "amdgpu_dpm.h" |
28 | #include "amdgpu_atombios.h" | 28 | #include "amdgpu_atombios.h" |
29 | #include "amd_pcie.h" | ||
29 | #include "sid.h" | 30 | #include "sid.h" |
30 | #include "r600_dpm.h" | 31 | #include "r600_dpm.h" |
31 | #include "si_dpm.h" | 32 | #include "si_dpm.h" |
@@ -3331,29 +3332,6 @@ static void btc_apply_voltage_delta_rules(struct amdgpu_device *adev, | |||
3331 | } | 3332 | } |
3332 | } | 3333 | } |
3333 | 3334 | ||
3334 | static enum amdgpu_pcie_gen r600_get_pcie_gen_support(struct amdgpu_device *adev, | ||
3335 | u32 sys_mask, | ||
3336 | enum amdgpu_pcie_gen asic_gen, | ||
3337 | enum amdgpu_pcie_gen default_gen) | ||
3338 | { | ||
3339 | switch (asic_gen) { | ||
3340 | case AMDGPU_PCIE_GEN1: | ||
3341 | return AMDGPU_PCIE_GEN1; | ||
3342 | case AMDGPU_PCIE_GEN2: | ||
3343 | return AMDGPU_PCIE_GEN2; | ||
3344 | case AMDGPU_PCIE_GEN3: | ||
3345 | return AMDGPU_PCIE_GEN3; | ||
3346 | default: | ||
3347 | if ((sys_mask & DRM_PCIE_SPEED_80) && (default_gen == AMDGPU_PCIE_GEN3)) | ||
3348 | return AMDGPU_PCIE_GEN3; | ||
3349 | else if ((sys_mask & DRM_PCIE_SPEED_50) && (default_gen == AMDGPU_PCIE_GEN2)) | ||
3350 | return AMDGPU_PCIE_GEN2; | ||
3351 | else | ||
3352 | return AMDGPU_PCIE_GEN1; | ||
3353 | } | ||
3354 | return AMDGPU_PCIE_GEN1; | ||
3355 | } | ||
3356 | |||
3357 | static void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b, | 3335 | static void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b, |
3358 | u32 *p, u32 *u) | 3336 | u32 *p, u32 *u) |
3359 | { | 3337 | { |
@@ -5028,10 +5006,11 @@ static int si_populate_smc_acpi_state(struct amdgpu_device *adev, | |||
5028 | table->ACPIState.levels[0].vddc.index, | 5006 | table->ACPIState.levels[0].vddc.index, |
5029 | &table->ACPIState.levels[0].std_vddc); | 5007 | &table->ACPIState.levels[0].std_vddc); |
5030 | } | 5008 | } |
5031 | table->ACPIState.levels[0].gen2PCIE = (u8)r600_get_pcie_gen_support(adev, | 5009 | table->ACPIState.levels[0].gen2PCIE = |
5032 | si_pi->sys_pcie_mask, | 5010 | (u8)amdgpu_get_pcie_gen_support(adev, |
5033 | si_pi->boot_pcie_gen, | 5011 | si_pi->sys_pcie_mask, |
5034 | AMDGPU_PCIE_GEN1); | 5012 | si_pi->boot_pcie_gen, |
5013 | AMDGPU_PCIE_GEN1); | ||
5035 | 5014 | ||
5036 | if (si_pi->vddc_phase_shed_control) | 5015 | if (si_pi->vddc_phase_shed_control) |
5037 | si_populate_phase_shedding_value(adev, | 5016 | si_populate_phase_shedding_value(adev, |
@@ -7168,10 +7147,10 @@ static void si_parse_pplib_clock_info(struct amdgpu_device *adev, | |||
7168 | pl->vddc = le16_to_cpu(clock_info->si.usVDDC); | 7147 | pl->vddc = le16_to_cpu(clock_info->si.usVDDC); |
7169 | pl->vddci = le16_to_cpu(clock_info->si.usVDDCI); | 7148 | pl->vddci = le16_to_cpu(clock_info->si.usVDDCI); |
7170 | pl->flags = le32_to_cpu(clock_info->si.ulFlags); | 7149 | pl->flags = le32_to_cpu(clock_info->si.ulFlags); |
7171 | pl->pcie_gen = r600_get_pcie_gen_support(adev, | 7150 | pl->pcie_gen = amdgpu_get_pcie_gen_support(adev, |
7172 | si_pi->sys_pcie_mask, | 7151 | si_pi->sys_pcie_mask, |
7173 | si_pi->boot_pcie_gen, | 7152 | si_pi->boot_pcie_gen, |
7174 | clock_info->si.ucPCIEGen); | 7153 | clock_info->si.ucPCIEGen); |
7175 | 7154 | ||
7176 | /* patch up vddc if necessary */ | 7155 | /* patch up vddc if necessary */ |
7177 | ret = si_get_leakage_voltage_from_leakage_index(adev, pl->vddc, | 7156 | ret = si_get_leakage_voltage_from_leakage_index(adev, pl->vddc, |
@@ -7326,7 +7305,6 @@ static int si_dpm_init(struct amdgpu_device *adev) | |||
7326 | struct si_power_info *si_pi; | 7305 | struct si_power_info *si_pi; |
7327 | struct atom_clock_dividers dividers; | 7306 | struct atom_clock_dividers dividers; |
7328 | int ret; | 7307 | int ret; |
7329 | u32 mask; | ||
7330 | 7308 | ||
7331 | si_pi = kzalloc(sizeof(struct si_power_info), GFP_KERNEL); | 7309 | si_pi = kzalloc(sizeof(struct si_power_info), GFP_KERNEL); |
7332 | if (si_pi == NULL) | 7310 | if (si_pi == NULL) |
@@ -7336,11 +7314,9 @@ static int si_dpm_init(struct amdgpu_device *adev) | |||
7336 | eg_pi = &ni_pi->eg; | 7314 | eg_pi = &ni_pi->eg; |
7337 | pi = &eg_pi->rv7xx; | 7315 | pi = &eg_pi->rv7xx; |
7338 | 7316 | ||
7339 | ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); | 7317 | si_pi->sys_pcie_mask = |
7340 | if (ret) | 7318 | (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_MASK) >> |
7341 | si_pi->sys_pcie_mask = 0; | 7319 | CAIL_PCIE_LINK_SPEED_SUPPORT_SHIFT; |
7342 | else | ||
7343 | si_pi->sys_pcie_mask = mask; | ||
7344 | si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID; | 7320 | si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID; |
7345 | si_pi->boot_pcie_gen = si_get_current_pcie_speed(adev); | 7321 | si_pi->boot_pcie_gen = si_get_current_pcie_speed(adev); |
7346 | 7322 | ||
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 862835dc054e..63c67346d316 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |||
@@ -1037,6 +1037,10 @@ static void handle_hpd_rx_irq(void *param) | |||
1037 | !is_mst_root_connector) { | 1037 | !is_mst_root_connector) { |
1038 | /* Downstream Port status changed. */ | 1038 | /* Downstream Port status changed. */ |
1039 | if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) { | 1039 | if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) { |
1040 | |||
1041 | if (aconnector->fake_enable) | ||
1042 | aconnector->fake_enable = false; | ||
1043 | |||
1040 | amdgpu_dm_update_connector_after_detect(aconnector); | 1044 | amdgpu_dm_update_connector_after_detect(aconnector); |
1041 | 1045 | ||
1042 | 1046 | ||
@@ -2012,30 +2016,32 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode, | |||
2012 | dst.width = stream->timing.h_addressable; | 2016 | dst.width = stream->timing.h_addressable; |
2013 | dst.height = stream->timing.v_addressable; | 2017 | dst.height = stream->timing.v_addressable; |
2014 | 2018 | ||
2015 | rmx_type = dm_state->scaling; | 2019 | if (dm_state) { |
2016 | if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) { | 2020 | rmx_type = dm_state->scaling; |
2017 | if (src.width * dst.height < | 2021 | if (rmx_type == RMX_ASPECT || rmx_type == RMX_OFF) { |
2018 | src.height * dst.width) { | 2022 | if (src.width * dst.height < |
2019 | /* height needs less upscaling/more downscaling */ | 2023 | src.height * dst.width) { |
2020 | dst.width = src.width * | 2024 | /* height needs less upscaling/more downscaling */ |
2021 | dst.height / src.height; | 2025 | dst.width = src.width * |
2022 | } else { | 2026 | dst.height / src.height; |
2023 | /* width needs less upscaling/more downscaling */ | 2027 | } else { |
2024 | dst.height = src.height * | 2028 | /* width needs less upscaling/more downscaling */ |
2025 | dst.width / src.width; | 2029 | dst.height = src.height * |
2030 | dst.width / src.width; | ||
2031 | } | ||
2032 | } else if (rmx_type == RMX_CENTER) { | ||
2033 | dst = src; | ||
2026 | } | 2034 | } |
2027 | } else if (rmx_type == RMX_CENTER) { | ||
2028 | dst = src; | ||
2029 | } | ||
2030 | 2035 | ||
2031 | dst.x = (stream->timing.h_addressable - dst.width) / 2; | 2036 | dst.x = (stream->timing.h_addressable - dst.width) / 2; |
2032 | dst.y = (stream->timing.v_addressable - dst.height) / 2; | 2037 | dst.y = (stream->timing.v_addressable - dst.height) / 2; |
2033 | 2038 | ||
2034 | if (dm_state->underscan_enable) { | 2039 | if (dm_state->underscan_enable) { |
2035 | dst.x += dm_state->underscan_hborder / 2; | 2040 | dst.x += dm_state->underscan_hborder / 2; |
2036 | dst.y += dm_state->underscan_vborder / 2; | 2041 | dst.y += dm_state->underscan_vborder / 2; |
2037 | dst.width -= dm_state->underscan_hborder; | 2042 | dst.width -= dm_state->underscan_hborder; |
2038 | dst.height -= dm_state->underscan_vborder; | 2043 | dst.height -= dm_state->underscan_vborder; |
2044 | } | ||
2039 | } | 2045 | } |
2040 | 2046 | ||
2041 | stream->src = src; | 2047 | stream->src = src; |
@@ -2360,12 +2366,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, | |||
2360 | 2366 | ||
2361 | if (aconnector == NULL) { | 2367 | if (aconnector == NULL) { |
2362 | DRM_ERROR("aconnector is NULL!\n"); | 2368 | DRM_ERROR("aconnector is NULL!\n"); |
2363 | goto drm_connector_null; | 2369 | return stream; |
2364 | } | ||
2365 | |||
2366 | if (dm_state == NULL) { | ||
2367 | DRM_ERROR("dm_state is NULL!\n"); | ||
2368 | goto dm_state_null; | ||
2369 | } | 2370 | } |
2370 | 2371 | ||
2371 | drm_connector = &aconnector->base; | 2372 | drm_connector = &aconnector->base; |
@@ -2377,18 +2378,18 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, | |||
2377 | */ | 2378 | */ |
2378 | if (aconnector->mst_port) { | 2379 | if (aconnector->mst_port) { |
2379 | dm_dp_mst_dc_sink_create(drm_connector); | 2380 | dm_dp_mst_dc_sink_create(drm_connector); |
2380 | goto mst_dc_sink_create_done; | 2381 | return stream; |
2381 | } | 2382 | } |
2382 | 2383 | ||
2383 | if (create_fake_sink(aconnector)) | 2384 | if (create_fake_sink(aconnector)) |
2384 | goto stream_create_fail; | 2385 | return stream; |
2385 | } | 2386 | } |
2386 | 2387 | ||
2387 | stream = dc_create_stream_for_sink(aconnector->dc_sink); | 2388 | stream = dc_create_stream_for_sink(aconnector->dc_sink); |
2388 | 2389 | ||
2389 | if (stream == NULL) { | 2390 | if (stream == NULL) { |
2390 | DRM_ERROR("Failed to create stream for sink!\n"); | 2391 | DRM_ERROR("Failed to create stream for sink!\n"); |
2391 | goto stream_create_fail; | 2392 | return stream; |
2392 | } | 2393 | } |
2393 | 2394 | ||
2394 | list_for_each_entry(preferred_mode, &aconnector->base.modes, head) { | 2395 | list_for_each_entry(preferred_mode, &aconnector->base.modes, head) { |
@@ -2414,9 +2415,12 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, | |||
2414 | } else { | 2415 | } else { |
2415 | decide_crtc_timing_for_drm_display_mode( | 2416 | decide_crtc_timing_for_drm_display_mode( |
2416 | &mode, preferred_mode, | 2417 | &mode, preferred_mode, |
2417 | dm_state->scaling != RMX_OFF); | 2418 | dm_state ? (dm_state->scaling != RMX_OFF) : false); |
2418 | } | 2419 | } |
2419 | 2420 | ||
2421 | if (!dm_state) | ||
2422 | drm_mode_set_crtcinfo(&mode, 0); | ||
2423 | |||
2420 | fill_stream_properties_from_drm_display_mode(stream, | 2424 | fill_stream_properties_from_drm_display_mode(stream, |
2421 | &mode, &aconnector->base); | 2425 | &mode, &aconnector->base); |
2422 | update_stream_scaling_settings(&mode, dm_state, stream); | 2426 | update_stream_scaling_settings(&mode, dm_state, stream); |
@@ -2426,10 +2430,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, | |||
2426 | drm_connector, | 2430 | drm_connector, |
2427 | aconnector->dc_sink); | 2431 | aconnector->dc_sink); |
2428 | 2432 | ||
2429 | stream_create_fail: | 2433 | update_stream_signal(stream); |
2430 | dm_state_null: | 2434 | |
2431 | drm_connector_null: | ||
2432 | mst_dc_sink_create_done: | ||
2433 | return stream; | 2435 | return stream; |
2434 | } | 2436 | } |
2435 | 2437 | ||
@@ -2497,6 +2499,27 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) | |||
2497 | return &state->base; | 2499 | return &state->base; |
2498 | } | 2500 | } |
2499 | 2501 | ||
2502 | |||
2503 | static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) | ||
2504 | { | ||
2505 | enum dc_irq_source irq_source; | ||
2506 | struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); | ||
2507 | struct amdgpu_device *adev = crtc->dev->dev_private; | ||
2508 | |||
2509 | irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst; | ||
2510 | return dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY; | ||
2511 | } | ||
2512 | |||
2513 | static int dm_enable_vblank(struct drm_crtc *crtc) | ||
2514 | { | ||
2515 | return dm_set_vblank(crtc, true); | ||
2516 | } | ||
2517 | |||
2518 | static void dm_disable_vblank(struct drm_crtc *crtc) | ||
2519 | { | ||
2520 | dm_set_vblank(crtc, false); | ||
2521 | } | ||
2522 | |||
2500 | /* Implemented only the options currently availible for the driver */ | 2523 | /* Implemented only the options currently availible for the driver */ |
2501 | static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { | 2524 | static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { |
2502 | .reset = dm_crtc_reset_state, | 2525 | .reset = dm_crtc_reset_state, |
@@ -2506,6 +2529,8 @@ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { | |||
2506 | .page_flip = drm_atomic_helper_page_flip, | 2529 | .page_flip = drm_atomic_helper_page_flip, |
2507 | .atomic_duplicate_state = dm_crtc_duplicate_state, | 2530 | .atomic_duplicate_state = dm_crtc_duplicate_state, |
2508 | .atomic_destroy_state = dm_crtc_destroy_state, | 2531 | .atomic_destroy_state = dm_crtc_destroy_state, |
2532 | .enable_vblank = dm_enable_vblank, | ||
2533 | .disable_vblank = dm_disable_vblank, | ||
2509 | }; | 2534 | }; |
2510 | 2535 | ||
2511 | static enum drm_connector_status | 2536 | static enum drm_connector_status |
@@ -2800,7 +2825,7 @@ int amdgpu_dm_connector_mode_valid(struct drm_connector *connector, | |||
2800 | goto fail; | 2825 | goto fail; |
2801 | } | 2826 | } |
2802 | 2827 | ||
2803 | stream = dc_create_stream_for_sink(dc_sink); | 2828 | stream = create_stream_for_sink(aconnector, mode, NULL); |
2804 | if (stream == NULL) { | 2829 | if (stream == NULL) { |
2805 | DRM_ERROR("Failed to create stream for sink!\n"); | 2830 | DRM_ERROR("Failed to create stream for sink!\n"); |
2806 | goto fail; | 2831 | goto fail; |
@@ -3060,6 +3085,9 @@ static int dm_plane_atomic_check(struct drm_plane *plane, | |||
3060 | if (!dm_plane_state->dc_state) | 3085 | if (!dm_plane_state->dc_state) |
3061 | return 0; | 3086 | return 0; |
3062 | 3087 | ||
3088 | if (!fill_rects_from_plane_state(state, dm_plane_state->dc_state)) | ||
3089 | return -EINVAL; | ||
3090 | |||
3063 | if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK) | 3091 | if (dc_validate_plane(dc, dm_plane_state->dc_state) == DC_OK) |
3064 | return 0; | 3092 | return 0; |
3065 | 3093 | ||
@@ -3106,8 +3134,6 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, | |||
3106 | 3134 | ||
3107 | switch (aplane->base.type) { | 3135 | switch (aplane->base.type) { |
3108 | case DRM_PLANE_TYPE_PRIMARY: | 3136 | case DRM_PLANE_TYPE_PRIMARY: |
3109 | aplane->base.format_default = true; | ||
3110 | |||
3111 | res = drm_universal_plane_init( | 3137 | res = drm_universal_plane_init( |
3112 | dm->adev->ddev, | 3138 | dm->adev->ddev, |
3113 | &aplane->base, | 3139 | &aplane->base, |
@@ -4632,8 +4658,6 @@ static int dm_update_planes_state(struct dc *dc, | |||
4632 | bool pflip_needed = !state->allow_modeset; | 4658 | bool pflip_needed = !state->allow_modeset; |
4633 | int ret = 0; | 4659 | int ret = 0; |
4634 | 4660 | ||
4635 | if (pflip_needed) | ||
4636 | return ret; | ||
4637 | 4661 | ||
4638 | /* Add new planes */ | 4662 | /* Add new planes */ |
4639 | for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { | 4663 | for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { |
@@ -4648,6 +4672,8 @@ static int dm_update_planes_state(struct dc *dc, | |||
4648 | 4672 | ||
4649 | /* Remove any changed/removed planes */ | 4673 | /* Remove any changed/removed planes */ |
4650 | if (!enable) { | 4674 | if (!enable) { |
4675 | if (pflip_needed) | ||
4676 | continue; | ||
4651 | 4677 | ||
4652 | if (!old_plane_crtc) | 4678 | if (!old_plane_crtc) |
4653 | continue; | 4679 | continue; |
@@ -4679,6 +4705,7 @@ static int dm_update_planes_state(struct dc *dc, | |||
4679 | *lock_and_validation_needed = true; | 4705 | *lock_and_validation_needed = true; |
4680 | 4706 | ||
4681 | } else { /* Add new planes */ | 4707 | } else { /* Add new planes */ |
4708 | struct dc_plane_state *dc_new_plane_state; | ||
4682 | 4709 | ||
4683 | if (drm_atomic_plane_disabling(plane->state, new_plane_state)) | 4710 | if (drm_atomic_plane_disabling(plane->state, new_plane_state)) |
4684 | continue; | 4711 | continue; |
@@ -4692,38 +4719,50 @@ static int dm_update_planes_state(struct dc *dc, | |||
4692 | if (!dm_new_crtc_state->stream) | 4719 | if (!dm_new_crtc_state->stream) |
4693 | continue; | 4720 | continue; |
4694 | 4721 | ||
4722 | if (pflip_needed) | ||
4723 | continue; | ||
4695 | 4724 | ||
4696 | WARN_ON(dm_new_plane_state->dc_state); | 4725 | WARN_ON(dm_new_plane_state->dc_state); |
4697 | 4726 | ||
4698 | dm_new_plane_state->dc_state = dc_create_plane_state(dc); | 4727 | dc_new_plane_state = dc_create_plane_state(dc); |
4699 | 4728 | if (!dc_new_plane_state) { | |
4700 | DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n", | ||
4701 | plane->base.id, new_plane_crtc->base.id); | ||
4702 | |||
4703 | if (!dm_new_plane_state->dc_state) { | ||
4704 | ret = -EINVAL; | 4729 | ret = -EINVAL; |
4705 | return ret; | 4730 | return ret; |
4706 | } | 4731 | } |
4707 | 4732 | ||
4733 | DRM_DEBUG_DRIVER("Enabling DRM plane: %d on DRM crtc %d\n", | ||
4734 | plane->base.id, new_plane_crtc->base.id); | ||
4735 | |||
4708 | ret = fill_plane_attributes( | 4736 | ret = fill_plane_attributes( |
4709 | new_plane_crtc->dev->dev_private, | 4737 | new_plane_crtc->dev->dev_private, |
4710 | dm_new_plane_state->dc_state, | 4738 | dc_new_plane_state, |
4711 | new_plane_state, | 4739 | new_plane_state, |
4712 | new_crtc_state); | 4740 | new_crtc_state); |
4713 | if (ret) | 4741 | if (ret) { |
4742 | dc_plane_state_release(dc_new_plane_state); | ||
4714 | return ret; | 4743 | return ret; |
4744 | } | ||
4715 | 4745 | ||
4716 | 4746 | /* | |
4747 | * Any atomic check errors that occur after this will | ||
4748 | * not need a release. The plane state will be attached | ||
4749 | * to the stream, and therefore part of the atomic | ||
4750 | * state. It'll be released when the atomic state is | ||
4751 | * cleaned. | ||
4752 | */ | ||
4717 | if (!dc_add_plane_to_context( | 4753 | if (!dc_add_plane_to_context( |
4718 | dc, | 4754 | dc, |
4719 | dm_new_crtc_state->stream, | 4755 | dm_new_crtc_state->stream, |
4720 | dm_new_plane_state->dc_state, | 4756 | dc_new_plane_state, |
4721 | dm_state->context)) { | 4757 | dm_state->context)) { |
4722 | 4758 | ||
4759 | dc_plane_state_release(dc_new_plane_state); | ||
4723 | ret = -EINVAL; | 4760 | ret = -EINVAL; |
4724 | return ret; | 4761 | return ret; |
4725 | } | 4762 | } |
4726 | 4763 | ||
4764 | dm_new_plane_state->dc_state = dc_new_plane_state; | ||
4765 | |||
4727 | /* Tell DC to do a full surface update every time there | 4766 | /* Tell DC to do a full surface update every time there |
4728 | * is a plane change. Inefficient, but works for now. | 4767 | * is a plane change. Inefficient, but works for now. |
4729 | */ | 4768 | */ |
@@ -4737,6 +4776,33 @@ static int dm_update_planes_state(struct dc *dc, | |||
4737 | return ret; | 4776 | return ret; |
4738 | } | 4777 | } |
4739 | 4778 | ||
4779 | static int dm_atomic_check_plane_state_fb(struct drm_atomic_state *state, | ||
4780 | struct drm_crtc *crtc) | ||
4781 | { | ||
4782 | struct drm_plane *plane; | ||
4783 | struct drm_crtc_state *crtc_state; | ||
4784 | |||
4785 | WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc)); | ||
4786 | |||
4787 | drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) { | ||
4788 | struct drm_plane_state *plane_state = | ||
4789 | drm_atomic_get_plane_state(state, plane); | ||
4790 | |||
4791 | if (IS_ERR(plane_state)) | ||
4792 | return -EDEADLK; | ||
4793 | |||
4794 | crtc_state = drm_atomic_get_crtc_state(plane_state->state, crtc); | ||
4795 | if (IS_ERR(crtc_state)) | ||
4796 | return PTR_ERR(crtc_state); | ||
4797 | |||
4798 | if (crtc->primary == plane && crtc_state->active) { | ||
4799 | if (!plane_state->fb) | ||
4800 | return -EINVAL; | ||
4801 | } | ||
4802 | } | ||
4803 | return 0; | ||
4804 | } | ||
4805 | |||
4740 | static int amdgpu_dm_atomic_check(struct drm_device *dev, | 4806 | static int amdgpu_dm_atomic_check(struct drm_device *dev, |
4741 | struct drm_atomic_state *state) | 4807 | struct drm_atomic_state *state) |
4742 | { | 4808 | { |
@@ -4760,6 +4826,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, | |||
4760 | goto fail; | 4826 | goto fail; |
4761 | 4827 | ||
4762 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { | 4828 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
4829 | ret = dm_atomic_check_plane_state_fb(state, crtc); | ||
4830 | if (ret) | ||
4831 | goto fail; | ||
4832 | |||
4763 | if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && | 4833 | if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && |
4764 | !new_crtc_state->color_mgmt_changed) | 4834 | !new_crtc_state->color_mgmt_changed) |
4765 | continue; | 4835 | continue; |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 9bd142f65f9b..e1acc10e35a2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | |||
@@ -109,7 +109,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps( | |||
109 | struct cea_sad *sad = &sads[i]; | 109 | struct cea_sad *sad = &sads[i]; |
110 | 110 | ||
111 | edid_caps->audio_modes[i].format_code = sad->format; | 111 | edid_caps->audio_modes[i].format_code = sad->format; |
112 | edid_caps->audio_modes[i].channel_count = sad->channels; | 112 | edid_caps->audio_modes[i].channel_count = sad->channels + 1; |
113 | edid_caps->audio_modes[i].sample_rate = sad->freq; | 113 | edid_caps->audio_modes[i].sample_rate = sad->freq; |
114 | edid_caps->audio_modes[i].sample_size = sad->byte2; | 114 | edid_caps->audio_modes[i].sample_size = sad->byte2; |
115 | } | 115 | } |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index 1874b6cee6af..422055080df4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | |||
@@ -683,10 +683,8 @@ static const struct amdgpu_irq_src_funcs dm_hpd_irq_funcs = { | |||
683 | 683 | ||
684 | void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev) | 684 | void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev) |
685 | { | 685 | { |
686 | if (adev->mode_info.num_crtc > 0) | 686 | |
687 | adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_VLINE1 + adev->mode_info.num_crtc; | 687 | adev->crtc_irq.num_types = adev->mode_info.num_crtc; |
688 | else | ||
689 | adev->crtc_irq.num_types = 0; | ||
690 | adev->crtc_irq.funcs = &dm_crtc_irq_funcs; | 688 | adev->crtc_irq.funcs = &dm_crtc_irq_funcs; |
691 | 689 | ||
692 | adev->pageflip_irq.num_types = adev->mode_info.num_crtc; | 690 | adev->pageflip_irq.num_types = adev->mode_info.num_crtc; |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index f3d87f418d2e..93421dad21bd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | |||
@@ -189,6 +189,12 @@ void dm_dp_mst_dc_sink_create(struct drm_connector *connector) | |||
189 | .link = aconnector->dc_link, | 189 | .link = aconnector->dc_link, |
190 | .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; | 190 | .sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; |
191 | 191 | ||
192 | /* | ||
193 | * TODO: Need to further figure out why ddc.algo is NULL while MST port exists | ||
194 | */ | ||
195 | if (!aconnector->port || !aconnector->port->aux.ddc.algo) | ||
196 | return; | ||
197 | |||
192 | edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); | 198 | edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port); |
193 | 199 | ||
194 | if (!edid) { | 200 | if (!edid) { |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 35e84ed031de..12868c769606 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c | |||
@@ -1358,13 +1358,13 @@ enum dc_irq_source dc_interrupt_to_irq_source( | |||
1358 | return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id); | 1358 | return dal_irq_service_to_irq_source(dc->res_pool->irqs, src_id, ext_id); |
1359 | } | 1359 | } |
1360 | 1360 | ||
1361 | void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) | 1361 | bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable) |
1362 | { | 1362 | { |
1363 | 1363 | ||
1364 | if (dc == NULL) | 1364 | if (dc == NULL) |
1365 | return; | 1365 | return false; |
1366 | 1366 | ||
1367 | dal_irq_service_set(dc->res_pool->irqs, src, enable); | 1367 | return dal_irq_service_set(dc->res_pool->irqs, src, enable); |
1368 | } | 1368 | } |
1369 | 1369 | ||
1370 | void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) | 1370 | void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index a37428271573..be5546181fa8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c | |||
@@ -1749,8 +1749,7 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx) | |||
1749 | link->link_enc, | 1749 | link->link_enc, |
1750 | pipe_ctx->clock_source->id, | 1750 | pipe_ctx->clock_source->id, |
1751 | display_color_depth, | 1751 | display_color_depth, |
1752 | pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A, | 1752 | pipe_ctx->stream->signal, |
1753 | pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK, | ||
1754 | stream->phy_pix_clk); | 1753 | stream->phy_pix_clk); |
1755 | 1754 | ||
1756 | if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) | 1755 | if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 95b8dd0e53c6..4d07ffebfd31 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c | |||
@@ -1360,9 +1360,6 @@ bool dc_is_stream_scaling_unchanged( | |||
1360 | return true; | 1360 | return true; |
1361 | } | 1361 | } |
1362 | 1362 | ||
1363 | /* Maximum TMDS single link pixel clock 165MHz */ | ||
1364 | #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ 165000 | ||
1365 | |||
1366 | static void update_stream_engine_usage( | 1363 | static void update_stream_engine_usage( |
1367 | struct resource_context *res_ctx, | 1364 | struct resource_context *res_ctx, |
1368 | const struct resource_pool *pool, | 1365 | const struct resource_pool *pool, |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 539c3e0a6292..cd5819789d76 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c | |||
@@ -33,8 +33,7 @@ | |||
33 | /******************************************************************************* | 33 | /******************************************************************************* |
34 | * Private functions | 34 | * Private functions |
35 | ******************************************************************************/ | 35 | ******************************************************************************/ |
36 | #define TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST 297000 | 36 | void update_stream_signal(struct dc_stream_state *stream) |
37 | static void update_stream_signal(struct dc_stream_state *stream) | ||
38 | { | 37 | { |
39 | 38 | ||
40 | struct dc_sink *dc_sink = stream->sink; | 39 | struct dc_sink *dc_sink = stream->sink; |
@@ -45,8 +44,9 @@ static void update_stream_signal(struct dc_stream_state *stream) | |||
45 | stream->signal = dc_sink->sink_signal; | 44 | stream->signal = dc_sink->sink_signal; |
46 | 45 | ||
47 | if (dc_is_dvi_signal(stream->signal)) { | 46 | if (dc_is_dvi_signal(stream->signal)) { |
48 | if (stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK_IN_KHZ_UPMOST && | 47 | if (stream->ctx->dc->caps.dual_link_dvi && |
49 | stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) | 48 | stream->timing.pix_clk_khz > TMDS_MAX_PIXEL_CLOCK && |
49 | stream->sink->sink_signal != SIGNAL_TYPE_DVI_SINGLE_LINK) | ||
50 | stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; | 50 | stream->signal = SIGNAL_TYPE_DVI_DUAL_LINK; |
51 | else | 51 | else |
52 | stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; | 52 | stream->signal = SIGNAL_TYPE_DVI_SINGLE_LINK; |
@@ -193,6 +193,7 @@ bool dc_stream_set_cursor_attributes( | |||
193 | 193 | ||
194 | core_dc = stream->ctx->dc; | 194 | core_dc = stream->ctx->dc; |
195 | res_ctx = &core_dc->current_state->res_ctx; | 195 | res_ctx = &core_dc->current_state->res_ctx; |
196 | stream->cursor_attributes = *attributes; | ||
196 | 197 | ||
197 | for (i = 0; i < MAX_PIPES; i++) { | 198 | for (i = 0; i < MAX_PIPES; i++) { |
198 | struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; | 199 | struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; |
@@ -204,34 +205,8 @@ bool dc_stream_set_cursor_attributes( | |||
204 | continue; | 205 | continue; |
205 | 206 | ||
206 | 207 | ||
207 | if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes != NULL) | 208 | core_dc->hwss.set_cursor_attribute(pipe_ctx); |
208 | pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( | ||
209 | pipe_ctx->plane_res.ipp, attributes); | ||
210 | |||
211 | if (pipe_ctx->plane_res.hubp != NULL && | ||
212 | pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes != NULL) | ||
213 | pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( | ||
214 | pipe_ctx->plane_res.hubp, attributes); | ||
215 | |||
216 | if (pipe_ctx->plane_res.mi != NULL && | ||
217 | pipe_ctx->plane_res.mi->funcs->set_cursor_attributes != NULL) | ||
218 | pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( | ||
219 | pipe_ctx->plane_res.mi, attributes); | ||
220 | |||
221 | |||
222 | if (pipe_ctx->plane_res.xfm != NULL && | ||
223 | pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes != NULL) | ||
224 | pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( | ||
225 | pipe_ctx->plane_res.xfm, attributes); | ||
226 | |||
227 | if (pipe_ctx->plane_res.dpp != NULL && | ||
228 | pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes != NULL) | ||
229 | pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( | ||
230 | pipe_ctx->plane_res.dpp, attributes->color_format); | ||
231 | } | 209 | } |
232 | |||
233 | stream->cursor_attributes = *attributes; | ||
234 | |||
235 | return true; | 210 | return true; |
236 | } | 211 | } |
237 | 212 | ||
@@ -255,21 +230,10 @@ bool dc_stream_set_cursor_position( | |||
255 | 230 | ||
256 | core_dc = stream->ctx->dc; | 231 | core_dc = stream->ctx->dc; |
257 | res_ctx = &core_dc->current_state->res_ctx; | 232 | res_ctx = &core_dc->current_state->res_ctx; |
233 | stream->cursor_position = *position; | ||
258 | 234 | ||
259 | for (i = 0; i < MAX_PIPES; i++) { | 235 | for (i = 0; i < MAX_PIPES; i++) { |
260 | struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; | 236 | struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; |
261 | struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; | ||
262 | struct mem_input *mi = pipe_ctx->plane_res.mi; | ||
263 | struct hubp *hubp = pipe_ctx->plane_res.hubp; | ||
264 | struct dpp *dpp = pipe_ctx->plane_res.dpp; | ||
265 | struct dc_cursor_position pos_cpy = *position; | ||
266 | struct dc_cursor_mi_param param = { | ||
267 | .pixel_clk_khz = stream->timing.pix_clk_khz, | ||
268 | .ref_clk_khz = core_dc->res_pool->ref_clock_inKhz, | ||
269 | .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x, | ||
270 | .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width, | ||
271 | .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz | ||
272 | }; | ||
273 | 237 | ||
274 | if (pipe_ctx->stream != stream || | 238 | if (pipe_ctx->stream != stream || |
275 | (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) || | 239 | (!pipe_ctx->plane_res.mi && !pipe_ctx->plane_res.hubp) || |
@@ -278,33 +242,9 @@ bool dc_stream_set_cursor_position( | |||
278 | !pipe_ctx->plane_res.ipp) | 242 | !pipe_ctx->plane_res.ipp) |
279 | continue; | 243 | continue; |
280 | 244 | ||
281 | if (pipe_ctx->plane_state->address.type | 245 | core_dc->hwss.set_cursor_position(pipe_ctx); |
282 | == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) | ||
283 | pos_cpy.enable = false; | ||
284 | |||
285 | if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) | ||
286 | pos_cpy.enable = false; | ||
287 | |||
288 | |||
289 | if (ipp != NULL && ipp->funcs->ipp_cursor_set_position != NULL) | ||
290 | ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); | ||
291 | |||
292 | if (mi != NULL && mi->funcs->set_cursor_position != NULL) | ||
293 | mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); | ||
294 | |||
295 | if (!hubp) | ||
296 | continue; | ||
297 | |||
298 | if (hubp->funcs->set_cursor_position != NULL) | ||
299 | hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); | ||
300 | |||
301 | if (dpp != NULL && dpp->funcs->set_cursor_position != NULL) | ||
302 | dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width); | ||
303 | |||
304 | } | 246 | } |
305 | 247 | ||
306 | stream->cursor_position = *position; | ||
307 | |||
308 | return true; | 248 | return true; |
309 | } | 249 | } |
310 | 250 | ||
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index e2e3c9df79ea..d6d56611604e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h | |||
@@ -62,6 +62,7 @@ struct dc_caps { | |||
62 | bool dcc_const_color; | 62 | bool dcc_const_color; |
63 | bool dynamic_audio; | 63 | bool dynamic_audio; |
64 | bool is_apu; | 64 | bool is_apu; |
65 | bool dual_link_dvi; | ||
65 | }; | 66 | }; |
66 | 67 | ||
67 | struct dc_dcc_surface_param { | 68 | struct dc_dcc_surface_param { |
@@ -672,7 +673,7 @@ enum dc_irq_source dc_interrupt_to_irq_source( | |||
672 | struct dc *dc, | 673 | struct dc *dc, |
673 | uint32_t src_id, | 674 | uint32_t src_id, |
674 | uint32_t ext_id); | 675 | uint32_t ext_id); |
675 | void dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable); | 676 | bool dc_interrupt_set(struct dc *dc, enum dc_irq_source src, bool enable); |
676 | void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src); | 677 | void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src); |
677 | enum dc_irq_source dc_get_hpd_irq_source_at_index( | 678 | enum dc_irq_source dc_get_hpd_irq_source_at_index( |
678 | struct dc *dc, uint32_t link_index); | 679 | struct dc *dc, uint32_t link_index); |
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 01c60f11b2bd..456e4d29eadd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h | |||
@@ -237,6 +237,8 @@ enum surface_update_type dc_check_update_surfaces_for_stream( | |||
237 | */ | 237 | */ |
238 | struct dc_stream_state *dc_create_stream_for_sink(struct dc_sink *dc_sink); | 238 | struct dc_stream_state *dc_create_stream_for_sink(struct dc_sink *dc_sink); |
239 | 239 | ||
240 | void update_stream_signal(struct dc_stream_state *stream); | ||
241 | |||
240 | void dc_stream_retain(struct dc_stream_state *dc_stream); | 242 | void dc_stream_retain(struct dc_stream_state *dc_stream); |
241 | void dc_stream_release(struct dc_stream_state *dc_stream); | 243 | void dc_stream_release(struct dc_stream_state *dc_stream); |
242 | 244 | ||
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h index b73db9e78437..f11f17fe08f9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_hwseq.h | |||
@@ -236,6 +236,7 @@ | |||
236 | SR(D2VGA_CONTROL), \ | 236 | SR(D2VGA_CONTROL), \ |
237 | SR(D3VGA_CONTROL), \ | 237 | SR(D3VGA_CONTROL), \ |
238 | SR(D4VGA_CONTROL), \ | 238 | SR(D4VGA_CONTROL), \ |
239 | SR(VGA_TEST_CONTROL), \ | ||
239 | SR(DC_IP_REQUEST_CNTL), \ | 240 | SR(DC_IP_REQUEST_CNTL), \ |
240 | BL_REG_LIST() | 241 | BL_REG_LIST() |
241 | 242 | ||
@@ -337,6 +338,7 @@ struct dce_hwseq_registers { | |||
337 | uint32_t D2VGA_CONTROL; | 338 | uint32_t D2VGA_CONTROL; |
338 | uint32_t D3VGA_CONTROL; | 339 | uint32_t D3VGA_CONTROL; |
339 | uint32_t D4VGA_CONTROL; | 340 | uint32_t D4VGA_CONTROL; |
341 | uint32_t VGA_TEST_CONTROL; | ||
340 | /* MMHUB registers. read only. temporary hack */ | 342 | /* MMHUB registers. read only. temporary hack */ |
341 | uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32; | 343 | uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32; |
342 | uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32; | 344 | uint32_t VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32; |
@@ -493,6 +495,12 @@ struct dce_hwseq_registers { | |||
493 | HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ | 495 | HWS_SF(, DOMAIN6_PG_STATUS, DOMAIN6_PGFSM_PWR_STATUS, mask_sh), \ |
494 | HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ | 496 | HWS_SF(, DOMAIN7_PG_STATUS, DOMAIN7_PGFSM_PWR_STATUS, mask_sh), \ |
495 | HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ | 497 | HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \ |
498 | HWS_SF(, D1VGA_CONTROL, D1VGA_MODE_ENABLE, mask_sh),\ | ||
499 | HWS_SF(, D2VGA_CONTROL, D2VGA_MODE_ENABLE, mask_sh),\ | ||
500 | HWS_SF(, D3VGA_CONTROL, D3VGA_MODE_ENABLE, mask_sh),\ | ||
501 | HWS_SF(, D4VGA_CONTROL, D4VGA_MODE_ENABLE, mask_sh),\ | ||
502 | HWS_SF(, VGA_TEST_CONTROL, VGA_TEST_ENABLE, mask_sh),\ | ||
503 | HWS_SF(, VGA_TEST_CONTROL, VGA_TEST_RENDER_START, mask_sh),\ | ||
496 | HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ | 504 | HWS_SF(, LVTMA_PWRSEQ_CNTL, LVTMA_BLON, mask_sh), \ |
497 | HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) | 505 | HWS_SF(, LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, mask_sh) |
498 | 506 | ||
@@ -583,7 +591,13 @@ struct dce_hwseq_registers { | |||
583 | type DCFCLK_GATE_DIS; \ | 591 | type DCFCLK_GATE_DIS; \ |
584 | type DCHUBBUB_GLOBAL_TIMER_REFDIV; \ | 592 | type DCHUBBUB_GLOBAL_TIMER_REFDIV; \ |
585 | type DENTIST_DPPCLK_WDIVIDER; \ | 593 | type DENTIST_DPPCLK_WDIVIDER; \ |
586 | type DENTIST_DISPCLK_WDIVIDER; | 594 | type DENTIST_DISPCLK_WDIVIDER; \ |
595 | type VGA_TEST_ENABLE; \ | ||
596 | type VGA_TEST_RENDER_START; \ | ||
597 | type D1VGA_MODE_ENABLE; \ | ||
598 | type D2VGA_MODE_ENABLE; \ | ||
599 | type D3VGA_MODE_ENABLE; \ | ||
600 | type D4VGA_MODE_ENABLE; | ||
587 | 601 | ||
588 | struct dce_hwseq_shift { | 602 | struct dce_hwseq_shift { |
589 | HWSEQ_REG_FIELD_LIST(uint8_t) | 603 | HWSEQ_REG_FIELD_LIST(uint8_t) |
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c index a266e3f5e75f..e4741f1a2b01 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | |||
@@ -82,13 +82,6 @@ | |||
82 | #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20 | 82 | #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20 |
83 | #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40 | 83 | #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40 |
84 | 84 | ||
85 | /* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ | ||
86 | #define TMDS_MIN_PIXEL_CLOCK 25000 | ||
87 | /* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ | ||
88 | #define TMDS_MAX_PIXEL_CLOCK 165000 | ||
89 | /* For current ASICs pixel clock - 600MHz */ | ||
90 | #define MAX_ENCODER_CLOCK 600000 | ||
91 | |||
92 | enum { | 85 | enum { |
93 | DP_MST_UPDATE_MAX_RETRY = 50 | 86 | DP_MST_UPDATE_MAX_RETRY = 50 |
94 | }; | 87 | }; |
@@ -683,6 +676,7 @@ void dce110_link_encoder_construct( | |||
683 | { | 676 | { |
684 | struct bp_encoder_cap_info bp_cap_info = {0}; | 677 | struct bp_encoder_cap_info bp_cap_info = {0}; |
685 | const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; | 678 | const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs; |
679 | enum bp_result result = BP_RESULT_OK; | ||
686 | 680 | ||
687 | enc110->base.funcs = &dce110_lnk_enc_funcs; | 681 | enc110->base.funcs = &dce110_lnk_enc_funcs; |
688 | enc110->base.ctx = init_data->ctx; | 682 | enc110->base.ctx = init_data->ctx; |
@@ -757,15 +751,24 @@ void dce110_link_encoder_construct( | |||
757 | enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; | 751 | enc110->base.preferred_engine = ENGINE_ID_UNKNOWN; |
758 | } | 752 | } |
759 | 753 | ||
754 | /* default to one to mirror Windows behavior */ | ||
755 | enc110->base.features.flags.bits.HDMI_6GB_EN = 1; | ||
756 | |||
757 | result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios, | ||
758 | enc110->base.id, &bp_cap_info); | ||
759 | |||
760 | /* Override features with DCE-specific values */ | 760 | /* Override features with DCE-specific values */ |
761 | if (BP_RESULT_OK == bp_funcs->get_encoder_cap_info( | 761 | if (BP_RESULT_OK == result) { |
762 | enc110->base.ctx->dc_bios, enc110->base.id, | ||
763 | &bp_cap_info)) { | ||
764 | enc110->base.features.flags.bits.IS_HBR2_CAPABLE = | 762 | enc110->base.features.flags.bits.IS_HBR2_CAPABLE = |
765 | bp_cap_info.DP_HBR2_EN; | 763 | bp_cap_info.DP_HBR2_EN; |
766 | enc110->base.features.flags.bits.IS_HBR3_CAPABLE = | 764 | enc110->base.features.flags.bits.IS_HBR3_CAPABLE = |
767 | bp_cap_info.DP_HBR3_EN; | 765 | bp_cap_info.DP_HBR3_EN; |
768 | enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; | 766 | enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; |
767 | } else { | ||
768 | dm_logger_write(enc110->base.ctx->logger, LOG_WARNING, | ||
769 | "%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", | ||
770 | __func__, | ||
771 | result); | ||
769 | } | 772 | } |
770 | } | 773 | } |
771 | 774 | ||
@@ -904,8 +907,7 @@ void dce110_link_encoder_enable_tmds_output( | |||
904 | struct link_encoder *enc, | 907 | struct link_encoder *enc, |
905 | enum clock_source_id clock_source, | 908 | enum clock_source_id clock_source, |
906 | enum dc_color_depth color_depth, | 909 | enum dc_color_depth color_depth, |
907 | bool hdmi, | 910 | enum signal_type signal, |
908 | bool dual_link, | ||
909 | uint32_t pixel_clock) | 911 | uint32_t pixel_clock) |
910 | { | 912 | { |
911 | struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); | 913 | struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc); |
@@ -919,16 +921,12 @@ void dce110_link_encoder_enable_tmds_output( | |||
919 | cntl.engine_id = enc->preferred_engine; | 921 | cntl.engine_id = enc->preferred_engine; |
920 | cntl.transmitter = enc110->base.transmitter; | 922 | cntl.transmitter = enc110->base.transmitter; |
921 | cntl.pll_id = clock_source; | 923 | cntl.pll_id = clock_source; |
922 | if (hdmi) { | 924 | cntl.signal = signal; |
923 | cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; | 925 | if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK) |
924 | cntl.lanes_number = 4; | ||
925 | } else if (dual_link) { | ||
926 | cntl.signal = SIGNAL_TYPE_DVI_DUAL_LINK; | ||
927 | cntl.lanes_number = 8; | 926 | cntl.lanes_number = 8; |
928 | } else { | 927 | else |
929 | cntl.signal = SIGNAL_TYPE_DVI_SINGLE_LINK; | ||
930 | cntl.lanes_number = 4; | 928 | cntl.lanes_number = 4; |
931 | } | 929 | |
932 | cntl.hpd_sel = enc110->base.hpd_source; | 930 | cntl.hpd_sel = enc110->base.hpd_source; |
933 | 931 | ||
934 | cntl.pixel_clock = pixel_clock; | 932 | cntl.pixel_clock = pixel_clock; |
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 8ca9afe47a2b..0ec3433d34b6 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h | |||
@@ -210,8 +210,7 @@ void dce110_link_encoder_enable_tmds_output( | |||
210 | struct link_encoder *enc, | 210 | struct link_encoder *enc, |
211 | enum clock_source_id clock_source, | 211 | enum clock_source_id clock_source, |
212 | enum dc_color_depth color_depth, | 212 | enum dc_color_depth color_depth, |
213 | bool hdmi, | 213 | enum signal_type signal, |
214 | bool dual_link, | ||
215 | uint32_t pixel_clock); | 214 | uint32_t pixel_clock); |
216 | 215 | ||
217 | /* enables DP PHY output */ | 216 | /* enables DP PHY output */ |
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c index 3931412ab6d3..87093894ea9e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c | |||
@@ -128,23 +128,22 @@ static void set_truncation( | |||
128 | return; | 128 | return; |
129 | } | 129 | } |
130 | /* on other format-to do */ | 130 | /* on other format-to do */ |
131 | if (params->flags.TRUNCATE_ENABLED == 0 || | 131 | if (params->flags.TRUNCATE_ENABLED == 0) |
132 | params->flags.TRUNCATE_DEPTH == 2) | ||
133 | return; | 132 | return; |
134 | /*Set truncation depth and Enable truncation*/ | 133 | /*Set truncation depth and Enable truncation*/ |
135 | REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, | 134 | REG_UPDATE_3(FMT_BIT_DEPTH_CONTROL, |
136 | FMT_TRUNCATE_EN, 1, | 135 | FMT_TRUNCATE_EN, 1, |
137 | FMT_TRUNCATE_DEPTH, | 136 | FMT_TRUNCATE_DEPTH, |
138 | params->flags.TRUNCATE_MODE, | 137 | params->flags.TRUNCATE_DEPTH, |
139 | FMT_TRUNCATE_MODE, | 138 | FMT_TRUNCATE_MODE, |
140 | params->flags.TRUNCATE_DEPTH); | 139 | params->flags.TRUNCATE_MODE); |
141 | } | 140 | } |
142 | 141 | ||
143 | 142 | ||
144 | /** | 143 | /** |
145 | * set_spatial_dither | 144 | * set_spatial_dither |
146 | * 1) set spatial dithering mode: pattern of seed | 145 | * 1) set spatial dithering mode: pattern of seed |
147 | * 2) set spatical dithering depth: 0 for 18bpp or 1 for 24bpp | 146 | * 2) set spatial dithering depth: 0 for 18bpp or 1 for 24bpp |
148 | * 3) set random seed | 147 | * 3) set random seed |
149 | * 4) set random mode | 148 | * 4) set random mode |
150 | * lfsr is reset every frame or not reset | 149 | * lfsr is reset every frame or not reset |
diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c index 3ea43e2a9450..442dd2d93618 100644 --- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c | |||
@@ -852,6 +852,7 @@ static bool construct( | |||
852 | dc->caps.max_downscale_ratio = 200; | 852 | dc->caps.max_downscale_ratio = 200; |
853 | dc->caps.i2c_speed_in_khz = 40; | 853 | dc->caps.i2c_speed_in_khz = 40; |
854 | dc->caps.max_cursor_size = 128; | 854 | dc->caps.max_cursor_size = 128; |
855 | dc->caps.dual_link_dvi = true; | ||
855 | 856 | ||
856 | for (i = 0; i < pool->base.pipe_count; i++) { | 857 | for (i = 0; i < pool->base.pipe_count; i++) { |
857 | pool->base.timing_generators[i] = | 858 | pool->base.timing_generators[i] = |
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 86cdd7b4811f..6f382a3ac90f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | |||
@@ -688,15 +688,22 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) | |||
688 | struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; | 688 | struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; |
689 | struct dc_link *link = pipe_ctx->stream->sink->link; | 689 | struct dc_link *link = pipe_ctx->stream->sink->link; |
690 | 690 | ||
691 | /* 1. update AVI info frame (HDMI, DP) | 691 | |
692 | * we always need to update info frame | ||
693 | */ | ||
694 | uint32_t active_total_with_borders; | 692 | uint32_t active_total_with_borders; |
695 | uint32_t early_control = 0; | 693 | uint32_t early_control = 0; |
696 | struct timing_generator *tg = pipe_ctx->stream_res.tg; | 694 | struct timing_generator *tg = pipe_ctx->stream_res.tg; |
697 | 695 | ||
698 | /* TODOFPGA may change to hwss.update_info_frame */ | 696 | /* For MST, there are multiply stream go to only one link. |
697 | * connect DIG back_end to front_end while enable_stream and | ||
698 | * disconnect them during disable_stream | ||
699 | * BY this, it is logic clean to separate stream and link */ | ||
700 | link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, | ||
701 | pipe_ctx->stream_res.stream_enc->id, true); | ||
702 | |||
703 | /* update AVI info frame (HDMI, DP)*/ | ||
704 | /* TODO: FPGA may change to hwss.update_info_frame */ | ||
699 | dce110_update_info_frame(pipe_ctx); | 705 | dce110_update_info_frame(pipe_ctx); |
706 | |||
700 | /* enable early control to avoid corruption on DP monitor*/ | 707 | /* enable early control to avoid corruption on DP monitor*/ |
701 | active_total_with_borders = | 708 | active_total_with_borders = |
702 | timing->h_addressable | 709 | timing->h_addressable |
@@ -717,12 +724,8 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) | |||
717 | pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); | 724 | pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); |
718 | } | 725 | } |
719 | 726 | ||
720 | /* For MST, there are multiply stream go to only one link. | 727 | |
721 | * connect DIG back_end to front_end while enable_stream and | 728 | |
722 | * disconnect them during disable_stream | ||
723 | * BY this, it is logic clean to separate stream and link */ | ||
724 | link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, | ||
725 | pipe_ctx->stream_res.stream_enc->id, true); | ||
726 | 729 | ||
727 | } | 730 | } |
728 | 731 | ||
@@ -1690,9 +1693,13 @@ static void apply_min_clocks( | |||
1690 | * Check if FBC can be enabled | 1693 | * Check if FBC can be enabled |
1691 | */ | 1694 | */ |
1692 | static bool should_enable_fbc(struct dc *dc, | 1695 | static bool should_enable_fbc(struct dc *dc, |
1693 | struct dc_state *context) | 1696 | struct dc_state *context, |
1697 | uint32_t *pipe_idx) | ||
1694 | { | 1698 | { |
1695 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; | 1699 | uint32_t i; |
1700 | struct pipe_ctx *pipe_ctx = NULL; | ||
1701 | struct resource_context *res_ctx = &context->res_ctx; | ||
1702 | |||
1696 | 1703 | ||
1697 | ASSERT(dc->fbc_compressor); | 1704 | ASSERT(dc->fbc_compressor); |
1698 | 1705 | ||
@@ -1704,6 +1711,14 @@ static bool should_enable_fbc(struct dc *dc, | |||
1704 | if (context->stream_count != 1) | 1711 | if (context->stream_count != 1) |
1705 | return false; | 1712 | return false; |
1706 | 1713 | ||
1714 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | ||
1715 | if (res_ctx->pipe_ctx[i].stream) { | ||
1716 | pipe_ctx = &res_ctx->pipe_ctx[i]; | ||
1717 | *pipe_idx = i; | ||
1718 | break; | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1707 | /* Only supports eDP */ | 1722 | /* Only supports eDP */ |
1708 | if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) | 1723 | if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP) |
1709 | return false; | 1724 | return false; |
@@ -1729,11 +1744,14 @@ static bool should_enable_fbc(struct dc *dc, | |||
1729 | static void enable_fbc(struct dc *dc, | 1744 | static void enable_fbc(struct dc *dc, |
1730 | struct dc_state *context) | 1745 | struct dc_state *context) |
1731 | { | 1746 | { |
1732 | if (should_enable_fbc(dc, context)) { | 1747 | uint32_t pipe_idx = 0; |
1748 | |||
1749 | if (should_enable_fbc(dc, context, &pipe_idx)) { | ||
1733 | /* Program GRPH COMPRESSED ADDRESS and PITCH */ | 1750 | /* Program GRPH COMPRESSED ADDRESS and PITCH */ |
1734 | struct compr_addr_and_pitch_params params = {0, 0, 0}; | 1751 | struct compr_addr_and_pitch_params params = {0, 0, 0}; |
1735 | struct compressor *compr = dc->fbc_compressor; | 1752 | struct compressor *compr = dc->fbc_compressor; |
1736 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[0]; | 1753 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx]; |
1754 | |||
1737 | 1755 | ||
1738 | params.source_view_width = pipe_ctx->stream->timing.h_addressable; | 1756 | params.source_view_width = pipe_ctx->stream->timing.h_addressable; |
1739 | params.source_view_height = pipe_ctx->stream->timing.v_addressable; | 1757 | params.source_view_height = pipe_ctx->stream->timing.v_addressable; |
@@ -2915,6 +2933,49 @@ static void program_csc_matrix(struct pipe_ctx *pipe_ctx, | |||
2915 | } | 2933 | } |
2916 | } | 2934 | } |
2917 | 2935 | ||
2936 | void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx) | ||
2937 | { | ||
2938 | struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; | ||
2939 | struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp; | ||
2940 | struct mem_input *mi = pipe_ctx->plane_res.mi; | ||
2941 | struct dc_cursor_mi_param param = { | ||
2942 | .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz, | ||
2943 | .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz, | ||
2944 | .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x, | ||
2945 | .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width, | ||
2946 | .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz | ||
2947 | }; | ||
2948 | |||
2949 | if (pipe_ctx->plane_state->address.type | ||
2950 | == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) | ||
2951 | pos_cpy.enable = false; | ||
2952 | |||
2953 | if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) | ||
2954 | pos_cpy.enable = false; | ||
2955 | |||
2956 | if (ipp->funcs->ipp_cursor_set_position) | ||
2957 | ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m); | ||
2958 | if (mi->funcs->set_cursor_position) | ||
2959 | mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m); | ||
2960 | } | ||
2961 | |||
2962 | void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx) | ||
2963 | { | ||
2964 | struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; | ||
2965 | |||
2966 | if (pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes) | ||
2967 | pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes( | ||
2968 | pipe_ctx->plane_res.ipp, attributes); | ||
2969 | |||
2970 | if (pipe_ctx->plane_res.mi->funcs->set_cursor_attributes) | ||
2971 | pipe_ctx->plane_res.mi->funcs->set_cursor_attributes( | ||
2972 | pipe_ctx->plane_res.mi, attributes); | ||
2973 | |||
2974 | if (pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes) | ||
2975 | pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes( | ||
2976 | pipe_ctx->plane_res.xfm, attributes); | ||
2977 | } | ||
2978 | |||
2918 | static void ready_shared_resources(struct dc *dc, struct dc_state *context) {} | 2979 | static void ready_shared_resources(struct dc *dc, struct dc_state *context) {} |
2919 | 2980 | ||
2920 | static void optimize_shared_resources(struct dc *dc) {} | 2981 | static void optimize_shared_resources(struct dc *dc) {} |
@@ -2957,6 +3018,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { | |||
2957 | .edp_backlight_control = hwss_edp_backlight_control, | 3018 | .edp_backlight_control = hwss_edp_backlight_control, |
2958 | .edp_power_control = hwss_edp_power_control, | 3019 | .edp_power_control = hwss_edp_power_control, |
2959 | .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, | 3020 | .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, |
3021 | .set_cursor_position = dce110_set_cursor_position, | ||
3022 | .set_cursor_attribute = dce110_set_cursor_attribute | ||
2960 | }; | 3023 | }; |
2961 | 3024 | ||
2962 | void dce110_hw_sequencer_construct(struct dc *dc) | 3025 | void dce110_hw_sequencer_construct(struct dc *dc) |
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index 7c4779578fb7..00f18c485e1e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | |||
@@ -846,6 +846,16 @@ static bool dce110_validate_bandwidth( | |||
846 | return result; | 846 | return result; |
847 | } | 847 | } |
848 | 848 | ||
849 | enum dc_status dce110_validate_plane(const struct dc_plane_state *plane_state, | ||
850 | struct dc_caps *caps) | ||
851 | { | ||
852 | if (((plane_state->dst_rect.width * 2) < plane_state->src_rect.width) || | ||
853 | ((plane_state->dst_rect.height * 2) < plane_state->src_rect.height)) | ||
854 | return DC_FAIL_SURFACE_VALIDATE; | ||
855 | |||
856 | return DC_OK; | ||
857 | } | ||
858 | |||
849 | static bool dce110_validate_surface_sets( | 859 | static bool dce110_validate_surface_sets( |
850 | struct dc_state *context) | 860 | struct dc_state *context) |
851 | { | 861 | { |
@@ -869,6 +879,13 @@ static bool dce110_validate_surface_sets( | |||
869 | plane->src_rect.height > 1080)) | 879 | plane->src_rect.height > 1080)) |
870 | return false; | 880 | return false; |
871 | 881 | ||
882 | /* we don't have the logic to support underlay | ||
883 | * only yet so block the use case where we get | ||
884 | * NV12 plane as top layer | ||
885 | */ | ||
886 | if (j == 0) | ||
887 | return false; | ||
888 | |||
872 | /* irrespective of plane format, | 889 | /* irrespective of plane format, |
873 | * stream should be RGB encoded | 890 | * stream should be RGB encoded |
874 | */ | 891 | */ |
@@ -1021,6 +1038,7 @@ static const struct resource_funcs dce110_res_pool_funcs = { | |||
1021 | .link_enc_create = dce110_link_encoder_create, | 1038 | .link_enc_create = dce110_link_encoder_create, |
1022 | .validate_guaranteed = dce110_validate_guaranteed, | 1039 | .validate_guaranteed = dce110_validate_guaranteed, |
1023 | .validate_bandwidth = dce110_validate_bandwidth, | 1040 | .validate_bandwidth = dce110_validate_bandwidth, |
1041 | .validate_plane = dce110_validate_plane, | ||
1024 | .acquire_idle_pipe_for_layer = dce110_acquire_underlay, | 1042 | .acquire_idle_pipe_for_layer = dce110_acquire_underlay, |
1025 | .add_stream_to_ctx = dce110_add_stream_to_ctx, | 1043 | .add_stream_to_ctx = dce110_add_stream_to_ctx, |
1026 | .validate_global = dce110_validate_global | 1044 | .validate_global = dce110_validate_global |
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c index 663e0a047a4b..98d9cd0109e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | |||
@@ -1103,6 +1103,8 @@ static bool construct( | |||
1103 | dc->caps.max_downscale_ratio = 200; | 1103 | dc->caps.max_downscale_ratio = 200; |
1104 | dc->caps.i2c_speed_in_khz = 100; | 1104 | dc->caps.i2c_speed_in_khz = 100; |
1105 | dc->caps.max_cursor_size = 128; | 1105 | dc->caps.max_cursor_size = 128; |
1106 | dc->caps.dual_link_dvi = true; | ||
1107 | |||
1106 | 1108 | ||
1107 | /************************************************* | 1109 | /************************************************* |
1108 | * Create resources * | 1110 | * Create resources * |
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index 57cd67359567..5aab01db28ee 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | |||
@@ -835,6 +835,8 @@ static bool construct( | |||
835 | dc->caps.max_downscale_ratio = 200; | 835 | dc->caps.max_downscale_ratio = 200; |
836 | dc->caps.i2c_speed_in_khz = 100; | 836 | dc->caps.i2c_speed_in_khz = 100; |
837 | dc->caps.max_cursor_size = 128; | 837 | dc->caps.max_cursor_size = 128; |
838 | dc->caps.dual_link_dvi = true; | ||
839 | |||
838 | dc->debug = debug_defaults; | 840 | dc->debug = debug_defaults; |
839 | 841 | ||
840 | /************************************************* | 842 | /************************************************* |
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c index 8f2bd56f3461..25d7eb1567ae 100644 --- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | |||
@@ -793,6 +793,7 @@ static bool dce80_construct( | |||
793 | dc->caps.max_downscale_ratio = 200; | 793 | dc->caps.max_downscale_ratio = 200; |
794 | dc->caps.i2c_speed_in_khz = 40; | 794 | dc->caps.i2c_speed_in_khz = 40; |
795 | dc->caps.max_cursor_size = 128; | 795 | dc->caps.max_cursor_size = 128; |
796 | dc->caps.dual_link_dvi = true; | ||
796 | 797 | ||
797 | /************************************************* | 798 | /************************************************* |
798 | * Create resources * | 799 | * Create resources * |
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 82572863acab..dc1e010725c1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | |||
@@ -238,10 +238,34 @@ static void enable_power_gating_plane( | |||
238 | static void disable_vga( | 238 | static void disable_vga( |
239 | struct dce_hwseq *hws) | 239 | struct dce_hwseq *hws) |
240 | { | 240 | { |
241 | unsigned int in_vga1_mode = 0; | ||
242 | unsigned int in_vga2_mode = 0; | ||
243 | unsigned int in_vga3_mode = 0; | ||
244 | unsigned int in_vga4_mode = 0; | ||
245 | |||
246 | REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga1_mode); | ||
247 | REG_GET(D2VGA_CONTROL, D2VGA_MODE_ENABLE, &in_vga2_mode); | ||
248 | REG_GET(D3VGA_CONTROL, D3VGA_MODE_ENABLE, &in_vga3_mode); | ||
249 | REG_GET(D4VGA_CONTROL, D4VGA_MODE_ENABLE, &in_vga4_mode); | ||
250 | |||
251 | if (in_vga1_mode == 0 && in_vga2_mode == 0 && | ||
252 | in_vga3_mode == 0 && in_vga4_mode == 0) | ||
253 | return; | ||
254 | |||
241 | REG_WRITE(D1VGA_CONTROL, 0); | 255 | REG_WRITE(D1VGA_CONTROL, 0); |
242 | REG_WRITE(D2VGA_CONTROL, 0); | 256 | REG_WRITE(D2VGA_CONTROL, 0); |
243 | REG_WRITE(D3VGA_CONTROL, 0); | 257 | REG_WRITE(D3VGA_CONTROL, 0); |
244 | REG_WRITE(D4VGA_CONTROL, 0); | 258 | REG_WRITE(D4VGA_CONTROL, 0); |
259 | |||
260 | /* HW Engineer's Notes: | ||
261 | * During switch from vga->extended, if we set the VGA_TEST_ENABLE and | ||
262 | * then hit the VGA_TEST_RENDER_START, then the DCHUBP timing gets updated correctly. | ||
263 | * | ||
264 | * Then vBIOS will have it poll for the VGA_TEST_RENDER_DONE and unset | ||
265 | * VGA_TEST_ENABLE, to leave it in the same state as before. | ||
266 | */ | ||
267 | REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_ENABLE, 1); | ||
268 | REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1); | ||
245 | } | 269 | } |
246 | 270 | ||
247 | static void dpp_pg_control( | 271 | static void dpp_pg_control( |
@@ -1761,6 +1785,11 @@ static void update_dchubp_dpp( | |||
1761 | &pipe_ctx->plane_res.scl_data.viewport_c); | 1785 | &pipe_ctx->plane_res.scl_data.viewport_c); |
1762 | } | 1786 | } |
1763 | 1787 | ||
1788 | if (pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { | ||
1789 | dc->hwss.set_cursor_position(pipe_ctx); | ||
1790 | dc->hwss.set_cursor_attribute(pipe_ctx); | ||
1791 | } | ||
1792 | |||
1764 | if (plane_state->update_flags.bits.full_update) { | 1793 | if (plane_state->update_flags.bits.full_update) { |
1765 | /*gamut remap*/ | 1794 | /*gamut remap*/ |
1766 | program_gamut_remap(pipe_ctx); | 1795 | program_gamut_remap(pipe_ctx); |
@@ -2296,7 +2325,7 @@ static bool dcn10_dummy_display_power_gating( | |||
2296 | return true; | 2325 | return true; |
2297 | } | 2326 | } |
2298 | 2327 | ||
2299 | void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) | 2328 | static void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) |
2300 | { | 2329 | { |
2301 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; | 2330 | struct dc_plane_state *plane_state = pipe_ctx->plane_state; |
2302 | struct timing_generator *tg = pipe_ctx->stream_res.tg; | 2331 | struct timing_generator *tg = pipe_ctx->stream_res.tg; |
@@ -2316,12 +2345,46 @@ void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx) | |||
2316 | } | 2345 | } |
2317 | } | 2346 | } |
2318 | 2347 | ||
2319 | void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) | 2348 | static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) |
2320 | { | 2349 | { |
2321 | if (hws->ctx->dc->res_pool->hubbub != NULL) | 2350 | if (hws->ctx->dc->res_pool->hubbub != NULL) |
2322 | hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data); | 2351 | hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data); |
2323 | } | 2352 | } |
2324 | 2353 | ||
2354 | static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx) | ||
2355 | { | ||
2356 | struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position; | ||
2357 | struct hubp *hubp = pipe_ctx->plane_res.hubp; | ||
2358 | struct dpp *dpp = pipe_ctx->plane_res.dpp; | ||
2359 | struct dc_cursor_mi_param param = { | ||
2360 | .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz, | ||
2361 | .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz, | ||
2362 | .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x, | ||
2363 | .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width, | ||
2364 | .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz | ||
2365 | }; | ||
2366 | |||
2367 | if (pipe_ctx->plane_state->address.type | ||
2368 | == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE) | ||
2369 | pos_cpy.enable = false; | ||
2370 | |||
2371 | if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state) | ||
2372 | pos_cpy.enable = false; | ||
2373 | |||
2374 | hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m); | ||
2375 | dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width); | ||
2376 | } | ||
2377 | |||
2378 | static void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx) | ||
2379 | { | ||
2380 | struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes; | ||
2381 | |||
2382 | pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes( | ||
2383 | pipe_ctx->plane_res.hubp, attributes); | ||
2384 | pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes( | ||
2385 | pipe_ctx->plane_res.dpp, attributes->color_format); | ||
2386 | } | ||
2387 | |||
2325 | static const struct hw_sequencer_funcs dcn10_funcs = { | 2388 | static const struct hw_sequencer_funcs dcn10_funcs = { |
2326 | .program_gamut_remap = program_gamut_remap, | 2389 | .program_gamut_remap = program_gamut_remap, |
2327 | .program_csc_matrix = program_csc_matrix, | 2390 | .program_csc_matrix = program_csc_matrix, |
@@ -2362,6 +2425,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { | |||
2362 | .edp_backlight_control = hwss_edp_backlight_control, | 2425 | .edp_backlight_control = hwss_edp_backlight_control, |
2363 | .edp_power_control = hwss_edp_power_control, | 2426 | .edp_power_control = hwss_edp_power_control, |
2364 | .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, | 2427 | .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready, |
2428 | .set_cursor_position = dcn10_set_cursor_position, | ||
2429 | .set_cursor_attribute = dcn10_set_cursor_attribute | ||
2365 | }; | 2430 | }; |
2366 | 2431 | ||
2367 | 2432 | ||
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 0fd329deacd8..54d8a1386142 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h | |||
@@ -123,8 +123,7 @@ struct link_encoder_funcs { | |||
123 | void (*enable_tmds_output)(struct link_encoder *enc, | 123 | void (*enable_tmds_output)(struct link_encoder *enc, |
124 | enum clock_source_id clock_source, | 124 | enum clock_source_id clock_source, |
125 | enum dc_color_depth color_depth, | 125 | enum dc_color_depth color_depth, |
126 | bool hdmi, | 126 | enum signal_type signal, |
127 | bool dual_link, | ||
128 | uint32_t pixel_clock); | 127 | uint32_t pixel_clock); |
129 | void (*enable_dp_output)(struct link_encoder *enc, | 128 | void (*enable_dp_output)(struct link_encoder *enc, |
130 | const struct dc_link_settings *link_settings, | 129 | const struct dc_link_settings *link_settings, |
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 4c0aa56f7bae..379c6ecd271a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | |||
@@ -198,6 +198,9 @@ struct hw_sequencer_funcs { | |||
198 | bool enable); | 198 | bool enable); |
199 | void (*edp_wait_for_hpd_ready)(struct dc_link *link, bool power_up); | 199 | void (*edp_wait_for_hpd_ready)(struct dc_link *link, bool power_up); |
200 | 200 | ||
201 | void (*set_cursor_position)(struct pipe_ctx *pipe); | ||
202 | void (*set_cursor_attribute)(struct pipe_ctx *pipe); | ||
203 | |||
201 | }; | 204 | }; |
202 | 205 | ||
203 | void color_space_to_black_color( | 206 | void color_space_to_black_color( |
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index f7e40b292dfb..d3e1923b01a8 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c | |||
@@ -217,7 +217,7 @@ bool dce110_vblank_set( | |||
217 | core_dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; | 217 | core_dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; |
218 | 218 | ||
219 | if (enable) { | 219 | if (enable) { |
220 | if (!tg->funcs->arm_vert_intr(tg, 2)) { | 220 | if (!tg || !tg->funcs->arm_vert_intr(tg, 2)) { |
221 | DC_ERROR("Failed to get VBLANK!\n"); | 221 | DC_ERROR("Failed to get VBLANK!\n"); |
222 | return false; | 222 | return false; |
223 | } | 223 | } |
diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c index 57a54a7b89e5..1c079ba37c30 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_link_encoder.c | |||
@@ -42,8 +42,7 @@ static void virtual_link_encoder_enable_tmds_output( | |||
42 | struct link_encoder *enc, | 42 | struct link_encoder *enc, |
43 | enum clock_source_id clock_source, | 43 | enum clock_source_id clock_source, |
44 | enum dc_color_depth color_depth, | 44 | enum dc_color_depth color_depth, |
45 | bool hdmi, | 45 | enum signal_type signal, |
46 | bool dual_link, | ||
47 | uint32_t pixel_clock) {} | 46 | uint32_t pixel_clock) {} |
48 | 47 | ||
49 | static void virtual_link_encoder_enable_dp_output( | 48 | static void virtual_link_encoder_enable_dp_output( |
diff --git a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h index 7a9b43f84a31..36bbad594267 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_ctrl_defs.h | |||
@@ -419,11 +419,6 @@ struct bios_event_info { | |||
419 | bool backlight_changed; | 419 | bool backlight_changed; |
420 | }; | 420 | }; |
421 | 421 | ||
422 | enum { | ||
423 | HDMI_PIXEL_CLOCK_IN_KHZ_297 = 297000, | ||
424 | TMDS_PIXEL_CLOCK_IN_KHZ_165 = 165000 | ||
425 | }; | ||
426 | |||
427 | /* | 422 | /* |
428 | * DFS-bypass flag | 423 | * DFS-bypass flag |
429 | */ | 424 | */ |
diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h index b5ebde642207..199c5db67cbc 100644 --- a/drivers/gpu/drm/amd/display/include/signal_types.h +++ b/drivers/gpu/drm/amd/display/include/signal_types.h | |||
@@ -26,6 +26,11 @@ | |||
26 | #ifndef __DC_SIGNAL_TYPES_H__ | 26 | #ifndef __DC_SIGNAL_TYPES_H__ |
27 | #define __DC_SIGNAL_TYPES_H__ | 27 | #define __DC_SIGNAL_TYPES_H__ |
28 | 28 | ||
29 | /* Minimum pixel clock, in KHz. For TMDS signal is 25.00 MHz */ | ||
30 | #define TMDS_MIN_PIXEL_CLOCK 25000 | ||
31 | /* Maximum pixel clock, in KHz. For TMDS signal is 165.00 MHz */ | ||
32 | #define TMDS_MAX_PIXEL_CLOCK 165000 | ||
33 | |||
29 | enum signal_type { | 34 | enum signal_type { |
30 | SIGNAL_TYPE_NONE = 0L, /* no signal */ | 35 | SIGNAL_TYPE_NONE = 0L, /* no signal */ |
31 | SIGNAL_TYPE_DVI_SINGLE_LINK = (1 << 0), | 36 | SIGNAL_TYPE_DVI_SINGLE_LINK = (1 << 0), |
diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h index 5f4c2e833a65..d665dd5af5dd 100644 --- a/drivers/gpu/drm/ast/ast_tables.h +++ b/drivers/gpu/drm/ast/ast_tables.h | |||
@@ -97,7 +97,7 @@ static const struct ast_vbios_dclk_info dclk_table[] = { | |||
97 | {0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */ | 97 | {0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */ |
98 | {0x6A, 0x22, 0x00}, /* 0F: VCLK162 */ | 98 | {0x6A, 0x22, 0x00}, /* 0F: VCLK162 */ |
99 | {0x4d, 0x4c, 0x80}, /* 10: VCLK154 */ | 99 | {0x4d, 0x4c, 0x80}, /* 10: VCLK154 */ |
100 | {0xa7, 0x78, 0x80}, /* 11: VCLK83.5 */ | 100 | {0x68, 0x6f, 0x80}, /* 11: VCLK83.5 */ |
101 | {0x28, 0x49, 0x80}, /* 12: VCLK106.5 */ | 101 | {0x28, 0x49, 0x80}, /* 12: VCLK106.5 */ |
102 | {0x37, 0x49, 0x80}, /* 13: VCLK146.25 */ | 102 | {0x37, 0x49, 0x80}, /* 13: VCLK146.25 */ |
103 | {0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */ | 103 | {0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */ |
@@ -127,7 +127,7 @@ static const struct ast_vbios_dclk_info dclk_table_ast2500[] = { | |||
127 | {0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */ | 127 | {0x67, 0x22, 0x00}, /* 0E: VCLK157_5 */ |
128 | {0x6A, 0x22, 0x00}, /* 0F: VCLK162 */ | 128 | {0x6A, 0x22, 0x00}, /* 0F: VCLK162 */ |
129 | {0x4d, 0x4c, 0x80}, /* 10: VCLK154 */ | 129 | {0x4d, 0x4c, 0x80}, /* 10: VCLK154 */ |
130 | {0xa7, 0x78, 0x80}, /* 11: VCLK83.5 */ | 130 | {0x68, 0x6f, 0x80}, /* 11: VCLK83.5 */ |
131 | {0x28, 0x49, 0x80}, /* 12: VCLK106.5 */ | 131 | {0x28, 0x49, 0x80}, /* 12: VCLK106.5 */ |
132 | {0x37, 0x49, 0x80}, /* 13: VCLK146.25 */ | 132 | {0x37, 0x49, 0x80}, /* 13: VCLK146.25 */ |
133 | {0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */ | 133 | {0x1f, 0x45, 0x80}, /* 14: VCLK148.5 */ |
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index c0530a1af5e3..2dc5e8bed172 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c | |||
@@ -461,6 +461,12 @@ int drm_mode_getfb(struct drm_device *dev, | |||
461 | if (!fb) | 461 | if (!fb) |
462 | return -ENOENT; | 462 | return -ENOENT; |
463 | 463 | ||
464 | /* Multi-planar framebuffers need getfb2. */ | ||
465 | if (fb->format->num_planes > 1) { | ||
466 | ret = -EINVAL; | ||
467 | goto out; | ||
468 | } | ||
469 | |||
464 | r->height = fb->height; | 470 | r->height = fb->height; |
465 | r->width = fb->width; | 471 | r->width = fb->width; |
466 | r->depth = fb->format->depth; | 472 | r->depth = fb->format->depth; |
@@ -484,6 +490,7 @@ int drm_mode_getfb(struct drm_device *dev, | |||
484 | ret = -ENODEV; | 490 | ret = -ENODEV; |
485 | } | 491 | } |
486 | 492 | ||
493 | out: | ||
487 | drm_framebuffer_put(fb); | 494 | drm_framebuffer_put(fb); |
488 | 495 | ||
489 | return ret; | 496 | return ret; |
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index c8454ac43fae..db6b94dda5df 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c | |||
@@ -471,6 +471,7 @@ struct parser_exec_state { | |||
471 | * used when ret from 2nd level batch buffer | 471 | * used when ret from 2nd level batch buffer |
472 | */ | 472 | */ |
473 | int saved_buf_addr_type; | 473 | int saved_buf_addr_type; |
474 | bool is_ctx_wa; | ||
474 | 475 | ||
475 | struct cmd_info *info; | 476 | struct cmd_info *info; |
476 | 477 | ||
@@ -1715,6 +1716,11 @@ static int perform_bb_shadow(struct parser_exec_state *s) | |||
1715 | bb->accessing = true; | 1716 | bb->accessing = true; |
1716 | bb->bb_start_cmd_va = s->ip_va; | 1717 | bb->bb_start_cmd_va = s->ip_va; |
1717 | 1718 | ||
1719 | if ((s->buf_type == BATCH_BUFFER_INSTRUCTION) && (!s->is_ctx_wa)) | ||
1720 | bb->bb_offset = s->ip_va - s->rb_va; | ||
1721 | else | ||
1722 | bb->bb_offset = 0; | ||
1723 | |||
1718 | /* | 1724 | /* |
1719 | * ip_va saves the virtual address of the shadow batch buffer, while | 1725 | * ip_va saves the virtual address of the shadow batch buffer, while |
1720 | * ip_gma saves the graphics address of the original batch buffer. | 1726 | * ip_gma saves the graphics address of the original batch buffer. |
@@ -2571,6 +2577,7 @@ static int scan_workload(struct intel_vgpu_workload *workload) | |||
2571 | s.ring_tail = gma_tail; | 2577 | s.ring_tail = gma_tail; |
2572 | s.rb_va = workload->shadow_ring_buffer_va; | 2578 | s.rb_va = workload->shadow_ring_buffer_va; |
2573 | s.workload = workload; | 2579 | s.workload = workload; |
2580 | s.is_ctx_wa = false; | ||
2574 | 2581 | ||
2575 | if ((bypass_scan_mask & (1 << workload->ring_id)) || | 2582 | if ((bypass_scan_mask & (1 << workload->ring_id)) || |
2576 | gma_head == gma_tail) | 2583 | gma_head == gma_tail) |
@@ -2624,6 +2631,7 @@ static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | |||
2624 | s.ring_tail = gma_tail; | 2631 | s.ring_tail = gma_tail; |
2625 | s.rb_va = wa_ctx->indirect_ctx.shadow_va; | 2632 | s.rb_va = wa_ctx->indirect_ctx.shadow_va; |
2626 | s.workload = workload; | 2633 | s.workload = workload; |
2634 | s.is_ctx_wa = true; | ||
2627 | 2635 | ||
2628 | if (!intel_gvt_ggtt_validate_range(s.vgpu, s.ring_start, s.ring_size)) { | 2636 | if (!intel_gvt_ggtt_validate_range(s.vgpu, s.ring_start, s.ring_size)) { |
2629 | ret = -EINVAL; | 2637 | ret = -EINVAL; |
diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index 256f1bb522b7..152df3d0291e 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c | |||
@@ -394,9 +394,11 @@ void intel_gvt_switch_mmio(struct intel_vgpu *pre, | |||
394 | * performace for batch mmio read/write, so we need | 394 | * performace for batch mmio read/write, so we need |
395 | * handle forcewake mannually. | 395 | * handle forcewake mannually. |
396 | */ | 396 | */ |
397 | intel_runtime_pm_get(dev_priv); | ||
397 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); | 398 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); |
398 | switch_mmio(pre, next, ring_id); | 399 | switch_mmio(pre, next, ring_id); |
399 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); | 400 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); |
401 | intel_runtime_pm_put(dev_priv); | ||
400 | } | 402 | } |
401 | 403 | ||
402 | /** | 404 | /** |
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index b55b3580ca1d..d74d6f05c62c 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c | |||
@@ -52,6 +52,54 @@ static void set_context_pdp_root_pointer( | |||
52 | pdp_pair[i].val = pdp[7 - i]; | 52 | pdp_pair[i].val = pdp[7 - i]; |
53 | } | 53 | } |
54 | 54 | ||
55 | /* | ||
56 | * when populating shadow ctx from guest, we should not overrride oa related | ||
57 | * registers, so that they will not be overlapped by guest oa configs. Thus | ||
58 | * made it possible to capture oa data from host for both host and guests. | ||
59 | */ | ||
60 | static void sr_oa_regs(struct intel_vgpu_workload *workload, | ||
61 | u32 *reg_state, bool save) | ||
62 | { | ||
63 | struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; | ||
64 | u32 ctx_oactxctrl = dev_priv->perf.oa.ctx_oactxctrl_offset; | ||
65 | u32 ctx_flexeu0 = dev_priv->perf.oa.ctx_flexeu0_offset; | ||
66 | int i = 0; | ||
67 | u32 flex_mmio[] = { | ||
68 | i915_mmio_reg_offset(EU_PERF_CNTL0), | ||
69 | i915_mmio_reg_offset(EU_PERF_CNTL1), | ||
70 | i915_mmio_reg_offset(EU_PERF_CNTL2), | ||
71 | i915_mmio_reg_offset(EU_PERF_CNTL3), | ||
72 | i915_mmio_reg_offset(EU_PERF_CNTL4), | ||
73 | i915_mmio_reg_offset(EU_PERF_CNTL5), | ||
74 | i915_mmio_reg_offset(EU_PERF_CNTL6), | ||
75 | }; | ||
76 | |||
77 | if (!workload || !reg_state || workload->ring_id != RCS) | ||
78 | return; | ||
79 | |||
80 | if (save) { | ||
81 | workload->oactxctrl = reg_state[ctx_oactxctrl + 1]; | ||
82 | |||
83 | for (i = 0; i < ARRAY_SIZE(workload->flex_mmio); i++) { | ||
84 | u32 state_offset = ctx_flexeu0 + i * 2; | ||
85 | |||
86 | workload->flex_mmio[i] = reg_state[state_offset + 1]; | ||
87 | } | ||
88 | } else { | ||
89 | reg_state[ctx_oactxctrl] = | ||
90 | i915_mmio_reg_offset(GEN8_OACTXCONTROL); | ||
91 | reg_state[ctx_oactxctrl + 1] = workload->oactxctrl; | ||
92 | |||
93 | for (i = 0; i < ARRAY_SIZE(workload->flex_mmio); i++) { | ||
94 | u32 state_offset = ctx_flexeu0 + i * 2; | ||
95 | u32 mmio = flex_mmio[i]; | ||
96 | |||
97 | reg_state[state_offset] = mmio; | ||
98 | reg_state[state_offset + 1] = workload->flex_mmio[i]; | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | |||
55 | static int populate_shadow_context(struct intel_vgpu_workload *workload) | 103 | static int populate_shadow_context(struct intel_vgpu_workload *workload) |
56 | { | 104 | { |
57 | struct intel_vgpu *vgpu = workload->vgpu; | 105 | struct intel_vgpu *vgpu = workload->vgpu; |
@@ -98,6 +146,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) | |||
98 | page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); | 146 | page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); |
99 | shadow_ring_context = kmap(page); | 147 | shadow_ring_context = kmap(page); |
100 | 148 | ||
149 | sr_oa_regs(workload, (u32 *)shadow_ring_context, true); | ||
101 | #define COPY_REG(name) \ | 150 | #define COPY_REG(name) \ |
102 | intel_gvt_hypervisor_read_gpa(vgpu, workload->ring_context_gpa \ | 151 | intel_gvt_hypervisor_read_gpa(vgpu, workload->ring_context_gpa \ |
103 | + RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4) | 152 | + RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4) |
@@ -122,6 +171,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) | |||
122 | sizeof(*shadow_ring_context), | 171 | sizeof(*shadow_ring_context), |
123 | I915_GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); | 172 | I915_GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); |
124 | 173 | ||
174 | sr_oa_regs(workload, (u32 *)shadow_ring_context, false); | ||
125 | kunmap(page); | 175 | kunmap(page); |
126 | return 0; | 176 | return 0; |
127 | } | 177 | } |
@@ -376,6 +426,17 @@ static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) | |||
376 | goto err; | 426 | goto err; |
377 | } | 427 | } |
378 | 428 | ||
429 | /* For privilge batch buffer and not wa_ctx, the bb_start_cmd_va | ||
430 | * is only updated into ring_scan_buffer, not real ring address | ||
431 | * allocated in later copy_workload_to_ring_buffer. pls be noted | ||
432 | * shadow_ring_buffer_va is now pointed to real ring buffer va | ||
433 | * in copy_workload_to_ring_buffer. | ||
434 | */ | ||
435 | |||
436 | if (bb->bb_offset) | ||
437 | bb->bb_start_cmd_va = workload->shadow_ring_buffer_va | ||
438 | + bb->bb_offset; | ||
439 | |||
379 | /* relocate shadow batch buffer */ | 440 | /* relocate shadow batch buffer */ |
380 | bb->bb_start_cmd_va[1] = i915_ggtt_offset(bb->vma); | 441 | bb->bb_start_cmd_va[1] = i915_ggtt_offset(bb->vma); |
381 | if (gmadr_bytes == 8) | 442 | if (gmadr_bytes == 8) |
@@ -1044,10 +1105,12 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu) | |||
1044 | 1105 | ||
1045 | bitmap_zero(s->shadow_ctx_desc_updated, I915_NUM_ENGINES); | 1106 | bitmap_zero(s->shadow_ctx_desc_updated, I915_NUM_ENGINES); |
1046 | 1107 | ||
1047 | s->workloads = kmem_cache_create("gvt-g_vgpu_workload", | 1108 | s->workloads = kmem_cache_create_usercopy("gvt-g_vgpu_workload", |
1048 | sizeof(struct intel_vgpu_workload), 0, | 1109 | sizeof(struct intel_vgpu_workload), 0, |
1049 | SLAB_HWCACHE_ALIGN, | 1110 | SLAB_HWCACHE_ALIGN, |
1050 | NULL); | 1111 | offsetof(struct intel_vgpu_workload, rb_tail), |
1112 | sizeof_field(struct intel_vgpu_workload, rb_tail), | ||
1113 | NULL); | ||
1051 | 1114 | ||
1052 | if (!s->workloads) { | 1115 | if (!s->workloads) { |
1053 | ret = -ENOMEM; | 1116 | ret = -ENOMEM; |
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index ff175a98b19e..a79a4f60637e 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h | |||
@@ -110,6 +110,10 @@ struct intel_vgpu_workload { | |||
110 | /* shadow batch buffer */ | 110 | /* shadow batch buffer */ |
111 | struct list_head shadow_bb; | 111 | struct list_head shadow_bb; |
112 | struct intel_shadow_wa_ctx wa_ctx; | 112 | struct intel_shadow_wa_ctx wa_ctx; |
113 | |||
114 | /* oa registers */ | ||
115 | u32 oactxctrl; | ||
116 | u32 flex_mmio[7]; | ||
113 | }; | 117 | }; |
114 | 118 | ||
115 | struct intel_vgpu_shadow_bb { | 119 | struct intel_vgpu_shadow_bb { |
@@ -120,6 +124,7 @@ struct intel_vgpu_shadow_bb { | |||
120 | u32 *bb_start_cmd_va; | 124 | u32 *bb_start_cmd_va; |
121 | unsigned int clflush; | 125 | unsigned int clflush; |
122 | bool accessing; | 126 | bool accessing; |
127 | unsigned long bb_offset; | ||
123 | }; | 128 | }; |
124 | 129 | ||
125 | #define workload_q_head(vgpu, ring_id) \ | 130 | #define workload_q_head(vgpu, ring_id) \ |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index dd89abd2263d..6ff5d655c202 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -434,20 +434,28 @@ i915_gem_object_wait_reservation(struct reservation_object *resv, | |||
434 | dma_fence_put(shared[i]); | 434 | dma_fence_put(shared[i]); |
435 | kfree(shared); | 435 | kfree(shared); |
436 | 436 | ||
437 | /* | ||
438 | * If both shared fences and an exclusive fence exist, | ||
439 | * then by construction the shared fences must be later | ||
440 | * than the exclusive fence. If we successfully wait for | ||
441 | * all the shared fences, we know that the exclusive fence | ||
442 | * must all be signaled. If all the shared fences are | ||
443 | * signaled, we can prune the array and recover the | ||
444 | * floating references on the fences/requests. | ||
445 | */ | ||
437 | prune_fences = count && timeout >= 0; | 446 | prune_fences = count && timeout >= 0; |
438 | } else { | 447 | } else { |
439 | excl = reservation_object_get_excl_rcu(resv); | 448 | excl = reservation_object_get_excl_rcu(resv); |
440 | } | 449 | } |
441 | 450 | ||
442 | if (excl && timeout >= 0) { | 451 | if (excl && timeout >= 0) |
443 | timeout = i915_gem_object_wait_fence(excl, flags, timeout, | 452 | timeout = i915_gem_object_wait_fence(excl, flags, timeout, |
444 | rps_client); | 453 | rps_client); |
445 | prune_fences = timeout >= 0; | ||
446 | } | ||
447 | 454 | ||
448 | dma_fence_put(excl); | 455 | dma_fence_put(excl); |
449 | 456 | ||
450 | /* Oportunistically prune the fences iff we know they have *all* been | 457 | /* |
458 | * Opportunistically prune the fences iff we know they have *all* been | ||
451 | * signaled and that the reservation object has not been changed (i.e. | 459 | * signaled and that the reservation object has not been changed (i.e. |
452 | * no new fences have been added). | 460 | * no new fences have been added). |
453 | */ | 461 | */ |
@@ -3205,8 +3213,10 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) | |||
3205 | * rolling the global seqno forward (since this would complete requests | 3213 | * rolling the global seqno forward (since this would complete requests |
3206 | * for which we haven't set the fence error to EIO yet). | 3214 | * for which we haven't set the fence error to EIO yet). |
3207 | */ | 3215 | */ |
3208 | for_each_engine(engine, i915, id) | 3216 | for_each_engine(engine, i915, id) { |
3217 | i915_gem_reset_prepare_engine(engine); | ||
3209 | engine->submit_request = nop_submit_request; | 3218 | engine->submit_request = nop_submit_request; |
3219 | } | ||
3210 | 3220 | ||
3211 | /* | 3221 | /* |
3212 | * Make sure no one is running the old callback before we proceed with | 3222 | * Make sure no one is running the old callback before we proceed with |
@@ -3244,6 +3254,8 @@ void i915_gem_set_wedged(struct drm_i915_private *i915) | |||
3244 | intel_engine_init_global_seqno(engine, | 3254 | intel_engine_init_global_seqno(engine, |
3245 | intel_engine_last_submit(engine)); | 3255 | intel_engine_last_submit(engine)); |
3246 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 3256 | spin_unlock_irqrestore(&engine->timeline->lock, flags); |
3257 | |||
3258 | i915_gem_reset_finish_engine(engine); | ||
3247 | } | 3259 | } |
3248 | 3260 | ||
3249 | set_bit(I915_WEDGED, &i915->gpu_error.flags); | 3261 | set_bit(I915_WEDGED, &i915->gpu_error.flags); |
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 0be50e43507d..f8fe5ffcdcff 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c | |||
@@ -1303,9 +1303,8 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream) | |||
1303 | */ | 1303 | */ |
1304 | mutex_lock(&dev_priv->drm.struct_mutex); | 1304 | mutex_lock(&dev_priv->drm.struct_mutex); |
1305 | dev_priv->perf.oa.exclusive_stream = NULL; | 1305 | dev_priv->perf.oa.exclusive_stream = NULL; |
1306 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
1307 | |||
1308 | dev_priv->perf.oa.ops.disable_metric_set(dev_priv); | 1306 | dev_priv->perf.oa.ops.disable_metric_set(dev_priv); |
1307 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
1309 | 1308 | ||
1310 | free_oa_buffer(dev_priv); | 1309 | free_oa_buffer(dev_priv); |
1311 | 1310 | ||
@@ -1756,22 +1755,13 @@ static int gen8_switch_to_updated_kernel_context(struct drm_i915_private *dev_pr | |||
1756 | * Note: it's only the RCS/Render context that has any OA state. | 1755 | * Note: it's only the RCS/Render context that has any OA state. |
1757 | */ | 1756 | */ |
1758 | static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, | 1757 | static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, |
1759 | const struct i915_oa_config *oa_config, | 1758 | const struct i915_oa_config *oa_config) |
1760 | bool interruptible) | ||
1761 | { | 1759 | { |
1762 | struct i915_gem_context *ctx; | 1760 | struct i915_gem_context *ctx; |
1763 | int ret; | 1761 | int ret; |
1764 | unsigned int wait_flags = I915_WAIT_LOCKED; | 1762 | unsigned int wait_flags = I915_WAIT_LOCKED; |
1765 | 1763 | ||
1766 | if (interruptible) { | 1764 | lockdep_assert_held(&dev_priv->drm.struct_mutex); |
1767 | ret = i915_mutex_lock_interruptible(&dev_priv->drm); | ||
1768 | if (ret) | ||
1769 | return ret; | ||
1770 | |||
1771 | wait_flags |= I915_WAIT_INTERRUPTIBLE; | ||
1772 | } else { | ||
1773 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
1774 | } | ||
1775 | 1765 | ||
1776 | /* Switch away from any user context. */ | 1766 | /* Switch away from any user context. */ |
1777 | ret = gen8_switch_to_updated_kernel_context(dev_priv, oa_config); | 1767 | ret = gen8_switch_to_updated_kernel_context(dev_priv, oa_config); |
@@ -1819,8 +1809,6 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, | |||
1819 | } | 1809 | } |
1820 | 1810 | ||
1821 | out: | 1811 | out: |
1822 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
1823 | |||
1824 | return ret; | 1812 | return ret; |
1825 | } | 1813 | } |
1826 | 1814 | ||
@@ -1863,7 +1851,7 @@ static int gen8_enable_metric_set(struct drm_i915_private *dev_priv, | |||
1863 | * to make sure all slices/subslices are ON before writing to NOA | 1851 | * to make sure all slices/subslices are ON before writing to NOA |
1864 | * registers. | 1852 | * registers. |
1865 | */ | 1853 | */ |
1866 | ret = gen8_configure_all_contexts(dev_priv, oa_config, true); | 1854 | ret = gen8_configure_all_contexts(dev_priv, oa_config); |
1867 | if (ret) | 1855 | if (ret) |
1868 | return ret; | 1856 | return ret; |
1869 | 1857 | ||
@@ -1878,7 +1866,7 @@ static int gen8_enable_metric_set(struct drm_i915_private *dev_priv, | |||
1878 | static void gen8_disable_metric_set(struct drm_i915_private *dev_priv) | 1866 | static void gen8_disable_metric_set(struct drm_i915_private *dev_priv) |
1879 | { | 1867 | { |
1880 | /* Reset all contexts' slices/subslices configurations. */ | 1868 | /* Reset all contexts' slices/subslices configurations. */ |
1881 | gen8_configure_all_contexts(dev_priv, NULL, false); | 1869 | gen8_configure_all_contexts(dev_priv, NULL); |
1882 | 1870 | ||
1883 | I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) & | 1871 | I915_WRITE(GDT_CHICKEN_BITS, (I915_READ(GDT_CHICKEN_BITS) & |
1884 | ~GT_NOA_ENABLE)); | 1872 | ~GT_NOA_ENABLE)); |
@@ -1888,7 +1876,7 @@ static void gen8_disable_metric_set(struct drm_i915_private *dev_priv) | |||
1888 | static void gen10_disable_metric_set(struct drm_i915_private *dev_priv) | 1876 | static void gen10_disable_metric_set(struct drm_i915_private *dev_priv) |
1889 | { | 1877 | { |
1890 | /* Reset all contexts' slices/subslices configurations. */ | 1878 | /* Reset all contexts' slices/subslices configurations. */ |
1891 | gen8_configure_all_contexts(dev_priv, NULL, false); | 1879 | gen8_configure_all_contexts(dev_priv, NULL); |
1892 | 1880 | ||
1893 | /* Make sure we disable noa to save power. */ | 1881 | /* Make sure we disable noa to save power. */ |
1894 | I915_WRITE(RPM_CONFIG1, | 1882 | I915_WRITE(RPM_CONFIG1, |
@@ -2138,6 +2126,10 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, | |||
2138 | if (ret) | 2126 | if (ret) |
2139 | goto err_oa_buf_alloc; | 2127 | goto err_oa_buf_alloc; |
2140 | 2128 | ||
2129 | ret = i915_mutex_lock_interruptible(&dev_priv->drm); | ||
2130 | if (ret) | ||
2131 | goto err_lock; | ||
2132 | |||
2141 | ret = dev_priv->perf.oa.ops.enable_metric_set(dev_priv, | 2133 | ret = dev_priv->perf.oa.ops.enable_metric_set(dev_priv, |
2142 | stream->oa_config); | 2134 | stream->oa_config); |
2143 | if (ret) | 2135 | if (ret) |
@@ -2145,23 +2137,17 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, | |||
2145 | 2137 | ||
2146 | stream->ops = &i915_oa_stream_ops; | 2138 | stream->ops = &i915_oa_stream_ops; |
2147 | 2139 | ||
2148 | /* Lock device for exclusive_stream access late because | ||
2149 | * enable_metric_set() might lock as well on gen8+. | ||
2150 | */ | ||
2151 | ret = i915_mutex_lock_interruptible(&dev_priv->drm); | ||
2152 | if (ret) | ||
2153 | goto err_lock; | ||
2154 | |||
2155 | dev_priv->perf.oa.exclusive_stream = stream; | 2140 | dev_priv->perf.oa.exclusive_stream = stream; |
2156 | 2141 | ||
2157 | mutex_unlock(&dev_priv->drm.struct_mutex); | 2142 | mutex_unlock(&dev_priv->drm.struct_mutex); |
2158 | 2143 | ||
2159 | return 0; | 2144 | return 0; |
2160 | 2145 | ||
2161 | err_lock: | 2146 | err_enable: |
2162 | dev_priv->perf.oa.ops.disable_metric_set(dev_priv); | 2147 | dev_priv->perf.oa.ops.disable_metric_set(dev_priv); |
2148 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
2163 | 2149 | ||
2164 | err_enable: | 2150 | err_lock: |
2165 | free_oa_buffer(dev_priv); | 2151 | free_oa_buffer(dev_priv); |
2166 | 2152 | ||
2167 | err_oa_buf_alloc: | 2153 | err_oa_buf_alloc: |
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index b33d2158c234..e5e6f6bb2b05 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c | |||
@@ -304,8 +304,9 @@ static ssize_t gt_boost_freq_mhz_store(struct device *kdev, | |||
304 | { | 304 | { |
305 | struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); | 305 | struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); |
306 | struct intel_rps *rps = &dev_priv->gt_pm.rps; | 306 | struct intel_rps *rps = &dev_priv->gt_pm.rps; |
307 | u32 val; | 307 | bool boost = false; |
308 | ssize_t ret; | 308 | ssize_t ret; |
309 | u32 val; | ||
309 | 310 | ||
310 | ret = kstrtou32(buf, 0, &val); | 311 | ret = kstrtou32(buf, 0, &val); |
311 | if (ret) | 312 | if (ret) |
@@ -317,8 +318,13 @@ static ssize_t gt_boost_freq_mhz_store(struct device *kdev, | |||
317 | return -EINVAL; | 318 | return -EINVAL; |
318 | 319 | ||
319 | mutex_lock(&dev_priv->pcu_lock); | 320 | mutex_lock(&dev_priv->pcu_lock); |
320 | rps->boost_freq = val; | 321 | if (val != rps->boost_freq) { |
322 | rps->boost_freq = val; | ||
323 | boost = atomic_read(&rps->num_waiters); | ||
324 | } | ||
321 | mutex_unlock(&dev_priv->pcu_lock); | 325 | mutex_unlock(&dev_priv->pcu_lock); |
326 | if (boost) | ||
327 | schedule_work(&rps->work); | ||
322 | 328 | ||
323 | return count; | 329 | return count; |
324 | } | 330 | } |
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index f51645a08dca..6aff9d096e13 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -2175,8 +2175,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, | |||
2175 | intel_prepare_dp_ddi_buffers(encoder, crtc_state); | 2175 | intel_prepare_dp_ddi_buffers(encoder, crtc_state); |
2176 | 2176 | ||
2177 | intel_ddi_init_dp_buf_reg(encoder); | 2177 | intel_ddi_init_dp_buf_reg(encoder); |
2178 | if (!is_mst) | 2178 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); |
2179 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); | ||
2180 | intel_dp_start_link_train(intel_dp); | 2179 | intel_dp_start_link_train(intel_dp); |
2181 | if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) | 2180 | if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) |
2182 | intel_dp_stop_link_train(intel_dp); | 2181 | intel_dp_stop_link_train(intel_dp); |
@@ -2274,14 +2273,12 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, | |||
2274 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 2273 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
2275 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); | 2274 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); |
2276 | struct intel_dp *intel_dp = &dig_port->dp; | 2275 | struct intel_dp *intel_dp = &dig_port->dp; |
2277 | bool is_mst = intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST); | ||
2278 | 2276 | ||
2279 | /* | 2277 | /* |
2280 | * Power down sink before disabling the port, otherwise we end | 2278 | * Power down sink before disabling the port, otherwise we end |
2281 | * up getting interrupts from the sink on detecting link loss. | 2279 | * up getting interrupts from the sink on detecting link loss. |
2282 | */ | 2280 | */ |
2283 | if (!is_mst) | 2281 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); |
2284 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); | ||
2285 | 2282 | ||
2286 | intel_disable_ddi_buf(encoder); | 2283 | intel_disable_ddi_buf(encoder); |
2287 | 2284 | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 35c5299feab6..a29868cd30c7 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -620,19 +620,15 @@ static int | |||
620 | bxt_power_sequencer_idx(struct intel_dp *intel_dp) | 620 | bxt_power_sequencer_idx(struct intel_dp *intel_dp) |
621 | { | 621 | { |
622 | struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | 622 | struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); |
623 | int backlight_controller = dev_priv->vbt.backlight.controller; | ||
623 | 624 | ||
624 | lockdep_assert_held(&dev_priv->pps_mutex); | 625 | lockdep_assert_held(&dev_priv->pps_mutex); |
625 | 626 | ||
626 | /* We should never land here with regular DP ports */ | 627 | /* We should never land here with regular DP ports */ |
627 | WARN_ON(!intel_dp_is_edp(intel_dp)); | 628 | WARN_ON(!intel_dp_is_edp(intel_dp)); |
628 | 629 | ||
629 | /* | ||
630 | * TODO: BXT has 2 PPS instances. The correct port->PPS instance | ||
631 | * mapping needs to be retrieved from VBT, for now just hard-code to | ||
632 | * use instance #0 always. | ||
633 | */ | ||
634 | if (!intel_dp->pps_reset) | 630 | if (!intel_dp->pps_reset) |
635 | return 0; | 631 | return backlight_controller; |
636 | 632 | ||
637 | intel_dp->pps_reset = false; | 633 | intel_dp->pps_reset = false; |
638 | 634 | ||
@@ -642,7 +638,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp) | |||
642 | */ | 638 | */ |
643 | intel_dp_init_panel_power_sequencer_registers(intel_dp, false); | 639 | intel_dp_init_panel_power_sequencer_registers(intel_dp, false); |
644 | 640 | ||
645 | return 0; | 641 | return backlight_controller; |
646 | } | 642 | } |
647 | 643 | ||
648 | typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv, | 644 | typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv, |
diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c index 348a4f7ffb67..53747318f4a7 100644 --- a/drivers/gpu/drm/i915/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/intel_hangcheck.c | |||
@@ -246,7 +246,7 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd) | |||
246 | */ | 246 | */ |
247 | tmp = I915_READ_CTL(engine); | 247 | tmp = I915_READ_CTL(engine); |
248 | if (tmp & RING_WAIT) { | 248 | if (tmp & RING_WAIT) { |
249 | i915_handle_error(dev_priv, 0, | 249 | i915_handle_error(dev_priv, BIT(engine->id), |
250 | "Kicking stuck wait on %s", | 250 | "Kicking stuck wait on %s", |
251 | engine->name); | 251 | engine->name); |
252 | I915_WRITE_CTL(engine, tmp); | 252 | I915_WRITE_CTL(engine, tmp); |
@@ -258,7 +258,7 @@ engine_stuck(struct intel_engine_cs *engine, u64 acthd) | |||
258 | default: | 258 | default: |
259 | return ENGINE_DEAD; | 259 | return ENGINE_DEAD; |
260 | case 1: | 260 | case 1: |
261 | i915_handle_error(dev_priv, 0, | 261 | i915_handle_error(dev_priv, ALL_ENGINES, |
262 | "Kicking stuck semaphore on %s", | 262 | "Kicking stuck semaphore on %s", |
263 | engine->name); | 263 | engine->name); |
264 | I915_WRITE_CTL(engine, tmp); | 264 | I915_WRITE_CTL(engine, tmp); |
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7ece2f061b9e..e0fca035ff78 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
@@ -719,6 +719,8 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) | |||
719 | struct rb_node *rb; | 719 | struct rb_node *rb; |
720 | unsigned long flags; | 720 | unsigned long flags; |
721 | 721 | ||
722 | GEM_TRACE("%s\n", engine->name); | ||
723 | |||
722 | spin_lock_irqsave(&engine->timeline->lock, flags); | 724 | spin_lock_irqsave(&engine->timeline->lock, flags); |
723 | 725 | ||
724 | /* Cancel the requests on the HW and clear the ELSP tracker. */ | 726 | /* Cancel the requests on the HW and clear the ELSP tracker. */ |
@@ -765,6 +767,9 @@ static void execlists_cancel_requests(struct intel_engine_cs *engine) | |||
765 | */ | 767 | */ |
766 | clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); | 768 | clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); |
767 | 769 | ||
770 | /* Mark all CS interrupts as complete */ | ||
771 | execlists->active = 0; | ||
772 | |||
768 | spin_unlock_irqrestore(&engine->timeline->lock, flags); | 773 | spin_unlock_irqrestore(&engine->timeline->lock, flags); |
769 | } | 774 | } |
770 | 775 | ||
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index 9a9961802f5c..e83af0f2be86 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c | |||
@@ -225,7 +225,11 @@ static void ipu_crtc_atomic_begin(struct drm_crtc *crtc, | |||
225 | struct drm_crtc_state *old_crtc_state) | 225 | struct drm_crtc_state *old_crtc_state) |
226 | { | 226 | { |
227 | drm_crtc_vblank_on(crtc); | 227 | drm_crtc_vblank_on(crtc); |
228 | } | ||
228 | 229 | ||
230 | static void ipu_crtc_atomic_flush(struct drm_crtc *crtc, | ||
231 | struct drm_crtc_state *old_crtc_state) | ||
232 | { | ||
229 | spin_lock_irq(&crtc->dev->event_lock); | 233 | spin_lock_irq(&crtc->dev->event_lock); |
230 | if (crtc->state->event) { | 234 | if (crtc->state->event) { |
231 | WARN_ON(drm_crtc_vblank_get(crtc)); | 235 | WARN_ON(drm_crtc_vblank_get(crtc)); |
@@ -293,6 +297,7 @@ static const struct drm_crtc_helper_funcs ipu_helper_funcs = { | |||
293 | .mode_set_nofb = ipu_crtc_mode_set_nofb, | 297 | .mode_set_nofb = ipu_crtc_mode_set_nofb, |
294 | .atomic_check = ipu_crtc_atomic_check, | 298 | .atomic_check = ipu_crtc_atomic_check, |
295 | .atomic_begin = ipu_crtc_atomic_begin, | 299 | .atomic_begin = ipu_crtc_atomic_begin, |
300 | .atomic_flush = ipu_crtc_atomic_flush, | ||
296 | .atomic_disable = ipu_crtc_atomic_disable, | 301 | .atomic_disable = ipu_crtc_atomic_disable, |
297 | .atomic_enable = ipu_crtc_atomic_enable, | 302 | .atomic_enable = ipu_crtc_atomic_enable, |
298 | }; | 303 | }; |
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 57ed56d8623f..d9113faaa62f 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <drm/drm_plane_helper.h> | 22 | #include <drm/drm_plane_helper.h> |
23 | 23 | ||
24 | #include "video/imx-ipu-v3.h" | 24 | #include "video/imx-ipu-v3.h" |
25 | #include "imx-drm.h" | ||
25 | #include "ipuv3-plane.h" | 26 | #include "ipuv3-plane.h" |
26 | 27 | ||
27 | struct ipu_plane_state { | 28 | struct ipu_plane_state { |
@@ -272,7 +273,7 @@ static void ipu_plane_destroy(struct drm_plane *plane) | |||
272 | kfree(ipu_plane); | 273 | kfree(ipu_plane); |
273 | } | 274 | } |
274 | 275 | ||
275 | void ipu_plane_state_reset(struct drm_plane *plane) | 276 | static void ipu_plane_state_reset(struct drm_plane *plane) |
276 | { | 277 | { |
277 | struct ipu_plane_state *ipu_state; | 278 | struct ipu_plane_state *ipu_state; |
278 | 279 | ||
@@ -292,7 +293,8 @@ void ipu_plane_state_reset(struct drm_plane *plane) | |||
292 | plane->state = &ipu_state->base; | 293 | plane->state = &ipu_state->base; |
293 | } | 294 | } |
294 | 295 | ||
295 | struct drm_plane_state *ipu_plane_duplicate_state(struct drm_plane *plane) | 296 | static struct drm_plane_state * |
297 | ipu_plane_duplicate_state(struct drm_plane *plane) | ||
296 | { | 298 | { |
297 | struct ipu_plane_state *state; | 299 | struct ipu_plane_state *state; |
298 | 300 | ||
@@ -306,8 +308,8 @@ struct drm_plane_state *ipu_plane_duplicate_state(struct drm_plane *plane) | |||
306 | return &state->base; | 308 | return &state->base; |
307 | } | 309 | } |
308 | 310 | ||
309 | void ipu_plane_destroy_state(struct drm_plane *plane, | 311 | static void ipu_plane_destroy_state(struct drm_plane *plane, |
310 | struct drm_plane_state *state) | 312 | struct drm_plane_state *state) |
311 | { | 313 | { |
312 | struct ipu_plane_state *ipu_state = to_ipu_plane_state(state); | 314 | struct ipu_plane_state *ipu_state = to_ipu_plane_state(state); |
313 | 315 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 380f340204e8..debbbf0fd4bd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c | |||
@@ -134,7 +134,7 @@ nv50_get_intensity(struct backlight_device *bd) | |||
134 | struct nouveau_encoder *nv_encoder = bl_get_data(bd); | 134 | struct nouveau_encoder *nv_encoder = bl_get_data(bd); |
135 | struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); | 135 | struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); |
136 | struct nvif_object *device = &drm->client.device.object; | 136 | struct nvif_object *device = &drm->client.device.object; |
137 | int or = nv_encoder->or; | 137 | int or = ffs(nv_encoder->dcb->or) - 1; |
138 | u32 div = 1025; | 138 | u32 div = 1025; |
139 | u32 val; | 139 | u32 val; |
140 | 140 | ||
@@ -149,7 +149,7 @@ nv50_set_intensity(struct backlight_device *bd) | |||
149 | struct nouveau_encoder *nv_encoder = bl_get_data(bd); | 149 | struct nouveau_encoder *nv_encoder = bl_get_data(bd); |
150 | struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); | 150 | struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); |
151 | struct nvif_object *device = &drm->client.device.object; | 151 | struct nvif_object *device = &drm->client.device.object; |
152 | int or = nv_encoder->or; | 152 | int or = ffs(nv_encoder->dcb->or) - 1; |
153 | u32 div = 1025; | 153 | u32 div = 1025; |
154 | u32 val = (bd->props.brightness * div) / 100; | 154 | u32 val = (bd->props.brightness * div) / 100; |
155 | 155 | ||
@@ -170,7 +170,7 @@ nva3_get_intensity(struct backlight_device *bd) | |||
170 | struct nouveau_encoder *nv_encoder = bl_get_data(bd); | 170 | struct nouveau_encoder *nv_encoder = bl_get_data(bd); |
171 | struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); | 171 | struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); |
172 | struct nvif_object *device = &drm->client.device.object; | 172 | struct nvif_object *device = &drm->client.device.object; |
173 | int or = nv_encoder->or; | 173 | int or = ffs(nv_encoder->dcb->or) - 1; |
174 | u32 div, val; | 174 | u32 div, val; |
175 | 175 | ||
176 | div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or)); | 176 | div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or)); |
@@ -188,7 +188,7 @@ nva3_set_intensity(struct backlight_device *bd) | |||
188 | struct nouveau_encoder *nv_encoder = bl_get_data(bd); | 188 | struct nouveau_encoder *nv_encoder = bl_get_data(bd); |
189 | struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); | 189 | struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); |
190 | struct nvif_object *device = &drm->client.device.object; | 190 | struct nvif_object *device = &drm->client.device.object; |
191 | int or = nv_encoder->or; | 191 | int or = ffs(nv_encoder->dcb->or) - 1; |
192 | u32 div, val; | 192 | u32 div, val; |
193 | 193 | ||
194 | div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or)); | 194 | div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or)); |
@@ -228,7 +228,7 @@ nv50_backlight_init(struct drm_connector *connector) | |||
228 | return -ENODEV; | 228 | return -ENODEV; |
229 | } | 229 | } |
230 | 230 | ||
231 | if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(nv_encoder->or))) | 231 | if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1))) |
232 | return 0; | 232 | return 0; |
233 | 233 | ||
234 | if (drm->client.device.info.chipset <= 0xa0 || | 234 | if (drm->client.device.info.chipset <= 0xa0 || |
@@ -268,13 +268,13 @@ nouveau_backlight_init(struct drm_device *dev) | |||
268 | struct nvif_device *device = &drm->client.device; | 268 | struct nvif_device *device = &drm->client.device; |
269 | struct drm_connector *connector; | 269 | struct drm_connector *connector; |
270 | 270 | ||
271 | INIT_LIST_HEAD(&drm->bl_connectors); | ||
272 | |||
271 | if (apple_gmux_present()) { | 273 | if (apple_gmux_present()) { |
272 | NV_INFO(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n"); | 274 | NV_INFO(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n"); |
273 | return 0; | 275 | return 0; |
274 | } | 276 | } |
275 | 277 | ||
276 | INIT_LIST_HEAD(&drm->bl_connectors); | ||
277 | |||
278 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 278 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
279 | if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && | 279 | if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && |
280 | connector->connector_type != DRM_MODE_CONNECTOR_eDP) | 280 | connector->connector_type != DRM_MODE_CONNECTOR_eDP) |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c index 93946dcee319..1c12e58f44c2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | |||
@@ -1354,7 +1354,7 @@ nvkm_vmm_get_locked(struct nvkm_vmm *vmm, bool getref, bool mapref, bool sparse, | |||
1354 | 1354 | ||
1355 | tail = this->addr + this->size; | 1355 | tail = this->addr + this->size; |
1356 | if (vmm->func->page_block && next && next->page != p) | 1356 | if (vmm->func->page_block && next && next->page != p) |
1357 | tail = ALIGN_DOWN(addr, vmm->func->page_block); | 1357 | tail = ALIGN_DOWN(tail, vmm->func->page_block); |
1358 | 1358 | ||
1359 | if (addr <= tail && tail - addr >= size) { | 1359 | if (addr <= tail && tail - addr >= size) { |
1360 | rb_erase(&this->tree, &vmm->free); | 1360 | rb_erase(&this->tree, &vmm->free); |
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index d3045a371a55..7c73bc7e2f85 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
@@ -3221,35 +3221,8 @@ static void cik_gpu_init(struct radeon_device *rdev) | |||
3221 | case CHIP_KAVERI: | 3221 | case CHIP_KAVERI: |
3222 | rdev->config.cik.max_shader_engines = 1; | 3222 | rdev->config.cik.max_shader_engines = 1; |
3223 | rdev->config.cik.max_tile_pipes = 4; | 3223 | rdev->config.cik.max_tile_pipes = 4; |
3224 | if ((rdev->pdev->device == 0x1304) || | 3224 | rdev->config.cik.max_cu_per_sh = 8; |
3225 | (rdev->pdev->device == 0x1305) || | 3225 | rdev->config.cik.max_backends_per_se = 2; |
3226 | (rdev->pdev->device == 0x130C) || | ||
3227 | (rdev->pdev->device == 0x130F) || | ||
3228 | (rdev->pdev->device == 0x1310) || | ||
3229 | (rdev->pdev->device == 0x1311) || | ||
3230 | (rdev->pdev->device == 0x131C)) { | ||
3231 | rdev->config.cik.max_cu_per_sh = 8; | ||
3232 | rdev->config.cik.max_backends_per_se = 2; | ||
3233 | } else if ((rdev->pdev->device == 0x1309) || | ||
3234 | (rdev->pdev->device == 0x130A) || | ||
3235 | (rdev->pdev->device == 0x130D) || | ||
3236 | (rdev->pdev->device == 0x1313) || | ||
3237 | (rdev->pdev->device == 0x131D)) { | ||
3238 | rdev->config.cik.max_cu_per_sh = 6; | ||
3239 | rdev->config.cik.max_backends_per_se = 2; | ||
3240 | } else if ((rdev->pdev->device == 0x1306) || | ||
3241 | (rdev->pdev->device == 0x1307) || | ||
3242 | (rdev->pdev->device == 0x130B) || | ||
3243 | (rdev->pdev->device == 0x130E) || | ||
3244 | (rdev->pdev->device == 0x1315) || | ||
3245 | (rdev->pdev->device == 0x1318) || | ||
3246 | (rdev->pdev->device == 0x131B)) { | ||
3247 | rdev->config.cik.max_cu_per_sh = 4; | ||
3248 | rdev->config.cik.max_backends_per_se = 1; | ||
3249 | } else { | ||
3250 | rdev->config.cik.max_cu_per_sh = 3; | ||
3251 | rdev->config.cik.max_backends_per_se = 1; | ||
3252 | } | ||
3253 | rdev->config.cik.max_sh_per_se = 1; | 3226 | rdev->config.cik.max_sh_per_se = 1; |
3254 | rdev->config.cik.max_texture_channel_caches = 4; | 3227 | rdev->config.cik.max_texture_channel_caches = 4; |
3255 | rdev->config.cik.max_gprs = 256; | 3228 | rdev->config.cik.max_gprs = 256; |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 2e2ca3c6b47d..df9469a8fdb1 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -90,25 +90,18 @@ void radeon_connector_hotplug(struct drm_connector *connector) | |||
90 | /* don't do anything if sink is not display port, i.e., | 90 | /* don't do anything if sink is not display port, i.e., |
91 | * passive dp->(dvi|hdmi) adaptor | 91 | * passive dp->(dvi|hdmi) adaptor |
92 | */ | 92 | */ |
93 | if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { | 93 | if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT && |
94 | int saved_dpms = connector->dpms; | 94 | radeon_hpd_sense(rdev, radeon_connector->hpd.hpd) && |
95 | /* Only turn off the display if it's physically disconnected */ | 95 | radeon_dp_needs_link_train(radeon_connector)) { |
96 | if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { | 96 | /* Don't start link training before we have the DPCD */ |
97 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | 97 | if (!radeon_dp_getdpcd(radeon_connector)) |
98 | } else if (radeon_dp_needs_link_train(radeon_connector)) { | 98 | return; |
99 | /* Don't try to start link training before we | 99 | |
100 | * have the dpcd */ | 100 | /* Turn the connector off and back on immediately, which |
101 | if (!radeon_dp_getdpcd(radeon_connector)) | 101 | * will trigger link training |
102 | return; | 102 | */ |
103 | 103 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | |
104 | /* set it to OFF so that drm_helper_connector_dpms() | 104 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); |
105 | * won't return immediately since the current state | ||
106 | * is ON at this point. | ||
107 | */ | ||
108 | connector->dpms = DRM_MODE_DPMS_OFF; | ||
109 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); | ||
110 | } | ||
111 | connector->dpms = saved_dpms; | ||
112 | } | 105 | } |
113 | } | 106 | } |
114 | } | 107 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index a9962ffba720..27d8e7dd2d06 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
@@ -34,8 +34,6 @@ void radeon_gem_object_free(struct drm_gem_object *gobj) | |||
34 | struct radeon_bo *robj = gem_to_radeon_bo(gobj); | 34 | struct radeon_bo *robj = gem_to_radeon_bo(gobj); |
35 | 35 | ||
36 | if (robj) { | 36 | if (robj) { |
37 | if (robj->gem_base.import_attach) | ||
38 | drm_prime_gem_destroy(&robj->gem_base, robj->tbo.sg); | ||
39 | radeon_mn_unregister(robj); | 37 | radeon_mn_unregister(robj); |
40 | radeon_bo_unref(&robj); | 38 | radeon_bo_unref(&robj); |
41 | } | 39 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 15404af9d740..31f5ad605e59 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
@@ -82,6 +82,8 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) | |||
82 | mutex_unlock(&bo->rdev->gem.mutex); | 82 | mutex_unlock(&bo->rdev->gem.mutex); |
83 | radeon_bo_clear_surface_reg(bo); | 83 | radeon_bo_clear_surface_reg(bo); |
84 | WARN_ON_ONCE(!list_empty(&bo->va)); | 84 | WARN_ON_ONCE(!list_empty(&bo->va)); |
85 | if (bo->gem_base.import_attach) | ||
86 | drm_prime_gem_destroy(&bo->gem_base, bo->tbo.sg); | ||
85 | drm_gem_object_release(&bo->gem_base); | 87 | drm_gem_object_release(&bo->gem_base); |
86 | kfree(bo); | 88 | kfree(bo); |
87 | } | 89 | } |
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 5decae0069d0..78cbc3145e44 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c | |||
@@ -93,6 +93,8 @@ static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc, | |||
93 | 93 | ||
94 | DRM_DEBUG_DRIVER("Disabling the CRTC\n"); | 94 | DRM_DEBUG_DRIVER("Disabling the CRTC\n"); |
95 | 95 | ||
96 | drm_crtc_vblank_off(crtc); | ||
97 | |||
96 | sun4i_tcon_set_status(scrtc->tcon, encoder, false); | 98 | sun4i_tcon_set_status(scrtc->tcon, encoder, false); |
97 | 99 | ||
98 | if (crtc->state->event && !crtc->state->active) { | 100 | if (crtc->state->event && !crtc->state->active) { |
@@ -113,6 +115,8 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc, | |||
113 | DRM_DEBUG_DRIVER("Enabling the CRTC\n"); | 115 | DRM_DEBUG_DRIVER("Enabling the CRTC\n"); |
114 | 116 | ||
115 | sun4i_tcon_set_status(scrtc->tcon, encoder, true); | 117 | sun4i_tcon_set_status(scrtc->tcon, encoder, true); |
118 | |||
119 | drm_crtc_vblank_on(crtc); | ||
116 | } | 120 | } |
117 | 121 | ||
118 | static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc) | 122 | static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc) |
diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c index 023f39bda633..e36004fbe453 100644 --- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c +++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c | |||
@@ -132,10 +132,13 @@ static int sun4i_dclk_get_phase(struct clk_hw *hw) | |||
132 | static int sun4i_dclk_set_phase(struct clk_hw *hw, int degrees) | 132 | static int sun4i_dclk_set_phase(struct clk_hw *hw, int degrees) |
133 | { | 133 | { |
134 | struct sun4i_dclk *dclk = hw_to_dclk(hw); | 134 | struct sun4i_dclk *dclk = hw_to_dclk(hw); |
135 | u32 val = degrees / 120; | ||
136 | |||
137 | val <<= 28; | ||
135 | 138 | ||
136 | regmap_update_bits(dclk->regmap, SUN4I_TCON0_IO_POL_REG, | 139 | regmap_update_bits(dclk->regmap, SUN4I_TCON0_IO_POL_REG, |
137 | GENMASK(29, 28), | 140 | GENMASK(29, 28), |
138 | degrees / 120); | 141 | val); |
139 | 142 | ||
140 | return 0; | 143 | return 0; |
141 | } | 144 | } |
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 4570da0227b4..d9a71f361b14 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c | |||
@@ -111,7 +111,7 @@ static int sun4i_drv_bind(struct device *dev) | |||
111 | /* drm_vblank_init calls kcalloc, which can fail */ | 111 | /* drm_vblank_init calls kcalloc, which can fail */ |
112 | ret = drm_vblank_init(drm, drm->mode_config.num_crtc); | 112 | ret = drm_vblank_init(drm, drm->mode_config.num_crtc); |
113 | if (ret) | 113 | if (ret) |
114 | goto free_mem_region; | 114 | goto cleanup_mode_config; |
115 | 115 | ||
116 | drm->irq_enabled = true; | 116 | drm->irq_enabled = true; |
117 | 117 | ||
@@ -139,7 +139,6 @@ finish_poll: | |||
139 | sun4i_framebuffer_free(drm); | 139 | sun4i_framebuffer_free(drm); |
140 | cleanup_mode_config: | 140 | cleanup_mode_config: |
141 | drm_mode_config_cleanup(drm); | 141 | drm_mode_config_cleanup(drm); |
142 | free_mem_region: | ||
143 | of_reserved_mem_device_release(dev); | 142 | of_reserved_mem_device_release(dev); |
144 | free_drm: | 143 | free_drm: |
145 | drm_dev_unref(drm); | 144 | drm_dev_unref(drm); |
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c index 500b6fb3e028..fa4bcd092eaf 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | |||
@@ -538,7 +538,8 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, | |||
538 | &sun4i_hdmi_regmap_config); | 538 | &sun4i_hdmi_regmap_config); |
539 | if (IS_ERR(hdmi->regmap)) { | 539 | if (IS_ERR(hdmi->regmap)) { |
540 | dev_err(dev, "Couldn't create HDMI encoder regmap\n"); | 540 | dev_err(dev, "Couldn't create HDMI encoder regmap\n"); |
541 | return PTR_ERR(hdmi->regmap); | 541 | ret = PTR_ERR(hdmi->regmap); |
542 | goto err_disable_mod_clk; | ||
542 | } | 543 | } |
543 | 544 | ||
544 | ret = sun4i_tmds_create(hdmi); | 545 | ret = sun4i_tmds_create(hdmi); |
@@ -551,7 +552,8 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, | |||
551 | hdmi->ddc_parent_clk = devm_clk_get(dev, "ddc"); | 552 | hdmi->ddc_parent_clk = devm_clk_get(dev, "ddc"); |
552 | if (IS_ERR(hdmi->ddc_parent_clk)) { | 553 | if (IS_ERR(hdmi->ddc_parent_clk)) { |
553 | dev_err(dev, "Couldn't get the HDMI DDC clock\n"); | 554 | dev_err(dev, "Couldn't get the HDMI DDC clock\n"); |
554 | return PTR_ERR(hdmi->ddc_parent_clk); | 555 | ret = PTR_ERR(hdmi->ddc_parent_clk); |
556 | goto err_disable_mod_clk; | ||
555 | } | 557 | } |
556 | } else { | 558 | } else { |
557 | hdmi->ddc_parent_clk = hdmi->tmds_clk; | 559 | hdmi->ddc_parent_clk = hdmi->tmds_clk; |
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index 832f8f9bc47f..b8da5a50a61d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c | |||
@@ -92,6 +92,8 @@ static int sun4i_rgb_mode_valid(struct drm_connector *connector, | |||
92 | 92 | ||
93 | DRM_DEBUG_DRIVER("Vertical parameters OK\n"); | 93 | DRM_DEBUG_DRIVER("Vertical parameters OK\n"); |
94 | 94 | ||
95 | tcon->dclk_min_div = 6; | ||
96 | tcon->dclk_max_div = 127; | ||
95 | rounded_rate = clk_round_rate(tcon->dclk, rate); | 97 | rounded_rate = clk_round_rate(tcon->dclk, rate); |
96 | if (rounded_rate < rate) | 98 | if (rounded_rate < rate) |
97 | return MODE_CLOCK_LOW; | 99 | return MODE_CLOCK_LOW; |
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index b3960118deb9..a818ca491605 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c | |||
@@ -101,10 +101,13 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel, | |||
101 | return; | 101 | return; |
102 | } | 102 | } |
103 | 103 | ||
104 | if (enabled) | 104 | if (enabled) { |
105 | clk_prepare_enable(clk); | 105 | clk_prepare_enable(clk); |
106 | else | 106 | clk_rate_exclusive_get(clk); |
107 | } else { | ||
108 | clk_rate_exclusive_put(clk); | ||
107 | clk_disable_unprepare(clk); | 109 | clk_disable_unprepare(clk); |
110 | } | ||
108 | } | 111 | } |
109 | 112 | ||
110 | static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, | 113 | static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, |
@@ -260,7 +263,7 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon, | |||
260 | const struct drm_display_mode *mode) | 263 | const struct drm_display_mode *mode) |
261 | { | 264 | { |
262 | /* Configure the dot clock */ | 265 | /* Configure the dot clock */ |
263 | clk_set_rate_exclusive(tcon->dclk, mode->crtc_clock * 1000); | 266 | clk_set_rate(tcon->dclk, mode->crtc_clock * 1000); |
264 | 267 | ||
265 | /* Set the resolution */ | 268 | /* Set the resolution */ |
266 | regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG, | 269 | regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG, |
@@ -421,7 +424,7 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, | |||
421 | WARN_ON(!tcon->quirks->has_channel_1); | 424 | WARN_ON(!tcon->quirks->has_channel_1); |
422 | 425 | ||
423 | /* Configure the dot clock */ | 426 | /* Configure the dot clock */ |
424 | clk_set_rate_exclusive(tcon->sclk1, mode->crtc_clock * 1000); | 427 | clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); |
425 | 428 | ||
426 | /* Adjust clock delay */ | 429 | /* Adjust clock delay */ |
427 | clk_delay = sun4i_tcon_get_clk_delay(mode, 1); | 430 | clk_delay = sun4i_tcon_get_clk_delay(mode, 1); |
@@ -873,52 +876,56 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, | |||
873 | return ret; | 876 | return ret; |
874 | } | 877 | } |
875 | 878 | ||
876 | /* | 879 | if (tcon->quirks->supports_lvds) { |
877 | * This can only be made optional since we've had DT nodes | 880 | /* |
878 | * without the LVDS reset properties. | 881 | * This can only be made optional since we've had DT |
879 | * | 882 | * nodes without the LVDS reset properties. |
880 | * If the property is missing, just disable LVDS, and print a | 883 | * |
881 | * warning. | 884 | * If the property is missing, just disable LVDS, and |
882 | */ | 885 | * print a warning. |
883 | tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds"); | 886 | */ |
884 | if (IS_ERR(tcon->lvds_rst)) { | 887 | tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds"); |
885 | dev_err(dev, "Couldn't get our reset line\n"); | 888 | if (IS_ERR(tcon->lvds_rst)) { |
886 | return PTR_ERR(tcon->lvds_rst); | 889 | dev_err(dev, "Couldn't get our reset line\n"); |
887 | } else if (tcon->lvds_rst) { | 890 | return PTR_ERR(tcon->lvds_rst); |
888 | has_lvds_rst = true; | 891 | } else if (tcon->lvds_rst) { |
889 | reset_control_reset(tcon->lvds_rst); | 892 | has_lvds_rst = true; |
890 | } else { | 893 | reset_control_reset(tcon->lvds_rst); |
891 | has_lvds_rst = false; | 894 | } else { |
892 | } | 895 | has_lvds_rst = false; |
896 | } | ||
893 | 897 | ||
894 | /* | 898 | /* |
895 | * This can only be made optional since we've had DT nodes | 899 | * This can only be made optional since we've had DT |
896 | * without the LVDS reset properties. | 900 | * nodes without the LVDS reset properties. |
897 | * | 901 | * |
898 | * If the property is missing, just disable LVDS, and print a | 902 | * If the property is missing, just disable LVDS, and |
899 | * warning. | 903 | * print a warning. |
900 | */ | 904 | */ |
901 | if (tcon->quirks->has_lvds_alt) { | 905 | if (tcon->quirks->has_lvds_alt) { |
902 | tcon->lvds_pll = devm_clk_get(dev, "lvds-alt"); | 906 | tcon->lvds_pll = devm_clk_get(dev, "lvds-alt"); |
903 | if (IS_ERR(tcon->lvds_pll)) { | 907 | if (IS_ERR(tcon->lvds_pll)) { |
904 | if (PTR_ERR(tcon->lvds_pll) == -ENOENT) { | 908 | if (PTR_ERR(tcon->lvds_pll) == -ENOENT) { |
905 | has_lvds_alt = false; | 909 | has_lvds_alt = false; |
910 | } else { | ||
911 | dev_err(dev, "Couldn't get the LVDS PLL\n"); | ||
912 | return PTR_ERR(tcon->lvds_pll); | ||
913 | } | ||
906 | } else { | 914 | } else { |
907 | dev_err(dev, "Couldn't get the LVDS PLL\n"); | 915 | has_lvds_alt = true; |
908 | return PTR_ERR(tcon->lvds_pll); | ||
909 | } | 916 | } |
910 | } else { | ||
911 | has_lvds_alt = true; | ||
912 | } | 917 | } |
913 | } | ||
914 | 918 | ||
915 | if (!has_lvds_rst || (tcon->quirks->has_lvds_alt && !has_lvds_alt)) { | 919 | if (!has_lvds_rst || |
916 | dev_warn(dev, | 920 | (tcon->quirks->has_lvds_alt && !has_lvds_alt)) { |
917 | "Missing LVDS properties, Please upgrade your DT\n"); | 921 | dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n"); |
918 | dev_warn(dev, "LVDS output disabled\n"); | 922 | dev_warn(dev, "LVDS output disabled\n"); |
919 | can_lvds = false; | 923 | can_lvds = false; |
924 | } else { | ||
925 | can_lvds = true; | ||
926 | } | ||
920 | } else { | 927 | } else { |
921 | can_lvds = true; | 928 | can_lvds = false; |
922 | } | 929 | } |
923 | 930 | ||
924 | ret = sun4i_tcon_init_clocks(dev, tcon); | 931 | ret = sun4i_tcon_init_clocks(dev, tcon); |
@@ -1137,7 +1144,7 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = { | |||
1137 | }; | 1144 | }; |
1138 | 1145 | ||
1139 | static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { | 1146 | static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { |
1140 | /* nothing is supported */ | 1147 | .supports_lvds = true, |
1141 | }; | 1148 | }; |
1142 | 1149 | ||
1143 | static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { | 1150 | static const struct sun4i_tcon_quirks sun8i_v3s_quirks = { |
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index b761c7b823c5..278700c7bf9f 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h | |||
@@ -175,6 +175,7 @@ struct sun4i_tcon_quirks { | |||
175 | bool has_channel_1; /* a33 does not have channel 1 */ | 175 | bool has_channel_1; /* a33 does not have channel 1 */ |
176 | bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */ | 176 | bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */ |
177 | bool needs_de_be_mux; /* sun6i needs mux to select backend */ | 177 | bool needs_de_be_mux; /* sun6i needs mux to select backend */ |
178 | bool supports_lvds; /* Does the TCON support an LVDS output? */ | ||
178 | 179 | ||
179 | /* callback to handle tcon muxing options */ | 180 | /* callback to handle tcon muxing options */ |
180 | int (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *); | 181 | int (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *); |
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index b8403ed48285..fbffe1948b3b 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -1903,8 +1903,12 @@ cleanup: | |||
1903 | if (!IS_ERR(primary)) | 1903 | if (!IS_ERR(primary)) |
1904 | drm_plane_cleanup(primary); | 1904 | drm_plane_cleanup(primary); |
1905 | 1905 | ||
1906 | if (group && tegra->domain) { | 1906 | if (group && dc->domain) { |
1907 | iommu_detach_group(tegra->domain, group); | 1907 | if (group == tegra->group) { |
1908 | iommu_detach_group(dc->domain, group); | ||
1909 | tegra->group = NULL; | ||
1910 | } | ||
1911 | |||
1908 | dc->domain = NULL; | 1912 | dc->domain = NULL; |
1909 | } | 1913 | } |
1910 | 1914 | ||
@@ -1913,8 +1917,10 @@ cleanup: | |||
1913 | 1917 | ||
1914 | static int tegra_dc_exit(struct host1x_client *client) | 1918 | static int tegra_dc_exit(struct host1x_client *client) |
1915 | { | 1919 | { |
1920 | struct drm_device *drm = dev_get_drvdata(client->parent); | ||
1916 | struct iommu_group *group = iommu_group_get(client->dev); | 1921 | struct iommu_group *group = iommu_group_get(client->dev); |
1917 | struct tegra_dc *dc = host1x_client_to_dc(client); | 1922 | struct tegra_dc *dc = host1x_client_to_dc(client); |
1923 | struct tegra_drm *tegra = drm->dev_private; | ||
1918 | int err; | 1924 | int err; |
1919 | 1925 | ||
1920 | devm_free_irq(dc->dev, dc->irq, dc); | 1926 | devm_free_irq(dc->dev, dc->irq, dc); |
@@ -1926,7 +1932,11 @@ static int tegra_dc_exit(struct host1x_client *client) | |||
1926 | } | 1932 | } |
1927 | 1933 | ||
1928 | if (group && dc->domain) { | 1934 | if (group && dc->domain) { |
1929 | iommu_detach_group(dc->domain, group); | 1935 | if (group == tegra->group) { |
1936 | iommu_detach_group(dc->domain, group); | ||
1937 | tegra->group = NULL; | ||
1938 | } | ||
1939 | |||
1930 | dc->domain = NULL; | 1940 | dc->domain = NULL; |
1931 | } | 1941 | } |
1932 | 1942 | ||
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index d50bddb2e447..7fcf4a242840 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
@@ -250,6 +250,7 @@ static void tegra_drm_unload(struct drm_device *drm) | |||
250 | 250 | ||
251 | drm_kms_helper_poll_fini(drm); | 251 | drm_kms_helper_poll_fini(drm); |
252 | tegra_drm_fb_exit(drm); | 252 | tegra_drm_fb_exit(drm); |
253 | drm_atomic_helper_shutdown(drm); | ||
253 | drm_mode_config_cleanup(drm); | 254 | drm_mode_config_cleanup(drm); |
254 | 255 | ||
255 | err = host1x_device_exit(device); | 256 | err = host1x_device_exit(device); |
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index 4d2ed966f9e3..87c5d89bc9ba 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c | |||
@@ -1072,7 +1072,6 @@ static int tegra_dsi_exit(struct host1x_client *client) | |||
1072 | struct tegra_dsi *dsi = host1x_client_to_dsi(client); | 1072 | struct tegra_dsi *dsi = host1x_client_to_dsi(client); |
1073 | 1073 | ||
1074 | tegra_output_exit(&dsi->output); | 1074 | tegra_output_exit(&dsi->output); |
1075 | regulator_disable(dsi->vdd); | ||
1076 | 1075 | ||
1077 | return 0; | 1076 | return 0; |
1078 | } | 1077 | } |
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index 36a06a993698..94dac79ac3c9 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c | |||
@@ -297,6 +297,10 @@ int tegra_plane_format_get_alpha(unsigned int opaque, unsigned int *alpha) | |||
297 | case WIN_COLOR_DEPTH_B8G8R8X8: | 297 | case WIN_COLOR_DEPTH_B8G8R8X8: |
298 | *alpha = WIN_COLOR_DEPTH_B8G8R8A8; | 298 | *alpha = WIN_COLOR_DEPTH_B8G8R8A8; |
299 | return 0; | 299 | return 0; |
300 | |||
301 | case WIN_COLOR_DEPTH_B5G6R5: | ||
302 | *alpha = opaque; | ||
303 | return 0; | ||
300 | } | 304 | } |
301 | 305 | ||
302 | return -EINVAL; | 306 | return -EINVAL; |
@@ -330,9 +334,6 @@ void tegra_plane_check_dependent(struct tegra_plane *tegra, | |||
330 | unsigned int zpos[2]; | 334 | unsigned int zpos[2]; |
331 | unsigned int i; | 335 | unsigned int i; |
332 | 336 | ||
333 | for (i = 0; i < 3; i++) | ||
334 | state->dependent[i] = false; | ||
335 | |||
336 | for (i = 0; i < 2; i++) | 337 | for (i = 0; i < 2; i++) |
337 | zpos[i] = 0; | 338 | zpos[i] = 0; |
338 | 339 | ||
@@ -346,6 +347,8 @@ void tegra_plane_check_dependent(struct tegra_plane *tegra, | |||
346 | 347 | ||
347 | index = tegra_plane_get_overlap_index(tegra, p); | 348 | index = tegra_plane_get_overlap_index(tegra, p); |
348 | 349 | ||
350 | state->dependent[index] = false; | ||
351 | |||
349 | /* | 352 | /* |
350 | * If any of the other planes is on top of this plane and uses | 353 | * If any of the other planes is on top of this plane and uses |
351 | * a format with an alpha component, mark this plane as being | 354 | * a format with an alpha component, mark this plane as being |
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index b5b335c9b2bb..2ebdc6d5a76e 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c | |||
@@ -159,10 +159,15 @@ static int udl_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | |||
159 | { | 159 | { |
160 | unsigned long start = vma->vm_start; | 160 | unsigned long start = vma->vm_start; |
161 | unsigned long size = vma->vm_end - vma->vm_start; | 161 | unsigned long size = vma->vm_end - vma->vm_start; |
162 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | 162 | unsigned long offset; |
163 | unsigned long page, pos; | 163 | unsigned long page, pos; |
164 | 164 | ||
165 | if (offset + size > info->fix.smem_len) | 165 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) |
166 | return -EINVAL; | ||
167 | |||
168 | offset = vma->vm_pgoff << PAGE_SHIFT; | ||
169 | |||
170 | if (offset > info->fix.smem_len || size > info->fix.smem_len - offset) | ||
166 | return -EINVAL; | 171 | return -EINVAL; |
167 | 172 | ||
168 | pos = (unsigned long)info->fix.smem_start + offset; | 173 | pos = (unsigned long)info->fix.smem_start + offset; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 184340d486c3..86d25f18aa99 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
@@ -1337,6 +1337,19 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv) | |||
1337 | */ | 1337 | */ |
1338 | void vmw_svga_disable(struct vmw_private *dev_priv) | 1338 | void vmw_svga_disable(struct vmw_private *dev_priv) |
1339 | { | 1339 | { |
1340 | /* | ||
1341 | * Disabling SVGA will turn off device modesetting capabilities, so | ||
1342 | * notify KMS about that so that it doesn't cache atomic state that | ||
1343 | * isn't valid anymore, for example crtcs turned on. | ||
1344 | * Strictly we'd want to do this under the SVGA lock (or an SVGA mutex), | ||
1345 | * but vmw_kms_lost_device() takes the reservation sem and thus we'll | ||
1346 | * end up with lock order reversal. Thus, a master may actually perform | ||
1347 | * a new modeset just after we call vmw_kms_lost_device() and race with | ||
1348 | * vmw_svga_disable(), but that should at worst cause atomic KMS state | ||
1349 | * to be inconsistent with the device, causing modesetting problems. | ||
1350 | * | ||
1351 | */ | ||
1352 | vmw_kms_lost_device(dev_priv->dev); | ||
1340 | ttm_write_lock(&dev_priv->reservation_sem, false); | 1353 | ttm_write_lock(&dev_priv->reservation_sem, false); |
1341 | spin_lock(&dev_priv->svga_lock); | 1354 | spin_lock(&dev_priv->svga_lock); |
1342 | if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) { | 1355 | if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index d08753e8fd94..9116fe8baebc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
@@ -938,6 +938,7 @@ int vmw_kms_present(struct vmw_private *dev_priv, | |||
938 | int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, | 938 | int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, |
939 | struct drm_file *file_priv); | 939 | struct drm_file *file_priv); |
940 | void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv); | 940 | void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv); |
941 | void vmw_kms_lost_device(struct drm_device *dev); | ||
941 | 942 | ||
942 | int vmw_dumb_create(struct drm_file *file_priv, | 943 | int vmw_dumb_create(struct drm_file *file_priv, |
943 | struct drm_device *dev, | 944 | struct drm_device *dev, |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index ead61015cd79..3c824fd7cbf3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <drm/drm_atomic_helper.h> | 31 | #include <drm/drm_atomic_helper.h> |
32 | #include <drm/drm_rect.h> | 32 | #include <drm/drm_rect.h> |
33 | 33 | ||
34 | |||
35 | /* Might need a hrtimer here? */ | 34 | /* Might need a hrtimer here? */ |
36 | #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1) | 35 | #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1) |
37 | 36 | ||
@@ -2517,9 +2516,12 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv, | |||
2517 | * Helper to be used if an error forces the caller to undo the actions of | 2516 | * Helper to be used if an error forces the caller to undo the actions of |
2518 | * vmw_kms_helper_resource_prepare. | 2517 | * vmw_kms_helper_resource_prepare. |
2519 | */ | 2518 | */ |
2520 | void vmw_kms_helper_resource_revert(struct vmw_resource *res) | 2519 | void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx) |
2521 | { | 2520 | { |
2522 | vmw_kms_helper_buffer_revert(res->backup); | 2521 | struct vmw_resource *res = ctx->res; |
2522 | |||
2523 | vmw_kms_helper_buffer_revert(ctx->buf); | ||
2524 | vmw_dmabuf_unreference(&ctx->buf); | ||
2523 | vmw_resource_unreserve(res, false, NULL, 0); | 2525 | vmw_resource_unreserve(res, false, NULL, 0); |
2524 | mutex_unlock(&res->dev_priv->cmdbuf_mutex); | 2526 | mutex_unlock(&res->dev_priv->cmdbuf_mutex); |
2525 | } | 2527 | } |
@@ -2536,10 +2538,14 @@ void vmw_kms_helper_resource_revert(struct vmw_resource *res) | |||
2536 | * interrupted by a signal. | 2538 | * interrupted by a signal. |
2537 | */ | 2539 | */ |
2538 | int vmw_kms_helper_resource_prepare(struct vmw_resource *res, | 2540 | int vmw_kms_helper_resource_prepare(struct vmw_resource *res, |
2539 | bool interruptible) | 2541 | bool interruptible, |
2542 | struct vmw_validation_ctx *ctx) | ||
2540 | { | 2543 | { |
2541 | int ret = 0; | 2544 | int ret = 0; |
2542 | 2545 | ||
2546 | ctx->buf = NULL; | ||
2547 | ctx->res = res; | ||
2548 | |||
2543 | if (interruptible) | 2549 | if (interruptible) |
2544 | ret = mutex_lock_interruptible(&res->dev_priv->cmdbuf_mutex); | 2550 | ret = mutex_lock_interruptible(&res->dev_priv->cmdbuf_mutex); |
2545 | else | 2551 | else |
@@ -2558,6 +2564,8 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res, | |||
2558 | res->dev_priv->has_mob); | 2564 | res->dev_priv->has_mob); |
2559 | if (ret) | 2565 | if (ret) |
2560 | goto out_unreserve; | 2566 | goto out_unreserve; |
2567 | |||
2568 | ctx->buf = vmw_dmabuf_reference(res->backup); | ||
2561 | } | 2569 | } |
2562 | ret = vmw_resource_validate(res); | 2570 | ret = vmw_resource_validate(res); |
2563 | if (ret) | 2571 | if (ret) |
@@ -2565,7 +2573,7 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res, | |||
2565 | return 0; | 2573 | return 0; |
2566 | 2574 | ||
2567 | out_revert: | 2575 | out_revert: |
2568 | vmw_kms_helper_buffer_revert(res->backup); | 2576 | vmw_kms_helper_buffer_revert(ctx->buf); |
2569 | out_unreserve: | 2577 | out_unreserve: |
2570 | vmw_resource_unreserve(res, false, NULL, 0); | 2578 | vmw_resource_unreserve(res, false, NULL, 0); |
2571 | out_unlock: | 2579 | out_unlock: |
@@ -2581,11 +2589,13 @@ out_unlock: | |||
2581 | * @out_fence: Optional pointer to a fence pointer. If non-NULL, a | 2589 | * @out_fence: Optional pointer to a fence pointer. If non-NULL, a |
2582 | * ref-counted fence pointer is returned here. | 2590 | * ref-counted fence pointer is returned here. |
2583 | */ | 2591 | */ |
2584 | void vmw_kms_helper_resource_finish(struct vmw_resource *res, | 2592 | void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx, |
2585 | struct vmw_fence_obj **out_fence) | 2593 | struct vmw_fence_obj **out_fence) |
2586 | { | 2594 | { |
2587 | if (res->backup || out_fence) | 2595 | struct vmw_resource *res = ctx->res; |
2588 | vmw_kms_helper_buffer_finish(res->dev_priv, NULL, res->backup, | 2596 | |
2597 | if (ctx->buf || out_fence) | ||
2598 | vmw_kms_helper_buffer_finish(res->dev_priv, NULL, ctx->buf, | ||
2589 | out_fence, NULL); | 2599 | out_fence, NULL); |
2590 | 2600 | ||
2591 | vmw_resource_unreserve(res, false, NULL, 0); | 2601 | vmw_resource_unreserve(res, false, NULL, 0); |
@@ -2851,3 +2861,14 @@ int vmw_kms_set_config(struct drm_mode_set *set, | |||
2851 | 2861 | ||
2852 | return drm_atomic_helper_set_config(set, ctx); | 2862 | return drm_atomic_helper_set_config(set, ctx); |
2853 | } | 2863 | } |
2864 | |||
2865 | |||
2866 | /** | ||
2867 | * vmw_kms_lost_device - Notify kms that modesetting capabilities will be lost | ||
2868 | * | ||
2869 | * @dev: Pointer to the drm device | ||
2870 | */ | ||
2871 | void vmw_kms_lost_device(struct drm_device *dev) | ||
2872 | { | ||
2873 | drm_atomic_helper_shutdown(dev); | ||
2874 | } | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index cd9da2dd79af..3d2ca280eaa7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | |||
@@ -240,6 +240,11 @@ struct vmw_display_unit { | |||
240 | int set_gui_y; | 240 | int set_gui_y; |
241 | }; | 241 | }; |
242 | 242 | ||
243 | struct vmw_validation_ctx { | ||
244 | struct vmw_resource *res; | ||
245 | struct vmw_dma_buffer *buf; | ||
246 | }; | ||
247 | |||
243 | #define vmw_crtc_to_du(x) \ | 248 | #define vmw_crtc_to_du(x) \ |
244 | container_of(x, struct vmw_display_unit, crtc) | 249 | container_of(x, struct vmw_display_unit, crtc) |
245 | #define vmw_connector_to_du(x) \ | 250 | #define vmw_connector_to_du(x) \ |
@@ -296,9 +301,10 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv, | |||
296 | struct drm_vmw_fence_rep __user * | 301 | struct drm_vmw_fence_rep __user * |
297 | user_fence_rep); | 302 | user_fence_rep); |
298 | int vmw_kms_helper_resource_prepare(struct vmw_resource *res, | 303 | int vmw_kms_helper_resource_prepare(struct vmw_resource *res, |
299 | bool interruptible); | 304 | bool interruptible, |
300 | void vmw_kms_helper_resource_revert(struct vmw_resource *res); | 305 | struct vmw_validation_ctx *ctx); |
301 | void vmw_kms_helper_resource_finish(struct vmw_resource *res, | 306 | void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx); |
307 | void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx, | ||
302 | struct vmw_fence_obj **out_fence); | 308 | struct vmw_fence_obj **out_fence); |
303 | int vmw_kms_readback(struct vmw_private *dev_priv, | 309 | int vmw_kms_readback(struct vmw_private *dev_priv, |
304 | struct drm_file *file_priv, | 310 | struct drm_file *file_priv, |
@@ -439,5 +445,4 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, | |||
439 | 445 | ||
440 | int vmw_kms_set_config(struct drm_mode_set *set, | 446 | int vmw_kms_set_config(struct drm_mode_set *set, |
441 | struct drm_modeset_acquire_ctx *ctx); | 447 | struct drm_modeset_acquire_ctx *ctx); |
442 | |||
443 | #endif | 448 | #endif |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 63a4cd794b73..3ec9eae831b8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | |||
@@ -909,12 +909,13 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, | |||
909 | struct vmw_framebuffer_surface *vfbs = | 909 | struct vmw_framebuffer_surface *vfbs = |
910 | container_of(framebuffer, typeof(*vfbs), base); | 910 | container_of(framebuffer, typeof(*vfbs), base); |
911 | struct vmw_kms_sou_surface_dirty sdirty; | 911 | struct vmw_kms_sou_surface_dirty sdirty; |
912 | struct vmw_validation_ctx ctx; | ||
912 | int ret; | 913 | int ret; |
913 | 914 | ||
914 | if (!srf) | 915 | if (!srf) |
915 | srf = &vfbs->surface->res; | 916 | srf = &vfbs->surface->res; |
916 | 917 | ||
917 | ret = vmw_kms_helper_resource_prepare(srf, true); | 918 | ret = vmw_kms_helper_resource_prepare(srf, true, &ctx); |
918 | if (ret) | 919 | if (ret) |
919 | return ret; | 920 | return ret; |
920 | 921 | ||
@@ -933,7 +934,7 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, | |||
933 | ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, | 934 | ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, |
934 | dest_x, dest_y, num_clips, inc, | 935 | dest_x, dest_y, num_clips, inc, |
935 | &sdirty.base); | 936 | &sdirty.base); |
936 | vmw_kms_helper_resource_finish(srf, out_fence); | 937 | vmw_kms_helper_resource_finish(&ctx, out_fence); |
937 | 938 | ||
938 | return ret; | 939 | return ret; |
939 | } | 940 | } |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index b68d74888ab1..6b969e5dea2a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | |||
@@ -980,12 +980,13 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, | |||
980 | struct vmw_framebuffer_surface *vfbs = | 980 | struct vmw_framebuffer_surface *vfbs = |
981 | container_of(framebuffer, typeof(*vfbs), base); | 981 | container_of(framebuffer, typeof(*vfbs), base); |
982 | struct vmw_stdu_dirty sdirty; | 982 | struct vmw_stdu_dirty sdirty; |
983 | struct vmw_validation_ctx ctx; | ||
983 | int ret; | 984 | int ret; |
984 | 985 | ||
985 | if (!srf) | 986 | if (!srf) |
986 | srf = &vfbs->surface->res; | 987 | srf = &vfbs->surface->res; |
987 | 988 | ||
988 | ret = vmw_kms_helper_resource_prepare(srf, true); | 989 | ret = vmw_kms_helper_resource_prepare(srf, true, &ctx); |
989 | if (ret) | 990 | if (ret) |
990 | return ret; | 991 | return ret; |
991 | 992 | ||
@@ -1008,7 +1009,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, | |||
1008 | dest_x, dest_y, num_clips, inc, | 1009 | dest_x, dest_y, num_clips, inc, |
1009 | &sdirty.base); | 1010 | &sdirty.base); |
1010 | out_finish: | 1011 | out_finish: |
1011 | vmw_kms_helper_resource_finish(srf, out_fence); | 1012 | vmw_kms_helper_resource_finish(&ctx, out_fence); |
1012 | 1013 | ||
1013 | return ret; | 1014 | return ret; |
1014 | } | 1015 | } |
diff --git a/drivers/gpu/ipu-v3/ipu-prg.c b/drivers/gpu/ipu-v3/ipu-prg.c index 97b99500153d..83f9dd934a5d 100644 --- a/drivers/gpu/ipu-v3/ipu-prg.c +++ b/drivers/gpu/ipu-v3/ipu-prg.c | |||
@@ -250,10 +250,14 @@ void ipu_prg_channel_disable(struct ipuv3_channel *ipu_chan) | |||
250 | { | 250 | { |
251 | int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num); | 251 | int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num); |
252 | struct ipu_prg *prg = ipu_chan->ipu->prg_priv; | 252 | struct ipu_prg *prg = ipu_chan->ipu->prg_priv; |
253 | struct ipu_prg_channel *chan = &prg->chan[prg_chan]; | 253 | struct ipu_prg_channel *chan; |
254 | u32 val; | 254 | u32 val; |
255 | 255 | ||
256 | if (!chan->enabled || prg_chan < 0) | 256 | if (prg_chan < 0) |
257 | return; | ||
258 | |||
259 | chan = &prg->chan[prg_chan]; | ||
260 | if (!chan->enabled) | ||
257 | return; | 261 | return; |
258 | 262 | ||
259 | pm_runtime_get_sync(prg->dev); | 263 | pm_runtime_get_sync(prg->dev); |
@@ -280,13 +284,15 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan, | |||
280 | { | 284 | { |
281 | int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num); | 285 | int prg_chan = ipu_prg_ipu_to_prg_chan(ipu_chan->num); |
282 | struct ipu_prg *prg = ipu_chan->ipu->prg_priv; | 286 | struct ipu_prg *prg = ipu_chan->ipu->prg_priv; |
283 | struct ipu_prg_channel *chan = &prg->chan[prg_chan]; | 287 | struct ipu_prg_channel *chan; |
284 | u32 val; | 288 | u32 val; |
285 | int ret; | 289 | int ret; |
286 | 290 | ||
287 | if (prg_chan < 0) | 291 | if (prg_chan < 0) |
288 | return prg_chan; | 292 | return prg_chan; |
289 | 293 | ||
294 | chan = &prg->chan[prg_chan]; | ||
295 | |||
290 | if (chan->enabled) { | 296 | if (chan->enabled) { |
291 | ipu_pre_update(prg->pres[chan->used_pre], *eba); | 297 | ipu_pre_update(prg->pres[chan->used_pre], *eba); |
292 | return 0; | 298 | return 0; |