summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-10-25 23:35:53 +0200
committerDave Airlie <airlied@redhat.com>2011-11-02 08:30:31 +0000
commitcd2b89e7e8c036903e7fa0c3dceca25e755fe78d (patch)
tree4ec5275d9650283de7b3be6d2e5eb0cd2e63cde6
parentbc1c4dc390c644106fa5b8d0fb44a473c4ba627c (diff)
downloadlinux-3.10-cd2b89e7e8c036903e7fa0c3dceca25e755fe78d.tar.gz
linux-3.10-cd2b89e7e8c036903e7fa0c3dceca25e755fe78d.tar.bz2
linux-3.10-cd2b89e7e8c036903e7fa0c3dceca25e755fe78d.zip
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 13afddc1f03..82f5c8b1284 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -103,6 +103,9 @@
#define DRM_IOCTL_VMW_PRESENT_READBACK \
DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK, \
struct drm_vmw_present_readback_arg)
+#define DRM_IOCTL_VMW_UPDATE_LAYOUT \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT, \
+ struct drm_vmw_update_layout_arg)
/**
* The core DRM version of this macro doesn't account for
@@ -165,6 +168,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
vmw_present_readback_ioctl,
DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
+ VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
+ vmw_kms_update_layout_ioctl,
+ DRM_MASTER | DRM_UNLOCKED),
};
static 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 30589d0aecd..8cca91a93bd 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -40,9 +40,9 @@
#include "ttm/ttm_module.h"
#include "vmwgfx_fence.h"
-#define VMWGFX_DRIVER_DATE "20111008"
+#define VMWGFX_DRIVER_DATE "20111025"
#define VMWGFX_DRIVER_MAJOR 2
-#define VMWGFX_DRIVER_MINOR 2
+#define VMWGFX_DRIVER_MINOR 3
#define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
@@ -633,6 +633,8 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
struct drm_vmw_fence_rep __user *user_fence_rep,
struct drm_vmw_rect *clips,
uint32_t num_clips);
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
/**
* Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 8b14dfd513a..f9a0f980c30 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,
du->pref_width = rects[du->unit].w;
du->pref_height = rects[du->unit].h;
du->pref_active = true;
+ du->gui_x = rects[du->unit].x;
+ du->gui_y = rects[du->unit].y;
} else {
du->pref_width = 800;
du->pref_height = 600;
@@ -1572,12 +1574,14 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force)
uint32_t num_displays;
struct drm_device *dev = connector->dev;
struct vmw_private *dev_priv = vmw_priv(dev);
+ struct vmw_display_unit *du = vmw_connector_to_du(connector);
mutex_lock(&dev_priv->hw_mutex);
num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS);
mutex_unlock(&dev_priv->hw_mutex);
- return ((vmw_connector_to_du(connector)->unit < num_displays) ?
+ return ((vmw_connector_to_du(connector)->unit < num_displays &&
+ du->pref_active) ?
connector_status_connected : connector_status_disconnected);
}
@@ -1723,3 +1727,63 @@ int vmw_du_connector_set_property(struct drm_connector *connector,
{
return 0;
}
+
+
+int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct vmw_private *dev_priv = vmw_priv(dev);
+ struct drm_vmw_update_layout_arg *arg =
+ (struct drm_vmw_update_layout_arg *)data;
+ struct vmw_master *vmaster = vmw_master(file_priv->master);
+ void __user *user_rects;
+ struct drm_vmw_rect *rects;
+ unsigned rects_size;
+ int ret;
+ int i;
+ struct drm_mode_config *mode_config = &dev->mode_config;
+
+ ret = ttm_read_lock(&vmaster->lock, true);
+ if (unlikely(ret != 0))
+ return ret;
+
+ if (!arg->num_outputs) {
+ struct drm_vmw_rect def_rect = {0, 0, 800, 600};
+ vmw_du_update_layout(dev_priv, 1, &def_rect);
+ goto out_unlock;
+ }
+
+ rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
+ rects = kzalloc(rects_size, GFP_KERNEL);
+ if (unlikely(!rects)) {
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+
+ user_rects = (void __user *)(unsigned long)arg->rects;
+ ret = copy_from_user(rects, user_rects, rects_size);
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("Failed to get rects.\n");
+ ret = -EFAULT;
+ goto out_free;
+ }
+
+ for (i = 0; i < arg->num_outputs; ++i) {
+ if (rects->x < 0 ||
+ rects->y < 0 ||
+ rects->x + rects->w > mode_config->max_width ||
+ rects->y + rects->h > mode_config->max_height) {
+ DRM_ERROR("Invalid GUI layout.\n");
+ ret = -EINVAL;
+ goto out_free;
+ }
+ }
+
+ vmw_du_update_layout(dev_priv, arg->num_outputs, rects);
+
+out_free:
+ kfree(rects);
+out_unlock:
+ ttm_read_unlock(&vmaster->lock);
+ return ret;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index db0b901f8c3..815cf99ce06 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 {
unsigned pref_height;
bool pref_active;
struct drm_display_mode *pref_mode;
+
+ /*
+ * Gui positioning
+ */
+ int gui_x;
+ int gui_y;
};
#define vmw_crtc_to_du(x) \
@@ -126,8 +132,7 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
int vmw_du_connector_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t val);
-int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
- struct drm_vmw_rect *rects);
+
/*
* Legacy display unit functions - vmwgfx_ldu.c
diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h
index cd7cd8162ed..bcb0912afe7 100644
--- a/include/drm/vmwgfx_drm.h
+++ b/include/drm/vmwgfx_drm.h
@@ -54,7 +54,7 @@
#define DRM_VMW_FENCE_EVENT 17
#define DRM_VMW_PRESENT 18
#define DRM_VMW_PRESENT_READBACK 19
-
+#define DRM_VMW_UPDATE_LAYOUT 20
/*************************************************************************/
/**
@@ -552,31 +552,6 @@ struct drm_vmw_get_3d_cap_arg {
/*************************************************************************/
/**
- * DRM_VMW_UPDATE_LAYOUT - Update layout
- *
- * Updates the preferred modes and connection status for connectors. The
- * command conisits of one drm_vmw_update_layout_arg pointing out a array
- * of num_outputs drm_vmw_rect's.
- */
-
-/**
- * struct drm_vmw_update_layout_arg
- *
- * @num_outputs: number of active
- * @rects: pointer to array of drm_vmw_rect
- *
- * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
- */
-
-struct drm_vmw_update_layout_arg {
- uint32_t num_outputs;
- uint32_t pad64;
- uint64_t rects;
-};
-
-
-/*************************************************************************/
-/**
* DRM_VMW_FENCE_WAIT
*
* Waits for a fence object to signal. The wait is interruptible, so that
@@ -788,4 +763,28 @@ struct drm_vmw_present_readback_arg {
uint64_t clips_ptr;
uint64_t fence_rep;
};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_UPDATE_LAYOUT - Update layout
+ *
+ * Updates the preferred modes and connection status for connectors. The
+ * command consists of one drm_vmw_update_layout_arg pointing to an array
+ * of num_outputs drm_vmw_rect's.
+ */
+
+/**
+ * struct drm_vmw_update_layout_arg
+ *
+ * @num_outputs: number of active connectors
+ * @rects: pointer to array of drm_vmw_rect cast to an uint64_t
+ *
+ * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
+ */
+struct drm_vmw_update_layout_arg {
+ uint32_t num_outputs;
+ uint32_t pad64;
+ uint64_t rects;
+};
+
#endif