aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-10-25 17:35:53 -0400
committerDave Airlie <airlied@redhat.com>2011-11-02 04:30:31 -0400
commitcd2b89e7e8c036903e7fa0c3dceca25e755fe78d (patch)
tree4ec5275d9650283de7b3be6d2e5eb0cd2e63cde6 /drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
parentbc1c4dc390c644106fa5b8d0fb44a473c4ba627c (diff)
vmwgfx: Reinstate the update_layout ioctl
We need to redefine a connector as "connected" if it matches a window in the host preferred GUI layout. Otherwise "smart" window managers would turn on Xorg outputs that we don't want to be on. This reinstates the update_layout and adds the following information to the modesetting system. a) Connection status <-> Equivalent to real hardware connection status b) Preferred mode <-> Equivalent to real hardware reading EDID c) Host window position <-> Equivalent to a real hardware scanout address dynamic register. It should be noted that there is no assumption here about what should be displayed and where. Only how to access the host windows. This also bumps minor to signal availability of the new IOCTL. Based on code originally written by Jakob Bornecrantz Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_kms.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c66
1 files changed, 65 insertions, 1 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 8b14dfd513a1..f9a0f980c300 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1517,6 +1517,8 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
1517 du->pref_width = rects[du->unit].w; 1517 du->pref_width = rects[du->unit].w;
1518 du->pref_height = rects[du->unit].h; 1518 du->pref_height = rects[du->unit].h;
1519 du->pref_active = true; 1519 du->pref_active = true;
1520 du->gui_x = rects[du->unit].x;
1521 du->gui_y = rects[du->unit].y;
1520 } else { 1522 } else {
1521 du->pref_width = 800; 1523 du->pref_width = 800;
1522 du->pref_height = 600; 1524 du->pref_height = 600;
@@ -1572,12 +1574,14 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force)
1572 uint32_t num_displays; 1574 uint32_t num_displays;
1573 struct drm_device *dev = connector->dev; 1575 struct drm_device *dev = connector->dev;
1574 struct vmw_private *dev_priv = vmw_priv(dev); 1576 struct vmw_private *dev_priv = vmw_priv(dev);
1577 struct vmw_display_unit *du = vmw_connector_to_du(connector);
1575 1578
1576 mutex_lock(&dev_priv->hw_mutex); 1579 mutex_lock(&dev_priv->hw_mutex);
1577 num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS); 1580 num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS);
1578 mutex_unlock(&dev_priv->hw_mutex); 1581 mutex_unlock(&dev_priv->hw_mutex);
1579 1582
1580 return ((vmw_connector_to_du(connector)->unit < num_displays) ? 1583 return ((vmw_connector_to_du(connector)->unit < num_displays &&
1584 du->pref_active) ?
1581 connector_status_connected : connector_status_disconnected); 1585 connector_status_connected : connector_status_disconnected);
1582} 1586}
1583 1587
@@ -1723,3 +1727,63 @@ int vmw_du_connector_set_property(struct drm_connector *connector,
1723{ 1727{
1724 return 0; 1728 return 0;
1725} 1729}
1730
1731
1732int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
1733 struct drm_file *file_priv)
1734{
1735 struct vmw_private *dev_priv = vmw_priv(dev);
1736 struct drm_vmw_update_layout_arg *arg =
1737 (struct drm_vmw_update_layout_arg *)data;
1738 struct vmw_master *vmaster = vmw_master(file_priv->master);
1739 void __user *user_rects;
1740 struct drm_vmw_rect *rects;
1741 unsigned rects_size;
1742 int ret;
1743 int i;
1744 struct drm_mode_config *mode_config = &dev->mode_config;
1745
1746 ret = ttm_read_lock(&vmaster->lock, true);
1747 if (unlikely(ret != 0))
1748 return ret;
1749
1750 if (!arg->num_outputs) {
1751 struct drm_vmw_rect def_rect = {0, 0, 800, 600};
1752 vmw_du_update_layout(dev_priv, 1, &def_rect);
1753 goto out_unlock;
1754 }
1755
1756 rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
1757 rects = kzalloc(rects_size, GFP_KERNEL);
1758 if (unlikely(!rects)) {
1759 ret = -ENOMEM;
1760 goto out_unlock;
1761 }
1762
1763 user_rects = (void __user *)(unsigned long)arg->rects;
1764 ret = copy_from_user(rects, user_rects, rects_size);
1765 if (unlikely(ret != 0)) {
1766 DRM_ERROR("Failed to get rects.\n");
1767 ret = -EFAULT;
1768 goto out_free;
1769 }
1770
1771 for (i = 0; i < arg->num_outputs; ++i) {
1772 if (rects->x < 0 ||
1773 rects->y < 0 ||
1774 rects->x + rects->w > mode_config->max_width ||
1775 rects->y + rects->h > mode_config->max_height) {
1776 DRM_ERROR("Invalid GUI layout.\n");
1777 ret = -EINVAL;
1778 goto out_free;
1779 }
1780 }
1781
1782 vmw_du_update_layout(dev_priv, arg->num_outputs, rects);
1783
1784out_free:
1785 kfree(rects);
1786out_unlock:
1787 ttm_read_unlock(&vmaster->lock);
1788 return ret;
1789}