summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSinclair Yeh <syeh@vmware.com>2014-11-24 11:57:24 -0800
committerSinclair Yeh <syeh@vmware.com>2014-12-22 08:03:01 -0800
commit3f6d507eb0011a66098406f010f53cddd07e8f97 (patch)
tree338fad8f88d120b9e3fa304d15f5cc711adec837
parente9606c2faa513b819d7f2136873ccf83c82e2656 (diff)
drm/vmwgfx: enforce Screen Target boundary conditionsfeature/syeh/screen-targets
Added code to enforce the following conditions * Mode cannot be larger than maximum screen target size * Unindented a block in vmwgfx_kms * Max topology dimensions have to be less than max texture dimensions * Remove limiting bounding box to VRAM size if Screen Target is used Signed-off-by: Sinclair Yeh <syeh@vmware.com> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
-rw-r--r--vmwgfx_drv.c24
-rw-r--r--vmwgfx_drv.h4
-rw-r--r--vmwgfx_kms.c74
-rw-r--r--vmwgfx_stdu.c2
4 files changed, 75 insertions, 29 deletions
diff --git a/vmwgfx_drv.c b/vmwgfx_drv.c
index 7128be9..54ecf2f 100644
--- a/vmwgfx_drv.c
+++ b/vmwgfx_drv.c
@@ -666,16 +666,28 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->prim_bb_mem =
vmw_read(dev_priv,
SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);
- dev_priv->max_mob_size =
+ 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;
- /*
- * Limit back buffer size to VRAM size. Remove this once
- * screen targets are implemented.
- */
- if (dev_priv->prim_bb_mem > dev_priv->vram_size)
+ /* For non-screen target displays, limit back buffer to VRAM size */
+ if (!VMWGFX_ENABLE_SCREEN_TARGET_OTABLE &&
+ dev_priv->prim_bb_mem > dev_priv->vram_size)
dev_priv->prim_bb_mem = dev_priv->vram_size;
mutex_unlock(&dev_priv->hw_mutex);
diff --git a/vmwgfx_drv.h b/vmwgfx_drv.h
index 6fbe9fe..908ec47 100644
--- a/vmwgfx_drv.h
+++ b/vmwgfx_drv.h
@@ -418,6 +418,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;
diff --git a/vmwgfx_kms.c b/vmwgfx_kms.c
index 20940c3..0acd885 100644
--- a/vmwgfx_kms.c
+++ b/vmwgfx_kms.c
@@ -72,6 +72,7 @@ void vmw_du_cleanup(struct vmw_display_unit *du)
vmw_surface_unreference(&du->cursor_surface);
if (du->cursor_dmabuf)
vmw_dmabuf_unreference(&du->cursor_dmabuf);
+ drm_sysfs_connector_remove(&du->connector);
drm_crtc_cleanup(&du->crtc);
drm_encoder_cleanup(&du->encoder);
drm_connector_cleanup(&du->connector);
@@ -772,7 +773,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
required_size = mode_cmd->pitch * mode_cmd->height;
if (unlikely(required_size > (u64) dev_priv->prim_bb_mem)) {
- DRM_ERROR("VRAM size is too small for requested mode.\n");
+ DRM_ERROR("Requested mode exceeds bounding box limit\n");
return ERR_PTR(-ENOMEM);
}
@@ -1532,33 +1533,36 @@ 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)
- return 0;
- mode->hdisplay = du->pref_width;
- mode->vdisplay = du->pref_height;
- vmw_guess_mode_timing(mode);
-
- if (vmw_kms_validate_mode_vram(dev_priv,
- mode->hdisplay * assumed_bpp,
- mode->vdisplay)) {
- drm_mode_probed_add(connector, mode);
- } else {
- drm_mode_destroy(dev, mode);
- mode = NULL;
- }
+ mode = drm_mode_duplicate(dev, &prefmode);
+ if (!mode)
+ return 0;
+ mode->hdisplay = du->pref_width;
+ mode->vdisplay = du->pref_height;
+ vmw_guess_mode_timing(mode);
- if (du->pref_mode) {
- list_del_init(&du->pref_mode->head);
- drm_mode_destroy(dev, du->pref_mode);
- }
+ if (vmw_kms_validate_mode_vram(dev_priv,
+ mode->hdisplay * assumed_bpp,
+ mode->vdisplay)) {
+ drm_mode_probed_add(connector, mode);
+ } else {
+ drm_mode_destroy(dev, mode);
+ mode = NULL;
+ }
- /* mode might be null here, this is intended */
- du->pref_mode = mode;
+ if (du->pref_mode) {
+ list_del_init(&du->pref_mode->head);
+ drm_mode_destroy(dev, du->pref_mode);
}
+ /* mode might be null here, this is intended */
+ du->pref_mode = mode;
+
for (i = 0; vmw_kms_connector_builtin[i].type != 0; i++) {
bmode = &vmw_kms_connector_builtin[i];
if (bmode->hdisplay > max_width ||
@@ -1608,6 +1612,7 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
int ret;
int i;
struct drm_mode_config *mode_config = &dev->mode_config;
+ struct drm_vmw_rect bounding_box = {0};
ret = ttm_read_lock(&vmaster->lock, true);
if (unlikely(ret != 0))
@@ -1644,8 +1649,31 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
ret = -EINVAL;
goto out_free;
}
+
+ /*
+ * bounding_box.w and bunding_box.h are used as
+ * lower-right coordinates
+ */
+ if (rects[i].x + rects[i].w > bounding_box.w)
+ bounding_box.w = rects[i].x + rects[i].w;
+
+ if (rects[i].y + rects[i].h > bounding_box.h)
+ 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:
diff --git a/vmwgfx_stdu.c b/vmwgfx_stdu.c
index 8274163..f48f343 100644
--- a/vmwgfx_stdu.c
+++ b/vmwgfx_stdu.c
@@ -979,6 +979,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
encoder->possible_crtcs = (1 << unit);
encoder->possible_clones = 0;
+ (void) drm_sysfs_connector_add(connector);
+
drm_crtc_init(dev, crtc, &vmw_stdu_crtc_funcs);
drm_mode_crtc_set_gamma_size(crtc, 256);