Commit dfc507b9 authored by Thomas Zimmermann's avatar Thomas Zimmermann

drm/mgag200: Allocate cursor BOs at high end of video memory

By putting cursor BOs at the high end of the video memory, we can avoid
memory fragmentation. Starting at the low end, contiguous video memory is
available for framebuffers.

The patch also simplifies the buffer swapping and aligns it with the
ast driver. If there are more drivers with similar requirements, the
code could be moved into a shared place.
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Acked-by: default avatarGerd Hoffmann <kraxel@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190927091301.10574-8-tzimmermann@suse.de
parent 2c51a660
...@@ -120,39 +120,25 @@ static int mgag200_show_cursor(struct mga_device *mdev, void *src, ...@@ -120,39 +120,25 @@ static int mgag200_show_cursor(struct mga_device *mdev, void *src,
unsigned int width, unsigned int height) unsigned int width, unsigned int height)
{ {
struct drm_device *dev = mdev->dev; struct drm_device *dev = mdev->dev;
struct drm_gem_vram_object *pixels_1 = mdev->cursor.pixels_1; struct drm_gem_vram_object *gbo;
struct drm_gem_vram_object *pixels_2 = mdev->cursor.pixels_2;
struct drm_gem_vram_object *pixels_current = mdev->cursor.pixels_current;
struct drm_gem_vram_object *pixels_next;
void *dst; void *dst;
s64 off; s64 off;
int ret; int ret;
if (!pixels_1 || !pixels_2) { gbo = mdev->cursor.gbo[mdev->cursor.next_index];
if (!gbo) {
WREG8(MGA_CURPOSXL, 0); WREG8(MGA_CURPOSXL, 0);
WREG8(MGA_CURPOSXH, 0); WREG8(MGA_CURPOSXH, 0);
return -ENOTSUPP; /* Didn't allocate space for cursors */ return -ENOTSUPP; /* Didn't allocate space for cursors */
} }
dst = drm_gem_vram_vmap(gbo);
if (WARN_ON(pixels_current &&
pixels_1 != pixels_current &&
pixels_2 != pixels_current)) {
return -ENOTSUPP; /* inconsistent state */
}
if (pixels_current == pixels_1)
pixels_next = pixels_2;
else
pixels_next = pixels_1;
dst = drm_gem_vram_vmap(pixels_next);
if (IS_ERR(dst)) { if (IS_ERR(dst)) {
ret = PTR_ERR(dst); ret = PTR_ERR(dst);
dev_err(&dev->pdev->dev, dev_err(&dev->pdev->dev,
"failed to map cursor updates: %d\n", ret); "failed to map cursor updates: %d\n", ret);
return ret; return ret;
} }
off = drm_gem_vram_offset(pixels_next); off = drm_gem_vram_offset(gbo);
if (off < 0) { if (off < 0) {
ret = (int)off; ret = (int)off;
dev_err(&dev->pdev->dev, dev_err(&dev->pdev->dev,
...@@ -168,16 +154,15 @@ static int mgag200_show_cursor(struct mga_device *mdev, void *src, ...@@ -168,16 +154,15 @@ static int mgag200_show_cursor(struct mga_device *mdev, void *src,
/* Adjust cursor control register to turn on the cursor */ /* Adjust cursor control register to turn on the cursor */
WREG_DAC(MGA1064_CURSOR_CTL, 4); /* 16-colour palletized cursor mode */ WREG_DAC(MGA1064_CURSOR_CTL, 4); /* 16-colour palletized cursor mode */
if (pixels_current) drm_gem_vram_vunmap(gbo, dst);
drm_gem_vram_unpin(pixels_current);
mdev->cursor.pixels_current = pixels_next;
drm_gem_vram_vunmap(pixels_next, dst); ++mdev->cursor.next_index;
mdev->cursor.next_index %= ARRAY_SIZE(mdev->cursor.gbo);
return 0; return 0;
err_drm_gem_vram_vunmap: err_drm_gem_vram_vunmap:
drm_gem_vram_vunmap(pixels_next, dst); drm_gem_vram_vunmap(gbo, dst);
return ret; return ret;
} }
...@@ -189,9 +174,6 @@ static void mgag200_hide_cursor(struct mga_device *mdev) ...@@ -189,9 +174,6 @@ static void mgag200_hide_cursor(struct mga_device *mdev)
{ {
WREG8(MGA_CURPOSXL, 0); WREG8(MGA_CURPOSXL, 0);
WREG8(MGA_CURPOSXH, 0); WREG8(MGA_CURPOSXH, 0);
if (mdev->cursor.pixels_current)
drm_gem_vram_unpin(mdev->cursor.pixels_current);
mdev->cursor.pixels_current = NULL;
} }
static void mgag200_move_cursor(struct mga_device *mdev, int x, int y) static void mgag200_move_cursor(struct mga_device *mdev, int x, int y)
...@@ -215,27 +197,32 @@ static void mgag200_move_cursor(struct mga_device *mdev, int x, int y) ...@@ -215,27 +197,32 @@ static void mgag200_move_cursor(struct mga_device *mdev, int x, int y)
int mgag200_cursor_init(struct mga_device *mdev) int mgag200_cursor_init(struct mga_device *mdev)
{ {
struct drm_device *dev = mdev->dev; struct drm_device *dev = mdev->dev;
size_t ncursors = ARRAY_SIZE(mdev->cursor.gbo);
size_t size; size_t size;
int ret;
size_t i;
struct drm_gem_vram_object *gbo;
size = roundup(64 * 48, PAGE_SIZE); size = roundup(64 * 48, PAGE_SIZE);
if (size * 2 > mdev->vram_fb_available) if (size * ncursors > mdev->vram_fb_available)
return -ENOMEM; return -ENOMEM;
/* for (i = 0; i < ncursors; ++i) {
* Make small buffers to store a hardware cursor (double gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev,
* buffered icon updates) size, 0, false);
*/ if (IS_ERR(gbo)) {
mdev->cursor.pixels_1 = drm_gem_vram_create(dev, &dev->vram_mm->bdev, ret = PTR_ERR(gbo);
size, 0, 0); goto err_drm_gem_vram_put;
mdev->cursor.pixels_2 = drm_gem_vram_create(dev, &dev->vram_mm->bdev, }
size, 0, 0); ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM |
if (IS_ERR(mdev->cursor.pixels_2) || IS_ERR(mdev->cursor.pixels_1)) { DRM_GEM_VRAM_PL_FLAG_TOPDOWN);
mdev->cursor.pixels_1 = NULL; if (ret) {
mdev->cursor.pixels_2 = NULL; drm_gem_vram_put(gbo);
dev_warn(&dev->pdev->dev, goto err_drm_gem_vram_put;
"Could not allocate space for cursors. Not doing hardware cursors.\n"); }
mdev->cursor.gbo[i] = gbo;
} }
mdev->cursor.pixels_current = NULL;
/* /*
* At the high end of video memory, we reserve space for * At the high end of video memory, we reserve space for
...@@ -243,13 +230,32 @@ int mgag200_cursor_init(struct mga_device *mdev) ...@@ -243,13 +230,32 @@ int mgag200_cursor_init(struct mga_device *mdev)
* a double-buffered image of the current cursor. Hence, it's * a double-buffered image of the current cursor. Hence, it's
* not available for framebuffers. * not available for framebuffers.
*/ */
mdev->vram_fb_available -= 2 * size; mdev->vram_fb_available -= ncursors * size;
return 0; return 0;
err_drm_gem_vram_put:
while (i) {
--i;
gbo = mdev->cursor.gbo[i];
drm_gem_vram_unpin(gbo);
drm_gem_vram_put(gbo);
mdev->cursor.gbo[i] = NULL;
}
return ret;
} }
void mgag200_cursor_fini(struct mga_device *mdev) void mgag200_cursor_fini(struct mga_device *mdev)
{ } {
size_t i;
struct drm_gem_vram_object *gbo;
for (i = 0; i < ARRAY_SIZE(mdev->cursor.gbo); ++i) {
gbo = mdev->cursor.gbo[i];
drm_gem_vram_unpin(gbo);
drm_gem_vram_put(gbo);
}
}
int mgag200_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, int mgag200_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
uint32_t handle, uint32_t width, uint32_t height) uint32_t handle, uint32_t width, uint32_t height)
......
...@@ -129,16 +129,8 @@ struct mga_connector { ...@@ -129,16 +129,8 @@ struct mga_connector {
}; };
struct mga_cursor { struct mga_cursor {
/* struct drm_gem_vram_object *gbo[2];
We have to have 2 buffers for the cursor to avoid occasional unsigned int next_index;
corruption while switching cursor icons.
If either of these is NULL, then don't do hardware cursors, and
fall back to software.
*/
struct drm_gem_vram_object *pixels_1;
struct drm_gem_vram_object *pixels_2;
/* The currently displayed icon, this points to one of pixels_1, or pixels_2 */
struct drm_gem_vram_object *pixels_current;
}; };
struct mga_mc { struct mga_mc {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment