[PATCH 1/2] drm/amd/display: Introduce overlay cursor mode
Harry Wentland
harry.wentland at amd.com
Thu Mar 28 15:52:17 UTC 2024
On 2024-03-28 11:48, Robert Mader wrote:
> Hi,
>
> On 15.03.24 18:09, sunpeng.li at amd.com wrote:
>> From: Leo Li <sunpeng.li at amd.com>
>>
>> [Why]
>>
>> DCN is the display hardware for amdgpu. DRM planes are backed by DCN
>> hardware pipes, which carry pixel data from one end (memory), to the
>> other (output encoder).
>>
>> Each DCN pipe has the ability to blend in a cursor early on in the
>> pipeline. In other words, there are no dedicated cursor planes in DCN,
>> which makes cursor behavior somewhat unintuitive for compositors.
>>
>> For example, if the cursor is in RGB format, but the top-most DRM plane
>> is in YUV format, DCN will not be able to blend them. Because of this,
>> amdgpu_dm rejects all configurations where a cursor needs to be enabled
>> on top of a YUV formatted plane.
>>
>> From a compositor's perspective, when computing an allocation for
>> hardware plane offloading, this cursor-on-yuv configuration result in an
>> atomic test failure. Since the failure reason is not obvious at all,
>> compositors will likely fall back to full rendering, which is not ideal.
>>
>> Instead, amdgpu_dm can try to accommodate the cursor-on-yuv
>> configuration by opportunistically reserving a separate DCN pipe just
>> for the cursor. We can refer to this as "overlay cursor mode". It is
>> contrasted with "native cursor mode", where the native DCN per-pipe
>> cursor is used.
>>
>> [How]
>>
>> On each crtc, compute whether the cursor plane should be enabled in
>> overlay mode (which currently, is iff the immediate plane below has a
>> YUV format). If it is, mark the CRTC as requesting overlay cursor mode.
>
> iff -> if
>
> IIRC another case where this would be needed is when the scale of the
> plane below doesn't match the cursor scale. This is especially common
> for videos and thus implicitly covered by the YUV check in most cases,
> but should probably be made explicit. Michel Dänzer might be able to
> comment here.
>
> Another possible case that could be covered here is when some area is
> not covered by any plane and just shows a black background. This happens
> e.g. if a compositor puts a YUV surface on the primary plane that has a
> different width/high ratio than the display. The compositor can add
> black bars by just leaving the area uncovered and thus require only a
> single hardware plane for video playback ("Unless explicitly specified
> (..), the active area of a CRTC will be black by default."
> https://dri.freedesktop.org/docs/drm/gpu/drm-kms.html#plane-abstraction). If the cursor is visible over this black bars, AMD currently refuses the commit IIUC (see also Michel Dänzers comment at https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3177#note_1924544)
>
Thanks for mentioning both of these scenarios. I agree it would be
good if we can expand the use of the overlay cursor to these cases.
Harry
> Thanks,
>
> Robert Mader
>
>>
>> During DC validation, attempt to enable a separate DCN pipe for the
>> cursor if it's in overlay mode. If that fails, or if no overlay mode is
>> requested, then fallback to native mode.
>>
>> Signed-off-by: Leo Li <sunpeng.li at amd.com>
>> ---
>> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 309 +++++++++++++++---
>> .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 7 +
>> .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 1 +
>> .../amd/display/amdgpu_dm/amdgpu_dm_plane.c | 13 +-
>> 4 files changed, 288 insertions(+), 42 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> index 21a61454c878..09ab330aed17 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> @@ -8359,8 +8359,19 @@ static void amdgpu_dm_commit_planes(struct
>> drm_atomic_state *state,
>> * Disable the cursor first if we're disabling all the planes.
>> * It'll remain on the screen after the planes are re-enabled
>> * if we don't.
>> + *
>> + * If the cursor is transitioning from native to overlay mode, the
>> + * native cursor needs to be disabled first.
>> */
>> - if (acrtc_state->active_planes == 0)
>> + if (acrtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE &&
>> + dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
>> + struct dc_cursor_position cursor_position = {0};
>> + dc_stream_set_cursor_position(acrtc_state->stream,
>> + &cursor_position);
>> + }
>> +
>> + if (acrtc_state->active_planes == 0 &&
>> + dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
>> amdgpu_dm_commit_cursors(state);
>> /* update planes when needed */
>> @@ -8374,7 +8385,8 @@ static void amdgpu_dm_commit_planes(struct
>> drm_atomic_state *state,
>> struct dm_plane_state *dm_new_plane_state =
>> to_dm_plane_state(new_plane_state);
>> /* Cursor plane is handled after stream updates */
>> - if (plane->type == DRM_PLANE_TYPE_CURSOR) {
>> + if (plane->type == DRM_PLANE_TYPE_CURSOR &&
>> + acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE) {
>> if ((fb && crtc == pcrtc) ||
>> (old_plane_state->fb && old_plane_state->crtc ==
>> pcrtc))
>> cursor_update = true;
>> @@ -8727,7 +8739,8 @@ static void amdgpu_dm_commit_planes(struct
>> drm_atomic_state *state,
>> * This avoids redundant programming in the case where we're going
>> * to be disabling a single plane - those pipes are being disabled.
>> */
>> - if (acrtc_state->active_planes)
>> + if (acrtc_state->active_planes &&
>> + acrtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE)
>> amdgpu_dm_commit_cursors(state);
>> cleanup:
>> @@ -10039,7 +10052,8 @@ static bool should_reset_plane(struct
>> drm_atomic_state *state,
>> {
>> struct drm_plane *other;
>> struct drm_plane_state *old_other_state, *new_other_state;
>> - struct drm_crtc_state *new_crtc_state;
>> + struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>> + struct dm_crtc_state *old_dm_crtc_state, *new_dm_crtc_state;
>> struct amdgpu_device *adev = drm_to_adev(plane->dev);
>> int i;
>> @@ -10061,10 +10075,24 @@ static bool should_reset_plane(struct
>> drm_atomic_state *state,
>> new_crtc_state =
>> drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
>> + old_crtc_state =
>> + drm_atomic_get_old_crtc_state(state, old_plane_state->crtc);
>> if (!new_crtc_state)
>> return true;
>> + /*
>> + * A change in cursor mode means a new dc pipe needs to be
>> acquired or
>> + * released from the state
>> + */
>> + old_dm_crtc_state = to_dm_crtc_state(old_crtc_state);
>> + new_dm_crtc_state = to_dm_crtc_state(new_crtc_state);
>> + if (plane->type == DRM_PLANE_TYPE_CURSOR &&
>> + old_dm_crtc_state != NULL &&
>> + old_dm_crtc_state->cursor_mode !=
>> new_dm_crtc_state->cursor_mode) {
>> + return true;
>> + }
>> +
>> /* CRTC Degamma changes currently require us to recreate planes. */
>> if (new_crtc_state->color_mgmt_changed)
>> return true;
>> @@ -10216,6 +10244,68 @@ static int dm_check_cursor_fb(struct
>> amdgpu_crtc *new_acrtc,
>> return 0;
>> }
>> +/*
>> + * Helper function for checking the cursor in native mode
>> + */
>> +static int dm_check_native_cursor_state(struct drm_crtc *new_plane_crtc,
>> + struct drm_plane *plane,
>> + struct drm_plane_state *new_plane_state,
>> + bool enable)
>> +{
>> +
>> + struct amdgpu_crtc *new_acrtc;
>> + int ret;
>> +
>> + if (!enable || !new_plane_crtc ||
>> + drm_atomic_plane_disabling(plane->state, new_plane_state))
>> + return 0;
>> +
>> + new_acrtc = to_amdgpu_crtc(new_plane_crtc);
>> +
>> + if (new_plane_state->src_x != 0 || new_plane_state->src_y != 0) {
>> + DRM_DEBUG_ATOMIC("Cropping not supported for cursor plane\n");
>> + return -EINVAL;
>> + }
>> +
>> + if (new_plane_state->fb) {
>> + ret = dm_check_cursor_fb(new_acrtc, new_plane_state,
>> + new_plane_state->fb);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static bool dm_should_update_native_cursor(struct drm_atomic_state
>> *state,
>> + struct drm_crtc *old_plane_crtc,
>> + struct drm_crtc *new_plane_crtc,
>> + bool enable)
>> +{
>> + struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>> + struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state;
>> +
>> + if (!enable) {
>> + if (old_plane_crtc == NULL)
>> + return true;
>> +
>> + old_crtc_state = drm_atomic_get_old_crtc_state(
>> + state, old_plane_crtc);
>> + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
>> +
>> + return dm_old_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE;
>> + } else {
>> + if (new_plane_crtc == NULL)
>> + return true;
>> +
>> + new_crtc_state = drm_atomic_get_new_crtc_state(
>> + state, new_plane_crtc);
>> + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
>> +
>> + return dm_new_crtc_state->cursor_mode == DM_CURSOR_NATIVE_MODE;
>> + }
>> +}
>> +
>> static int dm_update_plane_state(struct dc *dc,
>> struct drm_atomic_state *state,
>> struct drm_plane *plane,
>> @@ -10231,8 +10321,7 @@ static int dm_update_plane_state(struct dc *dc,
>> struct drm_crtc_state *old_crtc_state, *new_crtc_state;
>> struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state;
>> struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state;
>> - struct amdgpu_crtc *new_acrtc;
>> - bool needs_reset;
>> + bool needs_reset, update_native_cursor;
>> int ret = 0;
>> @@ -10241,24 +10330,16 @@ static int dm_update_plane_state(struct dc *dc,
>> dm_new_plane_state = to_dm_plane_state(new_plane_state);
>> dm_old_plane_state = to_dm_plane_state(old_plane_state);
>> - if (plane->type == DRM_PLANE_TYPE_CURSOR) {
>> - if (!enable || !new_plane_crtc ||
>> - drm_atomic_plane_disabling(plane->state, new_plane_state))
>> - return 0;
>> -
>> - new_acrtc = to_amdgpu_crtc(new_plane_crtc);
>> -
>> - if (new_plane_state->src_x != 0 || new_plane_state->src_y !=
>> 0) {
>> - DRM_DEBUG_ATOMIC("Cropping not supported for cursor
>> plane\n");
>> - return -EINVAL;
>> - }
>> + update_native_cursor = dm_should_update_native_cursor(state,
>> + old_plane_crtc,
>> + new_plane_crtc,
>> + enable);
>> - if (new_plane_state->fb) {
>> - ret = dm_check_cursor_fb(new_acrtc, new_plane_state,
>> - new_plane_state->fb);
>> - if (ret)
>> - return ret;
>> - }
>> + if (plane->type == DRM_PLANE_TYPE_CURSOR && update_native_cursor) {
>> + ret = dm_check_native_cursor_state(new_plane_crtc, plane,
>> + new_plane_state, enable);
>> + if (ret)
>> + return ret;
>> return 0;
>> }
>> @@ -10285,16 +10366,17 @@ static int dm_update_plane_state(struct dc *dc,
>> plane->base.id, old_plane_crtc->base.id);
>> ret = dm_atomic_get_state(state, &dm_state);
>> - if (ret)
>> - return ret;
>> + if (ret) {
>> + goto out;
>> + }
>> if (!dc_state_remove_plane(
>> dc,
>> dm_old_crtc_state->stream,
>> dm_old_plane_state->dc_state,
>> dm_state->context)) {
>> -
>> - return -EINVAL;
>> + ret = -EINVAL;
>> + goto out;
>> }
>> if (dm_old_plane_state->dc_state)
>> @@ -10323,21 +10405,16 @@ static int dm_update_plane_state(struct dc *dc,
>> return 0;
>> ret = amdgpu_dm_plane_helper_check_state(new_plane_state,
>> new_crtc_state);
>> - if (ret)
>> - return ret;
>> + if (ret) {
>> + goto out;
>> + }
>> WARN_ON(dm_new_plane_state->dc_state);
>> dc_new_plane_state = dc_create_plane_state(dc);
>> - if (!dc_new_plane_state)
>> - return -ENOMEM;
>> -
>> - /* Block top most plane from being a video plane */
>> - if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
>> - if
>> (amdgpu_dm_plane_is_video_format(new_plane_state->fb->format->format)
>> && *is_top_most_overlay)
>> - return -EINVAL;
>> -
>> - *is_top_most_overlay = false;
>> + if (!dc_new_plane_state) {
>> + ret = -ENOMEM;
>> + goto out;
>> }
>> DRM_DEBUG_ATOMIC("Enabling DRM plane: %d on DRM crtc %d\n",
>> @@ -10350,13 +10427,13 @@ static int dm_update_plane_state(struct dc *dc,
>> new_crtc_state);
>> if (ret) {
>> dc_plane_state_release(dc_new_plane_state);
>> - return ret;
>> + goto out;
>> }
>> ret = dm_atomic_get_state(state, &dm_state);
>> if (ret) {
>> dc_plane_state_release(dc_new_plane_state);
>> - return ret;
>> + goto out;
>> }
>> /*
>> @@ -10373,7 +10450,8 @@ static int dm_update_plane_state(struct dc *dc,
>> dm_state->context)) {
>> dc_plane_state_release(dc_new_plane_state);
>> - return -EINVAL;
>> + ret = -EINVAL;
>> + goto out;
>> }
>> dm_new_plane_state->dc_state = dc_new_plane_state;
>> @@ -10388,6 +10466,16 @@ static int dm_update_plane_state(struct dc *dc,
>> *lock_and_validation_needed = true;
>> }
>> +out:
>> + /* If cursor overlay failed, attempt fallback to native mode */
>> + if (ret == -EINVAL && plane->type == DRM_PLANE_TYPE_CURSOR) {
>> + ret = dm_check_native_cursor_state(new_plane_crtc, plane,
>> + new_plane_state, enable);
>> + if (ret) {
>> + return ret;
>> + }
>> + dm_new_crtc_state->cursor_mode = DM_CURSOR_NATIVE_MODE;
>> + }
>> return ret;
>> }
>> @@ -10544,6 +10632,126 @@ static int add_affected_mst_dsc_crtcs(struct
>> drm_atomic_state *state, struct drm
>> return drm_dp_mst_add_affected_dsc_crtcs(state,
>> &aconnector->mst_root->mst_mgr);
>> }
>> +/**
>> + * DOC: Cursor Modes - Native vs Overlay
>> + *
>> + * In native mode, the cursor uses a integrated cursor pipe within
>> each DCN hw
>> + * plane. It does not require a dedicated hw plane to enable, but it is
>> + * subjected to the same z-order and scaling as the hw plane. It also
>> has format
>> + * restrictions, a RGB cursor in native mode cannot be enabled within
>> a non-RGB
>> + * hw plane.
>> + *
>> + * In overlay mode, the cursor uses a separate DCN hw plane, and thus
>> has its
>> + * own scaling and z-pos. It also has no blending restrictions. It
>> lends to a
>> + * cursor behavior more akin to a DRM client's expectations. However,
>> it does
>> + * occupy an extra DCN plane, and therefore will only be used if a
>> DCN plane is
>> + * available.
>> +*/
>> +
>> +/**
>> + * Set whether the cursor should be enabled in native mode, or
>> overlay mode, on
>> + * the dm_crtc_state.
>> + *
>> + * The cursor should be enabled in overlay mode if the immediate
>> underlying
>> + * plane contains a video format.
>> + *
>> + * Since zpos info is required, drm_atomic_normalize_zpos must be
>> called before
>> + * calling this function.
>> +*/
>> +static int dm_crtc_set_cursor_mode(struct drm_atomic_state *state,
>> + struct dm_crtc_state *dm_crtc_state)
>> +{
>> + struct drm_plane_state *plane_state, *old_plane_state,
>> *target_plane_state;
>> + struct drm_crtc_state *crtc_state = &dm_crtc_state->base;
>> + struct drm_plane *plane;
>> + bool consider_mode_change = false;
>> + bool cursor_changed = false;
>> + unsigned int target_zpos;
>> + unsigned int cursor_zpos;
>> + int i;
>> +
>> + /*
>> + * Cursor mode can change if a plane's format changes, is
>> + * enabled/disabled, or z-order changes.
>> + */
>> + for_each_oldnew_plane_in_state(state, plane, old_plane_state,
>> plane_state, i) {
>> +
>> + /* Only care about planes on this CRTC */
>> + if ((drm_plane_mask(plane) & crtc_state->plane_mask) == 0)
>> + continue;
>> +
>> + if (plane->type == DRM_PLANE_TYPE_CURSOR)
>> + cursor_changed = true;
>> +
>> + if (drm_atomic_plane_enabling(old_plane_state, plane_state) ||
>> + drm_atomic_plane_disabling(old_plane_state, plane_state) ||
>> + old_plane_state->fb->format != plane_state->fb->format) {
>> + consider_mode_change = true;
>> + break;
>> + }
>> + }
>> +
>> + if (!consider_mode_change && !crtc_state->zpos_changed) {
>> + return 0;
>> + }
>> +
>> + /*
>> + * If no cursor change on this CRTC, and not enabled on this
>> CRTC, then
>> + * no need to set cursor mode. This avoids needlessly locking the
>> cursor
>> + * state.
>> + */
>> + if (!cursor_changed &&
>> + !(drm_plane_mask(crtc_state->crtc->cursor) &
>> crtc_state->plane_mask)) {
>> + return 0;
>> + }
>> +
>> + plane_state = drm_atomic_get_plane_state(state,
>> + crtc_state->crtc->cursor);
>> + if (IS_ERR(plane_state))
>> + return PTR_ERR(plane_state);
>> +
>> + /* Cursor is disabled */
>> + if (!plane_state->fb)
>> + return 0;
>> +
>> + cursor_zpos = plane_state->normalized_zpos;
>> +
>> + /* Get enabled plane immediately below cursor. */
>> + target_plane_state = NULL;
>> + target_zpos = 0;
>> + drm_for_each_plane_mask(plane, state->dev, crtc_state->plane_mask) {
>> + if (plane->type == DRM_PLANE_TYPE_CURSOR)
>> + continue;
>> +
>> + plane_state = drm_atomic_get_plane_state(state, plane);
>> + if (IS_ERR(plane_state))
>> + return PTR_ERR(plane_state);
>> +
>> + if (!plane_state->fb ||
>> + plane_state->normalized_zpos >= cursor_zpos)
>> + continue;
>> +
>> + if (plane_state->normalized_zpos >= target_zpos) {
>> + target_zpos = plane_state->normalized_zpos;
>> + target_plane_state = plane_state;
>> + }
>> + }
>> +
>> + /* Nothing below cursor - use overlay mode */
>> + if (target_plane_state == NULL) {
>> + dm_crtc_state->cursor_mode = DM_CURSOR_OVERLAY_MODE;
>> + return 0;
>> + }
>> +
>> + if
>> (amdgpu_dm_plane_is_video_format(target_plane_state->fb->format->format)) {
>> + dm_crtc_state->cursor_mode = DM_CURSOR_OVERLAY_MODE;
>> + } else {
>> + dm_crtc_state->cursor_mode = DM_CURSOR_NATIVE_MODE;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> /**
>> * amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu
>> DM.
>> *
>> @@ -10713,6 +10921,20 @@ static int amdgpu_dm_atomic_check(struct
>> drm_device *dev,
>> goto fail;
>> }
>> + /*
>> + * Determine whether cursors on each CRTC should be enabled in
>> native or
>> + * overlay mode.
>> + */
>> + for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
>> + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
>> +
>> + ret = dm_crtc_set_cursor_mode(state, dm_new_crtc_state);
>> + if (ret) {
>> + drm_dbg(dev, "Failed to determine cursor mode\n");
>> + goto fail;
>> + }
>> + }
>> +
>> /* Remove exiting planes if they are modified */
>> for_each_oldnew_plane_in_state_reverse(state, plane,
>> old_plane_state, new_plane_state, i) {
>> if (old_plane_state->fb && new_plane_state->fb &&
>> @@ -10793,6 +11015,11 @@ static int amdgpu_dm_atomic_check(struct
>> drm_device *dev,
>> /* Check cursor planes scaling */
>> for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
>> + /* Overlay cusor does not need scaling check */
>> + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
>> + if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
>> + continue;
>> +
>> ret = dm_check_crtc_cursor(state, crtc, new_crtc_state);
>> if (ret) {
>> DRM_DEBUG_DRIVER("dm_check_crtc_cursor() failed\n");
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>> index 09519b7abf67..b8d39fdd1e09 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
>> @@ -822,6 +822,11 @@ struct dm_plane_state {
>> enum amdgpu_transfer_function blend_tf;
>> };
>> +enum amdgpu_dm_cursor_mode {
>> + DM_CURSOR_NATIVE_MODE = 0,
>> + DM_CURSOR_OVERLAY_MODE,
>> +};
>> +
>> struct dm_crtc_state {
>> struct drm_crtc_state base;
>> struct dc_stream_state *stream;
>> @@ -852,6 +857,8 @@ struct dm_crtc_state {
>> * encoding.
>> */
>> enum amdgpu_transfer_function regamma_tf;
>> +
>> + enum amdgpu_dm_cursor_mode cursor_mode;
>> };
>> #define to_dm_crtc_state(x) container_of(x, struct dm_crtc_state, base)
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
>> index e23a0a276e33..67aea1d2feb9 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
>> @@ -304,6 +304,7 @@ static struct drm_crtc_state
>> *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr
>> state->regamma_tf = cur->regamma_tf;
>> state->crc_skip_count = cur->crc_skip_count;
>> state->mpo_requested = cur->mpo_requested;
>> + state->cursor_mode = cur->cursor_mode;
>> /* TODO Duplicate dc_stream after objects are stream object is
>> flattened */
>> return &state->base;
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>> index 8a4c40b4c27e..ed1fc01f1649 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>> @@ -104,7 +104,7 @@ void
>> amdgpu_dm_plane_fill_blending_from_plane_state(const struct
>> drm_plane_state
>> *global_alpha = false;
>> *global_alpha_value = 0xff;
>> - if (plane_state->plane->type != DRM_PLANE_TYPE_OVERLAY)
>> + if (plane_state->plane->type == DRM_PLANE_TYPE_PRIMARY)
>> return;
>> if (plane_state->pixel_blend_mode == DRM_MODE_BLEND_PREMULTI ||
>> @@ -1175,10 +1175,21 @@ static int amdgpu_dm_plane_atomic_check(struct
>> drm_plane *plane,
>> static int amdgpu_dm_plane_atomic_async_check(struct drm_plane *plane,
>> struct drm_atomic_state *state)
>> {
>> + struct drm_crtc_state *new_crtc_state;
>> + struct drm_plane_state *new_plane_state;
>> + struct dm_crtc_state *dm_new_crtc_state;
>> +
>> /* Only support async updates on cursor planes. */
>> if (plane->type != DRM_PLANE_TYPE_CURSOR)
>> return -EINVAL;
>> + new_plane_state = drm_atomic_get_new_plane_state(state, plane);
>> + new_crtc_state = drm_atomic_get_new_crtc_state(state,
>> new_plane_state->crtc);
>> + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
>> + /* Reject overlay cursors for now*/
>> + if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
>> + return -EINVAL;
>> +
>> return 0;
>> }
More information about the amd-gfx
mailing list