aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c66
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h9
-rw-r--r--include/drm/vmwgfx_drm.h51
5 files changed, 107 insertions, 31 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 13afddc1f034..82f5c8b12844 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -103,6 +103,9 @@
103#define DRM_IOCTL_VMW_PRESENT_READBACK \ 103#define DRM_IOCTL_VMW_PRESENT_READBACK \
104 DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK, \ 104 DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK, \
105 struct drm_vmw_present_readback_arg) 105 struct drm_vmw_present_readback_arg)
106#define DRM_IOCTL_VMW_UPDATE_LAYOUT \
107 DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT, \
108 struct drm_vmw_update_layout_arg)
106 109
107/** 110/**
108 * The core DRM version of this macro doesn't account for 111 * The core DRM version of this macro doesn't account for
@@ -165,6 +168,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
165 VMW_IOCTL_DEF(VMW_PRESENT_READBACK, 168 VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
166 vmw_present_readback_ioctl, 169 vmw_present_readback_ioctl,
167 DRM_MASTER | DRM_AUTH | DRM_UNLOCKED), 170 DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
171 VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
172 vmw_kms_update_layout_ioctl,
173 DRM_MASTER | DRM_UNLOCKED),
168}; 174};
169 175
170static struct pci_device_id vmw_pci_id_list[] = { 176static struct pci_device_id vmw_pci_id_list[] = {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 30589d0aecd9..8cca91a93bde 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -40,9 +40,9 @@
40#include "ttm/ttm_module.h" 40#include "ttm/ttm_module.h"
41#include "vmwgfx_fence.h" 41#include "vmwgfx_fence.h"
42 42
43#define VMWGFX_DRIVER_DATE "20111008" 43#define VMWGFX_DRIVER_DATE "20111025"
44#define VMWGFX_DRIVER_MAJOR 2 44#define VMWGFX_DRIVER_MAJOR 2
45#define VMWGFX_DRIVER_MINOR 2 45#define VMWGFX_DRIVER_MINOR 3
46#define VMWGFX_DRIVER_PATCHLEVEL 0 46#define VMWGFX_DRIVER_PATCHLEVEL 0
47#define VMWGFX_FILE_PAGE_OFFSET 0x00100000 47#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
48#define VMWGFX_FIFO_STATIC_SIZE (1024*1024) 48#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
@@ -633,6 +633,8 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
633 struct drm_vmw_fence_rep __user *user_fence_rep, 633 struct drm_vmw_fence_rep __user *user_fence_rep,
634 struct drm_vmw_rect *clips, 634 struct drm_vmw_rect *clips,
635 uint32_t num_clips); 635 uint32_t num_clips);
636int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
637 struct drm_file *file_priv);
636 638
637/** 639/**
638 * Overlay control - vmwgfx_overlay.c 640 * Overlay control - vmwgfx_overlay.c
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}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index db0b901f8c3f..815cf99ce06e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -96,6 +96,12 @@ struct vmw_display_unit {
96 unsigned pref_height; 96 unsigned pref_height;
97 bool pref_active; 97 bool pref_active;
98 struct drm_display_mode *pref_mode; 98 struct drm_display_mode *pref_mode;
99
100 /*
101 * Gui positioning
102 */
103 int gui_x;
104 int gui_y;
99}; 105};
100 106
101#define vmw_crtc_to_du(x) \ 107#define vmw_crtc_to_du(x) \
@@ -126,8 +132,7 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
126int vmw_du_connector_set_property(struct drm_connector *connector, 132int vmw_du_connector_set_property(struct drm_connector *connector,
127 struct drm_property *property, 133 struct drm_property *property,
128 uint64_t val); 134 uint64_t val);
129int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, 135
130 struct drm_vmw_rect *rects);
131 136
132/* 137/*
133 * Legacy display unit functions - vmwgfx_ldu.c 138 * Legacy display unit functions - vmwgfx_ldu.c
diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h
index cd7cd8162ed6..bcb0912afe7a 100644
--- a/include/drm/vmwgfx_drm.h
+++ b/include/drm/vmwgfx_drm.h
@@ -54,7 +54,7 @@
54#define DRM_VMW_FENCE_EVENT 17 54#define DRM_VMW_FENCE_EVENT 17
55#define DRM_VMW_PRESENT 18 55#define DRM_VMW_PRESENT 18
56#define DRM_VMW_PRESENT_READBACK 19 56#define DRM_VMW_PRESENT_READBACK 19
57 57#define DRM_VMW_UPDATE_LAYOUT 20
58 58
59/*************************************************************************/ 59/*************************************************************************/
60/** 60/**
@@ -552,31 +552,6 @@ struct drm_vmw_get_3d_cap_arg {
552 552
553/*************************************************************************/ 553/*************************************************************************/
554/** 554/**
555 * DRM_VMW_UPDATE_LAYOUT - Update layout
556 *
557 * Updates the preferred modes and connection status for connectors. The
558 * command conisits of one drm_vmw_update_layout_arg pointing out a array
559 * of num_outputs drm_vmw_rect's.
560 */
561
562/**
563 * struct drm_vmw_update_layout_arg
564 *
565 * @num_outputs: number of active
566 * @rects: pointer to array of drm_vmw_rect
567 *
568 * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
569 */
570
571struct drm_vmw_update_layout_arg {
572 uint32_t num_outputs;
573 uint32_t pad64;
574 uint64_t rects;
575};
576
577
578/*************************************************************************/
579/**
580 * DRM_VMW_FENCE_WAIT 555 * DRM_VMW_FENCE_WAIT
581 * 556 *
582 * Waits for a fence object to signal. The wait is interruptible, so that 557 * Waits for a fence object to signal. The wait is interruptible, so that
@@ -788,4 +763,28 @@ struct drm_vmw_present_readback_arg {
788 uint64_t clips_ptr; 763 uint64_t clips_ptr;
789 uint64_t fence_rep; 764 uint64_t fence_rep;
790}; 765};
766
767/*************************************************************************/
768/**
769 * DRM_VMW_UPDATE_LAYOUT - Update layout
770 *
771 * Updates the preferred modes and connection status for connectors. The
772 * command consists of one drm_vmw_update_layout_arg pointing to an array
773 * of num_outputs drm_vmw_rect's.
774 */
775
776/**
777 * struct drm_vmw_update_layout_arg
778 *
779 * @num_outputs: number of active connectors
780 * @rects: pointer to array of drm_vmw_rect cast to an uint64_t
781 *
782 * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
783 */
784struct drm_vmw_update_layout_arg {
785 uint32_t num_outputs;
786 uint32_t pad64;
787 uint64_t rects;
788};
789
791#endif 790#endif