mirror of https://gitee.com/openkylin/linux.git
drm/vmwgfx: Allow userspace to change default layout. Bump minor.
The host may change the layout and, since the change is communicated to the master, the master needs a way to communicate the change to the kernel driver. The minor version number is bumped to advertize the availability of this feature. Signed-off-by: Jakob Bornecrantz <jakob@vmware.com> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
991b7b44f8
commit
d8bd19d2af
|
@ -88,6 +88,9 @@
|
|||
#define DRM_IOCTL_VMW_FENCE_WAIT \
|
||||
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT, \
|
||||
struct drm_vmw_fence_wait_arg)
|
||||
#define DRM_IOCTL_VMW_UPDATE_LAYOUT \
|
||||
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT, \
|
||||
struct drm_vmw_update_layout_arg)
|
||||
|
||||
|
||||
/**
|
||||
|
@ -135,7 +138,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
|
|||
VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
|
||||
DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
|
||||
VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
|
||||
DRM_AUTH | DRM_UNLOCKED)
|
||||
DRM_AUTH | DRM_UNLOCKED),
|
||||
VMW_IOCTL_DEF(DRM_IOCTL_VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
|
||||
DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
|
||||
};
|
||||
|
||||
static struct pci_device_id vmw_pci_id_list[] = {
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#define VMWGFX_DRIVER_DATE "20100209"
|
||||
#define VMWGFX_DRIVER_MAJOR 1
|
||||
#define VMWGFX_DRIVER_MINOR 1
|
||||
#define VMWGFX_DRIVER_MINOR 2
|
||||
#define VMWGFX_DRIVER_PATCHLEVEL 0
|
||||
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
|
||||
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
|
||||
|
@ -509,6 +509,8 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
|
|||
void vmw_kms_write_svga(struct vmw_private *vmw_priv,
|
||||
unsigned width, unsigned height, unsigned pitch,
|
||||
unsigned bbp, unsigned depth);
|
||||
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/**
|
||||
* Overlay control - vmwgfx_overlay.c
|
||||
|
|
|
@ -938,3 +938,48 @@ int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
|
|||
|
||||
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;
|
||||
|
||||
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_kms_ldu_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");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
vmw_kms_ldu_update_layout(dev_priv, arg->num_outputs, rects);
|
||||
|
||||
out_free:
|
||||
kfree(rects);
|
||||
out_unlock:
|
||||
ttm_read_unlock(&vmaster->lock);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -94,9 +94,11 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
|
|||
int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
|
||||
|
||||
/*
|
||||
* Legacy display unit functions - vmwgfx_ldu.h
|
||||
* Legacy display unit functions - vmwgfx_ldu.c
|
||||
*/
|
||||
int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
|
||||
int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
|
||||
int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
|
||||
struct drm_vmw_rect *rects);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -49,6 +49,11 @@ struct vmw_legacy_display {
|
|||
struct vmw_legacy_display_unit {
|
||||
struct vmw_display_unit base;
|
||||
|
||||
unsigned pref_width;
|
||||
unsigned pref_height;
|
||||
bool pref_active;
|
||||
struct drm_display_mode *pref_mode;
|
||||
|
||||
struct list_head active;
|
||||
};
|
||||
|
||||
|
@ -332,8 +337,7 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector)
|
|||
static enum drm_connector_status
|
||||
vmw_ldu_connector_detect(struct drm_connector *connector)
|
||||
{
|
||||
/* XXX vmwctrl should control connection status */
|
||||
if (vmw_connector_to_ldu(connector)->base.unit == 0)
|
||||
if (vmw_connector_to_ldu(connector)->pref_active)
|
||||
return connector_status_connected;
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
@ -344,10 +348,9 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
|
|||
752, 800, 0, 480, 489, 492, 525, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
|
||||
/* 800x600@60Hz */
|
||||
{ DRM_MODE("800x600",
|
||||
DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
||||
40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628,
|
||||
0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
|
||||
968, 1056, 0, 600, 601, 605, 628, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
|
||||
/* 1024x768@60Hz */
|
||||
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
|
||||
1184, 1344, 0, 768, 771, 777, 806, 0,
|
||||
|
@ -419,10 +422,34 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
|
|||
static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
|
||||
uint32_t max_width, uint32_t max_height)
|
||||
{
|
||||
struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_display_mode *mode = NULL;
|
||||
struct drm_display_mode prefmode = { DRM_MODE("preferred",
|
||||
DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
|
||||
};
|
||||
int i;
|
||||
|
||||
/* Add preferred mode */
|
||||
{
|
||||
mode = drm_mode_duplicate(dev, &prefmode);
|
||||
if (!mode)
|
||||
return 0;
|
||||
mode->hdisplay = ldu->pref_width;
|
||||
mode->vdisplay = ldu->pref_height;
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
if (ldu->pref_mode) {
|
||||
list_del_init(&ldu->pref_mode->head);
|
||||
drm_mode_destroy(dev, ldu->pref_mode);
|
||||
}
|
||||
|
||||
ldu->pref_mode = mode;
|
||||
}
|
||||
|
||||
for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
|
||||
if (vmw_ldu_connector_builtin[i].hdisplay > max_width ||
|
||||
vmw_ldu_connector_builtin[i].vdisplay > max_height)
|
||||
|
@ -482,6 +509,11 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
|
|||
|
||||
INIT_LIST_HEAD(&ldu->active);
|
||||
|
||||
ldu->pref_active = (unit == 0);
|
||||
ldu->pref_width = 800;
|
||||
ldu->pref_height = 600;
|
||||
ldu->pref_mode = NULL;
|
||||
|
||||
drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_LVDS);
|
||||
connector->status = vmw_ldu_connector_detect(connector);
|
||||
|
@ -546,3 +578,42 @@ int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
|
||||
struct drm_vmw_rect *rects)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct vmw_legacy_display_unit *ldu;
|
||||
struct drm_connector *con;
|
||||
int i;
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
#if 0
|
||||
DRM_INFO("%s: new layout ", __func__);
|
||||
for (i = 0; i < (int)num; i++)
|
||||
DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
|
||||
rects[i].w, rects[i].h);
|
||||
DRM_INFO("\n");
|
||||
#else
|
||||
(void)i;
|
||||
#endif
|
||||
|
||||
list_for_each_entry(con, &dev->mode_config.connector_list, head) {
|
||||
ldu = vmw_connector_to_ldu(con);
|
||||
if (num > ldu->base.unit) {
|
||||
ldu->pref_width = rects[ldu->base.unit].w;
|
||||
ldu->pref_height = rects[ldu->base.unit].h;
|
||||
ldu->pref_active = true;
|
||||
} else {
|
||||
ldu->pref_width = 800;
|
||||
ldu->pref_height = 600;
|
||||
ldu->pref_active = false;
|
||||
}
|
||||
con->status = vmw_ldu_connector_detect(con);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@
|
|||
#define DRM_VMW_EXECBUF 12
|
||||
#define DRM_VMW_FIFO_DEBUG 13
|
||||
#define DRM_VMW_FENCE_WAIT 14
|
||||
/* guarded by minor version >= 2 */
|
||||
#define DRM_VMW_UPDATE_LAYOUT 15
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
@ -585,4 +587,28 @@ struct drm_vmw_stream_arg {
|
|||
* sure that the stream has been stopped.
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
/**
|
||||
* DRM_VMW_UPDATE_LAYOUT - Update layout
|
||||
*
|
||||
* Updates the prefered 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;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue