aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_kms.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c91
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
1684int 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
1742out_no_fence:
1743 crtc->fb = old_fb;
1744 return ret;
1745}
1746
1747
1675void vmw_du_crtc_save(struct drm_crtc *crtc) 1748void vmw_du_crtc_save(struct drm_crtc *crtc)
1676{ 1749{
1677} 1750}