Commit cd2b89e7 authored by Thomas Hellstrom's avatar Thomas Hellstrom Committed by Dave Airlie

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: default avatarThomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent bc1c4dc3
...@@ -103,6 +103,9 @@ ...@@ -103,6 +103,9 @@
#define DRM_IOCTL_VMW_PRESENT_READBACK \ #define DRM_IOCTL_VMW_PRESENT_READBACK \
DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK, \ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK, \
struct drm_vmw_present_readback_arg) 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 * The core DRM version of this macro doesn't account for
...@@ -165,6 +168,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = { ...@@ -165,6 +168,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
VMW_IOCTL_DEF(VMW_PRESENT_READBACK, VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
vmw_present_readback_ioctl, vmw_present_readback_ioctl,
DRM_MASTER | DRM_AUTH | DRM_UNLOCKED), 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[] = { static struct pci_device_id vmw_pci_id_list[] = {
......
...@@ -40,9 +40,9 @@ ...@@ -40,9 +40,9 @@
#include "ttm/ttm_module.h" #include "ttm/ttm_module.h"
#include "vmwgfx_fence.h" #include "vmwgfx_fence.h"
#define VMWGFX_DRIVER_DATE "20111008" #define VMWGFX_DRIVER_DATE "20111025"
#define VMWGFX_DRIVER_MAJOR 2 #define VMWGFX_DRIVER_MAJOR 2
#define VMWGFX_DRIVER_MINOR 2 #define VMWGFX_DRIVER_MINOR 3
#define VMWGFX_DRIVER_PATCHLEVEL 0 #define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024) #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
...@@ -633,6 +633,8 @@ int vmw_kms_readback(struct vmw_private *dev_priv, ...@@ -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_fence_rep __user *user_fence_rep,
struct drm_vmw_rect *clips, struct drm_vmw_rect *clips,
uint32_t num_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 * Overlay control - vmwgfx_overlay.c
......
...@@ -1517,6 +1517,8 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, ...@@ -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_width = rects[du->unit].w;
du->pref_height = rects[du->unit].h; du->pref_height = rects[du->unit].h;
du->pref_active = true; du->pref_active = true;
du->gui_x = rects[du->unit].x;
du->gui_y = rects[du->unit].y;
} else { } else {
du->pref_width = 800; du->pref_width = 800;
du->pref_height = 600; du->pref_height = 600;
...@@ -1572,12 +1574,14 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force) ...@@ -1572,12 +1574,14 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force)
uint32_t num_displays; uint32_t num_displays;
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct vmw_private *dev_priv = vmw_priv(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); mutex_lock(&dev_priv->hw_mutex);
num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS); num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS);
mutex_unlock(&dev_priv->hw_mutex); 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); connector_status_connected : connector_status_disconnected);
} }
...@@ -1723,3 +1727,63 @@ int vmw_du_connector_set_property(struct drm_connector *connector, ...@@ -1723,3 +1727,63 @@ int vmw_du_connector_set_property(struct drm_connector *connector,
{ {
return 0; 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;
}
...@@ -96,6 +96,12 @@ struct vmw_display_unit { ...@@ -96,6 +96,12 @@ struct vmw_display_unit {
unsigned pref_height; unsigned pref_height;
bool pref_active; bool pref_active;
struct drm_display_mode *pref_mode; struct drm_display_mode *pref_mode;
/*
* Gui positioning
*/
int gui_x;
int gui_y;
}; };
#define vmw_crtc_to_du(x) \ #define vmw_crtc_to_du(x) \
...@@ -126,8 +132,7 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, ...@@ -126,8 +132,7 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
int vmw_du_connector_set_property(struct drm_connector *connector, int vmw_du_connector_set_property(struct drm_connector *connector,
struct drm_property *property, struct drm_property *property,
uint64_t val); 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 * Legacy display unit functions - vmwgfx_ldu.c
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
#define DRM_VMW_FENCE_EVENT 17 #define DRM_VMW_FENCE_EVENT 17
#define DRM_VMW_PRESENT 18 #define DRM_VMW_PRESENT 18
#define DRM_VMW_PRESENT_READBACK 19 #define DRM_VMW_PRESENT_READBACK 19
#define DRM_VMW_UPDATE_LAYOUT 20
/*************************************************************************/ /*************************************************************************/
/** /**
...@@ -550,31 +550,6 @@ struct drm_vmw_get_3d_cap_arg { ...@@ -550,31 +550,6 @@ struct drm_vmw_get_3d_cap_arg {
uint32_t pad64; uint32_t pad64;
}; };
/*************************************************************************/
/**
* 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 * DRM_VMW_FENCE_WAIT
...@@ -788,4 +763,28 @@ struct drm_vmw_present_readback_arg { ...@@ -788,4 +763,28 @@ struct drm_vmw_present_readback_arg {
uint64_t clips_ptr; uint64_t clips_ptr;
uint64_t fence_rep; 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 #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment