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 /drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | |
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>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 83 |
1 files changed, 77 insertions, 6 deletions
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 | } | ||