forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
....@@ -25,12 +25,15 @@
2525 *
2626 ******************************************************************************/
2727
28
-#include "vmwgfx_kms.h"
29
-#include "device_include/svga3d_surfacedefs.h"
30
-#include <drm/drm_plane_helper.h>
3128 #include <drm/drm_atomic.h>
3229 #include <drm/drm_atomic_helper.h>
30
+#include <drm/drm_damage_helper.h>
31
+#include <drm/drm_fourcc.h>
32
+#include <drm/drm_plane_helper.h>
33
+#include <drm/drm_vblank.h>
3334
35
+#include "vmwgfx_kms.h"
36
+#include "device_include/svga3d_surfacedefs.h"
3437
3538 #define vmw_crtc_to_stdu(x) \
3639 container_of(x, struct vmw_screen_target_display_unit, base.crtc)
....@@ -92,6 +95,10 @@
9295 SVGA3dCmdSurfaceCopy body;
9396 };
9497
98
+struct vmw_stdu_update_gb_image {
99
+ SVGA3dCmdHeader header;
100
+ SVGA3dCmdUpdateGBImage body;
101
+};
95102
96103 /**
97104 * struct vmw_screen_target_display_unit
....@@ -107,7 +114,7 @@
107114 */
108115 struct vmw_screen_target_display_unit {
109116 struct vmw_display_unit base;
110
- const struct vmw_surface *display_srf;
117
+ struct vmw_surface *display_srf;
111118 enum stdu_content_type content_fb_type;
112119 s32 display_width, display_height;
113120
....@@ -163,12 +170,9 @@
163170 SVGA3dCmdDefineGBScreenTarget body;
164171 } *cmd;
165172
166
- cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
167
-
168
- if (unlikely(cmd == NULL)) {
169
- DRM_ERROR("Out of FIFO space defining Screen Target\n");
173
+ cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
174
+ if (unlikely(cmd == NULL))
170175 return -ENOMEM;
171
- }
172176
173177 cmd->header.id = SVGA_3D_CMD_DEFINE_GB_SCREENTARGET;
174178 cmd->header.size = sizeof(cmd->body);
....@@ -225,12 +229,9 @@
225229 memset(&image, 0, sizeof(image));
226230 image.sid = res ? res->id : SVGA3D_INVALID_ID;
227231
228
- cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
229
-
230
- if (unlikely(cmd == NULL)) {
231
- DRM_ERROR("Out of FIFO space binding a screen target\n");
232
+ cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
233
+ if (unlikely(cmd == NULL))
232234 return -ENOMEM;
233
- }
234235
235236 cmd->header.id = SVGA_3D_CMD_BIND_GB_SCREENTARGET;
236237 cmd->header.size = sizeof(cmd->body);
....@@ -292,12 +293,9 @@
292293 return -EINVAL;
293294 }
294295
295
- cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
296
-
297
- if (unlikely(cmd == NULL)) {
298
- DRM_ERROR("Out of FIFO space updating a Screen Target\n");
296
+ cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
297
+ if (unlikely(cmd == NULL))
299298 return -ENOMEM;
300
- }
301299
302300 vmw_stdu_populate_update(cmd, stdu->base.unit,
303301 0, stdu->display_width,
....@@ -331,12 +329,9 @@
331329 if (unlikely(!stdu->defined))
332330 return 0;
333331
334
- cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
335
-
336
- if (unlikely(cmd == NULL)) {
337
- DRM_ERROR("Out of FIFO space, screen target not destroyed\n");
332
+ cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
333
+ if (unlikely(cmd == NULL))
338334 return -ENOMEM;
339
- }
340335
341336 cmd->header.id = SVGA_3D_CMD_DESTROY_GB_SCREENTARGET;
342337 cmd->header.size = sizeof(cmd->body);
....@@ -396,13 +391,8 @@
396391 if (!crtc->state->enable)
397392 return;
398393
399
- if (stdu->base.is_implicit) {
400
- x = crtc->x;
401
- y = crtc->y;
402
- } else {
403
- x = vmw_conn_state->gui_x;
404
- y = vmw_conn_state->gui_y;
405
- }
394
+ x = vmw_conn_state->gui_x;
395
+ y = vmw_conn_state->gui_y;
406396
407397 vmw_svga_enable(dev_priv);
408398 ret = vmw_stdu_define_st(dev_priv, stdu, &crtc->mode, x, y);
....@@ -417,27 +407,9 @@
417407 {
418408 }
419409
420
-
421410 static void vmw_stdu_crtc_atomic_enable(struct drm_crtc *crtc,
422411 struct drm_crtc_state *old_state)
423412 {
424
- struct drm_plane_state *plane_state = crtc->primary->state;
425
- struct vmw_private *dev_priv;
426
- struct vmw_screen_target_display_unit *stdu;
427
- struct vmw_framebuffer *vfb;
428
- struct drm_framebuffer *fb;
429
-
430
-
431
- stdu = vmw_crtc_to_stdu(crtc);
432
- dev_priv = vmw_priv(crtc->dev);
433
- fb = plane_state->fb;
434
-
435
- vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
436
-
437
- if (vfb)
438
- vmw_kms_add_active(dev_priv, &stdu->base, vfb);
439
- else
440
- vmw_kms_del_active(dev_priv, &stdu->base);
441413 }
442414
443415 static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc,
....@@ -470,49 +442,6 @@
470442 stdu->content_fb_type = SAME_AS_DISPLAY;
471443 }
472444 }
473
-
474
-/**
475
- * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target
476
- *
477
- * @crtc: CRTC to attach FB to
478
- * @fb: FB to attach
479
- * @event: Event to be posted. This event should've been alloced
480
- * using k[mz]alloc, and should've been completely initialized.
481
- * @page_flip_flags: Input flags.
482
- *
483
- * If the STDU uses the same display and content buffers, i.e. a true flip,
484
- * this function will replace the existing display buffer with the new content
485
- * buffer.
486
- *
487
- * If the STDU uses different display and content buffers, i.e. a blit, then
488
- * only the content buffer will be updated.
489
- *
490
- * RETURNS:
491
- * 0 on success, error code on failure
492
- */
493
-static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
494
- struct drm_framebuffer *new_fb,
495
- struct drm_pending_vblank_event *event,
496
- uint32_t flags,
497
- struct drm_modeset_acquire_ctx *ctx)
498
-
499
-{
500
- struct vmw_private *dev_priv = vmw_priv(crtc->dev);
501
- struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
502
- int ret;
503
-
504
- if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc))
505
- return -EINVAL;
506
-
507
- ret = drm_atomic_helper_page_flip(crtc, new_fb, event, flags, ctx);
508
- if (ret) {
509
- DRM_ERROR("Page flip error %d.\n", ret);
510
- return ret;
511
- }
512
-
513
- return 0;
514
-}
515
-
516445
517446 /**
518447 * vmw_stdu_bo_clip - Callback to encode a suface DMA command cliprect
....@@ -595,6 +524,7 @@
595524
596525 vmw_fifo_commit(dirty->dev_priv, sizeof(*cmd) + blit_size);
597526
527
+ stdu->display_srf->res.res_dirty = true;
598528 ddirty->left = ddirty->top = S32_MAX;
599529 ddirty->right = ddirty->bottom = S32_MIN;
600530 }
....@@ -660,7 +590,7 @@
660590 return;
661591
662592 /* Assume we are blitting from Guest (bo) to Host (display_srf) */
663
- dst_pitch = stdu->display_srf->base_size.width * stdu->cpp;
593
+ dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
664594 dst_bo = &stdu->display_srf->res.backup->base;
665595 dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp;
666596
....@@ -691,20 +621,16 @@
691621 region.x2 = diff.rect.x2;
692622 region.y1 = diff.rect.y1;
693623 region.y2 = diff.rect.y2;
694
- ret = vmw_kms_update_proxy(
695
- (struct vmw_resource *) &stdu->display_srf->res,
696
- (const struct drm_clip_rect *) &region, 1, 1);
624
+ ret = vmw_kms_update_proxy(&stdu->display_srf->res, &region,
625
+ 1, 1);
697626 if (ret)
698627 goto out_cleanup;
699628
700629
701630 dev_priv = vmw_priv(stdu->base.crtc.dev);
702
- cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
703
-
704
- if (!cmd) {
705
- DRM_ERROR("Cannot reserve FIFO space to update STDU");
631
+ cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd));
632
+ if (!cmd)
706633 goto out_cleanup;
707
- }
708634
709635 vmw_stdu_populate_update(cmd, stdu->base.unit,
710636 region.x1, region.x2,
....@@ -759,16 +685,20 @@
759685 struct vmw_stdu_dirty ddirty;
760686 int ret;
761687 bool cpu_blit = !(dev_priv->capabilities & SVGA_CAP_3D);
688
+ DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
762689
763690 /*
764691 * VMs without 3D support don't have the surface DMA command and
765692 * we'll be using a CPU blit, and the framebuffer should be moved out
766693 * of VRAM.
767694 */
768
- ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, interruptible,
769
- false, cpu_blit);
695
+ ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit);
770696 if (ret)
771697 return ret;
698
+
699
+ ret = vmw_validation_prepare(&val_ctx, NULL, interruptible);
700
+ if (ret)
701
+ goto out_unref;
772702
773703 ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM :
774704 SVGA3D_READ_HOST_VRAM;
....@@ -796,9 +726,13 @@
796726
797727 ret = vmw_kms_helper_dirty(dev_priv, vfb, clips, vclips,
798728 0, 0, num_clips, increment, &ddirty.base);
799
- vmw_kms_helper_buffer_finish(dev_priv, file_priv, buf, NULL,
800
- user_fence_rep);
801729
730
+ vmw_kms_helper_validation_finish(dev_priv, file_priv, &val_ctx, NULL,
731
+ user_fence_rep);
732
+ return ret;
733
+
734
+out_unref:
735
+ vmw_validation_unref_lists(&val_ctx);
802736 return ret;
803737 }
804738
....@@ -874,6 +808,7 @@
874808 cmd->body.dest.sid = stdu->display_srf->res.id;
875809 update = (struct vmw_stdu_update *) &blit[dirty->num_hits];
876810 commit_size = sizeof(*cmd) + blit_size + sizeof(*update);
811
+ stdu->display_srf->res.res_dirty = true;
877812 } else {
878813 update = dirty->cmd;
879814 commit_size = sizeof(*update);
....@@ -924,15 +859,20 @@
924859 struct vmw_framebuffer_surface *vfbs =
925860 container_of(framebuffer, typeof(*vfbs), base);
926861 struct vmw_stdu_dirty sdirty;
927
- struct vmw_validation_ctx ctx;
862
+ DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
928863 int ret;
929864
930865 if (!srf)
931866 srf = &vfbs->surface->res;
932867
933
- ret = vmw_kms_helper_resource_prepare(srf, true, &ctx);
868
+ ret = vmw_validation_add_resource(&val_ctx, srf, 0, VMW_RES_DIRTY_NONE,
869
+ NULL, NULL);
934870 if (ret)
935871 return ret;
872
+
873
+ ret = vmw_validation_prepare(&val_ctx, &dev_priv->cmdbuf_mutex, true);
874
+ if (ret)
875
+ goto out_unref;
936876
937877 if (vfbs->is_bo_proxy) {
938878 ret = vmw_kms_update_proxy(srf, clips, num_clips, inc);
....@@ -954,8 +894,13 @@
954894 dest_x, dest_y, num_clips, inc,
955895 &sdirty.base);
956896 out_finish:
957
- vmw_kms_helper_resource_finish(&ctx, out_fence);
897
+ vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence,
898
+ NULL);
958899
900
+ return ret;
901
+
902
+out_unref:
903
+ vmw_validation_unref_lists(&val_ctx);
959904 return ret;
960905 }
961906
....@@ -969,8 +914,11 @@
969914 .reset = vmw_du_crtc_reset,
970915 .atomic_duplicate_state = vmw_du_crtc_duplicate_state,
971916 .atomic_destroy_state = vmw_du_crtc_destroy_state,
972
- .set_config = vmw_kms_set_config,
973
- .page_flip = vmw_stdu_crtc_page_flip,
917
+ .set_config = drm_atomic_helper_set_config,
918
+ .page_flip = drm_atomic_helper_page_flip,
919
+ .get_vblank_counter = vmw_get_vblank_counter,
920
+ .enable_vblank = vmw_enable_vblank,
921
+ .disable_vblank = vmw_disable_vblank,
974922 };
975923
976924
....@@ -1025,19 +973,15 @@
1025973 .dpms = vmw_du_connector_dpms,
1026974 .detect = vmw_du_connector_detect,
1027975 .fill_modes = vmw_du_connector_fill_modes,
1028
- .set_property = vmw_du_connector_set_property,
1029976 .destroy = vmw_stdu_connector_destroy,
1030977 .reset = vmw_du_connector_reset,
1031978 .atomic_duplicate_state = vmw_du_connector_duplicate_state,
1032979 .atomic_destroy_state = vmw_du_connector_destroy_state,
1033
- .atomic_set_property = vmw_du_connector_atomic_set_property,
1034
- .atomic_get_property = vmw_du_connector_atomic_get_property,
1035980 };
1036981
1037982
1038983 static const struct
1039984 drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
1040
- .best_encoder = drm_atomic_helper_best_encoder,
1041985 };
1042986
1043987
....@@ -1097,7 +1041,6 @@
10971041 struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
10981042 enum stdu_content_type new_content_type;
10991043 struct vmw_framebuffer_surface *new_vfbs;
1100
- struct drm_crtc *crtc = new_state->crtc;
11011044 uint32_t hdisplay = new_state->crtc_w, vdisplay = new_state->crtc_h;
11021045 int ret;
11031046
....@@ -1114,8 +1057,9 @@
11141057 vfb = vmw_framebuffer_to_vfb(new_fb);
11151058 new_vfbs = (vfb->bo) ? NULL : vmw_framebuffer_to_vfbs(new_fb);
11161059
1117
- if (new_vfbs && new_vfbs->surface->base_size.width == hdisplay &&
1118
- new_vfbs->surface->base_size.height == vdisplay)
1060
+ if (new_vfbs &&
1061
+ new_vfbs->surface->metadata.base_size.width == hdisplay &&
1062
+ new_vfbs->surface->metadata.base_size.height == vdisplay)
11191063 new_content_type = SAME_AS_DISPLAY;
11201064 else if (vfb->bo)
11211065 new_content_type = SEPARATE_BO;
....@@ -1123,12 +1067,7 @@
11231067 new_content_type = SEPARATE_SURFACE;
11241068
11251069 if (new_content_type != SAME_AS_DISPLAY) {
1126
- struct vmw_surface content_srf;
1127
- struct drm_vmw_size display_base_size = {0};
1128
-
1129
- display_base_size.width = hdisplay;
1130
- display_base_size.height = vdisplay;
1131
- display_base_size.depth = 1;
1070
+ struct vmw_surface_metadata metadata = {0};
11321071
11331072 /*
11341073 * If content buffer is a buffer object, then we have to
....@@ -1138,15 +1077,15 @@
11381077
11391078 switch (new_fb->format->cpp[0]*8) {
11401079 case 32:
1141
- content_srf.format = SVGA3D_X8R8G8B8;
1080
+ metadata.format = SVGA3D_X8R8G8B8;
11421081 break;
11431082
11441083 case 16:
1145
- content_srf.format = SVGA3D_R5G6B5;
1084
+ metadata.format = SVGA3D_R5G6B5;
11461085 break;
11471086
11481087 case 8:
1149
- content_srf.format = SVGA3D_P8;
1088
+ metadata.format = SVGA3D_P8;
11501089 break;
11511090
11521091 default:
....@@ -1154,22 +1093,24 @@
11541093 return -EINVAL;
11551094 }
11561095
1157
- content_srf.flags = 0;
1158
- content_srf.mip_levels[0] = 1;
1159
- content_srf.multisample_count = 0;
1160
- content_srf.multisample_pattern =
1161
- SVGA3D_MS_PATTERN_NONE;
1162
- content_srf.quality_level = SVGA3D_MS_QUALITY_NONE;
1096
+ metadata.mip_levels[0] = 1;
1097
+ metadata.num_sizes = 1;
1098
+ metadata.scanout = true;
11631099 } else {
1164
- content_srf = *new_vfbs->surface;
1100
+ metadata = new_vfbs->surface->metadata;
11651101 }
11661102
1167
- if (vps->surf) {
1168
- struct drm_vmw_size cur_base_size = vps->surf->base_size;
1103
+ metadata.base_size.width = hdisplay;
1104
+ metadata.base_size.height = vdisplay;
1105
+ metadata.base_size.depth = 1;
11691106
1170
- if (cur_base_size.width != display_base_size.width ||
1171
- cur_base_size.height != display_base_size.height ||
1172
- vps->surf->format != content_srf.format) {
1107
+ if (vps->surf) {
1108
+ struct drm_vmw_size cur_base_size =
1109
+ vps->surf->metadata.base_size;
1110
+
1111
+ if (cur_base_size.width != metadata.base_size.width ||
1112
+ cur_base_size.height != metadata.base_size.height ||
1113
+ vps->surf->metadata.format != metadata.format) {
11731114 WARN_ON(vps->pinned != 0);
11741115 vmw_surface_unreference(&vps->surf);
11751116 }
....@@ -1177,20 +1118,8 @@
11771118 }
11781119
11791120 if (!vps->surf) {
1180
- ret = vmw_surface_gb_priv_define
1181
- (crtc->dev,
1182
- /* Kernel visible only */
1183
- 0,
1184
- content_srf.flags,
1185
- content_srf.format,
1186
- true, /* a scanout buffer */
1187
- content_srf.mip_levels[0],
1188
- content_srf.multisample_count,
1189
- 0,
1190
- display_base_size,
1191
- content_srf.multisample_pattern,
1192
- content_srf.quality_level,
1193
- &vps->surf);
1121
+ ret = vmw_gb_surface_define(dev_priv, 0, &metadata,
1122
+ &vps->surf);
11941123 if (ret != 0) {
11951124 DRM_ERROR("Couldn't allocate STDU surface.\n");
11961125 return ret;
....@@ -1240,11 +1169,402 @@
12401169 return ret;
12411170 }
12421171
1172
+static uint32_t vmw_stdu_bo_fifo_size(struct vmw_du_update_plane *update,
1173
+ uint32_t num_hits)
1174
+{
1175
+ return sizeof(struct vmw_stdu_dma) + sizeof(SVGA3dCopyBox) * num_hits +
1176
+ sizeof(SVGA3dCmdSurfaceDMASuffix) +
1177
+ sizeof(struct vmw_stdu_update);
1178
+}
12431179
1180
+static uint32_t vmw_stdu_bo_fifo_size_cpu(struct vmw_du_update_plane *update,
1181
+ uint32_t num_hits)
1182
+{
1183
+ return sizeof(struct vmw_stdu_update_gb_image) +
1184
+ sizeof(struct vmw_stdu_update);
1185
+}
1186
+
1187
+static uint32_t vmw_stdu_bo_populate_dma(struct vmw_du_update_plane *update,
1188
+ void *cmd, uint32_t num_hits)
1189
+{
1190
+ struct vmw_screen_target_display_unit *stdu;
1191
+ struct vmw_framebuffer_bo *vfbbo;
1192
+ struct vmw_stdu_dma *cmd_dma = cmd;
1193
+
1194
+ stdu = container_of(update->du, typeof(*stdu), base);
1195
+ vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
1196
+
1197
+ cmd_dma->header.id = SVGA_3D_CMD_SURFACE_DMA;
1198
+ cmd_dma->header.size = sizeof(cmd_dma->body) +
1199
+ sizeof(struct SVGA3dCopyBox) * num_hits +
1200
+ sizeof(SVGA3dCmdSurfaceDMASuffix);
1201
+ vmw_bo_get_guest_ptr(&vfbbo->buffer->base, &cmd_dma->body.guest.ptr);
1202
+ cmd_dma->body.guest.pitch = update->vfb->base.pitches[0];
1203
+ cmd_dma->body.host.sid = stdu->display_srf->res.id;
1204
+ cmd_dma->body.host.face = 0;
1205
+ cmd_dma->body.host.mipmap = 0;
1206
+ cmd_dma->body.transfer = SVGA3D_WRITE_HOST_VRAM;
1207
+
1208
+ return sizeof(*cmd_dma);
1209
+}
1210
+
1211
+static uint32_t vmw_stdu_bo_populate_clip(struct vmw_du_update_plane *update,
1212
+ void *cmd, struct drm_rect *clip,
1213
+ uint32_t fb_x, uint32_t fb_y)
1214
+{
1215
+ struct SVGA3dCopyBox *box = cmd;
1216
+
1217
+ box->srcx = fb_x;
1218
+ box->srcy = fb_y;
1219
+ box->srcz = 0;
1220
+ box->x = clip->x1;
1221
+ box->y = clip->y1;
1222
+ box->z = 0;
1223
+ box->w = drm_rect_width(clip);
1224
+ box->h = drm_rect_height(clip);
1225
+ box->d = 1;
1226
+
1227
+ return sizeof(*box);
1228
+}
1229
+
1230
+static uint32_t vmw_stdu_bo_populate_update(struct vmw_du_update_plane *update,
1231
+ void *cmd, struct drm_rect *bb)
1232
+{
1233
+ struct vmw_screen_target_display_unit *stdu;
1234
+ struct vmw_framebuffer_bo *vfbbo;
1235
+ SVGA3dCmdSurfaceDMASuffix *suffix = cmd;
1236
+
1237
+ stdu = container_of(update->du, typeof(*stdu), base);
1238
+ vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
1239
+
1240
+ suffix->suffixSize = sizeof(*suffix);
1241
+ suffix->maximumOffset = vfbbo->buffer->base.num_pages * PAGE_SIZE;
1242
+
1243
+ vmw_stdu_populate_update(&suffix[1], stdu->base.unit, bb->x1, bb->x2,
1244
+ bb->y1, bb->y2);
1245
+
1246
+ return sizeof(*suffix) + sizeof(struct vmw_stdu_update);
1247
+}
1248
+
1249
+static uint32_t vmw_stdu_bo_pre_clip_cpu(struct vmw_du_update_plane *update,
1250
+ void *cmd, uint32_t num_hits)
1251
+{
1252
+ struct vmw_du_update_plane_buffer *bo_update =
1253
+ container_of(update, typeof(*bo_update), base);
1254
+
1255
+ bo_update->fb_left = INT_MAX;
1256
+ bo_update->fb_top = INT_MAX;
1257
+
1258
+ return 0;
1259
+}
1260
+
1261
+static uint32_t vmw_stdu_bo_clip_cpu(struct vmw_du_update_plane *update,
1262
+ void *cmd, struct drm_rect *clip,
1263
+ uint32_t fb_x, uint32_t fb_y)
1264
+{
1265
+ struct vmw_du_update_plane_buffer *bo_update =
1266
+ container_of(update, typeof(*bo_update), base);
1267
+
1268
+ bo_update->fb_left = min_t(int, bo_update->fb_left, fb_x);
1269
+ bo_update->fb_top = min_t(int, bo_update->fb_top, fb_y);
1270
+
1271
+ return 0;
1272
+}
1273
+
1274
+static uint32_t
1275
+vmw_stdu_bo_populate_update_cpu(struct vmw_du_update_plane *update, void *cmd,
1276
+ struct drm_rect *bb)
1277
+{
1278
+ struct vmw_du_update_plane_buffer *bo_update;
1279
+ struct vmw_screen_target_display_unit *stdu;
1280
+ struct vmw_framebuffer_bo *vfbbo;
1281
+ struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0);
1282
+ struct vmw_stdu_update_gb_image *cmd_img = cmd;
1283
+ struct vmw_stdu_update *cmd_update;
1284
+ struct ttm_buffer_object *src_bo, *dst_bo;
1285
+ u32 src_offset, dst_offset;
1286
+ s32 src_pitch, dst_pitch;
1287
+ s32 width, height;
1288
+
1289
+ bo_update = container_of(update, typeof(*bo_update), base);
1290
+ stdu = container_of(update->du, typeof(*stdu), base);
1291
+ vfbbo = container_of(update->vfb, typeof(*vfbbo), base);
1292
+
1293
+ width = bb->x2 - bb->x1;
1294
+ height = bb->y2 - bb->y1;
1295
+
1296
+ diff.cpp = stdu->cpp;
1297
+
1298
+ dst_bo = &stdu->display_srf->res.backup->base;
1299
+ dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp;
1300
+ dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp;
1301
+
1302
+ src_bo = &vfbbo->buffer->base;
1303
+ src_pitch = update->vfb->base.pitches[0];
1304
+ src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left *
1305
+ stdu->cpp;
1306
+
1307
+ (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, src_bo,
1308
+ src_offset, src_pitch, width * stdu->cpp, height,
1309
+ &diff);
1310
+
1311
+ if (drm_rect_visible(&diff.rect)) {
1312
+ SVGA3dBox *box = &cmd_img->body.box;
1313
+
1314
+ cmd_img->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
1315
+ cmd_img->header.size = sizeof(cmd_img->body);
1316
+ cmd_img->body.image.sid = stdu->display_srf->res.id;
1317
+ cmd_img->body.image.face = 0;
1318
+ cmd_img->body.image.mipmap = 0;
1319
+
1320
+ box->x = diff.rect.x1;
1321
+ box->y = diff.rect.y1;
1322
+ box->z = 0;
1323
+ box->w = drm_rect_width(&diff.rect);
1324
+ box->h = drm_rect_height(&diff.rect);
1325
+ box->d = 1;
1326
+
1327
+ cmd_update = (struct vmw_stdu_update *)&cmd_img[1];
1328
+ vmw_stdu_populate_update(cmd_update, stdu->base.unit,
1329
+ diff.rect.x1, diff.rect.x2,
1330
+ diff.rect.y1, diff.rect.y2);
1331
+
1332
+ return sizeof(*cmd_img) + sizeof(*cmd_update);
1333
+ }
1334
+
1335
+ return 0;
1336
+}
1337
+
1338
+/**
1339
+ * vmw_stdu_plane_update_bo - Update display unit for bo backed fb.
1340
+ * @dev_priv: device private.
1341
+ * @plane: plane state.
1342
+ * @old_state: old plane state.
1343
+ * @vfb: framebuffer which is blitted to display unit.
1344
+ * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj.
1345
+ * The returned fence pointer may be NULL in which case the device
1346
+ * has already synchronized.
1347
+ *
1348
+ * Return: 0 on success or a negative error code on failure.
1349
+ */
1350
+static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv,
1351
+ struct drm_plane *plane,
1352
+ struct drm_plane_state *old_state,
1353
+ struct vmw_framebuffer *vfb,
1354
+ struct vmw_fence_obj **out_fence)
1355
+{
1356
+ struct vmw_du_update_plane_buffer bo_update;
1357
+
1358
+ memset(&bo_update, 0, sizeof(struct vmw_du_update_plane_buffer));
1359
+ bo_update.base.plane = plane;
1360
+ bo_update.base.old_state = old_state;
1361
+ bo_update.base.dev_priv = dev_priv;
1362
+ bo_update.base.du = vmw_crtc_to_du(plane->state->crtc);
1363
+ bo_update.base.vfb = vfb;
1364
+ bo_update.base.out_fence = out_fence;
1365
+ bo_update.base.mutex = NULL;
1366
+ bo_update.base.cpu_blit = !(dev_priv->capabilities & SVGA_CAP_3D);
1367
+ bo_update.base.intr = false;
1368
+
1369
+ /*
1370
+ * VM without 3D support don't have surface DMA command and framebuffer
1371
+ * should be moved out of VRAM.
1372
+ */
1373
+ if (bo_update.base.cpu_blit) {
1374
+ bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size_cpu;
1375
+ bo_update.base.pre_clip = vmw_stdu_bo_pre_clip_cpu;
1376
+ bo_update.base.clip = vmw_stdu_bo_clip_cpu;
1377
+ bo_update.base.post_clip = vmw_stdu_bo_populate_update_cpu;
1378
+ } else {
1379
+ bo_update.base.calc_fifo_size = vmw_stdu_bo_fifo_size;
1380
+ bo_update.base.pre_clip = vmw_stdu_bo_populate_dma;
1381
+ bo_update.base.clip = vmw_stdu_bo_populate_clip;
1382
+ bo_update.base.post_clip = vmw_stdu_bo_populate_update;
1383
+ }
1384
+
1385
+ return vmw_du_helper_plane_update(&bo_update.base);
1386
+}
1387
+
1388
+static uint32_t
1389
+vmw_stdu_surface_fifo_size_same_display(struct vmw_du_update_plane *update,
1390
+ uint32_t num_hits)
1391
+{
1392
+ struct vmw_framebuffer_surface *vfbs;
1393
+ uint32_t size = 0;
1394
+
1395
+ vfbs = container_of(update->vfb, typeof(*vfbs), base);
1396
+
1397
+ if (vfbs->is_bo_proxy)
1398
+ size += sizeof(struct vmw_stdu_update_gb_image) * num_hits;
1399
+
1400
+ size += sizeof(struct vmw_stdu_update);
1401
+
1402
+ return size;
1403
+}
1404
+
1405
+static uint32_t vmw_stdu_surface_fifo_size(struct vmw_du_update_plane *update,
1406
+ uint32_t num_hits)
1407
+{
1408
+ struct vmw_framebuffer_surface *vfbs;
1409
+ uint32_t size = 0;
1410
+
1411
+ vfbs = container_of(update->vfb, typeof(*vfbs), base);
1412
+
1413
+ if (vfbs->is_bo_proxy)
1414
+ size += sizeof(struct vmw_stdu_update_gb_image) * num_hits;
1415
+
1416
+ size += sizeof(struct vmw_stdu_surface_copy) + sizeof(SVGA3dCopyBox) *
1417
+ num_hits + sizeof(struct vmw_stdu_update);
1418
+
1419
+ return size;
1420
+}
1421
+
1422
+static uint32_t
1423
+vmw_stdu_surface_update_proxy(struct vmw_du_update_plane *update, void *cmd)
1424
+{
1425
+ struct vmw_framebuffer_surface *vfbs;
1426
+ struct drm_plane_state *state = update->plane->state;
1427
+ struct drm_plane_state *old_state = update->old_state;
1428
+ struct vmw_stdu_update_gb_image *cmd_update = cmd;
1429
+ struct drm_atomic_helper_damage_iter iter;
1430
+ struct drm_rect clip;
1431
+ uint32_t copy_size = 0;
1432
+
1433
+ vfbs = container_of(update->vfb, typeof(*vfbs), base);
1434
+
1435
+ /*
1436
+ * proxy surface is special where a buffer object type fb is wrapped
1437
+ * in a surface and need an update gb image command to sync with device.
1438
+ */
1439
+ drm_atomic_helper_damage_iter_init(&iter, old_state, state);
1440
+ drm_atomic_for_each_plane_damage(&iter, &clip) {
1441
+ SVGA3dBox *box = &cmd_update->body.box;
1442
+
1443
+ cmd_update->header.id = SVGA_3D_CMD_UPDATE_GB_IMAGE;
1444
+ cmd_update->header.size = sizeof(cmd_update->body);
1445
+ cmd_update->body.image.sid = vfbs->surface->res.id;
1446
+ cmd_update->body.image.face = 0;
1447
+ cmd_update->body.image.mipmap = 0;
1448
+
1449
+ box->x = clip.x1;
1450
+ box->y = clip.y1;
1451
+ box->z = 0;
1452
+ box->w = drm_rect_width(&clip);
1453
+ box->h = drm_rect_height(&clip);
1454
+ box->d = 1;
1455
+
1456
+ copy_size += sizeof(*cmd_update);
1457
+ cmd_update++;
1458
+ }
1459
+
1460
+ return copy_size;
1461
+}
1462
+
1463
+static uint32_t
1464
+vmw_stdu_surface_populate_copy(struct vmw_du_update_plane *update, void *cmd,
1465
+ uint32_t num_hits)
1466
+{
1467
+ struct vmw_screen_target_display_unit *stdu;
1468
+ struct vmw_framebuffer_surface *vfbs;
1469
+ struct vmw_stdu_surface_copy *cmd_copy = cmd;
1470
+
1471
+ stdu = container_of(update->du, typeof(*stdu), base);
1472
+ vfbs = container_of(update->vfb, typeof(*vfbs), base);
1473
+
1474
+ cmd_copy->header.id = SVGA_3D_CMD_SURFACE_COPY;
1475
+ cmd_copy->header.size = sizeof(cmd_copy->body) + sizeof(SVGA3dCopyBox) *
1476
+ num_hits;
1477
+ cmd_copy->body.src.sid = vfbs->surface->res.id;
1478
+ cmd_copy->body.dest.sid = stdu->display_srf->res.id;
1479
+
1480
+ return sizeof(*cmd_copy);
1481
+}
1482
+
1483
+static uint32_t
1484
+vmw_stdu_surface_populate_clip(struct vmw_du_update_plane *update, void *cmd,
1485
+ struct drm_rect *clip, uint32_t fb_x,
1486
+ uint32_t fb_y)
1487
+{
1488
+ struct SVGA3dCopyBox *box = cmd;
1489
+
1490
+ box->srcx = fb_x;
1491
+ box->srcy = fb_y;
1492
+ box->srcz = 0;
1493
+ box->x = clip->x1;
1494
+ box->y = clip->y1;
1495
+ box->z = 0;
1496
+ box->w = drm_rect_width(clip);
1497
+ box->h = drm_rect_height(clip);
1498
+ box->d = 1;
1499
+
1500
+ return sizeof(*box);
1501
+}
1502
+
1503
+static uint32_t
1504
+vmw_stdu_surface_populate_update(struct vmw_du_update_plane *update, void *cmd,
1505
+ struct drm_rect *bb)
1506
+{
1507
+ vmw_stdu_populate_update(cmd, update->du->unit, bb->x1, bb->x2, bb->y1,
1508
+ bb->y2);
1509
+
1510
+ return sizeof(struct vmw_stdu_update);
1511
+}
1512
+
1513
+/**
1514
+ * vmw_stdu_plane_update_surface - Update display unit for surface backed fb
1515
+ * @dev_priv: Device private
1516
+ * @plane: Plane state
1517
+ * @old_state: Old plane state
1518
+ * @vfb: Framebuffer which is blitted to display unit
1519
+ * @out_fence: If non-NULL, will return a ref-counted pointer to vmw_fence_obj.
1520
+ * The returned fence pointer may be NULL in which case the device
1521
+ * has already synchronized.
1522
+ *
1523
+ * Return: 0 on success or a negative error code on failure.
1524
+ */
1525
+static int vmw_stdu_plane_update_surface(struct vmw_private *dev_priv,
1526
+ struct drm_plane *plane,
1527
+ struct drm_plane_state *old_state,
1528
+ struct vmw_framebuffer *vfb,
1529
+ struct vmw_fence_obj **out_fence)
1530
+{
1531
+ struct vmw_du_update_plane srf_update;
1532
+ struct vmw_screen_target_display_unit *stdu;
1533
+ struct vmw_framebuffer_surface *vfbs;
1534
+
1535
+ stdu = vmw_crtc_to_stdu(plane->state->crtc);
1536
+ vfbs = container_of(vfb, typeof(*vfbs), base);
1537
+
1538
+ memset(&srf_update, 0, sizeof(struct vmw_du_update_plane));
1539
+ srf_update.plane = plane;
1540
+ srf_update.old_state = old_state;
1541
+ srf_update.dev_priv = dev_priv;
1542
+ srf_update.du = vmw_crtc_to_du(plane->state->crtc);
1543
+ srf_update.vfb = vfb;
1544
+ srf_update.out_fence = out_fence;
1545
+ srf_update.mutex = &dev_priv->cmdbuf_mutex;
1546
+ srf_update.cpu_blit = false;
1547
+ srf_update.intr = true;
1548
+
1549
+ if (vfbs->is_bo_proxy)
1550
+ srf_update.post_prepare = vmw_stdu_surface_update_proxy;
1551
+
1552
+ if (vfbs->surface->res.id != stdu->display_srf->res.id) {
1553
+ srf_update.calc_fifo_size = vmw_stdu_surface_fifo_size;
1554
+ srf_update.pre_clip = vmw_stdu_surface_populate_copy;
1555
+ srf_update.clip = vmw_stdu_surface_populate_clip;
1556
+ } else {
1557
+ srf_update.calc_fifo_size =
1558
+ vmw_stdu_surface_fifo_size_same_display;
1559
+ }
1560
+
1561
+ srf_update.post_clip = vmw_stdu_surface_populate_update;
1562
+
1563
+ return vmw_du_helper_plane_update(&srf_update);
1564
+}
12441565
12451566 /**
12461567 * vmw_stdu_primary_plane_atomic_update - formally switches STDU to new plane
1247
- *
12481568 * @plane: display plane
12491569 * @old_state: Only used to get crtc info
12501570 *
....@@ -1261,17 +1581,14 @@
12611581 struct drm_crtc *crtc = plane->state->crtc;
12621582 struct vmw_screen_target_display_unit *stdu;
12631583 struct drm_pending_vblank_event *event;
1584
+ struct vmw_fence_obj *fence = NULL;
12641585 struct vmw_private *dev_priv;
12651586 int ret;
12661587
1267
- /*
1268
- * We cannot really fail this function, so if we do, then output an
1269
- * error and maintain consistent atomic state.
1270
- */
1588
+ /* If case of device error, maintain consistent atomic state */
12711589 if (crtc && plane->state->fb) {
12721590 struct vmw_framebuffer *vfb =
12731591 vmw_framebuffer_to_vfb(plane->state->fb);
1274
- struct drm_vmw_rect vclips;
12751592 stdu = vmw_crtc_to_stdu(crtc);
12761593 dev_priv = vmw_priv(crtc->dev);
12771594
....@@ -1279,23 +1596,17 @@
12791596 stdu->content_fb_type = vps->content_fb_type;
12801597 stdu->cpp = vps->cpp;
12811598
1282
- vclips.x = crtc->x;
1283
- vclips.y = crtc->y;
1284
- vclips.w = crtc->mode.hdisplay;
1285
- vclips.h = crtc->mode.vdisplay;
1286
-
12871599 ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
12881600 if (ret)
12891601 DRM_ERROR("Failed to bind surface to STDU.\n");
12901602
12911603 if (vfb->bo)
1292
- ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL,
1293
- &vclips, 1, 1, true, false,
1294
- crtc);
1604
+ ret = vmw_stdu_plane_update_bo(dev_priv, plane,
1605
+ old_state, vfb, &fence);
12951606 else
1296
- ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL,
1297
- &vclips, NULL, 0, 0,
1298
- 1, 1, NULL, crtc);
1607
+ ret = vmw_stdu_plane_update_surface(dev_priv, plane,
1608
+ old_state, vfb,
1609
+ &fence);
12991610 if (ret)
13001611 DRM_ERROR("Failed to update STDU.\n");
13011612 } else {
....@@ -1303,12 +1614,7 @@
13031614 stdu = vmw_crtc_to_stdu(crtc);
13041615 dev_priv = vmw_priv(crtc->dev);
13051616
1306
- /*
1307
- * When disabling a plane, CRTC and FB should always be NULL
1308
- * together, otherwise it's an error.
1309
- * Here primary plane is being disable so blank the screen
1310
- * target display unit, if not already done.
1311
- */
1617
+ /* Blank STDU when fb and crtc are NULL */
13121618 if (!stdu->defined)
13131619 return;
13141620
....@@ -1323,36 +1629,25 @@
13231629 return;
13241630 }
13251631
1632
+ /* In case of error, vblank event is send in vmw_du_crtc_atomic_flush */
13261633 event = crtc->state->event;
1327
- /*
1328
- * In case of failure and other cases, vblank event will be sent in
1329
- * vmw_du_crtc_atomic_flush.
1330
- */
1331
- if (event && (ret == 0)) {
1332
- struct vmw_fence_obj *fence = NULL;
1634
+ if (event && fence) {
13331635 struct drm_file *file_priv = event->base.file_priv;
13341636
1335
- vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
1336
-
1337
- /*
1338
- * If fence is NULL, then already sync.
1339
- */
1340
- if (fence) {
1341
- ret = vmw_event_fence_action_queue(
1342
- file_priv, fence, &event->base,
1343
- &event->event.vbl.tv_sec,
1344
- &event->event.vbl.tv_usec,
1345
- true);
1346
- if (ret)
1347
- DRM_ERROR("Failed to queue event on fence.\n");
1348
- else
1349
- crtc->state->event = NULL;
1350
-
1351
- vmw_fence_obj_unreference(&fence);
1352
- }
1353
- } else {
1354
- (void) vmw_fifo_flush(dev_priv, false);
1637
+ ret = vmw_event_fence_action_queue(file_priv,
1638
+ fence,
1639
+ &event->base,
1640
+ &event->event.vbl.tv_sec,
1641
+ &event->event.vbl.tv_usec,
1642
+ true);
1643
+ if (ret)
1644
+ DRM_ERROR("Failed to queue event on fence.\n");
1645
+ else
1646
+ crtc->state->event = NULL;
13551647 }
1648
+
1649
+ if (fence)
1650
+ vmw_fence_obj_unreference(&fence);
13561651 }
13571652
13581653
....@@ -1440,16 +1735,9 @@
14401735 stdu->base.pref_active = (unit == 0);
14411736 stdu->base.pref_width = dev_priv->initial_width;
14421737 stdu->base.pref_height = dev_priv->initial_height;
1443
-
1444
- /*
1445
- * Remove this after enabling atomic because property values can
1446
- * only exist in a state object
1447
- */
14481738 stdu->base.is_implicit = false;
14491739
14501740 /* Initialize primary plane */
1451
- vmw_du_plane_reset(primary);
1452
-
14531741 ret = drm_universal_plane_init(dev, primary,
14541742 0, &vmw_stdu_plane_funcs,
14551743 vmw_primary_plane_formats,
....@@ -1461,10 +1749,9 @@
14611749 }
14621750
14631751 drm_plane_helper_add(primary, &vmw_stdu_primary_plane_helper_funcs);
1752
+ drm_plane_enable_fb_damage_clips(primary);
14641753
14651754 /* Initialize cursor plane */
1466
- vmw_du_plane_reset(cursor);
1467
-
14681755 ret = drm_universal_plane_init(dev, cursor,
14691756 0, &vmw_stdu_cursor_funcs,
14701757 vmw_cursor_plane_formats,
....@@ -1478,8 +1765,6 @@
14781765
14791766 drm_plane_helper_add(cursor, &vmw_stdu_cursor_plane_helper_funcs);
14801767
1481
- vmw_du_connector_reset(connector);
1482
-
14831768 ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
14841769 DRM_MODE_CONNECTOR_VIRTUAL);
14851770 if (ret) {
....@@ -1489,7 +1774,6 @@
14891774
14901775 drm_connector_helper_add(connector, &vmw_stdu_connector_helper_funcs);
14911776 connector->status = vmw_du_connector_detect(connector, false);
1492
- vmw_connector_state_to_vcs(connector->state)->is_implicit = false;
14931777
14941778 ret = drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
14951779 DRM_MODE_ENCODER_VIRTUAL, NULL);
....@@ -1508,7 +1792,6 @@
15081792 goto err_free_encoder;
15091793 }
15101794
1511
- vmw_du_crtc_reset(crtc);
15121795 ret = drm_crtc_init_with_planes(dev, crtc, &stdu->base.primary,
15131796 &stdu->base.cursor,
15141797 &vmw_stdu_crtc_funcs, NULL);
....@@ -1527,11 +1810,6 @@
15271810 dev->mode_config.suggested_x_property, 0);
15281811 drm_object_attach_property(&connector->base,
15291812 dev->mode_config.suggested_y_property, 0);
1530
- if (dev_priv->implicit_placement_property)
1531
- drm_object_attach_property
1532
- (&connector->base,
1533
- dev_priv->implicit_placement_property,
1534
- stdu->base.is_implicit);
15351813 return 0;
15361814
15371815 err_free_unregister:
....@@ -1588,7 +1866,7 @@
15881866
15891867
15901868 /* Do nothing if Screen Target support is turned off */
1591
- if (!VMWGFX_ENABLE_SCREEN_TARGET_OTABLE)
1869
+ if (!VMWGFX_ENABLE_SCREEN_TARGET_OTABLE || !dev_priv->has_mob)
15921870 return -ENOSYS;
15931871
15941872 if (!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS))
....@@ -1600,8 +1878,6 @@
16001878
16011879 dev_priv->active_display_unit = vmw_du_screen_target;
16021880
1603
- vmw_kms_create_implicit_placement_property(dev_priv, false);
1604
-
16051881 for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) {
16061882 ret = vmw_stdu_init(dev_priv, i);
16071883
....@@ -1611,6 +1887,8 @@
16111887 }
16121888 }
16131889
1890
+ drm_mode_config_reset(dev);
1891
+
16141892 DRM_INFO("Screen Target Display device initialized\n");
16151893
16161894 return 0;