drm/vmwgfx: Implement screen targets

Add support for the screen target device interface.
Add a getparam parameter and bump minor to signal availability.

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
This commit is contained in:
Sinclair Yeh 2015-06-26 01:42:06 -07:00 committed by Thomas Hellstrom
parent c9146cd918
commit 35c051258e
10 changed files with 1475 additions and 24 deletions

View File

@ -7,6 +7,6 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \
vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o vmwgfx_context.o \
vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \
vmwgfx_cmdbuf_res.o vmwgfx_cmdbuf.o \
vmwgfx_cmdbuf_res.o vmwgfx_cmdbuf.o vmwgfx_stdu.o \
obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o

View File

@ -693,22 +693,28 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);
dev_priv->max_mob_size =
vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE);
dev_priv->stdu_max_width =
vmw_read(dev_priv, SVGA_REG_SCREENTARGET_MAX_WIDTH);
dev_priv->stdu_max_height =
vmw_read(dev_priv, SVGA_REG_SCREENTARGET_MAX_HEIGHT);
vmw_write(dev_priv, SVGA_REG_DEV_CAP,
SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH);
dev_priv->texture_max_width = vmw_read(dev_priv,
SVGA_REG_DEV_CAP);
vmw_write(dev_priv, SVGA_REG_DEV_CAP,
SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT);
dev_priv->texture_max_height = vmw_read(dev_priv,
SVGA_REG_DEV_CAP);
} else
dev_priv->prim_bb_mem = dev_priv->vram_size;
vmw_print_capabilities(dev_priv->capabilities);
ret = vmw_dma_masks(dev_priv);
if (unlikely(ret != 0))
goto out_err0;
/*
* Limit back buffer size to VRAM size. Remove this once
* screen targets are implemented.
*/
if (dev_priv->prim_bb_mem > dev_priv->vram_size)
dev_priv->prim_bb_mem = dev_priv->vram_size;
vmw_print_capabilities(dev_priv->capabilities);
if (dev_priv->capabilities & SVGA_CAP_GMR2) {
DRM_INFO("Max GMR ids is %u\n",
(unsigned)dev_priv->max_gmr_ids);

View File

@ -40,17 +40,17 @@
#include <drm/ttm/ttm_module.h>
#include "vmwgfx_fence.h"
#define VMWGFX_DRIVER_DATE "20140704"
#define VMWGFX_DRIVER_DATE "20150626"
#define VMWGFX_DRIVER_MAJOR 2
#define VMWGFX_DRIVER_MINOR 6
#define VMWGFX_DRIVER_PATCHLEVEL 1
#define VMWGFX_DRIVER_MINOR 7
#define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
#define VMWGFX_MAX_RELOCATIONS 2048
#define VMWGFX_MAX_VALIDATIONS 2048
#define VMWGFX_MAX_DISPLAYS 16
#define VMWGFX_CMD_BOUNCE_INIT_SIZE 32768
#define VMWGFX_ENABLE_SCREEN_TARGET_OTABLE 0
#define VMWGFX_ENABLE_SCREEN_TARGET_OTABLE 1
/*
* Perhaps we should have sysfs entries for these.
@ -337,7 +337,8 @@ struct vmw_ctx_binding_state {
enum vmw_display_unit_type {
vmw_du_invalid = 0,
vmw_du_legacy,
vmw_du_screen_object
vmw_du_screen_object,
vmw_du_screen_target
};
@ -402,6 +403,10 @@ struct vmw_private {
uint32_t mmio_size;
uint32_t fb_max_width;
uint32_t fb_max_height;
uint32_t texture_max_width;
uint32_t texture_max_height;
uint32_t stdu_max_width;
uint32_t stdu_max_height;
uint32_t initial_width;
uint32_t initial_height;
__le32 __iomem *mmio_virt;

View File

@ -105,6 +105,10 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
case DRM_VMW_PARAM_MAX_MOB_SIZE:
param->value = dev_priv->max_mob_size;
break;
case DRM_VMW_PARAM_SCREEN_TARGET:
param->value =
(dev_priv->active_display_unit == vmw_du_screen_target);
break;
default:
DRM_ERROR("Illegal vmwgfx get param request: %d\n",
param->param);

View File

@ -463,6 +463,11 @@ static int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer,
flags, color,
clips, num_clips,
inc, NULL);
else
ret = vmw_kms_stdu_do_surface_dirty(dev_priv, file_priv,
&vfbs->base,
clips, num_clips,
inc);
vmw_fifo_flush(dev_priv, false);
ttm_read_unlock(&dev_priv->reservation_sem);
@ -636,6 +641,11 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer,
flags, color,
clips, num_clips, increment,
NULL);
} else {
ret = vmw_kms_stdu_do_surface_dirty(dev_priv, file_priv,
&vfbd->base,
clips, num_clips,
increment);
}
vmw_fifo_flush(dev_priv, false);
@ -999,8 +1009,6 @@ int vmw_kms_generic_present(struct vmw_private *dev_priv,
break;
}
vmw_fifo_flush(dev_priv, false);
kfree(cmd);
out_free_tmp:
kfree(tmp);
@ -1017,8 +1025,21 @@ int vmw_kms_present(struct vmw_private *dev_priv,
struct drm_vmw_rect *clips,
uint32_t num_clips)
{
return vmw_kms_generic_present(dev_priv, file_priv, vfb, surface, sid,
destX, destY, clips, num_clips);
int ret;
if (dev_priv->active_display_unit == vmw_du_screen_target)
ret = vmw_kms_stdu_present(dev_priv, file_priv, vfb, sid,
destX, destY, clips, num_clips);
else
ret = vmw_kms_generic_present(dev_priv, file_priv, vfb,
surface, sid, destX, destY,
clips, num_clips);
if (ret)
return ret;
vmw_fifo_flush(dev_priv, false);
return 0;
}
int vmw_kms_readback(struct vmw_private *dev_priv,
@ -1141,9 +1162,12 @@ int vmw_kms_init(struct vmw_private *dev_priv)
dev->mode_config.max_width = 8192;
dev->mode_config.max_height = 8192;
ret = vmw_kms_sou_init_display(dev_priv);
if (ret) /* Fallback */
ret = vmw_kms_ldu_init_display(dev_priv);
ret = vmw_kms_stdu_init_display(dev_priv);
if (ret) {
ret = vmw_kms_sou_init_display(dev_priv);
if (ret) /* Fallback */
ret = vmw_kms_ldu_init_display(dev_priv);
}
return ret;
}
@ -1160,6 +1184,8 @@ int vmw_kms_close(struct vmw_private *dev_priv)
drm_mode_config_cleanup(dev_priv->dev);
if (dev_priv->active_display_unit == vmw_du_screen_object)
ret = vmw_kms_sou_close_display(dev_priv);
else if (dev_priv->active_display_unit == vmw_du_screen_target)
ret = vmw_kms_stdu_close_display(dev_priv);
else
ret = vmw_kms_ldu_close_display(dev_priv);
@ -1311,7 +1337,9 @@ bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
uint32_t pitch,
uint32_t height)
{
return ((u64) pitch * (u64) height) < (u64) dev_priv->prim_bb_mem;
return ((u64) pitch * (u64) height) < (u64)
((dev_priv->active_display_unit == vmw_du_screen_target) ?
dev_priv->prim_bb_mem : dev_priv->vram_size);
}
@ -1558,6 +1586,11 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
if (dev_priv->active_display_unit == vmw_du_screen_object)
assumed_bpp = 4;
if (dev_priv->active_display_unit == vmw_du_screen_target) {
max_width = min(max_width, dev_priv->stdu_max_width);
max_height = min(max_height, dev_priv->stdu_max_height);
}
/* Add preferred mode */
mode = drm_mode_duplicate(dev, &prefmode);
if (!mode)
@ -1674,6 +1707,19 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
bounding_box.h = rects[i].y + rects[i].h;
}
/*
* For Screen Target Display Unit, all the displays must fit
* inside of maximum texture size.
*/
if (dev_priv->active_display_unit == vmw_du_screen_target)
if (bounding_box.w > dev_priv->texture_max_width ||
bounding_box.h > dev_priv->texture_max_height) {
DRM_ERROR("Layout exceeds maximum texture size\n");
ret = -EINVAL;
goto out_free;
}
vmw_du_update_layout(dev_priv, arg->num_outputs, rects);
out_free:

