From: Andrey Grodzovsky <Andrey.Grodzovsky@xxxxxxx> Switch from legacy cursor to DRM cursor plane. Cursor is not an actual plane but more of a subplane of each pipe. Bind a DRM cursor plane instance to each CRTC. Eliminate seperate FB object allocation for cursor and clean dm_crtc_cursor_set. Change-Id: I1d716ffe1427c27ef070acabd850f6fd56864415 Signed-off-by: Andrey Grodzovsky <Andrey.Grodzovsky at amd.com> Signed-off-by: Leo (Sunpeng) Li <sunpeng.li at amd.com> Reviewed-by: Harry Wentland <Harry.Wentland at amd.com> --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_types.c | 242 ++++++++------------- 1 file changed, 91 insertions(+), 151 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c index 939ea8df3440..75102fd1f1f7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_types.c @@ -137,127 +137,27 @@ static void dm_set_cursor( } } -static int dm_crtc_unpin_cursor_bo_old( - struct amdgpu_crtc *amdgpu_crtc) -{ - struct amdgpu_bo *robj; - int ret = 0; - - if (NULL != amdgpu_crtc && NULL != amdgpu_crtc->cursor_bo) { - robj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo); - - ret = amdgpu_bo_reserve(robj, false); - - if (likely(ret == 0)) { - ret = amdgpu_bo_unpin(robj); - - if (unlikely(ret != 0)) { - DRM_ERROR( - "%s: unpin failed (ret=%d), bo %p\n", - __func__, - ret, - amdgpu_crtc->cursor_bo); - } - - amdgpu_bo_unreserve(robj); - } else { - DRM_ERROR( - "%s: reserve failed (ret=%d), bo %p\n", - __func__, - ret, - amdgpu_crtc->cursor_bo); - } - - drm_gem_object_unreference_unlocked(amdgpu_crtc->cursor_bo); - amdgpu_crtc->cursor_bo = NULL; - } - - return ret; -} - -static int dm_crtc_pin_cursor_bo_new( - struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - struct amdgpu_bo **ret_obj) -{ - struct amdgpu_crtc *amdgpu_crtc; - struct amdgpu_bo *robj; - struct drm_gem_object *obj; - int ret = -EINVAL; - - if (NULL != crtc) { - struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; - uint64_t gpu_addr; - - amdgpu_crtc = to_amdgpu_crtc(crtc); - - obj = drm_gem_object_lookup(file_priv, handle); - - if (!obj) { - DRM_ERROR( - "Cannot find cursor object %x for crtc %d\n", - handle, - amdgpu_crtc->crtc_id); - goto release; - } - robj = gem_to_amdgpu_bo(obj); - - ret = amdgpu_bo_reserve(robj, false); - - if (unlikely(ret != 0)) { - drm_gem_object_unreference_unlocked(obj); - DRM_ERROR("dm_crtc_pin_cursor_bo_new ret %x, handle %x\n", - ret, handle); - goto release; - } - - ret = amdgpu_bo_pin_restricted(robj, AMDGPU_GEM_DOMAIN_VRAM, 0, - adev->mc.visible_vram_size, - &gpu_addr); - - if (ret == 0) { - amdgpu_crtc->cursor_addr = gpu_addr; - *ret_obj = robj; - } - amdgpu_bo_unreserve(robj); - if (ret) - drm_gem_object_unreference_unlocked(obj); - - } -release: - - return ret; -} - static int dm_crtc_cursor_set( struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, + uint64_t address, uint32_t width, uint32_t height) { - struct amdgpu_bo *new_cursor_bo; struct dc_cursor_position position; int ret; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - ret = EINVAL; - new_cursor_bo = NULL; DRM_DEBUG_KMS( - "%s: crtc_id=%d with handle %d and size %d to %d, bo_object %p\n", + "%s: crtc_id=%d with size %d to %d \n", __func__, amdgpu_crtc->crtc_id, - handle, width, - height, - amdgpu_crtc->cursor_bo); + height); - if (!handle) { + if (!address) { /* turn off cursor */ position.enable = false; position.x = 0; @@ -269,8 +169,6 @@ static int dm_crtc_cursor_set( amdgpu_crtc->stream, &position); } - /*unpin old cursor buffer and update cache*/ - ret = dm_crtc_unpin_cursor_bo_old(amdgpu_crtc); goto release; } @@ -284,21 +182,9 @@ static int dm_crtc_cursor_set( height); goto release; } - /*try to pin new cursor bo*/ - ret = dm_crtc_pin_cursor_bo_new(crtc, file_priv, handle, &new_cursor_bo); - /*if map not successful then return an error*/ - if (ret) - goto release; /*program new cursor bo to hardware*/ - dm_set_cursor(amdgpu_crtc, amdgpu_crtc->cursor_addr, width, height); - - /*un map old, not used anymore cursor bo , - * return memory and mapping back */ - dm_crtc_unpin_cursor_bo_old(amdgpu_crtc); - - /*assign new cursor bo to our internal cache*/ - amdgpu_crtc->cursor_bo = &new_cursor_bo->gem_base; + dm_set_cursor(amdgpu_crtc, address, width, height); release: return ret; @@ -360,23 +246,6 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, return 0; } -static void dm_crtc_cursor_reset(struct drm_crtc *crtc) -{ - struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - - DRM_DEBUG_KMS( - "%s: with cursor_bo %p\n", - __func__, - amdgpu_crtc->cursor_bo); - - if (amdgpu_crtc->cursor_bo && amdgpu_crtc->stream) { - dm_set_cursor( - amdgpu_crtc, - amdgpu_crtc->cursor_addr, - amdgpu_crtc->cursor_width, - amdgpu_crtc->cursor_height); - } -} static bool fill_rects_from_plane_state( const struct drm_plane_state *state, struct dc_surface *surface) @@ -1172,8 +1041,6 @@ static int amdgpu_atomic_helper_page_flip(struct drm_crtc *crtc, /* Implemented only the options currently availible for the driver */ static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { .reset = drm_atomic_helper_crtc_reset, - .cursor_set = dm_crtc_cursor_set, - .cursor_move = dm_crtc_cursor_move, .destroy = amdgpu_dm_crtc_destroy, .gamma_set = drm_atomic_helper_legacy_gamma_set, .set_config = drm_atomic_helper_set_config, @@ -1742,6 +1609,18 @@ static int dm_plane_helper_prepare_fb( } amdgpu_bo_ref(rbo); + + /* It's a hack for s3 since in 4.9 kernel filter out cursor buffer + * prepare and cleanup in drm_atomic_helper_prepare_planes + * and drm_atomic_helper_cleanup_planes because fb doens't in s3. + * IN 4.10 kernel this code should be removed and amdgpu_device_suspend + * code touching fram buffers should be avoided for DC. + */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_state->crtc); + + acrtc->cursor_bo = obj; + } return 0; } @@ -1839,6 +1718,10 @@ static uint32_t yuv_formats[] = { DRM_FORMAT_NV21, }; +static const u32 cursor_formats[] = { + DRM_FORMAT_ARGB8888 +}; + int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, struct amdgpu_plane *aplane, unsigned long possible_crtcs) @@ -1869,7 +1752,14 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, aplane->plane_type, NULL); break; case DRM_PLANE_TYPE_CURSOR: - DRM_ERROR("KMS: Cursor plane not implemented."); + res = drm_universal_plane_init( + dm->adev->ddev, + &aplane->base, + possible_crtcs, + &dm_plane_funcs, + cursor_formats, + ARRAY_SIZE(cursor_formats), + aplane->plane_type, NULL); break; } @@ -1882,9 +1772,18 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, struct drm_plane *plane, uint32_t crtc_index) { - struct amdgpu_crtc *acrtc; + struct amdgpu_crtc *acrtc = NULL; + struct amdgpu_plane *cursor_plane; + int res = -ENOMEM; + cursor_plane = kzalloc(sizeof(*cursor_plane), GFP_KERNEL); + if (!cursor_plane) + goto fail; + + cursor_plane->base.type = DRM_PLANE_TYPE_CURSOR; + res = amdgpu_dm_plane_init(dm, cursor_plane, 0); + acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL); if (!acrtc) goto fail; @@ -1893,7 +1792,7 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, dm->ddev, &acrtc->base, plane, - NULL, + &cursor_plane->base, &amdgpu_dm_crtc_funcs, NULL); if (res) @@ -1911,12 +1810,17 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, drm_mode_crtc_set_gamma_size(&acrtc->base, 256); return 0; + fail: - kfree(acrtc); + if (acrtc) + kfree(acrtc); + if (cursor_plane) + kfree(cursor_plane); acrtc->crtc_id = -1; return res; } + static int to_drm_connector_type(enum signal_type st) { switch (st) { @@ -2431,6 +2335,34 @@ static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) acrtc->enabled = false; } +static void handle_cursor_update( + struct drm_plane *plane, + struct drm_plane_state *old_plane_state) +{ + if (!plane->state->fb && !old_plane_state->fb) + return; + + /* Check if it's a cursor on/off update or just cursor move*/ + if (plane->state->fb == old_plane_state->fb) + dm_crtc_cursor_move( + plane->state->crtc, + plane->state->crtc_x, + plane->state->crtc_y); + else { + struct amdgpu_framebuffer *afb = + to_amdgpu_framebuffer(plane->state->fb); + dm_crtc_cursor_set( + (!!plane->state->fb) ? + plane->state->crtc : + old_plane_state->crtc, + (!!plane->state->fb) ? + afb->address : + 0, + plane->state->crtc_w, + plane->state->crtc_h); + } +} + /* * Executes flip @@ -2522,6 +2454,11 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, struct dm_connector_state *con_state = NULL; bool pflip_needed; + if (plane->type == DRM_PLANE_TYPE_CURSOR) { + handle_cursor_update(plane, old_plane_state); + continue; + } + if (!fb || !crtc || !crtc->state->active) continue; @@ -2806,7 +2743,6 @@ void amdgpu_dm_atomic_commit_tail( adev->dm.freesync_module, &acrtc->stream, 1); manage_dm_interrupts(adev, acrtc, true); - dm_crtc_cursor_reset(&acrtc->base); } @@ -3186,18 +3122,19 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, } } + /* - * TODO revisit when removing commit action - * and looking at atomic flags directly + * Hack: Commit needs planes right now, specifically for gamma + * TODO rework commit to check CRTC for gamma change */ + if (crtc_state->color_mgmt_changed) { - /* commit needs planes right now (for gamma, eg.) */ - /* TODO rework commit to chack crtc for gamma change */ - ret = drm_atomic_add_affected_planes(state, crtc); - if (ret) - return ret; + ret = drm_atomic_add_affected_planes(state, crtc); + if (ret) + return ret; - ret = -EINVAL; + ret = -EINVAL; + } } /* Check scaling and undersacn changes*/ @@ -3252,6 +3189,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_crtc_state *crtc_state; bool pflip_needed; + /*TODO Implement atomic check for cursor plane */ + if (plane->type == DRM_PLANE_TYPE_CURSOR) + continue; if (!fb || !crtc || crtc_set[i] != crtc || !crtc->state->planes_changed || !crtc->state->active) -- 2.11.0