summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c102
1 files changed, 86 insertions, 16 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index a56e5d0ca3c6..a82fa9700370 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR MIT
/**************************************************************************
*
- * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA
+ * Copyright 2009-2023 VMware, Inc., Palo Alto, CA., USA
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
@@ -25,11 +25,13 @@
*
**************************************************************************/
+#include "vmwgfx_bo.h"
+#include "vmwgfx_kms.h"
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fourcc.h>
-#include "vmwgfx_kms.h"
#define vmw_crtc_to_ldu(x) \
container_of(x, struct vmw_legacy_display_unit, base.crtc)
@@ -134,6 +136,47 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
return 0;
}
+/*
+ * Pin the buffer in a location suitable for access by the
+ * display system.
+ */
+static int vmw_ldu_fb_pin(struct vmw_framebuffer *vfb)
+{
+ struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
+ struct vmw_bo *buf;
+ int ret;
+
+ buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer :
+ vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.guest_memory_bo;
+
+ if (!buf)
+ return 0;
+ WARN_ON(dev_priv->active_display_unit != vmw_du_legacy);
+
+ if (dev_priv->active_display_unit == vmw_du_legacy) {
+ vmw_overlay_pause_all(dev_priv);
+ ret = vmw_bo_pin_in_start_of_vram(dev_priv, buf, false);
+ vmw_overlay_resume_all(dev_priv);
+ } else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static int vmw_ldu_fb_unpin(struct vmw_framebuffer *vfb)
+{
+ struct vmw_private *dev_priv = vmw_priv(vfb->base.dev);
+ struct vmw_bo *buf;
+
+ buf = vfb->bo ? vmw_framebuffer_to_vfbd(&vfb->base)->buffer :
+ vmw_framebuffer_to_vfbs(&vfb->base)->surface->res.guest_memory_bo;
+
+ if (WARN_ON(!buf))
+ return 0;
+
+ return vmw_bo_unpin(dev_priv, buf, false);
+}
+
static int vmw_ldu_del_active(struct vmw_private *vmw_priv,
struct vmw_legacy_display_unit *ldu)
{
@@ -145,8 +188,7 @@ static int vmw_ldu_del_active(struct vmw_private *vmw_priv,
list_del_init(&ldu->active);
if (--(ld->num_active) == 0) {
BUG_ON(!ld->fb);
- if (ld->fb->unpin)
- ld->fb->unpin(ld->fb);
+ WARN_ON(vmw_ldu_fb_unpin(ld->fb));
ld->fb = NULL;
}
@@ -163,11 +205,10 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
BUG_ON(!ld->num_active && ld->fb);
if (vfb != ld->fb) {
- if (ld->fb && ld->fb->unpin)
- ld->fb->unpin(ld->fb);
+ if (ld->fb)
+ WARN_ON(vmw_ldu_fb_unpin(ld->fb));
vmw_svga_enable(vmw_priv);
- if (vfb->pin)
- vfb->pin(vfb);
+ WARN_ON(vmw_ldu_fb_pin(vfb));
ld->fb = vfb;
}
@@ -234,6 +275,7 @@ static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
.atomic_destroy_state = vmw_du_crtc_destroy_state,
.set_config = drm_atomic_helper_set_config,
+ .page_flip = drm_atomic_helper_page_flip,
};
@@ -273,6 +315,12 @@ static const struct
drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = {
};
+static int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
+ struct vmw_framebuffer *framebuffer,
+ unsigned int flags, unsigned int color,
+ struct drm_mode_rect *clips,
+ unsigned int num_clips);
+
/*
* Legacy Display Plane Functions
*/
@@ -291,7 +339,6 @@ vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_framebuffer *fb;
struct drm_crtc *crtc = new_state->crtc ?: old_state->crtc;
-
ldu = vmw_crtc_to_ldu(crtc);
dev_priv = vmw_priv(plane->dev);
fb = new_state->fb;
@@ -304,8 +351,31 @@ vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane,
vmw_ldu_del_active(dev_priv, ldu);
vmw_ldu_commit_list(dev_priv);
-}
+ if (vfb && vmw_cmd_supported(dev_priv)) {
+ struct drm_mode_rect fb_rect = {
+ .x1 = 0,
+ .y1 = 0,
+ .x2 = vfb->base.width,
+ .y2 = vfb->base.height
+ };
+ struct drm_mode_rect *damage_rects = drm_plane_get_damage_clips(new_state);
+ u32 rect_count = drm_plane_get_damage_clips_count(new_state);
+ int ret;
+
+ if (!damage_rects) {
+ damage_rects = &fb_rect;
+ rect_count = 1;
+ }
+
+ ret = vmw_kms_ldu_do_bo_dirty(dev_priv, vfb, 0, 0, damage_rects, rect_count);
+
+ drm_WARN_ONCE(plane->dev, ret,
+ "vmw_kms_ldu_do_bo_dirty failed with: ret=%d\n", ret);
+
+ vmw_cmd_flush(dev_priv, false);
+ }
+}
static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
@@ -536,11 +606,11 @@ int vmw_kms_ldu_close_display(struct vmw_private *dev_priv)
}
-int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
- struct vmw_framebuffer *framebuffer,
- unsigned int flags, unsigned int color,
- struct drm_clip_rect *clips,
- unsigned int num_clips, int increment)
+static int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
+ struct vmw_framebuffer *framebuffer,
+ unsigned int flags, unsigned int color,
+ struct drm_mode_rect *clips,
+ unsigned int num_clips)
{
size_t fifo_size;
int i;
@@ -556,7 +626,7 @@ int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
return -ENOMEM;
memset(cmd, 0, fifo_size);
- for (i = 0; i < num_clips; i++, clips += increment) {
+ for (i = 0; i < num_clips; i++, clips++) {
cmd[i].header = SVGA_CMD_UPDATE;
cmd[i].body.x = clips->x1;
cmd[i].body.y = clips->y1;