Dave, I saw the other two patches going into drm-fixes-staging, but this one was not included. It's pretty important because it fixes fighting when setting monitor topology between gnome-settings-daemon and the vmware-user daemon.
Thanks Thomas On 10/25/2011 11:35 PM, Thomas Hellstrom wrote: > 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 at vmware.com> > --- > drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 6 +++ > drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 6 ++- > drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 66 > ++++++++++++++++++++++++++++++++++- > drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 9 ++++- > include/drm/vmwgfx_drm.h | 51 +++++++++++++-------------- > 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 b8eb8cd..0bc20c1 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 30589d0..8cca91a 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 8b14dfd..f9a0f98 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 db0b901..815cf99 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 cd7cd81..bcb0912 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 >