Commit 2ea5e9a8 authored by Andrey Grodzovsky's avatar Andrey Grodzovsky Committed by Alex Deucher

drm/amd/display: Universal cursor plane hook-up.

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.
Signed-off-by: default avatarAndrey Grodzovsky <Andrey.Grodzovsky@amd.com>
Signed-off-by: default avatarLeo (Sunpeng) Li <sunpeng.li@amd.com>
Reviewed-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 0f9a536f
...@@ -136,127 +136,27 @@ static void dm_set_cursor( ...@@ -136,127 +136,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( static int dm_crtc_cursor_set(
struct drm_crtc *crtc, struct drm_crtc *crtc,
struct drm_file *file_priv, uint64_t address,
uint32_t handle,
uint32_t width, uint32_t width,
uint32_t height) uint32_t height)
{ {
struct amdgpu_bo *new_cursor_bo;
struct dc_cursor_position position; struct dc_cursor_position position;
int ret; int ret;
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
ret = EINVAL; ret = EINVAL;
new_cursor_bo = NULL;
DRM_DEBUG_KMS( 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__, __func__,
amdgpu_crtc->crtc_id, amdgpu_crtc->crtc_id,
handle,
width, width,
height, height);
amdgpu_crtc->cursor_bo);
if (!handle) { if (!address) {
/* turn off cursor */ /* turn off cursor */
position.enable = false; position.enable = false;
position.x = 0; position.x = 0;
...@@ -268,8 +168,6 @@ static int dm_crtc_cursor_set( ...@@ -268,8 +168,6 @@ static int dm_crtc_cursor_set(
amdgpu_crtc->stream, amdgpu_crtc->stream,
&position); &position);
} }
/*unpin old cursor buffer and update cache*/
ret = dm_crtc_unpin_cursor_bo_old(amdgpu_crtc);
goto release; goto release;
} }
...@@ -283,21 +181,9 @@ static int dm_crtc_cursor_set( ...@@ -283,21 +181,9 @@ static int dm_crtc_cursor_set(
height); height);
goto release; 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*/ /*program new cursor bo to hardware*/
dm_set_cursor(amdgpu_crtc, amdgpu_crtc->cursor_addr, width, height); dm_set_cursor(amdgpu_crtc, address, 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;
release: release:
return ret; return ret;
...@@ -359,23 +245,6 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc, ...@@ -359,23 +245,6 @@ static int dm_crtc_cursor_move(struct drm_crtc *crtc,
return 0; 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( static bool fill_rects_from_plane_state(
const struct drm_plane_state *state, const struct drm_plane_state *state,
struct dc_surface *surface) struct dc_surface *surface)
...@@ -1094,8 +963,6 @@ void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc) ...@@ -1094,8 +963,6 @@ void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
/* Implemented only the options currently availible for the driver */ /* Implemented only the options currently availible for the driver */
static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = { static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
.reset = drm_atomic_helper_crtc_reset, .reset = drm_atomic_helper_crtc_reset,
.cursor_set = dm_crtc_cursor_set,
.cursor_move = dm_crtc_cursor_move,
.destroy = amdgpu_dm_crtc_destroy, .destroy = amdgpu_dm_crtc_destroy,
.gamma_set = drm_atomic_helper_legacy_gamma_set, .gamma_set = drm_atomic_helper_legacy_gamma_set,
.set_config = drm_atomic_helper_set_config, .set_config = drm_atomic_helper_set_config,
...@@ -1571,6 +1438,18 @@ static int dm_plane_helper_prepare_fb( ...@@ -1571,6 +1438,18 @@ static int dm_plane_helper_prepare_fb(
} }
amdgpu_bo_ref(rbo); 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; return 0;
} }
...@@ -1668,6 +1547,10 @@ static uint32_t yuv_formats[] = { ...@@ -1668,6 +1547,10 @@ static uint32_t yuv_formats[] = {
DRM_FORMAT_NV21, DRM_FORMAT_NV21,
}; };
static const u32 cursor_formats[] = {
DRM_FORMAT_ARGB8888
};
int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
struct amdgpu_plane *aplane, struct amdgpu_plane *aplane,
unsigned long possible_crtcs) unsigned long possible_crtcs)
...@@ -1698,7 +1581,14 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, ...@@ -1698,7 +1581,14 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
NULL, aplane->plane_type, NULL); NULL, aplane->plane_type, NULL);
break; break;
case DRM_PLANE_TYPE_CURSOR: 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),
NULL, aplane->plane_type, NULL);
break; break;
} }
...@@ -1711,9 +1601,18 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, ...@@ -1711,9 +1601,18 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
struct drm_plane *plane, struct drm_plane *plane,
uint32_t crtc_index) uint32_t crtc_index)
{ {
struct amdgpu_crtc *acrtc; struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_plane *cursor_plane;
int res = -ENOMEM; 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); acrtc = kzalloc(sizeof(struct amdgpu_crtc), GFP_KERNEL);
if (!acrtc) if (!acrtc)
goto fail; goto fail;
...@@ -1722,7 +1621,7 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, ...@@ -1722,7 +1621,7 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
dm->ddev, dm->ddev,
&acrtc->base, &acrtc->base,
plane, plane,
NULL, &cursor_plane->base,
&amdgpu_dm_crtc_funcs, NULL); &amdgpu_dm_crtc_funcs, NULL);
if (res) if (res)
...@@ -1740,12 +1639,17 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm, ...@@ -1740,12 +1639,17 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
drm_mode_crtc_set_gamma_size(&acrtc->base, 256); drm_mode_crtc_set_gamma_size(&acrtc->base, 256);
return 0; return 0;
fail: fail:
if (acrtc)
kfree(acrtc); kfree(acrtc);
if (cursor_plane)
kfree(cursor_plane);
acrtc->crtc_id = -1; acrtc->crtc_id = -1;
return res; return res;
} }
static int to_drm_connector_type(enum signal_type st) static int to_drm_connector_type(enum signal_type st)
{ {
switch (st) { switch (st) {
...@@ -2252,6 +2156,34 @@ static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc) ...@@ -2252,6 +2156,34 @@ static void remove_stream(struct amdgpu_device *adev, struct amdgpu_crtc *acrtc)
acrtc->enabled = false; 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 * Executes flip
...@@ -2343,6 +2275,11 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state, ...@@ -2343,6 +2275,11 @@ static void amdgpu_dm_commit_surfaces(struct drm_atomic_state *state,
struct dm_connector_state *con_state = NULL; struct dm_connector_state *con_state = NULL;
bool pflip_needed; bool pflip_needed;
if (plane->type == DRM_PLANE_TYPE_CURSOR) {
handle_cursor_update(plane, old_plane_state);
continue;
}
if (!fb || !crtc || !crtc->state->active) if (!fb || !crtc || !crtc->state->active)
continue; continue;
...@@ -2627,7 +2564,6 @@ void amdgpu_dm_atomic_commit_tail( ...@@ -2627,7 +2564,6 @@ void amdgpu_dm_atomic_commit_tail(
adev->dm.freesync_module, &acrtc->stream, 1); adev->dm.freesync_module, &acrtc->stream, 1);
manage_dm_interrupts(adev, acrtc, true); manage_dm_interrupts(adev, acrtc, true);
dm_crtc_cursor_reset(&acrtc->base);
} }
...@@ -3007,19 +2943,20 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3007,19 +2943,20 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
} }
} }
/* /*
* TODO revisit when removing commit action * Hack: Commit needs planes right now, specifically for gamma
* and looking at atomic flags directly * 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); ret = drm_atomic_add_affected_planes(state, crtc);
if (ret) if (ret)
return ret; return ret;
ret = -EINVAL; ret = -EINVAL;
} }
}
/* Check scaling and undersacn changes*/ /* Check scaling and undersacn changes*/
for_each_connector_in_state(state, connector, conn_state, i) { for_each_connector_in_state(state, connector, conn_state, i) {
...@@ -3073,6 +3010,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev, ...@@ -3073,6 +3010,9 @@ int amdgpu_dm_atomic_check(struct drm_device *dev,
struct drm_crtc_state *crtc_state; struct drm_crtc_state *crtc_state;
bool pflip_needed; 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 || if (!fb || !crtc || crtc_set[i] != crtc ||
!crtc->state->planes_changed || !crtc->state->active) !crtc->state->planes_changed || !crtc->state->active)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment