diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_kms.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 163 |
1 files changed, 158 insertions, 5 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index b221a8c40282..4742ec4ead27 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -236,8 +236,8 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) struct vmw_display_unit *du = vmw_crtc_to_du(crtc); bool shown = du->cursor_surface || du->cursor_dmabuf ? true : false; - du->cursor_x = x + crtc->x; - du->cursor_y = y + crtc->y; + du->cursor_x = x + du->set_gui_x; + du->cursor_y = y + du->set_gui_y; /* * FIXME: Unclear whether there's any global state touched by the @@ -663,9 +663,8 @@ static int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, break; case vmw_du_screen_object: ret = vmw_kms_sou_do_dmabuf_dirty(dev_priv, &vfbd->base, - clips, num_clips, increment, - true, - NULL); + clips, NULL, num_clips, + increment, true, NULL); break; case vmw_du_legacy: ret = vmw_kms_ldu_do_dmabuf_dirty(dev_priv, &vfbd->base, 0, 0, @@ -1109,6 +1108,22 @@ int vmw_kms_present(struct vmw_private *dev_priv, return 0; } +static void +vmw_kms_create_hotplug_mode_update_property(struct vmw_private *dev_priv) +{ + if (dev_priv->hotplug_mode_update_property) + return; + + dev_priv->hotplug_mode_update_property = + drm_property_create_range(dev_priv->dev, + DRM_MODE_PROP_IMMUTABLE, + "hotplug_mode_update", 0, 1); + + if (!dev_priv->hotplug_mode_update_property) + return; + +} + int vmw_kms_init(struct vmw_private *dev_priv) { struct drm_device *dev = dev_priv->dev; @@ -1121,6 +1136,9 @@ int vmw_kms_init(struct vmw_private *dev_priv) dev->mode_config.max_width = dev_priv->texture_max_width; dev->mode_config.max_height = dev_priv->texture_max_height; + drm_mode_create_suggested_offset_properties(dev); + vmw_kms_create_hotplug_mode_update_property(dev_priv); + ret = vmw_kms_stdu_init_display(dev_priv); if (ret) { ret = vmw_kms_sou_init_display(dev_priv); @@ -1360,15 +1378,28 @@ static int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, du->pref_active = true; du->gui_x = rects[du->unit].x; du->gui_y = rects[du->unit].y; + drm_object_property_set_value + (&con->base, dev->mode_config.suggested_x_property, + du->gui_x); + drm_object_property_set_value + (&con->base, dev->mode_config.suggested_y_property, + du->gui_y); } else { du->pref_width = 800; du->pref_height = 600; du->pref_active = false; + drm_object_property_set_value + (&con->base, dev->mode_config.suggested_x_property, + 0); + drm_object_property_set_value + (&con->base, dev->mode_config.suggested_y_property, + 0); } con->status = vmw_du_connector_detect(con, true); } mutex_unlock(&dev->mode_config.mutex); + drm_sysfs_hotplug_event(dev); return 0; } @@ -1591,6 +1622,12 @@ int vmw_du_connector_set_property(struct drm_connector *connector, struct drm_property *property, uint64_t val) { + struct vmw_display_unit *du = vmw_connector_to_du(connector); + struct vmw_private *dev_priv = vmw_priv(connector->dev); + + if (property == dev_priv->implicit_placement_property) + du->is_implicit = val; + return 0; } @@ -2096,3 +2133,119 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv, return 0; } + +/** + * vmw_kms_del_active - unregister a crtc binding to the implicit framebuffer + * + * @dev_priv: Pointer to a device private struct. + * @du: The display unit of the crtc. + */ +void vmw_kms_del_active(struct vmw_private *dev_priv, + struct vmw_display_unit *du) +{ + lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex); + + if (du->active_implicit) { + if (--(dev_priv->num_implicit) == 0) + dev_priv->implicit_fb = NULL; + du->active_implicit = false; + } +} + +/** + * vmw_kms_add_active - register a crtc binding to an implicit framebuffer + * + * @vmw_priv: Pointer to a device private struct. + * @du: The display unit of the crtc. + * @vfb: The implicit framebuffer + * + * Registers a binding to an implicit framebuffer. + */ +void vmw_kms_add_active(struct vmw_private *dev_priv, + struct vmw_display_unit *du, + struct vmw_framebuffer *vfb) +{ + lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex); + + WARN_ON_ONCE(!dev_priv->num_implicit && dev_priv->implicit_fb); + + if (!du->active_implicit && du->is_implicit) { + dev_priv->implicit_fb = vfb; + du->active_implicit = true; + dev_priv->num_implicit++; + } +} + +/** + * vmw_kms_screen_object_flippable - Check whether we can page-flip a crtc. + * + * @dev_priv: Pointer to device-private struct. + * @crtc: The crtc we want to flip. + * + * Returns true or false depending whether it's OK to flip this crtc + * based on the criterion that we must not have more than one implicit + * frame-buffer at any one time. + */ +bool vmw_kms_crtc_flippable(struct vmw_private *dev_priv, + struct drm_crtc *crtc) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + + lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex); + + if (!du->is_implicit) + return true; + + if (dev_priv->num_implicit != 1) + return false; + + return true; +} + +/** + * vmw_kms_update_implicit_fb - Update the implicit fb. + * + * @dev_priv: Pointer to device-private struct. + * @crtc: The crtc the new implicit frame-buffer is bound to. + */ +void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv, + struct drm_crtc *crtc) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + struct vmw_framebuffer *vfb; + + lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex); + + if (!du->is_implicit) + return; + + vfb = vmw_framebuffer_to_vfb(crtc->primary->fb); + WARN_ON_ONCE(dev_priv->num_implicit != 1 && + dev_priv->implicit_fb != vfb); + + dev_priv->implicit_fb = vfb; +} + +/** + * vmw_kms_create_implicit_placement_proparty - Set up the implicit placement + * property. + * + * @dev_priv: Pointer to a device private struct. + * @immutable: Whether the property is immutable. + * + * Sets up the implicit placement property unless it's already set up. + */ +void +vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv, + bool immutable) +{ + if (dev_priv->implicit_placement_property) + return; + + dev_priv->implicit_placement_property = + drm_property_create_range(dev_priv->dev, + immutable ? + DRM_MODE_PROP_IMMUTABLE : 0, + "implicit_placement", 0, 1); + +} |