aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakob Bornecrantz <jakob@vmware.com>2010-06-01 05:54:20 -0400
committerDave Airlie <airlied@redhat.com>2010-06-02 23:13:36 -0400
commitd8bd19d2aff95e52c7f356cc2fc722584a656065 (patch)
treee9312e761aede46a030030288a4a51a576019396
parent991b7b44f8cfa1b9beff8c4c2f2ec888b925c2a7 (diff)
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>
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c45
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c83
-rw-r--r--include/drm/vmwgfx_drm.h26
6 files changed, 160 insertions, 9 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 7597323d5a5a..b793c8c9acb3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -88,6 +88,9 @@
88#define DRM_IOCTL_VMW_FENCE_WAIT \ 88#define DRM_IOCTL_VMW_FENCE_WAIT \
89 DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT, \ 89 DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_FENCE_WAIT, \
90 struct drm_vmw_fence_wait_arg) 90 struct drm_vmw_fence_wait_arg)
91#define DRM_IOCTL_VMW_UPDATE_LAYOUT \
92 DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT, \
93 struct drm_vmw_update_layout_arg)
91 94
92 95
93/** 96/**
@@ -135,7 +138,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
135 VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl, 138 VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl,
136 DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED), 139 DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED),
137 VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl, 140 VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl,
138 DRM_AUTH | DRM_UNLOCKED) 141 DRM_AUTH | DRM_UNLOCKED),
142 VMW_IOCTL_DEF(DRM_IOCTL_VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl,
143 DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED)
139}; 144};
140 145
141static struct pci_device_id vmw_pci_id_list[] = { 146static 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 e577af5bb3d6..eaad52095339 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -41,7 +41,7 @@
41 41
42#define VMWGFX_DRIVER_DATE "20100209" 42#define VMWGFX_DRIVER_DATE "20100209"
43#define VMWGFX_DRIVER_MAJOR 1 43#define VMWGFX_DRIVER_MAJOR 1
44#define VMWGFX_DRIVER_MINOR 1 44#define VMWGFX_DRIVER_MINOR 2
45#define VMWGFX_DRIVER_PATCHLEVEL 0 45#define VMWGFX_DRIVER_PATCHLEVEL 0
46#define VMWGFX_FILE_PAGE_OFFSET 0x00100000 46#define VMWGFX_FILE_PAGE_OFFSET 0x00100000
47#define VMWGFX_FIFO_STATIC_SIZE (1024*1024) 47#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
@@ -509,6 +509,8 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
509void vmw_kms_write_svga(struct vmw_private *vmw_priv, 509void vmw_kms_write_svga(struct vmw_private *vmw_priv,
510 unsigned width, unsigned height, unsigned pitch, 510 unsigned width, unsigned height, unsigned pitch,
511 unsigned bbp, unsigned depth); 511 unsigned bbp, unsigned depth);
512int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
513 struct drm_file *file_priv);
512 514
513/** 515/**
514 * Overlay control - vmwgfx_overlay.c 516 * Overlay control - vmwgfx_overlay.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 648ba044f6f8..f1d626112415 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -938,3 +938,48 @@ int vmw_kms_restore_vga(struct vmw_private *vmw_priv)
938 938
939 return 0; 939 return 0;
940} 940}
941
942int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
943 struct drm_file *file_priv)
944{
945 struct vmw_private *dev_priv = vmw_priv(dev);
946 struct drm_vmw_update_layout_arg *arg =
947 (struct drm_vmw_update_layout_arg *)data;
948 struct vmw_master *vmaster = vmw_master(file_priv->master);
949 void __user *user_rects;
950 struct drm_vmw_rect *rects;
951 unsigned rects_size;
952 int ret;
953
954 ret = ttm_read_lock(&vmaster->lock, true);
955 if (unlikely(ret != 0))
956 return ret;
957
958 if (!arg->num_outputs) {
959 struct drm_vmw_rect def_rect = {0, 0, 800, 600};
960 vmw_kms_ldu_update_layout(dev_priv, 1, &def_rect);
961 goto out_unlock;
962 }
963
964 rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
965 rects = kzalloc(rects_size, GFP_KERNEL);
966 if (unlikely(!rects)) {
967 ret = -ENOMEM;
968 goto out_unlock;
969 }
970
971 user_rects = (void __user *)(unsigned long)arg->rects;
972 ret = copy_from_user(rects, user_rects, rects_size);
973 if (unlikely(ret != 0)) {
974 DRM_ERROR("Failed to get rects.\n");
975 goto out_free;
976 }
977
978 vmw_kms_ldu_update_layout(dev_priv, arg->num_outputs, rects);
979
980out_free:
981 kfree(rects);
982out_unlock:
983 ttm_read_unlock(&vmaster->lock);
984 return ret;
985}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 8b95249f0531..8a398a0339b6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -94,9 +94,11 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
94int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); 94int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
95 95
96/* 96/*
97 * Legacy display unit functions - vmwgfx_ldu.h 97 * Legacy display unit functions - vmwgfx_ldu.c
98 */ 98 */
99int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv); 99int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv);
100int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv); 100int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv);
101int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
102 struct drm_vmw_rect *rects);
101 103
102#endif 104#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index f7094dde18f9..cfaf690a5b2f 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -49,6 +49,11 @@ struct vmw_legacy_display {
49struct vmw_legacy_display_unit { 49struct vmw_legacy_display_unit {
50 struct vmw_display_unit base; 50 struct vmw_display_unit base;
51 51
52 unsigned pref_width;
53 unsigned pref_height;
54 bool pref_active;
55 struct drm_display_mode *pref_mode;
56
52 struct list_head active; 57 struct list_head active;
53}; 58};
54 59
@@ -332,8 +337,7 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector)
332static enum drm_connector_status 337static enum drm_connector_status
333 vmw_ldu_connector_detect(struct drm_connector *connector) 338 vmw_ldu_connector_detect(struct drm_connector *connector)
334{ 339{
335 /* XXX vmwctrl should control connection status */ 340 if (vmw_connector_to_ldu(connector)->pref_active)
336 if (vmw_connector_to_ldu(connector)->base.unit == 0)
337 return connector_status_connected; 341 return connector_status_connected;
338 return connector_status_disconnected; 342 return connector_status_disconnected;
339} 343}
@@ -344,10 +348,9 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
344 752, 800, 0, 480, 489, 492, 525, 0, 348 752, 800, 0, 480, 489, 492, 525, 0,
345 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, 349 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
346 /* 800x600@60Hz */ 350 /* 800x600@60Hz */
347 { DRM_MODE("800x600", 351 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
348 DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 352 968, 1056, 0, 600, 601, 605, 628, 0,
349 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 353 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
350 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
351 /* 1024x768@60Hz */ 354 /* 1024x768@60Hz */
352 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, 355 { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
353 1184, 1344, 0, 768, 771, 777, 806, 0, 356 1184, 1344, 0, 768, 771, 777, 806, 0,
@@ -419,10 +422,34 @@ static struct drm_display_mode vmw_ldu_connector_builtin[] = {
419static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, 422static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
420 uint32_t max_width, uint32_t max_height) 423 uint32_t max_width, uint32_t max_height)
421{ 424{
425 struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector);
422 struct drm_device *dev = connector->dev; 426 struct drm_device *dev = connector->dev;
423 struct drm_display_mode *mode = NULL; 427 struct drm_display_mode *mode = NULL;
428 struct drm_display_mode prefmode = { DRM_MODE("preferred",
429 DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
430 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
431 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
432 };
424 int i; 433 int i;
425 434
435 /* Add preferred mode */
436 {
437 mode = drm_mode_duplicate(dev, &prefmode);
438 if (!mode)
439 return 0;
440 mode->hdisplay = ldu->pref_width;
441 mode->vdisplay = ldu->pref_height;
442 mode->vrefresh = drm_mode_vrefresh(mode);
443 drm_mode_probed_add(connector, mode);
444
445 if (ldu->pref_mode) {
446 list_del_init(&ldu->pref_mode->head);
447 drm_mode_destroy(dev, ldu->pref_mode);
448 }
449
450 ldu->pref_mode = mode;
451 }
452
426 for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) { 453 for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
427 if (vmw_ldu_connector_builtin[i].hdisplay > max_width || 454 if (vmw_ldu_connector_builtin[i].hdisplay > max_width ||
428 vmw_ldu_connector_builtin[i].vdisplay > max_height) 455 vmw_ldu_connector_builtin[i].vdisplay > max_height)
@@ -482,6 +509,11 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
482 509
483 INIT_LIST_HEAD(&ldu->active); 510 INIT_LIST_HEAD(&ldu->active);
484 511
512 ldu->pref_active = (unit == 0);
513 ldu->pref_width = 800;
514 ldu->pref_height = 600;
515 ldu->pref_mode = NULL;
516
485 drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, 517 drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
486 DRM_MODE_CONNECTOR_LVDS); 518 DRM_MODE_CONNECTOR_LVDS);
487 connector->status = vmw_ldu_connector_detect(connector); 519 connector->status = vmw_ldu_connector_detect(connector);
@@ -546,3 +578,42 @@ int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv)
546 578
547 return 0; 579 return 0;
548} 580}
581
582int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num,
583 struct drm_vmw_rect *rects)
584{
585 struct drm_device *dev = dev_priv->dev;
586 struct vmw_legacy_display_unit *ldu;
587 struct drm_connector *con;
588 int i;
589
590 mutex_lock(&dev->mode_config.mutex);
591
592#if 0
593 DRM_INFO("%s: new layout ", __func__);
594 for (i = 0; i < (int)num; i++)
595 DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y,
596 rects[i].w, rects[i].h);
597 DRM_INFO("\n");
598#else
599 (void)i;
600#endif
601
602 list_for_each_entry(con, &dev->mode_config.connector_list, head) {
603 ldu = vmw_connector_to_ldu(con);
604 if (num > ldu->base.unit) {
605 ldu->pref_width = rects[ldu->base.unit].w;
606 ldu->pref_height = rects[ldu->base.unit].h;
607 ldu->pref_active = true;
608 } else {
609 ldu->pref_width = 800;
610 ldu->pref_height = 600;
611 ldu->pref_active = false;
612 }
613 con->status = vmw_ldu_connector_detect(con);
614 }
615
616 mutex_unlock(&dev->mode_config.mutex);
617
618 return 0;
619}
diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h
index c7645f480d12..4d0842391edc 100644
--- a/include/drm/vmwgfx_drm.h
+++ b/include/drm/vmwgfx_drm.h
@@ -50,6 +50,8 @@
50#define DRM_VMW_EXECBUF 12 50#define DRM_VMW_EXECBUF 12
51#define DRM_VMW_FIFO_DEBUG 13 51#define DRM_VMW_FIFO_DEBUG 13
52#define DRM_VMW_FENCE_WAIT 14 52#define DRM_VMW_FENCE_WAIT 14
53/* guarded by minor version >= 2 */
54#define DRM_VMW_UPDATE_LAYOUT 15
53 55
54 56
55/*************************************************************************/ 57/*************************************************************************/
@@ -585,4 +587,28 @@ struct drm_vmw_stream_arg {
585 * sure that the stream has been stopped. 587 * sure that the stream has been stopped.
586 */ 588 */
587 589
590/*************************************************************************/
591/**
592 * DRM_VMW_UPDATE_LAYOUT - Update layout
593 *
594 * Updates the prefered modes and connection status for connectors. The
595 * command conisits of one drm_vmw_update_layout_arg pointing out a array
596 * of num_outputs drm_vmw_rect's.
597 */
598
599/**
600 * struct drm_vmw_update_layout_arg
601 *
602 * @num_outputs: number of active
603 * @rects: pointer to array of drm_vmw_rect
604 *
605 * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
606 */
607
608struct drm_vmw_update_layout_arg {
609 uint32_t num_outputs;
610 uint32_t pad64;
611 uint64_t rects;
612};
613
588#endif 614#endif