diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 280 |
1 files changed, 132 insertions, 148 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index b68d74888ab1..8eec88920851 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | |||
@@ -114,7 +114,6 @@ struct vmw_screen_target_display_unit { | |||
114 | bool defined; | 114 | bool defined; |
115 | 115 | ||
116 | /* For CPU Blit */ | 116 | /* For CPU Blit */ |
117 | struct ttm_bo_kmap_obj host_map; | ||
118 | unsigned int cpp; | 117 | unsigned int cpp; |
119 | }; | 118 | }; |
120 | 119 | ||
@@ -492,71 +491,17 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, | |||
492 | { | 491 | { |
493 | struct vmw_private *dev_priv = vmw_priv(crtc->dev); | 492 | struct vmw_private *dev_priv = vmw_priv(crtc->dev); |
494 | struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc); | 493 | struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc); |
495 | struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb); | ||
496 | struct drm_vmw_rect vclips; | ||
497 | int ret; | 494 | int ret; |
498 | 495 | ||
499 | dev_priv = vmw_priv(crtc->dev); | ||
500 | stdu = vmw_crtc_to_stdu(crtc); | ||
501 | |||
502 | if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc)) | 496 | if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc)) |
503 | return -EINVAL; | 497 | return -EINVAL; |
504 | 498 | ||
505 | /* | 499 | ret = drm_atomic_helper_page_flip(crtc, new_fb, event, flags, ctx); |
506 | * We're always async, but the helper doesn't know how to set async | ||
507 | * so lie to the helper. Also, the helper expects someone | ||
508 | * to pick the event up from the crtc state, and if nobody does, | ||
509 | * it will free it. Since we handle the event in this function, | ||
510 | * don't hand it to the helper. | ||
511 | */ | ||
512 | flags &= ~DRM_MODE_PAGE_FLIP_ASYNC; | ||
513 | ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags, ctx); | ||
514 | if (ret) { | 500 | if (ret) { |
515 | DRM_ERROR("Page flip error %d.\n", ret); | 501 | DRM_ERROR("Page flip error %d.\n", ret); |
516 | return ret; | 502 | return ret; |
517 | } | 503 | } |
518 | 504 | ||
519 | if (stdu->base.is_implicit) | ||
520 | vmw_kms_update_implicit_fb(dev_priv, crtc); | ||
521 | |||
522 | /* | ||
523 | * Now that we've bound a new surface to the screen target, | ||
524 | * update the contents. | ||
525 | */ | ||
526 | vclips.x = crtc->x; | ||
527 | vclips.y = crtc->y; | ||
528 | vclips.w = crtc->mode.hdisplay; | ||
529 | vclips.h = crtc->mode.vdisplay; | ||
530 | |||
531 | if (vfb->dmabuf) | ||
532 | ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL, &vclips, | ||
533 | 1, 1, true, false); | ||
534 | else | ||
535 | ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, &vclips, | ||
536 | NULL, 0, 0, 1, 1, NULL); | ||
537 | if (ret) { | ||
538 | DRM_ERROR("Page flip update error %d.\n", ret); | ||
539 | return ret; | ||
540 | } | ||
541 | |||
542 | if (event) { | ||
543 | struct vmw_fence_obj *fence = NULL; | ||
544 | struct drm_file *file_priv = event->base.file_priv; | ||
545 | |||
546 | vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); | ||
547 | if (!fence) | ||
548 | return -ENOMEM; | ||
549 | |||
550 | ret = vmw_event_fence_action_queue(file_priv, fence, | ||
551 | &event->base, | ||
552 | &event->event.vbl.tv_sec, | ||
553 | &event->event.vbl.tv_usec, | ||
554 | true); | ||
555 | vmw_fence_obj_unreference(&fence); | ||
556 | } else { | ||
557 | (void) vmw_fifo_flush(dev_priv, false); | ||
558 | } | ||
559 | |||
560 | return 0; | 505 | return 0; |
561 | } | 506 | } |
562 | 507 | ||
@@ -693,10 +638,9 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) | |||
693 | container_of(dirty->unit, typeof(*stdu), base); | 638 | container_of(dirty->unit, typeof(*stdu), base); |
694 | s32 width, height; | 639 | s32 width, height; |
695 | s32 src_pitch, dst_pitch; | 640 | s32 src_pitch, dst_pitch; |
696 | u8 *src, *dst; | 641 | struct ttm_buffer_object *src_bo, *dst_bo; |
697 | bool not_used; | 642 | u32 src_offset, dst_offset; |
698 | struct ttm_bo_kmap_obj guest_map; | 643 | struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(stdu->cpp); |
699 | int ret; | ||
700 | 644 | ||
701 | if (!dirty->num_hits) | 645 | if (!dirty->num_hits) |
702 | return; | 646 | return; |
@@ -707,57 +651,38 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) | |||
707 | if (width == 0 || height == 0) | 651 | if (width == 0 || height == 0) |
708 | return; | 652 | return; |
709 | 653 | ||
710 | ret = ttm_bo_kmap(&ddirty->buf->base, 0, ddirty->buf->base.num_pages, | 654 | /* Assume we are blitting from Guest (dmabuf) to Host (display_srf) */ |
711 | &guest_map); | 655 | dst_pitch = stdu->display_srf->base_size.width * stdu->cpp; |
712 | if (ret) { | 656 | dst_bo = &stdu->display_srf->res.backup->base; |
713 | DRM_ERROR("Failed mapping framebuffer for blit: %d\n", | 657 | dst_offset = ddirty->top * dst_pitch + ddirty->left * stdu->cpp; |
714 | ret); | ||
715 | goto out_cleanup; | ||
716 | } | ||
717 | |||
718 | /* Assume we are blitting from Host (display_srf) to Guest (dmabuf) */ | ||
719 | src_pitch = stdu->display_srf->base_size.width * stdu->cpp; | ||
720 | src = ttm_kmap_obj_virtual(&stdu->host_map, ¬_used); | ||
721 | src += ddirty->top * src_pitch + ddirty->left * stdu->cpp; | ||
722 | |||
723 | dst_pitch = ddirty->pitch; | ||
724 | dst = ttm_kmap_obj_virtual(&guest_map, ¬_used); | ||
725 | dst += ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp; | ||
726 | |||
727 | |||
728 | /* Figure out the real direction */ | ||
729 | if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) { | ||
730 | u8 *tmp; | ||
731 | s32 tmp_pitch; | ||
732 | |||
733 | tmp = src; | ||
734 | tmp_pitch = src_pitch; | ||
735 | 658 | ||
736 | src = dst; | 659 | src_pitch = ddirty->pitch; |
737 | src_pitch = dst_pitch; | 660 | src_bo = &ddirty->buf->base; |
661 | src_offset = ddirty->fb_top * src_pitch + ddirty->fb_left * stdu->cpp; | ||
738 | 662 | ||
739 | dst = tmp; | 663 | /* Swap src and dst if the assumption was wrong. */ |
740 | dst_pitch = tmp_pitch; | 664 | if (ddirty->transfer != SVGA3D_WRITE_HOST_VRAM) { |
665 | swap(dst_pitch, src_pitch); | ||
666 | swap(dst_bo, src_bo); | ||
667 | swap(src_offset, dst_offset); | ||
741 | } | 668 | } |
742 | 669 | ||
743 | /* CPU Blit */ | 670 | (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, |
744 | while (height-- > 0) { | 671 | src_bo, src_offset, src_pitch, |
745 | memcpy(dst, src, width * stdu->cpp); | 672 | width * stdu->cpp, height, &diff); |
746 | dst += dst_pitch; | ||
747 | src += src_pitch; | ||
748 | } | ||
749 | 673 | ||
750 | if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM) { | 674 | if (ddirty->transfer == SVGA3D_WRITE_HOST_VRAM && |
675 | drm_rect_visible(&diff.rect)) { | ||
751 | struct vmw_private *dev_priv; | 676 | struct vmw_private *dev_priv; |
752 | struct vmw_stdu_update *cmd; | 677 | struct vmw_stdu_update *cmd; |
753 | struct drm_clip_rect region; | 678 | struct drm_clip_rect region; |
754 | int ret; | 679 | int ret; |
755 | 680 | ||
756 | /* We are updating the actual surface, not a proxy */ | 681 | /* We are updating the actual surface, not a proxy */ |
757 | region.x1 = ddirty->left; | 682 | region.x1 = diff.rect.x1; |
758 | region.x2 = ddirty->right; | 683 | region.x2 = diff.rect.x2; |
759 | region.y1 = ddirty->top; | 684 | region.y1 = diff.rect.y1; |
760 | region.y2 = ddirty->bottom; | 685 | region.y2 = diff.rect.y2; |
761 | ret = vmw_kms_update_proxy( | 686 | ret = vmw_kms_update_proxy( |
762 | (struct vmw_resource *) &stdu->display_srf->res, | 687 | (struct vmw_resource *) &stdu->display_srf->res, |
763 | (const struct drm_clip_rect *) ®ion, 1, 1); | 688 | (const struct drm_clip_rect *) ®ion, 1, 1); |
@@ -774,13 +699,12 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) | |||
774 | } | 699 | } |
775 | 700 | ||
776 | vmw_stdu_populate_update(cmd, stdu->base.unit, | 701 | vmw_stdu_populate_update(cmd, stdu->base.unit, |
777 | ddirty->left, ddirty->right, | 702 | region.x1, region.x2, |
778 | ddirty->top, ddirty->bottom); | 703 | region.y1, region.y2); |
779 | 704 | ||
780 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); | 705 | vmw_fifo_commit(dev_priv, sizeof(*cmd)); |
781 | } | 706 | } |
782 | 707 | ||
783 | ttm_bo_kunmap(&guest_map); | ||
784 | out_cleanup: | 708 | out_cleanup: |
785 | ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX; | 709 | ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX; |
786 | ddirty->right = ddirty->bottom = S32_MIN; | 710 | ddirty->right = ddirty->bottom = S32_MIN; |
@@ -802,6 +726,7 @@ out_cleanup: | |||
802 | * @to_surface: Whether to DMA to the screen target system as opposed to | 726 | * @to_surface: Whether to DMA to the screen target system as opposed to |
803 | * from the screen target system. | 727 | * from the screen target system. |
804 | * @interruptible: Whether to perform waits interruptible if possible. | 728 | * @interruptible: Whether to perform waits interruptible if possible. |
729 | * @crtc: If crtc is passed, perform stdu dma on that crtc only. | ||
805 | * | 730 | * |
806 | * If DMA-ing till the screen target system, the function will also notify | 731 | * If DMA-ing till the screen target system, the function will also notify |
807 | * the screen target system that a bounding box of the cliprects has been | 732 | * the screen target system that a bounding box of the cliprects has been |
@@ -818,15 +743,22 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, | |||
818 | uint32_t num_clips, | 743 | uint32_t num_clips, |
819 | int increment, | 744 | int increment, |
820 | bool to_surface, | 745 | bool to_surface, |
821 | bool interruptible) | 746 | bool interruptible, |
747 | struct drm_crtc *crtc) | ||
822 | { | 748 | { |
823 | struct vmw_dma_buffer *buf = | 749 | struct vmw_dma_buffer *buf = |
824 | container_of(vfb, struct vmw_framebuffer_dmabuf, base)->buffer; | 750 | container_of(vfb, struct vmw_framebuffer_dmabuf, base)->buffer; |
825 | struct vmw_stdu_dirty ddirty; | 751 | struct vmw_stdu_dirty ddirty; |
826 | int ret; | 752 | int ret; |
753 | bool cpu_blit = !(dev_priv->capabilities & SVGA_CAP_3D); | ||
827 | 754 | ||
755 | /* | ||
756 | * VMs without 3D support don't have the surface DMA command and | ||
757 | * we'll be using a CPU blit, and the framebuffer should be moved out | ||
758 | * of VRAM. | ||
759 | */ | ||
828 | ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, interruptible, | 760 | ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, interruptible, |
829 | false); | 761 | false, cpu_blit); |
830 | if (ret) | 762 | if (ret) |
831 | return ret; | 763 | return ret; |
832 | 764 | ||
@@ -845,13 +777,15 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, | |||
845 | if (to_surface) | 777 | if (to_surface) |
846 | ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update); | 778 | ddirty.base.fifo_reserve_size += sizeof(struct vmw_stdu_update); |
847 | 779 | ||
848 | /* 2D VMs cannot use SVGA_3D_CMD_SURFACE_DMA so do CPU blit instead */ | 780 | |
849 | if (!(dev_priv->capabilities & SVGA_CAP_3D)) { | 781 | if (cpu_blit) { |
850 | ddirty.base.fifo_commit = vmw_stdu_dmabuf_cpu_commit; | 782 | ddirty.base.fifo_commit = vmw_stdu_dmabuf_cpu_commit; |
851 | ddirty.base.clip = vmw_stdu_dmabuf_cpu_clip; | 783 | ddirty.base.clip = vmw_stdu_dmabuf_cpu_clip; |
852 | ddirty.base.fifo_reserve_size = 0; | 784 | ddirty.base.fifo_reserve_size = 0; |
853 | } | 785 | } |
854 | 786 | ||
787 | ddirty.base.crtc = crtc; | ||
788 | |||
855 | ret = vmw_kms_helper_dirty(dev_priv, vfb, clips, vclips, | 789 | ret = vmw_kms_helper_dirty(dev_priv, vfb, clips, vclips, |
856 | 0, 0, num_clips, increment, &ddirty.base); | 790 | 0, 0, num_clips, increment, &ddirty.base); |
857 | vmw_kms_helper_buffer_finish(dev_priv, file_priv, buf, NULL, | 791 | vmw_kms_helper_buffer_finish(dev_priv, file_priv, buf, NULL, |
@@ -963,6 +897,7 @@ static void vmw_kms_stdu_surface_fifo_commit(struct vmw_kms_dirty *dirty) | |||
963 | * @out_fence: If non-NULL, will return a ref-counted pointer to a | 897 | * @out_fence: If non-NULL, will return a ref-counted pointer to a |
964 | * struct vmw_fence_obj. The returned fence pointer may be NULL in which | 898 | * struct vmw_fence_obj. The returned fence pointer may be NULL in which |
965 | * case the device has already synchronized. | 899 | * case the device has already synchronized. |
900 | * @crtc: If crtc is passed, perform surface dirty on that crtc only. | ||
966 | * | 901 | * |
967 | * Returns 0 on success, negative error code on failure. -ERESTARTSYS if | 902 | * Returns 0 on success, negative error code on failure. -ERESTARTSYS if |
968 | * interrupted. | 903 | * interrupted. |
@@ -975,7 +910,8 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, | |||
975 | s32 dest_x, | 910 | s32 dest_x, |
976 | s32 dest_y, | 911 | s32 dest_y, |
977 | unsigned num_clips, int inc, | 912 | unsigned num_clips, int inc, |
978 | struct vmw_fence_obj **out_fence) | 913 | struct vmw_fence_obj **out_fence, |
914 | struct drm_crtc *crtc) | ||
979 | { | 915 | { |
980 | struct vmw_framebuffer_surface *vfbs = | 916 | struct vmw_framebuffer_surface *vfbs = |
981 | container_of(framebuffer, typeof(*vfbs), base); | 917 | container_of(framebuffer, typeof(*vfbs), base); |
@@ -1000,6 +936,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, | |||
1000 | sdirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_surface_copy) + | 936 | sdirty.base.fifo_reserve_size = sizeof(struct vmw_stdu_surface_copy) + |
1001 | sizeof(SVGA3dCopyBox) * num_clips + | 937 | sizeof(SVGA3dCopyBox) * num_clips + |
1002 | sizeof(struct vmw_stdu_update); | 938 | sizeof(struct vmw_stdu_update); |
939 | sdirty.base.crtc = crtc; | ||
1003 | sdirty.sid = srf->id; | 940 | sdirty.sid = srf->id; |
1004 | sdirty.left = sdirty.top = S32_MAX; | 941 | sdirty.left = sdirty.top = S32_MAX; |
1005 | sdirty.right = sdirty.bottom = S32_MIN; | 942 | sdirty.right = sdirty.bottom = S32_MIN; |
@@ -1118,9 +1055,6 @@ vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane, | |||
1118 | { | 1055 | { |
1119 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); | 1056 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); |
1120 | 1057 | ||
1121 | if (vps->host_map.virtual) | ||
1122 | ttm_bo_kunmap(&vps->host_map); | ||
1123 | |||
1124 | if (vps->surf) | 1058 | if (vps->surf) |
1125 | WARN_ON(!vps->pinned); | 1059 | WARN_ON(!vps->pinned); |
1126 | 1060 | ||
@@ -1282,24 +1216,11 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, | |||
1282 | * so cache these mappings | 1216 | * so cache these mappings |
1283 | */ | 1217 | */ |
1284 | if (vps->content_fb_type == SEPARATE_DMA && | 1218 | if (vps->content_fb_type == SEPARATE_DMA && |
1285 | !(dev_priv->capabilities & SVGA_CAP_3D)) { | 1219 | !(dev_priv->capabilities & SVGA_CAP_3D)) |
1286 | ret = ttm_bo_kmap(&vps->surf->res.backup->base, 0, | ||
1287 | vps->surf->res.backup->base.num_pages, | ||
1288 | &vps->host_map); | ||
1289 | if (ret) { | ||
1290 | DRM_ERROR("Failed to map display buffer to CPU\n"); | ||
1291 | goto out_srf_unpin; | ||
1292 | } | ||
1293 | |||
1294 | vps->cpp = new_fb->pitches[0] / new_fb->width; | 1220 | vps->cpp = new_fb->pitches[0] / new_fb->width; |
1295 | } | ||
1296 | 1221 | ||
1297 | return 0; | 1222 | return 0; |
1298 | 1223 | ||
1299 | out_srf_unpin: | ||
1300 | vmw_resource_unpin(&vps->surf->res); | ||
1301 | vps->pinned--; | ||
1302 | |||
1303 | out_srf_unref: | 1224 | out_srf_unref: |
1304 | vmw_surface_unreference(&vps->surf); | 1225 | vmw_surface_unreference(&vps->surf); |
1305 | return ret; | 1226 | return ret; |
@@ -1322,41 +1243,104 @@ static void | |||
1322 | vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane, | 1243 | vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane, |
1323 | struct drm_plane_state *old_state) | 1244 | struct drm_plane_state *old_state) |
1324 | { | 1245 | { |
1325 | struct vmw_private *dev_priv; | ||
1326 | struct vmw_screen_target_display_unit *stdu; | ||
1327 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(plane->state); | 1246 | struct vmw_plane_state *vps = vmw_plane_state_to_vps(plane->state); |
1328 | struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc; | 1247 | struct drm_crtc *crtc = plane->state->crtc; |
1248 | struct vmw_screen_target_display_unit *stdu; | ||
1249 | struct drm_pending_vblank_event *event; | ||
1250 | struct vmw_private *dev_priv; | ||
1329 | int ret; | 1251 | int ret; |
1330 | 1252 | ||
1331 | stdu = vmw_crtc_to_stdu(crtc); | 1253 | /* |
1332 | dev_priv = vmw_priv(crtc->dev); | 1254 | * We cannot really fail this function, so if we do, then output an |
1255 | * error and maintain consistent atomic state. | ||
1256 | */ | ||
1257 | if (crtc && plane->state->fb) { | ||
1258 | struct vmw_framebuffer *vfb = | ||
1259 | vmw_framebuffer_to_vfb(plane->state->fb); | ||
1260 | struct drm_vmw_rect vclips; | ||
1261 | stdu = vmw_crtc_to_stdu(crtc); | ||
1262 | dev_priv = vmw_priv(crtc->dev); | ||
1263 | |||
1264 | stdu->display_srf = vps->surf; | ||
1265 | stdu->content_fb_type = vps->content_fb_type; | ||
1266 | stdu->cpp = vps->cpp; | ||
1267 | |||
1268 | vclips.x = crtc->x; | ||
1269 | vclips.y = crtc->y; | ||
1270 | vclips.w = crtc->mode.hdisplay; | ||
1271 | vclips.h = crtc->mode.vdisplay; | ||
1272 | |||
1273 | ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res); | ||
1274 | if (ret) | ||
1275 | DRM_ERROR("Failed to bind surface to STDU.\n"); | ||
1276 | |||
1277 | if (vfb->dmabuf) | ||
1278 | ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL, | ||
1279 | &vclips, 1, 1, true, false, | ||
1280 | crtc); | ||
1281 | else | ||
1282 | ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, | ||
1283 | &vclips, NULL, 0, 0, | ||
1284 | 1, 1, NULL, crtc); | ||
1285 | if (ret) | ||
1286 | DRM_ERROR("Failed to update STDU.\n"); | ||
1333 | 1287 | ||
1334 | stdu->display_srf = vps->surf; | 1288 | crtc->primary->fb = plane->state->fb; |
1335 | stdu->content_fb_type = vps->content_fb_type; | 1289 | } else { |
1336 | stdu->cpp = vps->cpp; | 1290 | crtc = old_state->crtc; |
1337 | memcpy(&stdu->host_map, &vps->host_map, sizeof(vps->host_map)); | 1291 | stdu = vmw_crtc_to_stdu(crtc); |
1292 | dev_priv = vmw_priv(crtc->dev); | ||
1338 | 1293 | ||
1339 | if (!stdu->defined) | 1294 | /* |
1340 | return; | 1295 | * When disabling a plane, CRTC and FB should always be NULL |
1296 | * together, otherwise it's an error. | ||
1297 | * Here primary plane is being disable so blank the screen | ||
1298 | * target display unit, if not already done. | ||
1299 | */ | ||
1300 | if (!stdu->defined) | ||
1301 | return; | ||
1341 | 1302 | ||
1342 | if (plane->state->fb) | ||
1343 | ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res); | ||
1344 | else | ||
1345 | ret = vmw_stdu_bind_st(dev_priv, stdu, NULL); | 1303 | ret = vmw_stdu_bind_st(dev_priv, stdu, NULL); |
1304 | if (ret) | ||
1305 | DRM_ERROR("Failed to blank STDU\n"); | ||
1306 | |||
1307 | ret = vmw_stdu_update_st(dev_priv, stdu); | ||
1308 | if (ret) | ||
1309 | DRM_ERROR("Failed to update STDU.\n"); | ||
1310 | |||
1311 | return; | ||
1312 | } | ||
1346 | 1313 | ||
1314 | event = crtc->state->event; | ||
1347 | /* | 1315 | /* |
1348 | * We cannot really fail this function, so if we do, then output an | 1316 | * In case of failure and other cases, vblank event will be sent in |
1349 | * error and quit | 1317 | * vmw_du_crtc_atomic_flush. |
1350 | */ | 1318 | */ |
1351 | if (ret) | 1319 | if (event && (ret == 0)) { |
1352 | DRM_ERROR("Failed to bind surface to STDU.\n"); | 1320 | struct vmw_fence_obj *fence = NULL; |
1353 | else | 1321 | struct drm_file *file_priv = event->base.file_priv; |
1354 | crtc->primary->fb = plane->state->fb; | ||
1355 | 1322 | ||
1356 | ret = vmw_stdu_update_st(dev_priv, stdu); | 1323 | vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); |
1357 | 1324 | ||
1358 | if (ret) | 1325 | /* |
1359 | DRM_ERROR("Failed to update STDU.\n"); | 1326 | * If fence is NULL, then already sync. |
1327 | */ | ||
1328 | if (fence) { | ||
1329 | ret = vmw_event_fence_action_queue( | ||
1330 | file_priv, fence, &event->base, | ||
1331 | &event->event.vbl.tv_sec, | ||
1332 | &event->event.vbl.tv_usec, | ||
1333 | true); | ||
1334 | if (ret) | ||
1335 | DRM_ERROR("Failed to queue event on fence.\n"); | ||
1336 | else | ||
1337 | crtc->state->event = NULL; | ||
1338 | |||
1339 | vmw_fence_obj_unreference(&fence); | ||
1340 | } | ||
1341 | } else { | ||
1342 | (void) vmw_fifo_flush(dev_priv, false); | ||
1343 | } | ||
1360 | } | 1344 | } |
1361 | 1345 | ||
1362 | 1346 | ||