diff options
author | Jakob Bornecrantz <jakob@vmware.com> | 2010-06-01 05:54:20 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-06-02 23:13:36 -0400 |
commit | d8bd19d2aff95e52c7f356cc2fc722584a656065 (patch) | |
tree | e9312e761aede46a030030288a4a51a576019396 | |
parent | 991b7b44f8cfa1b9beff8c4c2f2ec888b925c2a7 (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.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 45 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 83 | ||||
-rw-r--r-- | include/drm/vmwgfx_drm.h | 26 |
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 | ||
141 | static struct pci_device_id vmw_pci_id_list[] = { | 146 | 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 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, | |||
509 | void vmw_kms_write_svga(struct vmw_private *vmw_priv, | 509 | void 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); |
512 | int 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 | |||
942 | int 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 | |||
980 | out_free: | ||
981 | kfree(rects); | ||
982 | out_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, | |||
94 | int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); | 94 | int 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 | */ |
99 | int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv); | 99 | int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv); |
100 | int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv); | 100 | int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv); |
101 | int 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 { | |||
49 | struct vmw_legacy_display_unit { | 49 | struct 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) | |||
332 | static enum drm_connector_status | 337 | static 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[] = { | |||
419 | static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, | 422 | static 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 | |||
582 | int 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 | |||
608 | struct drm_vmw_update_layout_arg { | ||
609 | uint32_t num_outputs; | ||
610 | uint32_t pad64; | ||
611 | uint64_t rects; | ||
612 | }; | ||
613 | |||
588 | #endif | 614 | #endif |