diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_kms.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 91 |
1 files changed, 82 insertions, 9 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index b66ef0e3cde1..2286d47e5022 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -422,7 +422,8 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, | |||
422 | struct vmw_framebuffer *framebuffer, | 422 | struct vmw_framebuffer *framebuffer, |
423 | unsigned flags, unsigned color, | 423 | unsigned flags, unsigned color, |
424 | struct drm_clip_rect *clips, | 424 | struct drm_clip_rect *clips, |
425 | unsigned num_clips, int inc) | 425 | unsigned num_clips, int inc, |
426 | struct vmw_fence_obj **out_fence) | ||
426 | { | 427 | { |
427 | struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; | 428 | struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; |
428 | struct drm_clip_rect *clips_ptr; | 429 | struct drm_clip_rect *clips_ptr; |
@@ -542,12 +543,15 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, | |||
542 | if (num == 0) | 543 | if (num == 0) |
543 | continue; | 544 | continue; |
544 | 545 | ||
546 | /* only return the last fence */ | ||
547 | if (out_fence && *out_fence) | ||
548 | vmw_fence_obj_unreference(out_fence); | ||
545 | 549 | ||
546 | /* recalculate package length */ | 550 | /* recalculate package length */ |
547 | fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; | 551 | fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; |
548 | cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); | 552 | cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); |
549 | ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, | 553 | ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, |
550 | fifo_size, 0, NULL); | 554 | fifo_size, 0, NULL, out_fence); |
551 | 555 | ||
552 | if (unlikely(ret != 0)) | 556 | if (unlikely(ret != 0)) |
553 | break; | 557 | break; |
@@ -598,7 +602,7 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, | |||
598 | 602 | ||
599 | ret = do_surface_dirty_sou(dev_priv, file_priv, &vfbs->base, | 603 | ret = do_surface_dirty_sou(dev_priv, file_priv, &vfbs->base, |
600 | flags, color, | 604 | flags, color, |
601 | clips, num_clips, inc); | 605 | clips, num_clips, inc, NULL); |
602 | 606 | ||
603 | ttm_read_unlock(&vmaster->lock); | 607 | ttm_read_unlock(&vmaster->lock); |
604 | return 0; | 608 | return 0; |
@@ -809,7 +813,7 @@ static int do_dmabuf_define_gmrfb(struct drm_file *file_priv, | |||
809 | cmd->body.ptr.offset = 0; | 813 | cmd->body.ptr.offset = 0; |
810 | 814 | ||
811 | ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, | 815 | ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, |
812 | fifo_size, 0, NULL); | 816 | fifo_size, 0, NULL, NULL); |
813 | 817 | ||
814 | kfree(cmd); | 818 | kfree(cmd); |
815 | 819 | ||
@@ -821,7 +825,8 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv, | |||
821 | struct vmw_framebuffer *framebuffer, | 825 | struct vmw_framebuffer *framebuffer, |
822 | unsigned flags, unsigned color, | 826 | unsigned flags, unsigned color, |
823 | struct drm_clip_rect *clips, | 827 | struct drm_clip_rect *clips, |
824 | unsigned num_clips, int increment) | 828 | unsigned num_clips, int increment, |
829 | struct vmw_fence_obj **out_fence) | ||
825 | { | 830 | { |
826 | struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; | 831 | struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; |
827 | struct drm_clip_rect *clips_ptr; | 832 | struct drm_clip_rect *clips_ptr; |
@@ -894,9 +899,13 @@ static int do_dmabuf_dirty_sou(struct drm_file *file_priv, | |||
894 | if (hit_num == 0) | 899 | if (hit_num == 0) |
895 | continue; | 900 | continue; |
896 | 901 | ||
902 | /* only return the last fence */ | ||
903 | if (out_fence && *out_fence) | ||
904 | vmw_fence_obj_unreference(out_fence); | ||
905 | |||
897 | fifo_size = sizeof(*blits) * hit_num; | 906 | fifo_size = sizeof(*blits) * hit_num; |
898 | ret = vmw_execbuf_process(file_priv, dev_priv, NULL, blits, | 907 | ret = vmw_execbuf_process(file_priv, dev_priv, NULL, blits, |
899 | fifo_size, 0, NULL); | 908 | fifo_size, 0, NULL, out_fence); |
900 | 909 | ||
901 | if (unlikely(ret != 0)) | 910 | if (unlikely(ret != 0)) |
902 | break; | 911 | break; |
@@ -942,7 +951,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, | |||
942 | } else { | 951 | } else { |
943 | ret = do_dmabuf_dirty_sou(file_priv, dev_priv, &vfbd->base, | 952 | ret = do_dmabuf_dirty_sou(file_priv, dev_priv, &vfbd->base, |
944 | flags, color, | 953 | flags, color, |
945 | clips, num_clips, increment); | 954 | clips, num_clips, increment, NULL); |
946 | } | 955 | } |
947 | 956 | ||
948 | ttm_read_unlock(&vmaster->lock); | 957 | ttm_read_unlock(&vmaster->lock); |
@@ -1296,7 +1305,7 @@ int vmw_kms_present(struct vmw_private *dev_priv, | |||
1296 | fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; | 1305 | fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num; |
1297 | cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); | 1306 | cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); |
1298 | ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, | 1307 | ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, |
1299 | fifo_size, 0, NULL); | 1308 | fifo_size, 0, NULL, NULL); |
1300 | 1309 | ||
1301 | if (unlikely(ret != 0)) | 1310 | if (unlikely(ret != 0)) |
1302 | break; | 1311 | break; |
@@ -1409,7 +1418,7 @@ int vmw_kms_readback(struct vmw_private *dev_priv, | |||
1409 | fifo_size = sizeof(*cmd) + sizeof(*blits) * blits_pos; | 1418 | fifo_size = sizeof(*cmd) + sizeof(*blits) * blits_pos; |
1410 | 1419 | ||
1411 | ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size, | 1420 | ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size, |
1412 | 0, user_fence_rep); | 1421 | 0, user_fence_rep, NULL); |
1413 | 1422 | ||
1414 | kfree(cmd); | 1423 | kfree(cmd); |
1415 | 1424 | ||
@@ -1672,6 +1681,70 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, | |||
1672 | return 0; | 1681 | return 0; |
1673 | } | 1682 | } |
1674 | 1683 | ||
1684 | int vmw_du_page_flip(struct drm_crtc *crtc, | ||
1685 | struct drm_framebuffer *fb, | ||
1686 | struct drm_pending_vblank_event *event) | ||
1687 | { | ||
1688 | struct vmw_private *dev_priv = vmw_priv(crtc->dev); | ||
1689 | struct drm_framebuffer *old_fb = crtc->fb; | ||
1690 | struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); | ||
1691 | struct drm_file *file_priv = event->base.file_priv; | ||
1692 | struct vmw_fence_obj *fence = NULL; | ||
1693 | struct drm_clip_rect clips; | ||
1694 | int ret; | ||
1695 | |||
1696 | /* require ScreenObject support for page flipping */ | ||
1697 | if (!dev_priv->sou_priv) | ||
1698 | return -ENOSYS; | ||
1699 | |||
1700 | if (!vmw_kms_screen_object_flippable(dev_priv, crtc)) | ||
1701 | return -EINVAL; | ||
1702 | |||
1703 | crtc->fb = fb; | ||
1704 | |||
1705 | /* do a full screen dirty update */ | ||
1706 | clips.x1 = clips.y1 = 0; | ||
1707 | clips.x2 = fb->width; | ||
1708 | clips.y2 = fb->height; | ||
1709 | |||
1710 | if (vfb->dmabuf) | ||
1711 | ret = do_dmabuf_dirty_sou(file_priv, dev_priv, vfb, | ||
1712 | 0, 0, &clips, 1, 1, &fence); | ||
1713 | else | ||
1714 | ret = do_surface_dirty_sou(dev_priv, file_priv, vfb, | ||
1715 | 0, 0, &clips, 1, 1, &fence); | ||
1716 | |||
1717 | |||
1718 | if (ret != 0) | ||
1719 | goto out_no_fence; | ||
1720 | if (!fence) { | ||
1721 | ret = -EINVAL; | ||
1722 | goto out_no_fence; | ||
1723 | } | ||
1724 | |||
1725 | ret = vmw_event_fence_action_queue(file_priv, fence, | ||
1726 | &event->base, | ||
1727 | &event->event.tv_sec, | ||
1728 | &event->event.tv_usec, | ||
1729 | true); | ||
1730 | |||
1731 | /* | ||
1732 | * No need to hold on to this now. The only cleanup | ||
1733 | * we need to do if we fail is unref the fence. | ||
1734 | */ | ||
1735 | vmw_fence_obj_unreference(&fence); | ||
1736 | |||
1737 | if (vmw_crtc_to_du(crtc)->is_implicit) | ||
1738 | vmw_kms_screen_object_update_implicit_fb(dev_priv, crtc); | ||
1739 | |||
1740 | return ret; | ||
1741 | |||
1742 | out_no_fence: | ||
1743 | crtc->fb = old_fb; | ||
1744 | return ret; | ||
1745 | } | ||
1746 | |||
1747 | |||
1675 | void vmw_du_crtc_save(struct drm_crtc *crtc) | 1748 | void vmw_du_crtc_save(struct drm_crtc *crtc) |
1676 | { | 1749 | { |
1677 | } | 1750 | } |