diff options
author | Sinclair Yeh <syeh@vmware.com> | 2017-03-23 14:18:32 -0700 |
---|---|---|
committer | Sinclair Yeh <syeh@vmware.com> | 2017-03-31 13:37:03 -0700 |
commit | 060e2ad57041b42ccecd0047ef4d893f200692c2 (patch) | |
tree | c81a5a4b61edb5017d0aa1b3c79f102c271f98e7 /drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | |
parent | 06ec41909e31be3347f8679e9667d12ac6f7ee6e (diff) | |
download | lwn-060e2ad57041b42ccecd0047ef4d893f200692c2.tar.gz lwn-060e2ad57041b42ccecd0047ef4d893f200692c2.zip |
drm/vmwgfx: Add and connect plane helper functions
Refactor previous FB and cursor plane update code into their
atomic counterparts: check, update, prepare, cleanup, and disable.
These helpers won't be called until we flip on the atomic support
flag or set drm_crtc_funcs->set_config to using the atomic
helper.
v2:
* Removed unnecessary pinning of cursor surface
* Added a few function headers
v3:
* Set clip region equal to the destination region
* Fixed surface pinning policy
* Enable SVGA mode in vmw_sou_primary_plane_prepare_fb
Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 662024c9f351..eca055ec27c8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -612,6 +612,100 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = { * Screen Object Display Plane Functions */ +/** + * vmw_sou_primary_plane_cleanup_fb - Frees sou backing buffer + * + * @plane: display plane + * @old_state: Contains the FB to clean up + * + * Unpins the display surface + * + * Returns 0 on success + */ +static void +vmw_sou_primary_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); + + vmw_dmabuf_unreference(&vps->dmabuf); + vps->dmabuf_size = 0; + + vmw_du_plane_cleanup_fb(plane, old_state); +} + + +/** + * vmw_sou_primary_plane_prepare_fb - allocate backing buffer + * + * @plane: display plane + * @new_state: info on the new plane state, including the FB + * + * The SOU backing buffer is our equivalent of the display plane. + * + * Returns 0 on success + */ +static int +vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + struct drm_framebuffer *new_fb = new_state->fb; + struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc; + struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); + struct vmw_private *dev_priv; + size_t size; + int ret; + + + if (!new_fb) { + vmw_dmabuf_unreference(&vps->dmabuf); + vps->dmabuf_size = 0; + + return 0; + } + + size = new_state->crtc_w * new_state->crtc_h * 4; + + if (vps->dmabuf) { + if (vps->dmabuf_size == size) + return 0; + + vmw_dmabuf_unreference(&vps->dmabuf); + vps->dmabuf_size = 0; + } + + vps->dmabuf = kzalloc(sizeof(*vps->dmabuf), GFP_KERNEL); + if (!vps->dmabuf) + return -ENOMEM; + + dev_priv = vmw_priv(crtc->dev); + vmw_svga_enable(dev_priv); + + /* After we have alloced the backing store might not be able to + * resume the overlays, this is preferred to failing to alloc. + */ + vmw_overlay_pause_all(dev_priv); + ret = vmw_dmabuf_init(dev_priv, vps->dmabuf, size, + &vmw_vram_ne_placement, + false, &vmw_dmabuf_bo_free); + vmw_overlay_resume_all(dev_priv); + + if (ret != 0) + vps->dmabuf = NULL; /* vmw_dmabuf_init frees on error */ + else + vps->dmabuf_size = size; + + return ret; +} + + +static void +vmw_sou_primary_plane_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ +} + + static const struct drm_plane_funcs vmw_sou_plane_funcs = { .update_plane = drm_primary_helper_update, .disable_plane = drm_primary_helper_disable, @@ -633,6 +727,22 @@ static const struct drm_plane_funcs vmw_sou_cursor_funcs = { /* * Atomic Helpers */ +static const struct +drm_plane_helper_funcs vmw_sou_cursor_plane_helper_funcs = { + .atomic_check = vmw_du_cursor_plane_atomic_check, + .atomic_update = vmw_du_cursor_plane_atomic_update, + .prepare_fb = vmw_du_cursor_plane_prepare_fb, + .cleanup_fb = vmw_du_plane_cleanup_fb, +}; + +static const struct +drm_plane_helper_funcs vmw_sou_primary_plane_helper_funcs = { + .atomic_check = vmw_du_primary_plane_atomic_check, + .atomic_update = vmw_sou_primary_plane_atomic_update, + .prepare_fb = vmw_sou_primary_plane_prepare_fb, + .cleanup_fb = vmw_sou_primary_plane_cleanup_fb, +}; + static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = { .prepare = vmw_sou_crtc_helper_prepare, .commit = vmw_sou_crtc_helper_commit, @@ -691,6 +801,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) goto err_free; } + drm_plane_helper_add(primary, &vmw_sou_primary_plane_helper_funcs); + /* Initialize cursor plane */ vmw_du_plane_reset(cursor); @@ -705,6 +817,9 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) goto err_free; } + drm_plane_helper_add(cursor, &vmw_sou_cursor_plane_helper_funcs); + + vmw_du_connector_reset(connector); ret = drm_connector_init(dev, connector, &vmw_sou_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL); if (ret) { |