diff options
| -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 |