View File

@ -204,4 +204,24 @@ int vmw_kms_sou_do_dmabuf_dirty(struct drm_file *file_priv,
struct drm_clip_rect *clips,
unsigned num_clips, int increment,
struct vmw_fence_obj **out_fence);
/*
* Screen Target Display Unit functions - vmwgfx_stdu.c
*/
int vmw_kms_stdu_init_display(struct vmw_private *dev_priv);
int vmw_kms_stdu_close_display(struct vmw_private *dev_priv);
int vmw_kms_stdu_do_surface_dirty(struct vmw_private *dev_priv,
struct drm_file *file_priv,
struct vmw_framebuffer *framebuffer,
struct drm_clip_rect *clips,
unsigned num_clips, int increment);
int vmw_kms_stdu_present(struct vmw_private *dev_priv,
struct drm_file *file_priv,
struct vmw_framebuffer *vfb,
uint32_t user_handle,
int32_t dest_x, int32_t dest_y,
struct drm_vmw_rect *clips,
uint32_t num_clips);
#endif

View File

@ -31,7 +31,8 @@
* If we set up the screen target otable, screen objects stop working.
*/
#define VMW_OTABLE_SETUP_SUB ((VMWGFX_ENABLE_SCREEN_TARGET_OTABLE) ? 0 : 1)
#define VMW_OTABLE_SETUP_SUB ((VMWGFX_ENABLE_SCREEN_TARGET_OTABLE && \
(dev_priv->capabilities & SVGA_CAP_3D)) ? 0 : 1)
#ifdef CONFIG_64BIT
#define VMW_PPN_SIZE 8

File diff suppressed because it is too large Load Diff

View File

@ -1486,6 +1486,10 @@ int vmw_surface_gb_priv_define(struct drm_device *dev,
srf->mip_levels[0],
srf->flags & SVGA3D_SURFACE_CUBEMAP);
if (dev_priv->active_display_unit == vmw_du_screen_target &&
for_scanout)
srf->flags |= SVGA3D_SURFACE_SCREENTARGET;
/*
* From this point, the generic resource management functions
* destroy the object on failure.

View File

@ -88,6 +88,7 @@
#define DRM_VMW_PARAM_3D_CAPS_SIZE 8
#define DRM_VMW_PARAM_MAX_MOB_MEMORY 9
#define DRM_VMW_PARAM_MAX_MOB_SIZE 10
#define DRM_VMW_PARAM_SCREEN_TARGET 11
/**
* enum drm_vmw_handle_type - handle type for ref ioctls