diff options
author | Dave Airlie <airlied@redhat.com> | 2018-03-28 00:30:41 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-03-28 00:30:41 -0400 |
commit | 2b4f44eec2be2688511c2b617d0e1b4f94c45ba4 (patch) | |
tree | 533c03602f4ae6d6404db6fa56c88e6f83e1bebe /drivers/gpu/drm | |
parent | 33d009cd889490838c5db9b9339856c9e3d3facc (diff) | |
parent | 3eb2ce825ea1ad89d20f7a3b5780df850e4be274 (diff) |
Backmerge tag 'v4.16-rc7' into drm-next
Linux 4.16-rc7
This was requested by Daniel, and things were getting
a bit hard to reconcile, most of the conflicts were
trivial though.
Diffstat (limited to 'drivers/gpu/drm')
55 files changed, 569 insertions, 228 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 9da8d5802980..96501ff0e55b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | |||
@@ -729,9 +729,11 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force) | |||
729 | enum drm_connector_status ret = connector_status_disconnected; | 729 | enum drm_connector_status ret = connector_status_disconnected; |
730 | int r; | 730 | int r; |
731 | 731 | ||
732 | r = pm_runtime_get_sync(connector->dev->dev); | 732 | if (!drm_kms_helper_is_poll_worker()) { |
733 | if (r < 0) | 733 | r = pm_runtime_get_sync(connector->dev->dev); |
734 | return connector_status_disconnected; | 734 | if (r < 0) |
735 | return connector_status_disconnected; | ||
736 | } | ||
735 | 737 | ||
736 | if (encoder) { | 738 | if (encoder) { |
737 | struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); | 739 | struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); |
@@ -750,8 +752,12 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force) | |||
750 | /* check acpi lid status ??? */ | 752 | /* check acpi lid status ??? */ |
751 | 753 | ||
752 | amdgpu_connector_update_scratch_regs(connector, ret); | 754 | amdgpu_connector_update_scratch_regs(connector, ret); |
753 | pm_runtime_mark_last_busy(connector->dev->dev); | 755 | |
754 | pm_runtime_put_autosuspend(connector->dev->dev); | 756 | if (!drm_kms_helper_is_poll_worker()) { |
757 | pm_runtime_mark_last_busy(connector->dev->dev); | ||
758 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
759 | } | ||
760 | |||
755 | return ret; | 761 | return ret; |
756 | } | 762 | } |
757 | 763 | ||
@@ -861,9 +867,11 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force) | |||
861 | enum drm_connector_status ret = connector_status_disconnected; | 867 | enum drm_connector_status ret = connector_status_disconnected; |
862 | int r; | 868 | int r; |
863 | 869 | ||
864 | r = pm_runtime_get_sync(connector->dev->dev); | 870 | if (!drm_kms_helper_is_poll_worker()) { |
865 | if (r < 0) | 871 | r = pm_runtime_get_sync(connector->dev->dev); |
866 | return connector_status_disconnected; | 872 | if (r < 0) |
873 | return connector_status_disconnected; | ||
874 | } | ||
867 | 875 | ||
868 | encoder = amdgpu_connector_best_single_encoder(connector); | 876 | encoder = amdgpu_connector_best_single_encoder(connector); |
869 | if (!encoder) | 877 | if (!encoder) |
@@ -917,8 +925,10 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force) | |||
917 | amdgpu_connector_update_scratch_regs(connector, ret); | 925 | amdgpu_connector_update_scratch_regs(connector, ret); |
918 | 926 | ||
919 | out: | 927 | out: |
920 | pm_runtime_mark_last_busy(connector->dev->dev); | 928 | if (!drm_kms_helper_is_poll_worker()) { |
921 | pm_runtime_put_autosuspend(connector->dev->dev); | 929 | pm_runtime_mark_last_busy(connector->dev->dev); |
930 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
931 | } | ||
922 | 932 | ||
923 | return ret; | 933 | return ret; |
924 | } | 934 | } |
@@ -981,9 +991,11 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) | |||
981 | enum drm_connector_status ret = connector_status_disconnected; | 991 | enum drm_connector_status ret = connector_status_disconnected; |
982 | bool dret = false, broken_edid = false; | 992 | bool dret = false, broken_edid = false; |
983 | 993 | ||
984 | r = pm_runtime_get_sync(connector->dev->dev); | 994 | if (!drm_kms_helper_is_poll_worker()) { |
985 | if (r < 0) | 995 | r = pm_runtime_get_sync(connector->dev->dev); |
986 | return connector_status_disconnected; | 996 | if (r < 0) |
997 | return connector_status_disconnected; | ||
998 | } | ||
987 | 999 | ||
988 | if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) { | 1000 | if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) { |
989 | ret = connector->status; | 1001 | ret = connector->status; |
@@ -1108,8 +1120,10 @@ out: | |||
1108 | amdgpu_connector_update_scratch_regs(connector, ret); | 1120 | amdgpu_connector_update_scratch_regs(connector, ret); |
1109 | 1121 | ||
1110 | exit: | 1122 | exit: |
1111 | pm_runtime_mark_last_busy(connector->dev->dev); | 1123 | if (!drm_kms_helper_is_poll_worker()) { |
1112 | pm_runtime_put_autosuspend(connector->dev->dev); | 1124 | pm_runtime_mark_last_busy(connector->dev->dev); |
1125 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
1126 | } | ||
1113 | 1127 | ||
1114 | return ret; | 1128 | return ret; |
1115 | } | 1129 | } |
@@ -1352,9 +1366,11 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force) | |||
1352 | struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector); | 1366 | struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector); |
1353 | int r; | 1367 | int r; |
1354 | 1368 | ||
1355 | r = pm_runtime_get_sync(connector->dev->dev); | 1369 | if (!drm_kms_helper_is_poll_worker()) { |
1356 | if (r < 0) | 1370 | r = pm_runtime_get_sync(connector->dev->dev); |
1357 | return connector_status_disconnected; | 1371 | if (r < 0) |
1372 | return connector_status_disconnected; | ||
1373 | } | ||
1358 | 1374 | ||
1359 | if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) { | 1375 | if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) { |
1360 | ret = connector->status; | 1376 | ret = connector->status; |
@@ -1424,8 +1440,10 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force) | |||
1424 | 1440 | ||
1425 | amdgpu_connector_update_scratch_regs(connector, ret); | 1441 | amdgpu_connector_update_scratch_regs(connector, ret); |
1426 | out: | 1442 | out: |
1427 | pm_runtime_mark_last_busy(connector->dev->dev); | 1443 | if (!drm_kms_helper_is_poll_worker()) { |
1428 | pm_runtime_put_autosuspend(connector->dev->dev); | 1444 | pm_runtime_mark_last_busy(connector->dev->dev); |
1445 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
1446 | } | ||
1429 | 1447 | ||
1430 | return ret; | 1448 | return ret; |
1431 | } | 1449 | } |
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 13a5362d074e..e42a28e3adc5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |||
@@ -3172,8 +3172,6 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, | |||
3172 | 3172 | ||
3173 | switch (aplane->base.type) { | 3173 | switch (aplane->base.type) { |
3174 | case DRM_PLANE_TYPE_PRIMARY: | 3174 | case DRM_PLANE_TYPE_PRIMARY: |
3175 | aplane->base.format_default = true; | ||
3176 | |||
3177 | res = drm_universal_plane_init( | 3175 | res = drm_universal_plane_init( |
3178 | dm->adev->ddev, | 3176 | dm->adev->ddev, |
3179 | &aplane->base, | 3177 | &aplane->base, |
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 9ab69b22b989..ca0b08bfa2cf 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/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/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/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index cd23b1b28259..c91b9b054e3f 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c | |||
@@ -294,22 +294,7 @@ static void cirrus_crtc_prepare(struct drm_crtc *crtc) | |||
294 | { | 294 | { |
295 | } | 295 | } |
296 | 296 | ||
297 | /* | 297 | static void cirrus_crtc_load_lut(struct drm_crtc *crtc) |
298 | * This is called after a mode is programmed. It should reverse anything done | ||
299 | * by the prepare function | ||
300 | */ | ||
301 | static void cirrus_crtc_commit(struct drm_crtc *crtc) | ||
302 | { | ||
303 | } | ||
304 | |||
305 | /* | ||
306 | * The core can pass us a set of gamma values to program. We actually only | ||
307 | * use this for 8-bit mode so can't perform smooth fades on deeper modes, | ||
308 | * but it's a requirement that we provide the function | ||
309 | */ | ||
310 | static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | ||
311 | u16 *blue, uint32_t size, | ||
312 | struct drm_modeset_acquire_ctx *ctx) | ||
313 | { | 298 | { |
314 | struct drm_device *dev = crtc->dev; | 299 | struct drm_device *dev = crtc->dev; |
315 | struct cirrus_device *cdev = dev->dev_private; | 300 | struct cirrus_device *cdev = dev->dev_private; |
@@ -317,7 +302,7 @@ static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
317 | int i; | 302 | int i; |
318 | 303 | ||
319 | if (!crtc->enabled) | 304 | if (!crtc->enabled) |
320 | return 0; | 305 | return; |
321 | 306 | ||
322 | r = crtc->gamma_store; | 307 | r = crtc->gamma_store; |
323 | g = r + crtc->gamma_size; | 308 | g = r + crtc->gamma_size; |
@@ -330,6 +315,27 @@ static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
330 | WREG8(PALETTE_DATA, *g++ >> 8); | 315 | WREG8(PALETTE_DATA, *g++ >> 8); |
331 | WREG8(PALETTE_DATA, *b++ >> 8); | 316 | WREG8(PALETTE_DATA, *b++ >> 8); |
332 | } | 317 | } |
318 | } | ||
319 | |||
320 | /* | ||
321 | * This is called after a mode is programmed. It should reverse anything done | ||
322 | * by the prepare function | ||
323 | */ | ||
324 | static void cirrus_crtc_commit(struct drm_crtc *crtc) | ||
325 | { | ||
326 | cirrus_crtc_load_lut(crtc); | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * The core can pass us a set of gamma values to program. We actually only | ||
331 | * use this for 8-bit mode so can't perform smooth fades on deeper modes, | ||
332 | * but it's a requirement that we provide the function | ||
333 | */ | ||
334 | static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | ||
335 | u16 *blue, uint32_t size, | ||
336 | struct drm_modeset_acquire_ctx *ctx) | ||
337 | { | ||
338 | cirrus_crtc_load_lut(crtc); | ||
333 | 339 | ||
334 | return 0; | 340 | return 0; |
335 | } | 341 | } |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 49147b2aa288..134069f36482 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -113,6 +113,9 @@ static const struct edid_quirk { | |||
113 | /* AEO model 0 reports 8 bpc, but is a 6 bpc panel */ | 113 | /* AEO model 0 reports 8 bpc, but is a 6 bpc panel */ |
114 | { "AEO", 0, EDID_QUIRK_FORCE_6BPC }, | 114 | { "AEO", 0, EDID_QUIRK_FORCE_6BPC }, |
115 | 115 | ||
116 | /* CPT panel of Asus UX303LA reports 8 bpc, but is a 6 bpc panel */ | ||
117 | { "CPT", 0x17df, EDID_QUIRK_FORCE_6BPC }, | ||
118 | |||
116 | /* Belinea 10 15 55 */ | 119 | /* Belinea 10 15 55 */ |
117 | { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, | 120 | { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, |
118 | { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, | 121 | { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, |
@@ -162,6 +165,24 @@ static const struct edid_quirk { | |||
162 | 165 | ||
163 | /* HTC Vive VR Headset */ | 166 | /* HTC Vive VR Headset */ |
164 | { "HVR", 0xaa01, EDID_QUIRK_NON_DESKTOP }, | 167 | { "HVR", 0xaa01, EDID_QUIRK_NON_DESKTOP }, |
168 | |||
169 | /* Oculus Rift DK1, DK2, and CV1 VR Headsets */ | ||
170 | { "OVR", 0x0001, EDID_QUIRK_NON_DESKTOP }, | ||
171 | { "OVR", 0x0003, EDID_QUIRK_NON_DESKTOP }, | ||
172 | { "OVR", 0x0004, EDID_QUIRK_NON_DESKTOP }, | ||
173 | |||
174 | /* Windows Mixed Reality Headsets */ | ||
175 | { "ACR", 0x7fce, EDID_QUIRK_NON_DESKTOP }, | ||
176 | { "HPN", 0x3515, EDID_QUIRK_NON_DESKTOP }, | ||
177 | { "LEN", 0x0408, EDID_QUIRK_NON_DESKTOP }, | ||
178 | { "LEN", 0xb800, EDID_QUIRK_NON_DESKTOP }, | ||
179 | { "FUJ", 0x1970, EDID_QUIRK_NON_DESKTOP }, | ||
180 | { "DEL", 0x7fce, EDID_QUIRK_NON_DESKTOP }, | ||
181 | { "SEC", 0x144a, EDID_QUIRK_NON_DESKTOP }, | ||
182 | { "AUS", 0xc102, EDID_QUIRK_NON_DESKTOP }, | ||
183 | |||
184 | /* Sony PlayStation VR Headset */ | ||
185 | { "SNY", 0x0704, EDID_QUIRK_NON_DESKTOP }, | ||
165 | }; | 186 | }; |
166 | 187 | ||
167 | /* | 188 | /* |
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 0eebe8ba8a2c..ad67203de715 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c | |||
@@ -121,6 +121,10 @@ int drm_mode_addfb(struct drm_device *dev, | |||
121 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); | 121 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); |
122 | r.handles[0] = or->handle; | 122 | r.handles[0] = or->handle; |
123 | 123 | ||
124 | if (r.pixel_format == DRM_FORMAT_XRGB2101010 && | ||
125 | dev->driver->driver_features & DRIVER_PREFER_XBGR_30BPP) | ||
126 | r.pixel_format = DRM_FORMAT_XBGR2101010; | ||
127 | |||
124 | ret = drm_mode_addfb2(dev, &r, file_priv); | 128 | ret = drm_mode_addfb2(dev, &r, file_priv); |
125 | if (ret) | 129 | if (ret) |
126 | return ret; | 130 | return ret; |
@@ -458,6 +462,12 @@ int drm_mode_getfb(struct drm_device *dev, | |||
458 | if (!fb) | 462 | if (!fb) |
459 | return -ENOENT; | 463 | return -ENOENT; |
460 | 464 | ||
465 | /* Multi-planar framebuffers need getfb2. */ | ||
466 | if (fb->format->num_planes > 1) { | ||
467 | ret = -EINVAL; | ||
468 | goto out; | ||
469 | } | ||
470 | |||
461 | r->height = fb->height; | 471 | r->height = fb->height; |
462 | r->width = fb->width; | 472 | r->width = fb->width; |
463 | r->depth = fb->format->depth; | 473 | r->depth = fb->format->depth; |
@@ -481,6 +491,7 @@ int drm_mode_getfb(struct drm_device *dev, | |||
481 | ret = -ENODEV; | 491 | ret = -ENODEV; |
482 | } | 492 | } |
483 | 493 | ||
494 | out: | ||
484 | drm_framebuffer_put(fb); | 495 | drm_framebuffer_put(fb); |
485 | 496 | ||
486 | return ret; | 497 | return ret; |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index a351bd888a61..3166026a1874 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
@@ -837,9 +837,24 @@ struct drm_mm_node *drm_mm_scan_color_evict(struct drm_mm_scan *scan) | |||
837 | if (!mm->color_adjust) | 837 | if (!mm->color_adjust) |
838 | return NULL; | 838 | return NULL; |
839 | 839 | ||
840 | hole = list_first_entry(&mm->hole_stack, typeof(*hole), hole_stack); | 840 | /* |
841 | hole_start = __drm_mm_hole_node_start(hole); | 841 | * The hole found during scanning should ideally be the first element |
842 | hole_end = hole_start + hole->hole_size; | 842 | * in the hole_stack list, but due to side-effects in the driver it |
843 | * may not be. | ||
844 | */ | ||
845 | list_for_each_entry(hole, &mm->hole_stack, hole_stack) { | ||
846 | hole_start = __drm_mm_hole_node_start(hole); | ||
847 | hole_end = hole_start + hole->hole_size; | ||
848 | |||
849 | if (hole_start <= scan->hit_start && | ||
850 | hole_end >= scan->hit_end) | ||
851 | break; | ||
852 | } | ||
853 | |||
854 | /* We should only be called after we found the hole previously */ | ||
855 | DRM_MM_BUG_ON(&hole->hole_stack == &mm->hole_stack); | ||
856 | if (unlikely(&hole->hole_stack == &mm->hole_stack)) | ||
857 | return NULL; | ||
843 | 858 | ||
844 | DRM_MM_BUG_ON(hole_start > scan->hit_start); | 859 | DRM_MM_BUG_ON(hole_start > scan->hit_start); |
845 | DRM_MM_BUG_ON(hole_end < scan->hit_end); | 860 | DRM_MM_BUG_ON(hole_end < scan->hit_end); |
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 2d1643bdae78..527743394150 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c | |||
@@ -654,6 +654,26 @@ out: | |||
654 | } | 654 | } |
655 | 655 | ||
656 | /** | 656 | /** |
657 | * drm_kms_helper_is_poll_worker - is %current task an output poll worker? | ||
658 | * | ||
659 | * Determine if %current task is an output poll worker. This can be used | ||
660 | * to select distinct code paths for output polling versus other contexts. | ||
661 | * | ||
662 | * One use case is to avoid a deadlock between the output poll worker and | ||
663 | * the autosuspend worker wherein the latter waits for polling to finish | ||
664 | * upon calling drm_kms_helper_poll_disable(), while the former waits for | ||
665 | * runtime suspend to finish upon calling pm_runtime_get_sync() in a | ||
666 | * connector ->detect hook. | ||
667 | */ | ||
668 | bool drm_kms_helper_is_poll_worker(void) | ||
669 | { | ||
670 | struct work_struct *work = current_work(); | ||
671 | |||
672 | return work && work->func == output_poll_execute; | ||
673 | } | ||
674 | EXPORT_SYMBOL(drm_kms_helper_is_poll_worker); | ||
675 | |||
676 | /** | ||
657 | * drm_kms_helper_poll_disable - disable output polling | 677 | * drm_kms_helper_poll_disable - disable output polling |
658 | * @dev: drm_device | 678 | * @dev: drm_device |
659 | * | 679 | * |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 2b8bf2dd6387..f68ef1b3a28c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c | |||
@@ -286,7 +286,6 @@ static int g2d_init_cmdlist(struct g2d_data *g2d) | |||
286 | 286 | ||
287 | node = kcalloc(G2D_CMDLIST_NUM, sizeof(*node), GFP_KERNEL); | 287 | node = kcalloc(G2D_CMDLIST_NUM, sizeof(*node), GFP_KERNEL); |
288 | if (!node) { | 288 | if (!node) { |
289 | dev_err(dev, "failed to allocate memory\n"); | ||
290 | ret = -ENOMEM; | 289 | ret = -ENOMEM; |
291 | goto err; | 290 | goto err; |
292 | } | 291 | } |
@@ -926,7 +925,7 @@ static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no) | |||
926 | struct drm_device *drm_dev = g2d->subdrv.drm_dev; | 925 | struct drm_device *drm_dev = g2d->subdrv.drm_dev; |
927 | struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node; | 926 | struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node; |
928 | struct drm_exynos_pending_g2d_event *e; | 927 | struct drm_exynos_pending_g2d_event *e; |
929 | struct timeval now; | 928 | struct timespec64 now; |
930 | 929 | ||
931 | if (list_empty(&runqueue_node->event_list)) | 930 | if (list_empty(&runqueue_node->event_list)) |
932 | return; | 931 | return; |
@@ -934,9 +933,9 @@ static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no) | |||
934 | e = list_first_entry(&runqueue_node->event_list, | 933 | e = list_first_entry(&runqueue_node->event_list, |
935 | struct drm_exynos_pending_g2d_event, base.link); | 934 | struct drm_exynos_pending_g2d_event, base.link); |
936 | 935 | ||
937 | do_gettimeofday(&now); | 936 | ktime_get_ts64(&now); |
938 | e->event.tv_sec = now.tv_sec; | 937 | e->event.tv_sec = now.tv_sec; |
939 | e->event.tv_usec = now.tv_usec; | 938 | e->event.tv_usec = now.tv_nsec / NSEC_PER_USEC; |
940 | e->event.cmdlist_no = cmdlist_no; | 939 | e->event.cmdlist_no = cmdlist_no; |
941 | 940 | ||
942 | drm_send_event(drm_dev, &e->base); | 941 | drm_send_event(drm_dev, &e->base); |
@@ -1358,10 +1357,9 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data, | |||
1358 | return -EFAULT; | 1357 | return -EFAULT; |
1359 | 1358 | ||
1360 | runqueue_node = kmem_cache_alloc(g2d->runqueue_slab, GFP_KERNEL); | 1359 | runqueue_node = kmem_cache_alloc(g2d->runqueue_slab, GFP_KERNEL); |
1361 | if (!runqueue_node) { | 1360 | if (!runqueue_node) |
1362 | dev_err(dev, "failed to allocate memory\n"); | ||
1363 | return -ENOMEM; | 1361 | return -ENOMEM; |
1364 | } | 1362 | |
1365 | run_cmdlist = &runqueue_node->run_cmdlist; | 1363 | run_cmdlist = &runqueue_node->run_cmdlist; |
1366 | event_list = &runqueue_node->event_list; | 1364 | event_list = &runqueue_node->event_list; |
1367 | INIT_LIST_HEAD(run_cmdlist); | 1365 | INIT_LIST_HEAD(run_cmdlist); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.h b/drivers/gpu/drm/exynos/exynos_drm_rotator.h deleted file mode 100644 index 71a0b4c0c1e8..000000000000 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.h +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
3 | * | ||
4 | * Authors: | ||
5 | * YoungJun Cho <yj44.cho@samsung.com> | ||
6 | * Eunchul Kim <chulspro.kim@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef _EXYNOS_DRM_ROTATOR_H_ | ||
15 | #define _EXYNOS_DRM_ROTATOR_H_ | ||
16 | |||
17 | /* TODO */ | ||
18 | |||
19 | #endif | ||
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index a4b75a46f946..abd84cbcf1c2 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -1068,10 +1068,13 @@ static void hdmi_audio_config(struct hdmi_context *hdata) | |||
1068 | /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */ | 1068 | /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */ |
1069 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5) | 1069 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5) |
1070 | | HDMI_I2S_SEL_LRCK(6)); | 1070 | | HDMI_I2S_SEL_LRCK(6)); |
1071 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1) | 1071 | |
1072 | | HDMI_I2S_SEL_SDATA2(4)); | 1072 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(3) |
1073 | | HDMI_I2S_SEL_SDATA0(4)); | ||
1074 | |||
1073 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1) | 1075 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1) |
1074 | | HDMI_I2S_SEL_SDATA2(2)); | 1076 | | HDMI_I2S_SEL_SDATA2(2)); |
1077 | |||
1075 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0)); | 1078 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0)); |
1076 | 1079 | ||
1077 | /* I2S_CON_1 & 2 */ | 1080 | /* I2S_CON_1 & 2 */ |
diff --git a/drivers/gpu/drm/exynos/regs-fimc.h b/drivers/gpu/drm/exynos/regs-fimc.h index 30496134a3d0..d7cbe53c4c01 100644 --- a/drivers/gpu/drm/exynos/regs-fimc.h +++ b/drivers/gpu/drm/exynos/regs-fimc.h | |||
@@ -569,7 +569,7 @@ | |||
569 | #define EXYNOS_CIIMGEFF_FIN_EMBOSSING (4 << 26) | 569 | #define EXYNOS_CIIMGEFF_FIN_EMBOSSING (4 << 26) |
570 | #define EXYNOS_CIIMGEFF_FIN_SILHOUETTE (5 << 26) | 570 | #define EXYNOS_CIIMGEFF_FIN_SILHOUETTE (5 << 26) |
571 | #define EXYNOS_CIIMGEFF_FIN_MASK (7 << 26) | 571 | #define EXYNOS_CIIMGEFF_FIN_MASK (7 << 26) |
572 | #define EXYNOS_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff < 0)) | 572 | #define EXYNOS_CIIMGEFF_PAT_CBCR_MASK ((0xff << 13) | (0xff << 0)) |
573 | 573 | ||
574 | /* Real input DMA size register */ | 574 | /* Real input DMA size register */ |
575 | #define EXYNOS_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31) | 575 | #define EXYNOS_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31) |
diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h index 04be0f7e8193..4420c203ac85 100644 --- a/drivers/gpu/drm/exynos/regs-hdmi.h +++ b/drivers/gpu/drm/exynos/regs-hdmi.h | |||
@@ -464,7 +464,7 @@ | |||
464 | 464 | ||
465 | /* I2S_PIN_SEL_1 */ | 465 | /* I2S_PIN_SEL_1 */ |
466 | #define HDMI_I2S_SEL_SDATA1(x) (((x) & 0x7) << 4) | 466 | #define HDMI_I2S_SEL_SDATA1(x) (((x) & 0x7) << 4) |
467 | #define HDMI_I2S_SEL_SDATA2(x) ((x) & 0x7) | 467 | #define HDMI_I2S_SEL_SDATA0(x) ((x) & 0x7) |
468 | 468 | ||
469 | /* I2S_PIN_SEL_2 */ | 469 | /* I2S_PIN_SEL_2 */ |
470 | #define HDMI_I2S_SEL_SDATA3(x) (((x) & 0x7) << 4) | 470 | #define HDMI_I2S_SEL_SDATA3(x) (((x) & 0x7) << 4) |
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/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 520fe3d0a882..c16a492449d7 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c | |||
@@ -750,6 +750,25 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf, | |||
750 | return ret == 0 ? count : ret; | 750 | return ret == 0 ? count : ret; |
751 | } | 751 | } |
752 | 752 | ||
753 | static bool gtt_entry(struct mdev_device *mdev, loff_t *ppos) | ||
754 | { | ||
755 | struct intel_vgpu *vgpu = mdev_get_drvdata(mdev); | ||
756 | unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos); | ||
757 | struct intel_gvt *gvt = vgpu->gvt; | ||
758 | int offset; | ||
759 | |||
760 | /* Only allow MMIO GGTT entry access */ | ||
761 | if (index != PCI_BASE_ADDRESS_0) | ||
762 | return false; | ||
763 | |||
764 | offset = (u64)(*ppos & VFIO_PCI_OFFSET_MASK) - | ||
765 | intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_0); | ||
766 | |||
767 | return (offset >= gvt->device_info.gtt_start_offset && | ||
768 | offset < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt)) ? | ||
769 | true : false; | ||
770 | } | ||
771 | |||
753 | static ssize_t intel_vgpu_read(struct mdev_device *mdev, char __user *buf, | 772 | static ssize_t intel_vgpu_read(struct mdev_device *mdev, char __user *buf, |
754 | size_t count, loff_t *ppos) | 773 | size_t count, loff_t *ppos) |
755 | { | 774 | { |
@@ -759,7 +778,21 @@ static ssize_t intel_vgpu_read(struct mdev_device *mdev, char __user *buf, | |||
759 | while (count) { | 778 | while (count) { |
760 | size_t filled; | 779 | size_t filled; |
761 | 780 | ||
762 | if (count >= 4 && !(*ppos % 4)) { | 781 | /* Only support GGTT entry 8 bytes read */ |
782 | if (count >= 8 && !(*ppos % 8) && | ||
783 | gtt_entry(mdev, ppos)) { | ||
784 | u64 val; | ||
785 | |||
786 | ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val), | ||
787 | ppos, false); | ||
788 | if (ret <= 0) | ||
789 | goto read_err; | ||
790 | |||
791 | if (copy_to_user(buf, &val, sizeof(val))) | ||
792 | goto read_err; | ||
793 | |||
794 | filled = 8; | ||
795 | } else if (count >= 4 && !(*ppos % 4)) { | ||
763 | u32 val; | 796 | u32 val; |
764 | 797 | ||
765 | ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val), | 798 | ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val), |
@@ -819,7 +852,21 @@ static ssize_t intel_vgpu_write(struct mdev_device *mdev, | |||
819 | while (count) { | 852 | while (count) { |
820 | size_t filled; | 853 | size_t filled; |
821 | 854 | ||
822 | if (count >= 4 && !(*ppos % 4)) { | 855 | /* Only support GGTT entry 8 bytes write */ |
856 | if (count >= 8 && !(*ppos % 8) && | ||
857 | gtt_entry(mdev, ppos)) { | ||
858 | u64 val; | ||
859 | |||
860 | if (copy_from_user(&val, buf, sizeof(val))) | ||
861 | goto write_err; | ||
862 | |||
863 | ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val), | ||
864 | ppos, true); | ||
865 | if (ret <= 0) | ||
866 | goto write_err; | ||
867 | |||
868 | filled = 8; | ||
869 | } else if (count >= 4 && !(*ppos % 4)) { | ||
823 | u32 val; | 870 | u32 val; |
824 | 871 | ||
825 | if (copy_from_user(&val, buf, sizeof(val))) | 872 | if (copy_from_user(&val, buf, sizeof(val))) |
diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index 74a9c7b5516e..a5bac83d53a9 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c | |||
@@ -120,6 +120,7 @@ static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = { | |||
120 | {RCS, HALF_SLICE_CHICKEN3, 0xffff, true}, /* 0xe184 */ | 120 | {RCS, HALF_SLICE_CHICKEN3, 0xffff, true}, /* 0xe184 */ |
121 | {RCS, GEN9_HALF_SLICE_CHICKEN5, 0xffff, true}, /* 0xe188 */ | 121 | {RCS, GEN9_HALF_SLICE_CHICKEN5, 0xffff, true}, /* 0xe188 */ |
122 | {RCS, GEN9_HALF_SLICE_CHICKEN7, 0xffff, true}, /* 0xe194 */ | 122 | {RCS, GEN9_HALF_SLICE_CHICKEN7, 0xffff, true}, /* 0xe194 */ |
123 | {RCS, GEN8_ROW_CHICKEN, 0xffff, true}, /* 0xe4f0 */ | ||
123 | {RCS, TRVATTL3PTRDW(0), 0, false}, /* 0x4de0 */ | 124 | {RCS, TRVATTL3PTRDW(0), 0, false}, /* 0x4de0 */ |
124 | {RCS, TRVATTL3PTRDW(1), 0, false}, /* 0x4de4 */ | 125 | {RCS, TRVATTL3PTRDW(1), 0, false}, /* 0x4de4 */ |
125 | {RCS, TRNULLDETCT, 0, false}, /* 0x4de8 */ | 126 | {RCS, TRNULLDETCT, 0, false}, /* 0x4de8 */ |
@@ -557,9 +558,11 @@ void intel_gvt_switch_mmio(struct intel_vgpu *pre, | |||
557 | * performace for batch mmio read/write, so we need | 558 | * performace for batch mmio read/write, so we need |
558 | * handle forcewake mannually. | 559 | * handle forcewake mannually. |
559 | */ | 560 | */ |
561 | intel_runtime_pm_get(dev_priv); | ||
560 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); | 562 | intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); |
561 | switch_mmio(pre, next, ring_id); | 563 | switch_mmio(pre, next, ring_id); |
562 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); | 564 | intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); |
565 | intel_runtime_pm_put(dev_priv); | ||
563 | } | 566 | } |
564 | 567 | ||
565 | /** | 568 | /** |
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index a55b4975c154..638abe84857c 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c | |||
@@ -75,6 +75,54 @@ static void update_shadow_pdps(struct intel_vgpu_workload *workload) | |||
75 | kunmap(page); | 75 | kunmap(page); |
76 | } | 76 | } |
77 | 77 | ||
78 | /* | ||
79 | * when populating shadow ctx from guest, we should not overrride oa related | ||
80 | * registers, so that they will not be overlapped by guest oa configs. Thus | ||
81 | * made it possible to capture oa data from host for both host and guests. | ||
82 | */ | ||
83 | static void sr_oa_regs(struct intel_vgpu_workload *workload, | ||
84 | u32 *reg_state, bool save) | ||
85 | { | ||
86 | struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; | ||
87 | u32 ctx_oactxctrl = dev_priv->perf.oa.ctx_oactxctrl_offset; | ||
88 | u32 ctx_flexeu0 = dev_priv->perf.oa.ctx_flexeu0_offset; | ||
89 | int i = 0; | ||
90 | u32 flex_mmio[] = { | ||
91 | i915_mmio_reg_offset(EU_PERF_CNTL0), | ||
92 | i915_mmio_reg_offset(EU_PERF_CNTL1), | ||
93 | i915_mmio_reg_offset(EU_PERF_CNTL2), | ||
94 | i915_mmio_reg_offset(EU_PERF_CNTL3), | ||
95 | i915_mmio_reg_offset(EU_PERF_CNTL4), | ||
96 | i915_mmio_reg_offset(EU_PERF_CNTL5), | ||
97 | i915_mmio_reg_offset(EU_PERF_CNTL6), | ||
98 | }; | ||
99 | |||
100 | if (!workload || !reg_state || workload->ring_id != RCS) | ||
101 | return; | ||
102 | |||
103 | if (save) { | ||
104 | workload->oactxctrl = reg_state[ctx_oactxctrl + 1]; | ||
105 | |||
106 | for (i = 0; i < ARRAY_SIZE(workload->flex_mmio); i++) { | ||
107 | u32 state_offset = ctx_flexeu0 + i * 2; | ||
108 | |||
109 | workload->flex_mmio[i] = reg_state[state_offset + 1]; | ||
110 | } | ||
111 | } else { | ||
112 | reg_state[ctx_oactxctrl] = | ||
113 | i915_mmio_reg_offset(GEN8_OACTXCONTROL); | ||
114 | reg_state[ctx_oactxctrl + 1] = workload->oactxctrl; | ||
115 | |||
116 | for (i = 0; i < ARRAY_SIZE(workload->flex_mmio); i++) { | ||
117 | u32 state_offset = ctx_flexeu0 + i * 2; | ||
118 | u32 mmio = flex_mmio[i]; | ||
119 | |||
120 | reg_state[state_offset] = mmio; | ||
121 | reg_state[state_offset + 1] = workload->flex_mmio[i]; | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | |||
78 | static int populate_shadow_context(struct intel_vgpu_workload *workload) | 126 | static int populate_shadow_context(struct intel_vgpu_workload *workload) |
79 | { | 127 | { |
80 | struct intel_vgpu *vgpu = workload->vgpu; | 128 | struct intel_vgpu *vgpu = workload->vgpu; |
@@ -121,6 +169,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) | |||
121 | page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); | 169 | page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); |
122 | shadow_ring_context = kmap(page); | 170 | shadow_ring_context = kmap(page); |
123 | 171 | ||
172 | sr_oa_regs(workload, (u32 *)shadow_ring_context, true); | ||
124 | #define COPY_REG(name) \ | 173 | #define COPY_REG(name) \ |
125 | intel_gvt_hypervisor_read_gpa(vgpu, workload->ring_context_gpa \ | 174 | intel_gvt_hypervisor_read_gpa(vgpu, workload->ring_context_gpa \ |
126 | + RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4) | 175 | + RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4) |
@@ -149,6 +198,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) | |||
149 | sizeof(*shadow_ring_context), | 198 | sizeof(*shadow_ring_context), |
150 | I915_GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); | 199 | I915_GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); |
151 | 200 | ||
201 | sr_oa_regs(workload, (u32 *)shadow_ring_context, false); | ||
152 | kunmap(page); | 202 | kunmap(page); |
153 | return 0; | 203 | return 0; |
154 | } | 204 | } |
@@ -408,6 +458,17 @@ static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) | |||
408 | goto err; | 458 | goto err; |
409 | } | 459 | } |
410 | 460 | ||
461 | /* For privilge batch buffer and not wa_ctx, the bb_start_cmd_va | ||
462 | * is only updated into ring_scan_buffer, not real ring address | ||
463 | * allocated in later copy_workload_to_ring_buffer. pls be noted | ||
464 | * shadow_ring_buffer_va is now pointed to real ring buffer va | ||
465 | * in copy_workload_to_ring_buffer. | ||
466 | */ | ||
467 | |||
468 | if (bb->bb_offset) | ||
469 | bb->bb_start_cmd_va = workload->shadow_ring_buffer_va | ||
470 | + bb->bb_offset; | ||
471 | |||
411 | /* relocate shadow batch buffer */ | 472 | /* relocate shadow batch buffer */ |
412 | bb->bb_start_cmd_va[1] = i915_ggtt_offset(bb->vma); | 473 | bb->bb_start_cmd_va[1] = i915_ggtt_offset(bb->vma); |
413 | if (gmadr_bytes == 8) | 474 | if (gmadr_bytes == 8) |
@@ -1078,10 +1139,12 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu) | |||
1078 | 1139 | ||
1079 | bitmap_zero(s->shadow_ctx_desc_updated, I915_NUM_ENGINES); | 1140 | bitmap_zero(s->shadow_ctx_desc_updated, I915_NUM_ENGINES); |
1080 | 1141 | ||
1081 | s->workloads = kmem_cache_create("gvt-g_vgpu_workload", | 1142 | s->workloads = kmem_cache_create_usercopy("gvt-g_vgpu_workload", |
1082 | sizeof(struct intel_vgpu_workload), 0, | 1143 | sizeof(struct intel_vgpu_workload), 0, |
1083 | SLAB_HWCACHE_ALIGN, | 1144 | SLAB_HWCACHE_ALIGN, |
1084 | NULL); | 1145 | offsetof(struct intel_vgpu_workload, rb_tail), |
1146 | sizeof_field(struct intel_vgpu_workload, rb_tail), | ||
1147 | NULL); | ||
1085 | 1148 | ||
1086 | if (!s->workloads) { | 1149 | if (!s->workloads) { |
1087 | ret = -ENOMEM; | 1150 | ret = -ENOMEM; |
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index bab4097aa6d7..486ed57a4ad1 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/gvt/trace.h b/drivers/gpu/drm/i915/gvt/trace.h index fc7831a62121..82093f1e8612 100644 --- a/drivers/gpu/drm/i915/gvt/trace.h +++ b/drivers/gpu/drm/i915/gvt/trace.h | |||
@@ -333,7 +333,7 @@ TRACE_EVENT(render_mmio, | |||
333 | TP_PROTO(int old_id, int new_id, char *action, unsigned int reg, | 333 | TP_PROTO(int old_id, int new_id, char *action, unsigned int reg, |
334 | unsigned int old_val, unsigned int new_val), | 334 | unsigned int old_val, unsigned int new_val), |
335 | 335 | ||
336 | TP_ARGS(old_id, new_id, action, reg, new_val, old_val), | 336 | TP_ARGS(old_id, new_id, action, reg, old_val, new_val), |
337 | 337 | ||
338 | TP_STRUCT__entry( | 338 | TP_STRUCT__entry( |
339 | __field(int, old_id) | 339 | __field(int, old_id) |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0359d6f870b4..7b5a9d7c9593 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -433,20 +433,28 @@ i915_gem_object_wait_reservation(struct reservation_object *resv, | |||
433 | dma_fence_put(shared[i]); | 433 | dma_fence_put(shared[i]); |
434 | kfree(shared); | 434 | kfree(shared); |
435 | 435 | ||
436 | /* | ||
437 | * If both shared fences and an exclusive fence exist, | ||
438 | * then by construction the shared fences must be later | ||
439 | * than the exclusive fence. If we successfully wait for | ||
440 | * all the shared fences, we know that the exclusive fence | ||
441 | * must all be signaled. If all the shared fences are | ||
442 | * signaled, we can prune the array and recover the | ||
443 | * floating references on the fences/requests. | ||
444 | */ | ||
436 | prune_fences = count && timeout >= 0; | 445 | prune_fences = count && timeout >= 0; |
437 | } else { | 446 | } else { |
438 | excl = reservation_object_get_excl_rcu(resv); | 447 | excl = reservation_object_get_excl_rcu(resv); |
439 | } | 448 | } |
440 | 449 | ||
441 | if (excl && timeout >= 0) { | 450 | if (excl && timeout >= 0) |
442 | timeout = i915_gem_object_wait_fence(excl, flags, timeout, | 451 | timeout = i915_gem_object_wait_fence(excl, flags, timeout, |
443 | rps_client); | 452 | rps_client); |
444 | prune_fences = timeout >= 0; | ||
445 | } | ||
446 | 453 | ||
447 | dma_fence_put(excl); | 454 | dma_fence_put(excl); |
448 | 455 | ||
449 | /* Oportunistically prune the fences iff we know they have *all* been | 456 | /* |
457 | * Opportunistically prune the fences iff we know they have *all* been | ||
450 | * signaled and that the reservation object has not been changed (i.e. | 458 | * signaled and that the reservation object has not been changed (i.e. |
451 | * no new fences have been added). | 459 | * no new fences have been added). |
452 | */ | 460 | */ |
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 dbcf1a0586f9..8c2d778560f0 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -2205,8 +2205,7 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, | |||
2205 | intel_prepare_dp_ddi_buffers(encoder, crtc_state); | 2205 | intel_prepare_dp_ddi_buffers(encoder, crtc_state); |
2206 | 2206 | ||
2207 | intel_ddi_init_dp_buf_reg(encoder); | 2207 | intel_ddi_init_dp_buf_reg(encoder); |
2208 | if (!is_mst) | 2208 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); |
2209 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); | ||
2210 | intel_dp_start_link_train(intel_dp); | 2209 | intel_dp_start_link_train(intel_dp); |
2211 | if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) | 2210 | if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) |
2212 | intel_dp_stop_link_train(intel_dp); | 2211 | intel_dp_stop_link_train(intel_dp); |
@@ -2304,14 +2303,12 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, | |||
2304 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 2303 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
2305 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); | 2304 | struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); |
2306 | struct intel_dp *intel_dp = &dig_port->dp; | 2305 | struct intel_dp *intel_dp = &dig_port->dp; |
2307 | bool is_mst = intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST); | ||
2308 | 2306 | ||
2309 | /* | 2307 | /* |
2310 | * Power down sink before disabling the port, otherwise we end | 2308 | * Power down sink before disabling the port, otherwise we end |
2311 | * up getting interrupts from the sink on detecting link loss. | 2309 | * up getting interrupts from the sink on detecting link loss. |
2312 | */ | 2310 | */ |
2313 | if (!is_mst) | 2311 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); |
2314 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); | ||
2315 | 2312 | ||
2316 | intel_disable_ddi_buf(encoder); | 2313 | intel_disable_ddi_buf(encoder); |
2317 | 2314 | ||
diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c index 42e45ae87393..c8ea510629fa 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/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 d7e3583e608e..203f247d4854 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/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c index 5155f0179b61..05520202c967 100644 --- a/drivers/gpu/drm/meson/meson_crtc.c +++ b/drivers/gpu/drm/meson/meson_crtc.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "meson_venc.h" | 36 | #include "meson_venc.h" |
37 | #include "meson_vpp.h" | 37 | #include "meson_vpp.h" |
38 | #include "meson_viu.h" | 38 | #include "meson_viu.h" |
39 | #include "meson_canvas.h" | ||
39 | #include "meson_registers.h" | 40 | #include "meson_registers.h" |
40 | 41 | ||
41 | /* CRTC definition */ | 42 | /* CRTC definition */ |
@@ -192,6 +193,11 @@ void meson_crtc_irq(struct meson_drm *priv) | |||
192 | } else | 193 | } else |
193 | meson_vpp_disable_interlace_vscaler_osd1(priv); | 194 | meson_vpp_disable_interlace_vscaler_osd1(priv); |
194 | 195 | ||
196 | meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1, | ||
197 | priv->viu.osd1_addr, priv->viu.osd1_stride, | ||
198 | priv->viu.osd1_height, MESON_CANVAS_WRAP_NONE, | ||
199 | MESON_CANVAS_BLKMODE_LINEAR); | ||
200 | |||
195 | /* Enable OSD1 */ | 201 | /* Enable OSD1 */ |
196 | writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND, | 202 | writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND, |
197 | priv->io_base + _REG(VPP_MISC)); | 203 | priv->io_base + _REG(VPP_MISC)); |
diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h index 5e8b392b9d1f..8450d6ac8c9b 100644 --- a/drivers/gpu/drm/meson/meson_drv.h +++ b/drivers/gpu/drm/meson/meson_drv.h | |||
@@ -43,6 +43,9 @@ struct meson_drm { | |||
43 | bool osd1_commit; | 43 | bool osd1_commit; |
44 | uint32_t osd1_ctrl_stat; | 44 | uint32_t osd1_ctrl_stat; |
45 | uint32_t osd1_blk0_cfg[5]; | 45 | uint32_t osd1_blk0_cfg[5]; |
46 | uint32_t osd1_addr; | ||
47 | uint32_t osd1_stride; | ||
48 | uint32_t osd1_height; | ||
46 | } viu; | 49 | } viu; |
47 | 50 | ||
48 | struct { | 51 | struct { |
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index c78a3a59f58c..12c80dfcff59 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c | |||
@@ -160,10 +160,9 @@ static void meson_plane_atomic_update(struct drm_plane *plane, | |||
160 | /* Update Canvas with buffer address */ | 160 | /* Update Canvas with buffer address */ |
161 | gem = drm_fb_cma_get_gem_obj(fb, 0); | 161 | gem = drm_fb_cma_get_gem_obj(fb, 0); |
162 | 162 | ||
163 | meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1, | 163 | priv->viu.osd1_addr = gem->paddr; |
164 | gem->paddr, fb->pitches[0], | 164 | priv->viu.osd1_stride = fb->pitches[0]; |
165 | fb->height, MESON_CANVAS_WRAP_NONE, | 165 | priv->viu.osd1_height = fb->height; |
166 | MESON_CANVAS_BLKMODE_LINEAR); | ||
167 | 166 | ||
168 | spin_unlock_irqrestore(&priv->drm->event_lock, flags); | 167 | spin_unlock_irqrestore(&priv->drm->event_lock, flags); |
169 | } | 168 | } |
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/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 69d6e61a01ec..6ed9cb053dfa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -570,9 +570,15 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
570 | nv_connector->edid = NULL; | 570 | nv_connector->edid = NULL; |
571 | } | 571 | } |
572 | 572 | ||
573 | ret = pm_runtime_get_sync(connector->dev->dev); | 573 | /* Outputs are only polled while runtime active, so acquiring a |
574 | if (ret < 0 && ret != -EACCES) | 574 | * runtime PM ref here is unnecessary (and would deadlock upon |
575 | return conn_status; | 575 | * runtime suspend because it waits for polling to finish). |
576 | */ | ||
577 | if (!drm_kms_helper_is_poll_worker()) { | ||
578 | ret = pm_runtime_get_sync(connector->dev->dev); | ||
579 | if (ret < 0 && ret != -EACCES) | ||
580 | return conn_status; | ||
581 | } | ||
576 | 582 | ||
577 | nv_encoder = nouveau_connector_ddc_detect(connector); | 583 | nv_encoder = nouveau_connector_ddc_detect(connector); |
578 | if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { | 584 | if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { |
@@ -647,8 +653,10 @@ detect_analog: | |||
647 | 653 | ||
648 | out: | 654 | out: |
649 | 655 | ||
650 | pm_runtime_mark_last_busy(connector->dev->dev); | 656 | if (!drm_kms_helper_is_poll_worker()) { |
651 | pm_runtime_put_autosuspend(connector->dev->dev); | 657 | pm_runtime_mark_last_busy(connector->dev->dev); |
658 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
659 | } | ||
652 | 660 | ||
653 | return conn_status; | 661 | return conn_status; |
654 | } | 662 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 6af3bc483c84..8bd739cfd00d 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -4469,6 +4469,7 @@ nv50_display_create(struct drm_device *dev) | |||
4469 | nouveau_display(dev)->fini = nv50_display_fini; | 4469 | nouveau_display(dev)->fini = nv50_display_fini; |
4470 | disp->disp = &nouveau_display(dev)->disp; | 4470 | disp->disp = &nouveau_display(dev)->disp; |
4471 | dev->mode_config.funcs = &nv50_disp_func; | 4471 | dev->mode_config.funcs = &nv50_disp_func; |
4472 | dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP; | ||
4472 | if (nouveau_atomic) | 4473 | if (nouveau_atomic) |
4473 | dev->driver->driver_features |= DRIVER_ATOMIC; | 4474 | dev->driver->driver_features |= DRIVER_ATOMIC; |
4474 | 4475 | ||
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/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index bf62303571b3..3695cde669f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c | |||
@@ -301,7 +301,7 @@ nvkm_therm_attr_set(struct nvkm_therm *therm, | |||
301 | void | 301 | void |
302 | nvkm_therm_clkgate_enable(struct nvkm_therm *therm) | 302 | nvkm_therm_clkgate_enable(struct nvkm_therm *therm) |
303 | { | 303 | { |
304 | if (!therm->func->clkgate_enable || !therm->clkgating_enabled) | 304 | if (!therm || !therm->func->clkgate_enable || !therm->clkgating_enabled) |
305 | return; | 305 | return; |
306 | 306 | ||
307 | nvkm_debug(&therm->subdev, | 307 | nvkm_debug(&therm->subdev, |
@@ -312,7 +312,7 @@ nvkm_therm_clkgate_enable(struct nvkm_therm *therm) | |||
312 | void | 312 | void |
313 | nvkm_therm_clkgate_fini(struct nvkm_therm *therm, bool suspend) | 313 | nvkm_therm_clkgate_fini(struct nvkm_therm *therm, bool suspend) |
314 | { | 314 | { |
315 | if (!therm->func->clkgate_fini || !therm->clkgating_enabled) | 315 | if (!therm || !therm->func->clkgate_fini || !therm->clkgating_enabled) |
316 | return; | 316 | return; |
317 | 317 | ||
318 | nvkm_debug(&therm->subdev, | 318 | nvkm_debug(&therm->subdev, |
@@ -395,7 +395,7 @@ void | |||
395 | nvkm_therm_clkgate_init(struct nvkm_therm *therm, | 395 | nvkm_therm_clkgate_init(struct nvkm_therm *therm, |
396 | const struct nvkm_therm_clkgate_pack *p) | 396 | const struct nvkm_therm_clkgate_pack *p) |
397 | { | 397 | { |
398 | if (!therm->func->clkgate_init || !therm->clkgating_enabled) | 398 | if (!therm || !therm->func->clkgate_init || !therm->clkgating_enabled) |
399 | return; | 399 | return; |
400 | 400 | ||
401 | therm->func->clkgate_init(therm, p); | 401 | therm->func->clkgate_init(therm, p); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index b108eaabb6df..df9469a8fdb1 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
@@ -892,9 +892,11 @@ radeon_lvds_detect(struct drm_connector *connector, bool force) | |||
892 | enum drm_connector_status ret = connector_status_disconnected; | 892 | enum drm_connector_status ret = connector_status_disconnected; |
893 | int r; | 893 | int r; |
894 | 894 | ||
895 | r = pm_runtime_get_sync(connector->dev->dev); | 895 | if (!drm_kms_helper_is_poll_worker()) { |
896 | if (r < 0) | 896 | r = pm_runtime_get_sync(connector->dev->dev); |
897 | return connector_status_disconnected; | 897 | if (r < 0) |
898 | return connector_status_disconnected; | ||
899 | } | ||
898 | 900 | ||
899 | if (encoder) { | 901 | if (encoder) { |
900 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 902 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
@@ -917,8 +919,12 @@ radeon_lvds_detect(struct drm_connector *connector, bool force) | |||
917 | /* check acpi lid status ??? */ | 919 | /* check acpi lid status ??? */ |
918 | 920 | ||
919 | radeon_connector_update_scratch_regs(connector, ret); | 921 | radeon_connector_update_scratch_regs(connector, ret); |
920 | pm_runtime_mark_last_busy(connector->dev->dev); | 922 | |
921 | pm_runtime_put_autosuspend(connector->dev->dev); | 923 | if (!drm_kms_helper_is_poll_worker()) { |
924 | pm_runtime_mark_last_busy(connector->dev->dev); | ||
925 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
926 | } | ||
927 | |||
922 | return ret; | 928 | return ret; |
923 | } | 929 | } |
924 | 930 | ||
@@ -1032,9 +1038,11 @@ radeon_vga_detect(struct drm_connector *connector, bool force) | |||
1032 | enum drm_connector_status ret = connector_status_disconnected; | 1038 | enum drm_connector_status ret = connector_status_disconnected; |
1033 | int r; | 1039 | int r; |
1034 | 1040 | ||
1035 | r = pm_runtime_get_sync(connector->dev->dev); | 1041 | if (!drm_kms_helper_is_poll_worker()) { |
1036 | if (r < 0) | 1042 | r = pm_runtime_get_sync(connector->dev->dev); |
1037 | return connector_status_disconnected; | 1043 | if (r < 0) |
1044 | return connector_status_disconnected; | ||
1045 | } | ||
1038 | 1046 | ||
1039 | encoder = radeon_best_single_encoder(connector); | 1047 | encoder = radeon_best_single_encoder(connector); |
1040 | if (!encoder) | 1048 | if (!encoder) |
@@ -1101,8 +1109,10 @@ radeon_vga_detect(struct drm_connector *connector, bool force) | |||
1101 | radeon_connector_update_scratch_regs(connector, ret); | 1109 | radeon_connector_update_scratch_regs(connector, ret); |
1102 | 1110 | ||
1103 | out: | 1111 | out: |
1104 | pm_runtime_mark_last_busy(connector->dev->dev); | 1112 | if (!drm_kms_helper_is_poll_worker()) { |
1105 | pm_runtime_put_autosuspend(connector->dev->dev); | 1113 | pm_runtime_mark_last_busy(connector->dev->dev); |
1114 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
1115 | } | ||
1106 | 1116 | ||
1107 | return ret; | 1117 | return ret; |
1108 | } | 1118 | } |
@@ -1166,9 +1176,11 @@ radeon_tv_detect(struct drm_connector *connector, bool force) | |||
1166 | if (!radeon_connector->dac_load_detect) | 1176 | if (!radeon_connector->dac_load_detect) |
1167 | return ret; | 1177 | return ret; |
1168 | 1178 | ||
1169 | r = pm_runtime_get_sync(connector->dev->dev); | 1179 | if (!drm_kms_helper_is_poll_worker()) { |
1170 | if (r < 0) | 1180 | r = pm_runtime_get_sync(connector->dev->dev); |
1171 | return connector_status_disconnected; | 1181 | if (r < 0) |
1182 | return connector_status_disconnected; | ||
1183 | } | ||
1172 | 1184 | ||
1173 | encoder = radeon_best_single_encoder(connector); | 1185 | encoder = radeon_best_single_encoder(connector); |
1174 | if (!encoder) | 1186 | if (!encoder) |
@@ -1180,8 +1192,12 @@ radeon_tv_detect(struct drm_connector *connector, bool force) | |||
1180 | if (ret == connector_status_connected) | 1192 | if (ret == connector_status_connected) |
1181 | ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); | 1193 | ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); |
1182 | radeon_connector_update_scratch_regs(connector, ret); | 1194 | radeon_connector_update_scratch_regs(connector, ret); |
1183 | pm_runtime_mark_last_busy(connector->dev->dev); | 1195 | |
1184 | pm_runtime_put_autosuspend(connector->dev->dev); | 1196 | if (!drm_kms_helper_is_poll_worker()) { |
1197 | pm_runtime_mark_last_busy(connector->dev->dev); | ||
1198 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
1199 | } | ||
1200 | |||
1185 | return ret; | 1201 | return ret; |
1186 | } | 1202 | } |
1187 | 1203 | ||
@@ -1244,9 +1260,11 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) | |||
1244 | enum drm_connector_status ret = connector_status_disconnected; | 1260 | enum drm_connector_status ret = connector_status_disconnected; |
1245 | bool dret = false, broken_edid = false; | 1261 | bool dret = false, broken_edid = false; |
1246 | 1262 | ||
1247 | r = pm_runtime_get_sync(connector->dev->dev); | 1263 | if (!drm_kms_helper_is_poll_worker()) { |
1248 | if (r < 0) | 1264 | r = pm_runtime_get_sync(connector->dev->dev); |
1249 | return connector_status_disconnected; | 1265 | if (r < 0) |
1266 | return connector_status_disconnected; | ||
1267 | } | ||
1250 | 1268 | ||
1251 | if (radeon_connector->detected_hpd_without_ddc) { | 1269 | if (radeon_connector->detected_hpd_without_ddc) { |
1252 | force = true; | 1270 | force = true; |
@@ -1429,8 +1447,10 @@ out: | |||
1429 | } | 1447 | } |
1430 | 1448 | ||
1431 | exit: | 1449 | exit: |
1432 | pm_runtime_mark_last_busy(connector->dev->dev); | 1450 | if (!drm_kms_helper_is_poll_worker()) { |
1433 | pm_runtime_put_autosuspend(connector->dev->dev); | 1451 | pm_runtime_mark_last_busy(connector->dev->dev); |
1452 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
1453 | } | ||
1434 | 1454 | ||
1435 | return ret; | 1455 | return ret; |
1436 | } | 1456 | } |
@@ -1681,9 +1701,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force) | |||
1681 | if (radeon_dig_connector->is_mst) | 1701 | if (radeon_dig_connector->is_mst) |
1682 | return connector_status_disconnected; | 1702 | return connector_status_disconnected; |
1683 | 1703 | ||
1684 | r = pm_runtime_get_sync(connector->dev->dev); | 1704 | if (!drm_kms_helper_is_poll_worker()) { |
1685 | if (r < 0) | 1705 | r = pm_runtime_get_sync(connector->dev->dev); |
1686 | return connector_status_disconnected; | 1706 | if (r < 0) |
1707 | return connector_status_disconnected; | ||
1708 | } | ||
1687 | 1709 | ||
1688 | if (!force && radeon_check_hpd_status_unchanged(connector)) { | 1710 | if (!force && radeon_check_hpd_status_unchanged(connector)) { |
1689 | ret = connector->status; | 1711 | ret = connector->status; |
@@ -1770,8 +1792,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force) | |||
1770 | } | 1792 | } |
1771 | 1793 | ||
1772 | out: | 1794 | out: |
1773 | pm_runtime_mark_last_busy(connector->dev->dev); | 1795 | if (!drm_kms_helper_is_poll_worker()) { |
1774 | pm_runtime_put_autosuspend(connector->dev->dev); | 1796 | pm_runtime_mark_last_busy(connector->dev->dev); |
1797 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
1798 | } | ||
1775 | 1799 | ||
1776 | return ret; | 1800 | return ret; |
1777 | } | 1801 | } |
diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 3b2d11b675e8..2d7c57406715 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c | |||
@@ -111,6 +111,8 @@ static void sun4i_crtc_atomic_disable(struct drm_crtc *crtc, | |||
111 | 111 | ||
112 | DRM_DEBUG_DRIVER("Disabling the CRTC\n"); | 112 | DRM_DEBUG_DRIVER("Disabling the CRTC\n"); |
113 | 113 | ||
114 | drm_crtc_vblank_off(crtc); | ||
115 | |||
114 | sun4i_tcon_set_status(scrtc->tcon, encoder, false); | 116 | sun4i_tcon_set_status(scrtc->tcon, encoder, false); |
115 | 117 | ||
116 | if (crtc->state->event && !crtc->state->active) { | 118 | if (crtc->state->event && !crtc->state->active) { |
@@ -131,6 +133,8 @@ static void sun4i_crtc_atomic_enable(struct drm_crtc *crtc, | |||
131 | DRM_DEBUG_DRIVER("Enabling the CRTC\n"); | 133 | DRM_DEBUG_DRIVER("Enabling the CRTC\n"); |
132 | 134 | ||
133 | sun4i_tcon_set_status(scrtc->tcon, encoder, true); | 135 | sun4i_tcon_set_status(scrtc->tcon, encoder, true); |
136 | |||
137 | drm_crtc_vblank_on(crtc); | ||
134 | } | 138 | } |
135 | 139 | ||
136 | static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc) | 140 | 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 7f0705ef9f4e..50d19605c38f 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c | |||
@@ -113,7 +113,7 @@ static int sun4i_drv_bind(struct device *dev) | |||
113 | /* drm_vblank_init calls kcalloc, which can fail */ | 113 | /* drm_vblank_init calls kcalloc, which can fail */ |
114 | ret = drm_vblank_init(drm, drm->mode_config.num_crtc); | 114 | ret = drm_vblank_init(drm, drm->mode_config.num_crtc); |
115 | if (ret) | 115 | if (ret) |
116 | goto free_mem_region; | 116 | goto cleanup_mode_config; |
117 | 117 | ||
118 | drm->irq_enabled = true; | 118 | drm->irq_enabled = true; |
119 | 119 | ||
@@ -141,7 +141,6 @@ finish_poll: | |||
141 | sun4i_framebuffer_free(drm); | 141 | sun4i_framebuffer_free(drm); |
142 | cleanup_mode_config: | 142 | cleanup_mode_config: |
143 | drm_mode_config_cleanup(drm); | 143 | drm_mode_config_cleanup(drm); |
144 | free_mem_region: | ||
145 | of_reserved_mem_device_release(dev); | 144 | of_reserved_mem_device_release(dev); |
146 | free_drm: | 145 | free_drm: |
147 | drm_dev_unref(drm); | 146 | 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 a2a697a099e6..f2fa1f210509 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c | |||
@@ -92,6 +92,8 @@ static enum drm_mode_status sun4i_rgb_mode_valid(struct drm_encoder *crtc, | |||
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 1a114e380f13..c3d92d537240 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c | |||
@@ -103,10 +103,13 @@ static void sun4i_tcon_channel_set_status(struct sun4i_tcon *tcon, int channel, | |||
103 | return; | 103 | return; |
104 | } | 104 | } |
105 | 105 | ||
106 | if (enabled) | 106 | if (enabled) { |
107 | clk_prepare_enable(clk); | 107 | clk_prepare_enable(clk); |
108 | else | 108 | clk_rate_exclusive_get(clk); |
109 | } else { | ||
110 | clk_rate_exclusive_put(clk); | ||
109 | clk_disable_unprepare(clk); | 111 | clk_disable_unprepare(clk); |
112 | } | ||
110 | } | 113 | } |
111 | 114 | ||
112 | static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, | 115 | static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon, |
@@ -339,6 +342,9 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, | |||
339 | regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, | 342 | regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG, |
340 | SUN4I_TCON_GCTL_IOMAP_MASK, | 343 | SUN4I_TCON_GCTL_IOMAP_MASK, |
341 | SUN4I_TCON_GCTL_IOMAP_TCON0); | 344 | SUN4I_TCON_GCTL_IOMAP_TCON0); |
345 | |||
346 | /* Enable the output on the pins */ | ||
347 | regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000); | ||
342 | } | 348 | } |
343 | 349 | ||
344 | static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, | 350 | static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, |
@@ -921,52 +927,56 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, | |||
921 | return ret; | 927 | return ret; |
922 | } | 928 | } |
923 | 929 | ||
924 | /* | 930 | if (tcon->quirks->supports_lvds) { |
925 | * This can only be made optional since we've had DT nodes | 931 | /* |
926 | * without the LVDS reset properties. | 932 | * This can only be made optional since we've had DT |
927 | * | 933 | * nodes without the LVDS reset properties. |
928 | * If the property is missing, just disable LVDS, and print a | 934 | * |
929 | * warning. | 935 | * If the property is missing, just disable LVDS, and |
930 | */ | 936 | * print a warning. |
931 | tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds"); | 937 | */ |
932 | if (IS_ERR(tcon->lvds_rst)) { | 938 | tcon->lvds_rst = devm_reset_control_get_optional(dev, "lvds"); |
933 | dev_err(dev, "Couldn't get our reset line\n"); | 939 | if (IS_ERR(tcon->lvds_rst)) { |
934 | return PTR_ERR(tcon->lvds_rst); | 940 | dev_err(dev, "Couldn't get our reset line\n"); |
935 | } else if (tcon->lvds_rst) { | 941 | return PTR_ERR(tcon->lvds_rst); |
936 | has_lvds_rst = true; | 942 | } else if (tcon->lvds_rst) { |
937 | reset_control_reset(tcon->lvds_rst); | 943 | has_lvds_rst = true; |
938 | } else { | 944 | reset_control_reset(tcon->lvds_rst); |
939 | has_lvds_rst = false; | 945 | } else { |
940 | } | 946 | has_lvds_rst = false; |
947 | } | ||
941 | 948 | ||
942 | /* | 949 | /* |
943 | * This can only be made optional since we've had DT nodes | 950 | * This can only be made optional since we've had DT |
944 | * without the LVDS reset properties. | 951 | * nodes without the LVDS reset properties. |
945 | * | 952 | * |
946 | * If the property is missing, just disable LVDS, and print a | 953 | * If the property is missing, just disable LVDS, and |
947 | * warning. | 954 | * print a warning. |
948 | */ | 955 | */ |
949 | if (tcon->quirks->has_lvds_alt) { | 956 | if (tcon->quirks->has_lvds_alt) { |
950 | tcon->lvds_pll = devm_clk_get(dev, "lvds-alt"); | 957 | tcon->lvds_pll = devm_clk_get(dev, "lvds-alt"); |
951 | if (IS_ERR(tcon->lvds_pll)) { | 958 | if (IS_ERR(tcon->lvds_pll)) { |
952 | if (PTR_ERR(tcon->lvds_pll) == -ENOENT) { | 959 | if (PTR_ERR(tcon->lvds_pll) == -ENOENT) { |
953 | has_lvds_alt = false; | 960 | has_lvds_alt = false; |
961 | } else { | ||
962 | dev_err(dev, "Couldn't get the LVDS PLL\n"); | ||
963 | return PTR_ERR(tcon->lvds_pll); | ||
964 | } | ||
954 | } else { | 965 | } else { |
955 | dev_err(dev, "Couldn't get the LVDS PLL\n"); | 966 | has_lvds_alt = true; |
956 | return PTR_ERR(tcon->lvds_pll); | ||
957 | } | 967 | } |
958 | } else { | ||
959 | has_lvds_alt = true; | ||
960 | } | 968 | } |
961 | } | ||
962 | 969 | ||
963 | if (!has_lvds_rst || (tcon->quirks->has_lvds_alt && !has_lvds_alt)) { | 970 | if (!has_lvds_rst || |
964 | dev_warn(dev, | 971 | (tcon->quirks->has_lvds_alt && !has_lvds_alt)) { |
965 | "Missing LVDS properties, Please upgrade your DT\n"); | 972 | dev_warn(dev, "Missing LVDS properties, Please upgrade your DT\n"); |
966 | dev_warn(dev, "LVDS output disabled\n"); | 973 | dev_warn(dev, "LVDS output disabled\n"); |
967 | can_lvds = false; | 974 | can_lvds = false; |
975 | } else { | ||
976 | can_lvds = true; | ||
977 | } | ||
968 | } else { | 978 | } else { |
969 | can_lvds = true; | 979 | can_lvds = false; |
970 | } | 980 | } |
971 | 981 | ||
972 | ret = sun4i_tcon_init_clocks(dev, tcon); | 982 | ret = sun4i_tcon_init_clocks(dev, tcon); |
@@ -1195,6 +1205,7 @@ static const struct sun4i_tcon_quirks sun8i_a33_quirks = { | |||
1195 | }; | 1205 | }; |
1196 | 1206 | ||
1197 | static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { | 1207 | static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = { |
1208 | .supports_lvds = true, | ||
1198 | .has_channel_0 = true, | 1209 | .has_channel_0 = true, |
1199 | }; | 1210 | }; |
1200 | 1211 | ||
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h index d3a945b7bb60..161e09427124 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.h +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h | |||
@@ -177,6 +177,7 @@ struct sun4i_tcon_quirks { | |||
177 | bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */ | 177 | bool has_lvds_alt; /* Does the LVDS clock have a parent other than the TCON clock? */ |
178 | bool needs_de_be_mux; /* sun6i needs mux to select backend */ | 178 | bool needs_de_be_mux; /* sun6i needs mux to select backend */ |
179 | bool needs_edp_reset; /* a80 edp reset needed for tcon0 access */ | 179 | bool needs_edp_reset; /* a80 edp reset needed for tcon0 access */ |
180 | bool supports_lvds; /* Does the TCON support an LVDS output? */ | ||
180 | 181 | ||
181 | /* callback to handle tcon muxing options */ | 182 | /* callback to handle tcon muxing options */ |
182 | int (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *); | 183 | 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 71152776b04c..616c9634585e 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -1916,8 +1916,12 @@ cleanup: | |||
1916 | if (!IS_ERR(primary)) | 1916 | if (!IS_ERR(primary)) |
1917 | drm_plane_cleanup(primary); | 1917 | drm_plane_cleanup(primary); |
1918 | 1918 | ||
1919 | if (group && tegra->domain) { | 1919 | if (group && dc->domain) { |
1920 | iommu_detach_group(tegra->domain, group); | 1920 | if (group == tegra->group) { |
1921 | iommu_detach_group(dc->domain, group); | ||
1922 | tegra->group = NULL; | ||
1923 | } | ||
1924 | |||
1921 | dc->domain = NULL; | 1925 | dc->domain = NULL; |
1922 | } | 1926 | } |
1923 | 1927 | ||
@@ -1926,8 +1930,10 @@ cleanup: | |||
1926 | 1930 | ||
1927 | static int tegra_dc_exit(struct host1x_client *client) | 1931 | static int tegra_dc_exit(struct host1x_client *client) |
1928 | { | 1932 | { |
1933 | struct drm_device *drm = dev_get_drvdata(client->parent); | ||
1929 | struct iommu_group *group = iommu_group_get(client->dev); | 1934 | struct iommu_group *group = iommu_group_get(client->dev); |
1930 | struct tegra_dc *dc = host1x_client_to_dc(client); | 1935 | struct tegra_dc *dc = host1x_client_to_dc(client); |
1936 | struct tegra_drm *tegra = drm->dev_private; | ||
1931 | int err; | 1937 | int err; |
1932 | 1938 | ||
1933 | devm_free_irq(dc->dev, dc->irq, dc); | 1939 | devm_free_irq(dc->dev, dc->irq, dc); |
@@ -1939,7 +1945,11 @@ static int tegra_dc_exit(struct host1x_client *client) | |||
1939 | } | 1945 | } |
1940 | 1946 | ||
1941 | if (group && dc->domain) { | 1947 | if (group && dc->domain) { |
1942 | iommu_detach_group(dc->domain, group); | 1948 | if (group == tegra->group) { |
1949 | iommu_detach_group(dc->domain, group); | ||
1950 | tegra->group = NULL; | ||
1951 | } | ||
1952 | |||
1943 | dc->domain = NULL; | 1953 | dc->domain = NULL; |
1944 | } | 1954 | } |
1945 | 1955 | ||
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index e20e013151f0..7afe2f635f74 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
@@ -222,6 +222,7 @@ static void tegra_drm_unload(struct drm_device *drm) | |||
222 | 222 | ||
223 | drm_kms_helper_poll_fini(drm); | 223 | drm_kms_helper_poll_fini(drm); |
224 | tegra_drm_fb_exit(drm); | 224 | tegra_drm_fb_exit(drm); |
225 | drm_atomic_helper_shutdown(drm); | ||
225 | drm_mode_config_cleanup(drm); | 226 | drm_mode_config_cleanup(drm); |
226 | 227 | ||
227 | err = host1x_device_exit(device); | 228 | 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 6d6e2d0091eb..176ef46c615c 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c | |||
@@ -307,6 +307,10 @@ int tegra_plane_format_get_alpha(unsigned int opaque, unsigned int *alpha) | |||
307 | case WIN_COLOR_DEPTH_B8G8R8X8: | 307 | case WIN_COLOR_DEPTH_B8G8R8X8: |
308 | *alpha = WIN_COLOR_DEPTH_B8G8R8A8; | 308 | *alpha = WIN_COLOR_DEPTH_B8G8R8A8; |
309 | return 0; | 309 | return 0; |
310 | |||
311 | case WIN_COLOR_DEPTH_B5G6R5: | ||
312 | *alpha = opaque; | ||
313 | return 0; | ||
310 | } | 314 | } |
311 | 315 | ||
312 | return -EINVAL; | 316 | return -EINVAL; |
@@ -340,9 +344,6 @@ void tegra_plane_check_dependent(struct tegra_plane *tegra, | |||
340 | unsigned int zpos[2]; | 344 | unsigned int zpos[2]; |
341 | unsigned int i; | 345 | unsigned int i; |
342 | 346 | ||
343 | for (i = 0; i < 3; i++) | ||
344 | state->dependent[i] = false; | ||
345 | |||
346 | for (i = 0; i < 2; i++) | 347 | for (i = 0; i < 2; i++) |
347 | zpos[i] = 0; | 348 | zpos[i] = 0; |
348 | 349 | ||
@@ -356,6 +357,8 @@ void tegra_plane_check_dependent(struct tegra_plane *tegra, | |||
356 | 357 | ||
357 | index = tegra_plane_get_overlap_index(tegra, p); | 358 | index = tegra_plane_get_overlap_index(tegra, p); |
358 | 359 | ||
360 | state->dependent[index] = false; | ||
361 | |||
359 | /* | 362 | /* |
360 | * If any of the other planes is on top of this plane and uses | 363 | * If any of the other planes is on top of this plane and uses |
361 | * a format with an alpha component, mark this plane as being | 364 | * 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/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index a14e8a2ec682..7bdf6f0e58a5 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c | |||
@@ -198,6 +198,9 @@ static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data, | |||
198 | case VIRTGPU_PARAM_3D_FEATURES: | 198 | case VIRTGPU_PARAM_3D_FEATURES: |
199 | value = vgdev->has_virgl_3d == true ? 1 : 0; | 199 | value = vgdev->has_virgl_3d == true ? 1 : 0; |
200 | break; | 200 | break; |
201 | case VIRTGPU_PARAM_CAPSET_QUERY_FIX: | ||
202 | value = 1; | ||
203 | break; | ||
201 | default: | 204 | default: |
202 | return -EINVAL; | 205 | return -EINVAL; |
203 | } | 206 | } |
@@ -473,7 +476,7 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev, | |||
473 | { | 476 | { |
474 | struct virtio_gpu_device *vgdev = dev->dev_private; | 477 | struct virtio_gpu_device *vgdev = dev->dev_private; |
475 | struct drm_virtgpu_get_caps *args = data; | 478 | struct drm_virtgpu_get_caps *args = data; |
476 | int size; | 479 | unsigned size, host_caps_size; |
477 | int i; | 480 | int i; |
478 | int found_valid = -1; | 481 | int found_valid = -1; |
479 | int ret; | 482 | int ret; |
@@ -483,6 +486,10 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev, | |||
483 | if (vgdev->num_capsets == 0) | 486 | if (vgdev->num_capsets == 0) |
484 | return -ENOSYS; | 487 | return -ENOSYS; |
485 | 488 | ||
489 | /* don't allow userspace to pass 0 */ | ||
490 | if (args->size == 0) | ||
491 | return -EINVAL; | ||
492 | |||
486 | spin_lock(&vgdev->display_info_lock); | 493 | spin_lock(&vgdev->display_info_lock); |
487 | for (i = 0; i < vgdev->num_capsets; i++) { | 494 | for (i = 0; i < vgdev->num_capsets; i++) { |
488 | if (vgdev->capsets[i].id == args->cap_set_id) { | 495 | if (vgdev->capsets[i].id == args->cap_set_id) { |
@@ -498,11 +505,9 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev, | |||
498 | return -EINVAL; | 505 | return -EINVAL; |
499 | } | 506 | } |
500 | 507 | ||
501 | size = vgdev->capsets[found_valid].max_size; | 508 | host_caps_size = vgdev->capsets[found_valid].max_size; |
502 | if (args->size > size) { | 509 | /* only copy to user the minimum of the host caps size or the guest caps size */ |
503 | spin_unlock(&vgdev->display_info_lock); | 510 | size = min(args->size, host_caps_size); |
504 | return -EINVAL; | ||
505 | } | ||
506 | 511 | ||
507 | list_for_each_entry(cache_ent, &vgdev->cap_cache, head) { | 512 | list_for_each_entry(cache_ent, &vgdev->cap_cache, head) { |
508 | if (cache_ent->id == args->cap_set_id && | 513 | if (cache_ent->id == args->cap_set_id && |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 61a03ac90f8c..70e1a8820a7c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
@@ -1338,6 +1338,19 @@ static void __vmw_svga_disable(struct vmw_private *dev_priv) | |||
1338 | */ | 1338 | */ |
1339 | void vmw_svga_disable(struct vmw_private *dev_priv) | 1339 | void vmw_svga_disable(struct vmw_private *dev_priv) |
1340 | { | 1340 | { |
1341 | /* | ||
1342 | * Disabling SVGA will turn off device modesetting capabilities, so | ||
1343 | * notify KMS about that so that it doesn't cache atomic state that | ||
1344 | * isn't valid anymore, for example crtcs turned on. | ||
1345 | * Strictly we'd want to do this under the SVGA lock (or an SVGA mutex), | ||
1346 | * but vmw_kms_lost_device() takes the reservation sem and thus we'll | ||
1347 | * end up with lock order reversal. Thus, a master may actually perform | ||
1348 | * a new modeset just after we call vmw_kms_lost_device() and race with | ||
1349 | * vmw_svga_disable(), but that should at worst cause atomic KMS state | ||
1350 | * to be inconsistent with the device, causing modesetting problems. | ||
1351 | * | ||
1352 | */ | ||
1353 | vmw_kms_lost_device(dev_priv->dev); | ||
1341 | ttm_write_lock(&dev_priv->reservation_sem, false); | 1354 | ttm_write_lock(&dev_priv->reservation_sem, false); |
1342 | spin_lock(&dev_priv->svga_lock); | 1355 | spin_lock(&dev_priv->svga_lock); |
1343 | if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) { | 1356 | 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 9e60de95b863..f34f368c1a2e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
@@ -949,6 +949,7 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, | |||
949 | void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv); | 949 | void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv); |
950 | int vmw_kms_suspend(struct drm_device *dev); | 950 | int vmw_kms_suspend(struct drm_device *dev); |
951 | int vmw_kms_resume(struct drm_device *dev); | 951 | int vmw_kms_resume(struct drm_device *dev); |
952 | void vmw_kms_lost_device(struct drm_device *dev); | ||
952 | 953 | ||
953 | int vmw_dumb_create(struct drm_file *file_priv, | 954 | int vmw_dumb_create(struct drm_file *file_priv, |
954 | struct drm_device *dev, | 955 | struct drm_device *dev, |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 3628a9fe705f..f11601b6fd74 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 | ||
@@ -2513,9 +2512,12 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv, | |||
2513 | * Helper to be used if an error forces the caller to undo the actions of | 2512 | * Helper to be used if an error forces the caller to undo the actions of |
2514 | * vmw_kms_helper_resource_prepare. | 2513 | * vmw_kms_helper_resource_prepare. |
2515 | */ | 2514 | */ |
2516 | void vmw_kms_helper_resource_revert(struct vmw_resource *res) | 2515 | void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx) |
2517 | { | 2516 | { |
2518 | vmw_kms_helper_buffer_revert(res->backup); | 2517 | struct vmw_resource *res = ctx->res; |
2518 | |||
2519 | vmw_kms_helper_buffer_revert(ctx->buf); | ||
2520 | vmw_dmabuf_unreference(&ctx->buf); | ||
2519 | vmw_resource_unreserve(res, false, NULL, 0); | 2521 | vmw_resource_unreserve(res, false, NULL, 0); |
2520 | mutex_unlock(&res->dev_priv->cmdbuf_mutex); | 2522 | mutex_unlock(&res->dev_priv->cmdbuf_mutex); |
2521 | } | 2523 | } |
@@ -2532,10 +2534,14 @@ void vmw_kms_helper_resource_revert(struct vmw_resource *res) | |||
2532 | * interrupted by a signal. | 2534 | * interrupted by a signal. |
2533 | */ | 2535 | */ |
2534 | int vmw_kms_helper_resource_prepare(struct vmw_resource *res, | 2536 | int vmw_kms_helper_resource_prepare(struct vmw_resource *res, |
2535 | bool interruptible) | 2537 | bool interruptible, |
2538 | struct vmw_validation_ctx *ctx) | ||
2536 | { | 2539 | { |
2537 | int ret = 0; | 2540 | int ret = 0; |
2538 | 2541 | ||
2542 | ctx->buf = NULL; | ||
2543 | ctx->res = res; | ||
2544 | |||
2539 | if (interruptible) | 2545 | if (interruptible) |
2540 | ret = mutex_lock_interruptible(&res->dev_priv->cmdbuf_mutex); | 2546 | ret = mutex_lock_interruptible(&res->dev_priv->cmdbuf_mutex); |
2541 | else | 2547 | else |
@@ -2555,6 +2561,8 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res, | |||
2555 | false); | 2561 | false); |
2556 | if (ret) | 2562 | if (ret) |
2557 | goto out_unreserve; | 2563 | goto out_unreserve; |
2564 | |||
2565 | ctx->buf = vmw_dmabuf_reference(res->backup); | ||
2558 | } | 2566 | } |
2559 | ret = vmw_resource_validate(res); | 2567 | ret = vmw_resource_validate(res); |
2560 | if (ret) | 2568 | if (ret) |
@@ -2562,7 +2570,7 @@ int vmw_kms_helper_resource_prepare(struct vmw_resource *res, | |||
2562 | return 0; | 2570 | return 0; |
2563 | 2571 | ||
2564 | out_revert: | 2572 | out_revert: |
2565 | vmw_kms_helper_buffer_revert(res->backup); | 2573 | vmw_kms_helper_buffer_revert(ctx->buf); |
2566 | out_unreserve: | 2574 | out_unreserve: |
2567 | vmw_resource_unreserve(res, false, NULL, 0); | 2575 | vmw_resource_unreserve(res, false, NULL, 0); |
2568 | out_unlock: | 2576 | out_unlock: |
@@ -2578,11 +2586,13 @@ out_unlock: | |||
2578 | * @out_fence: Optional pointer to a fence pointer. If non-NULL, a | 2586 | * @out_fence: Optional pointer to a fence pointer. If non-NULL, a |
2579 | * ref-counted fence pointer is returned here. | 2587 | * ref-counted fence pointer is returned here. |
2580 | */ | 2588 | */ |
2581 | void vmw_kms_helper_resource_finish(struct vmw_resource *res, | 2589 | void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx, |
2582 | struct vmw_fence_obj **out_fence) | 2590 | struct vmw_fence_obj **out_fence) |
2583 | { | 2591 | { |
2584 | if (res->backup || out_fence) | 2592 | struct vmw_resource *res = ctx->res; |
2585 | vmw_kms_helper_buffer_finish(res->dev_priv, NULL, res->backup, | 2593 | |
2594 | if (ctx->buf || out_fence) | ||
2595 | vmw_kms_helper_buffer_finish(res->dev_priv, NULL, ctx->buf, | ||
2586 | out_fence, NULL); | 2596 | out_fence, NULL); |
2587 | 2597 | ||
2588 | vmw_resource_unreserve(res, false, NULL, 0); | 2598 | vmw_resource_unreserve(res, false, NULL, 0); |
@@ -2896,3 +2906,13 @@ int vmw_kms_resume(struct drm_device *dev) | |||
2896 | 2906 | ||
2897 | return ret; | 2907 | return ret; |
2898 | } | 2908 | } |
2909 | |||
2910 | /** | ||
2911 | * vmw_kms_lost_device - Notify kms that modesetting capabilities will be lost | ||
2912 | * | ||
2913 | * @dev: Pointer to the drm device | ||
2914 | */ | ||
2915 | void vmw_kms_lost_device(struct drm_device *dev) | ||
2916 | { | ||
2917 | drm_atomic_helper_shutdown(dev); | ||
2918 | } | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 4e8749a8717e..6b7c012719f1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | |||
@@ -241,6 +241,11 @@ struct vmw_display_unit { | |||
241 | int set_gui_y; | 241 | int set_gui_y; |
242 | }; | 242 | }; |
243 | 243 | ||
244 | struct vmw_validation_ctx { | ||
245 | struct vmw_resource *res; | ||
246 | struct vmw_dma_buffer *buf; | ||
247 | }; | ||
248 | |||
244 | #define vmw_crtc_to_du(x) \ | 249 | #define vmw_crtc_to_du(x) \ |
245 | container_of(x, struct vmw_display_unit, crtc) | 250 | container_of(x, struct vmw_display_unit, crtc) |
246 | #define vmw_connector_to_du(x) \ | 251 | #define vmw_connector_to_du(x) \ |
@@ -298,9 +303,10 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv, | |||
298 | struct drm_vmw_fence_rep __user * | 303 | struct drm_vmw_fence_rep __user * |
299 | user_fence_rep); | 304 | user_fence_rep); |
300 | int vmw_kms_helper_resource_prepare(struct vmw_resource *res, | 305 | int vmw_kms_helper_resource_prepare(struct vmw_resource *res, |
301 | bool interruptible); | 306 | bool interruptible, |
302 | void vmw_kms_helper_resource_revert(struct vmw_resource *res); | 307 | struct vmw_validation_ctx *ctx); |
303 | void vmw_kms_helper_resource_finish(struct vmw_resource *res, | 308 | void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx); |
309 | void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx, | ||
304 | struct vmw_fence_obj **out_fence); | 310 | struct vmw_fence_obj **out_fence); |
305 | int vmw_kms_readback(struct vmw_private *dev_priv, | 311 | int vmw_kms_readback(struct vmw_private *dev_priv, |
306 | struct drm_file *file_priv, | 312 | struct drm_file *file_priv, |
@@ -446,5 +452,4 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, | |||
446 | 452 | ||
447 | int vmw_kms_set_config(struct drm_mode_set *set, | 453 | int vmw_kms_set_config(struct drm_mode_set *set, |
448 | struct drm_modeset_acquire_ctx *ctx); | 454 | struct drm_modeset_acquire_ctx *ctx); |
449 | |||
450 | #endif | 455 | #endif |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 419185f60278..648f8127f65a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | |||
@@ -938,12 +938,13 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, | |||
938 | struct vmw_framebuffer_surface *vfbs = | 938 | struct vmw_framebuffer_surface *vfbs = |
939 | container_of(framebuffer, typeof(*vfbs), base); | 939 | container_of(framebuffer, typeof(*vfbs), base); |
940 | struct vmw_kms_sou_surface_dirty sdirty; | 940 | struct vmw_kms_sou_surface_dirty sdirty; |
941 | struct vmw_validation_ctx ctx; | ||
941 | int ret; | 942 | int ret; |
942 | 943 | ||
943 | if (!srf) | 944 | if (!srf) |
944 | srf = &vfbs->surface->res; | 945 | srf = &vfbs->surface->res; |
945 | 946 | ||
946 | ret = vmw_kms_helper_resource_prepare(srf, true); | 947 | ret = vmw_kms_helper_resource_prepare(srf, true, &ctx); |
947 | if (ret) | 948 | if (ret) |
948 | return ret; | 949 | return ret; |
949 | 950 | ||
@@ -963,7 +964,7 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv, | |||
963 | ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, | 964 | ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips, |
964 | dest_x, dest_y, num_clips, inc, | 965 | dest_x, dest_y, num_clips, inc, |
965 | &sdirty.base); | 966 | &sdirty.base); |
966 | vmw_kms_helper_resource_finish(srf, out_fence); | 967 | vmw_kms_helper_resource_finish(&ctx, out_fence); |
967 | 968 | ||
968 | return ret; | 969 | return ret; |
969 | } | 970 | } |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 8eec88920851..67331f01ef32 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | |||
@@ -916,12 +916,13 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, | |||
916 | struct vmw_framebuffer_surface *vfbs = | 916 | struct vmw_framebuffer_surface *vfbs = |
917 | container_of(framebuffer, typeof(*vfbs), base); | 917 | container_of(framebuffer, typeof(*vfbs), base); |
918 | struct vmw_stdu_dirty sdirty; | 918 | struct vmw_stdu_dirty sdirty; |
919 | struct vmw_validation_ctx ctx; | ||
919 | int ret; | 920 | int ret; |
920 | 921 | ||
921 | if (!srf) | 922 | if (!srf) |
922 | srf = &vfbs->surface->res; | 923 | srf = &vfbs->surface->res; |
923 | 924 | ||
924 | ret = vmw_kms_helper_resource_prepare(srf, true); | 925 | ret = vmw_kms_helper_resource_prepare(srf, true, &ctx); |
925 | if (ret) | 926 | if (ret) |
926 | return ret; | 927 | return ret; |
927 | 928 | ||
@@ -945,7 +946,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, | |||
945 | dest_x, dest_y, num_clips, inc, | 946 | dest_x, dest_y, num_clips, inc, |
946 | &sdirty.base); | 947 | &sdirty.base); |
947 | out_finish: | 948 | out_finish: |
948 | vmw_kms_helper_resource_finish(srf, out_fence); | 949 | vmw_kms_helper_resource_finish(&ctx, out_fence); |
949 | 950 | ||
950 | return ret; | 951 | return ret; |
951 | } | 952 | } |