From 0af59135c2a9e05af87bc82f492fab13fff52fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Almeida?= Date: Wed, 22 Nov 2023 13:19:38 -0300 Subject: [PATCH] drm: Refuse to async flip with atomic prop changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given that prop changes may lead to modesetting, which would defeat the fast path of the async flip, refuse any atomic prop change for async flips in atomic API. The only exception is the framebuffer ID to flip to. Currently the only plane type supported is the primary one. Signed-off-by: André Almeida Reviewed-by: Simon Ser --- drivers/gpu/drm/drm_atomic_uapi.c | 52 +++++++++++++++++++++++++++-- drivers/gpu/drm/drm_crtc_internal.h | 2 +- drivers/gpu/drm/drm_mode_object.c | 2 +- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 37caa6c33e22b3..86083184ac6bb2 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -964,13 +964,28 @@ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, return ret; } +static int drm_atomic_check_prop_changes(int ret, uint64_t old_val, uint64_t prop_value, + struct drm_property *prop) +{ + if (ret != 0 || old_val != prop_value) { + drm_dbg_atomic(prop->dev, + "[PROP:%d:%s] No prop can be changed during async flip\n", + prop->base.id, prop->name); + return -EINVAL; + } + + return 0; +} + int drm_atomic_set_property(struct drm_atomic_state *state, struct drm_file *file_priv, struct drm_mode_object *obj, struct drm_property *prop, - uint64_t prop_value) + uint64_t prop_value, + bool async_flip) { struct drm_mode_object *ref; + uint64_t old_val; int ret; if (!drm_property_change_valid_get(prop, prop_value, &ref)) @@ -987,6 +1002,13 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } + if (async_flip) { + ret = drm_atomic_connector_get_property(connector, connector_state, + prop, &old_val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + break; + } + ret = drm_atomic_connector_set_property(connector, connector_state, file_priv, prop, prop_value); @@ -1002,6 +1024,13 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } + if (async_flip) { + ret = drm_atomic_crtc_get_property(crtc, crtc_state, + prop, &old_val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + break; + } + ret = drm_atomic_crtc_set_property(crtc, crtc_state, prop, prop_value); break; @@ -1009,6 +1038,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, case DRM_MODE_OBJECT_PLANE: { struct drm_plane *plane = obj_to_plane(obj); struct drm_plane_state *plane_state; + struct drm_mode_config *config = &plane->dev->mode_config; plane_state = drm_atomic_get_plane_state(state, plane); if (IS_ERR(plane_state)) { @@ -1016,6 +1046,21 @@ int drm_atomic_set_property(struct drm_atomic_state *state, break; } + if (async_flip && prop != config->prop_fb_id) { + ret = drm_atomic_plane_get_property(plane, plane_state, + prop, &old_val); + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); + break; + } + + if (async_flip && plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY) { + drm_dbg_atomic(prop->dev, + "[OBJECT:%d] Only primary planes can be changed during async flip\n", + obj->id); + ret = -EINVAL; + break; + } + ret = drm_atomic_plane_set_property(plane, plane_state, file_priv, prop, prop_value); @@ -1295,6 +1340,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, struct drm_out_fence_state *fence_state; int ret = 0; unsigned int i, j, num_fences; + bool async_flip = false; /* disallow for drivers not supporting atomic: */ if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) @@ -1408,8 +1454,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, goto out; } - ret = drm_atomic_set_property(state, file_priv, - obj, prop, prop_value); + ret = drm_atomic_set_property(state, file_priv, obj, + prop, prop_value, async_flip); if (ret) { drm_mode_object_put(obj); goto out; diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 501a10edd0e1dc..381130cebe811c 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -251,7 +251,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, struct drm_file *file_priv, struct drm_mode_object *obj, struct drm_property *prop, - uint64_t prop_value); + uint64_t prop_value, bool async_flip); int drm_atomic_get_property(struct drm_mode_object *obj, struct drm_property *property, uint64_t *val); diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index ac0d2ce3f87041..0e8355063eee36 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -538,7 +538,7 @@ static int set_property_atomic(struct drm_mode_object *obj, obj_to_connector(obj), prop_value); } else { - ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value); + ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value, false); if (ret) goto out; ret = drm_atomic_commit(state); From dd4a6dbc71451975ff33ad6f3fcf5f440f67be5b Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 22 Nov 2023 13:19:39 -0300 Subject: [PATCH] drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the driver supports it, allow user-space to supply the DRM_MODE_PAGE_FLIP_ASYNC flag to request an async page-flip. Set drm_crtc_state.async_flip accordingly. Document that drivers will reject atomic commits if an async flip isn't possible. This allows user-space to fall back to something else. For instance, Xorg falls back to a blit. Another option is to wait as close to the next vblank as possible before performing the page-flip to reduce latency. Signed-off-by: Simon Ser Reviewed-by: Alex Deucher Co-developed-by: André Almeida Signed-off-by: André Almeida --- drivers/gpu/drm/drm_atomic_uapi.c | 25 ++++++++++++++++++++++--- include/uapi/drm/drm_mode.h | 9 +++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 86083184ac6bb2..fd429c61a54ecd 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1326,6 +1326,18 @@ static void complete_signaling(struct drm_device *dev, kfree(fence_state); } +static void +set_async_flip(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int i; + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + crtc_state->async_flip = true; + } +} + int drm_mode_atomic_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -1367,9 +1379,13 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, } if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) { - drm_dbg_atomic(dev, - "commit failed: invalid flag DRM_MODE_PAGE_FLIP_ASYNC\n"); - return -EINVAL; + if (!dev->mode_config.async_page_flip) { + drm_dbg_atomic(dev, + "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported\n"); + return -EINVAL; + } + + async_flip = true; } /* can't test and expect an event at the same time. */ @@ -1472,6 +1488,9 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, if (ret) goto out; + if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) + set_async_flip(state); + if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { ret = drm_atomic_check_only(state); } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index cea5653e4020b3..c0b76575f11787 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -965,6 +965,15 @@ struct hdr_output_metadata { * Request that the page-flip is performed as soon as possible, ie. with no * delay due to waiting for vblank. This may cause tearing to be visible on * the screen. + * + * When used with atomic uAPI, the driver will return an error if the hardware + * doesn't support performing an asynchronous page-flip for this update. + * User-space should handle this, e.g. by falling back to a regular page-flip. + * + * Note, some hardware might need to perform one last synchronous page-flip + * before being able to switch to asynchronous page-flips. As an exception, + * the driver will return success even though that first page-flip is not + * asynchronous. */ #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4 From 631191c0d1ef5884b6c4ed760013da05ec3c0005 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 22 Nov 2023 13:19:40 -0300 Subject: [PATCH] drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new kernel capability indicates whether async page-flips are supported via the atomic uAPI. DRM clients can use it to check for support before feeding DRM_MODE_PAGE_FLIP_ASYNC to the kernel. Make it clear that DRM_CAP_ASYNC_PAGE_FLIP is for legacy uAPI only. Signed-off-by: Simon Ser Reviewed-by: André Almeida Reviewed-by: Alex Deucher Signed-off-by: André Almeida --- drivers/gpu/drm/drm_ioctl.c | 4 ++++ include/uapi/drm/drm.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index f03ffbacfe9b48..7810fce89a446c 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -301,6 +301,10 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ case DRM_CAP_CRTC_IN_VBLANK_EVENT: req->value = 1; break; + case DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP: + req->value = drm_core_check_feature(dev, DRIVER_ATOMIC) && + dev->mode_config.async_page_flip; + break; default: return -EINVAL; } diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 794c1d857677d9..58baefe32c23c7 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -713,7 +713,8 @@ struct drm_gem_open { /** * DRM_CAP_ASYNC_PAGE_FLIP * - * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC. + * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for legacy + * page-flips. */ #define DRM_CAP_ASYNC_PAGE_FLIP 0x7 /** @@ -773,6 +774,13 @@ struct drm_gem_open { * :ref:`drm_sync_objects`. */ #define DRM_CAP_SYNCOBJ_TIMELINE 0x14 +/** + * DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP + * + * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for atomic + * commits. + */ +#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15 /* DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { From 949c86212c122d35a463478f1aeb44cd52722e3c Mon Sep 17 00:00:00 2001 From: Krunoslav Kovac Date: Tue, 8 Aug 2023 14:33:42 -0400 Subject: [PATCH] drm/amd/display: PQ tail accuracy [WHY & HOW] HW LUTs changed slightly in DCN3: 256 base+slope pairs were replaced by 257 bases. Code was still calculating all 256 base+slope and then creating 257th pt as last base + last slope. This was done in wrong format, and then "fixed" it by making the last two points the same thus making the last slope=0. However, this also created some precision problems near the end that are not visible but they do show up with capture cards. Solution is to calculate 257 and remove deltas since we no longer have those HW registers. Reviewed-by: Anthony Koo Acked-by: Wayne Lin Signed-off-by: Krunoslav Kovac Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher (cherry picked from commit 4d5fd3d08ea9926fb2031ff7cfb4d72b7c950301) Signed-off-by: Cristian Ciocaltea --- .../amd/display/dc/dcn30/dcn30_cm_common.c | 104 ++++++------------ .../gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c | 17 --- 2 files changed, 33 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c index e0df9b0065f9c0..ddb344056d4013 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c @@ -114,7 +114,6 @@ bool cm3_helper_translate_curve_to_hw_format( struct pwl_result_data *rgb; struct pwl_result_data *rgb_plus_1; struct pwl_result_data *rgb_minus_1; - struct fixed31_32 end_value; int32_t region_start, region_end; int32_t i; @@ -176,7 +175,7 @@ bool cm3_helper_translate_curve_to_hw_format( NUMBER_SW_SEGMENTS; for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS; i += increment) { - if (j == hw_points - 1) + if (j == hw_points) break; rgb_resulted[j].red = output_tf->tf_pts.red[i]; rgb_resulted[j].green = output_tf->tf_pts.green[i]; @@ -187,13 +186,13 @@ bool cm3_helper_translate_curve_to_hw_format( /* last point */ start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS; - rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index]; - rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index]; - rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index]; + rgb_resulted[hw_points].red = output_tf->tf_pts.red[start_index]; + rgb_resulted[hw_points].green = output_tf->tf_pts.green[start_index]; + rgb_resulted[hw_points].blue = output_tf->tf_pts.blue[start_index]; - rgb_resulted[hw_points].red = rgb_resulted[hw_points - 1].red; - rgb_resulted[hw_points].green = rgb_resulted[hw_points - 1].green; - rgb_resulted[hw_points].blue = rgb_resulted[hw_points - 1].blue; + rgb_resulted[hw_points+1].red = rgb_resulted[hw_points].red; + rgb_resulted[hw_points+1].green = rgb_resulted[hw_points].green; + rgb_resulted[hw_points+1].blue = rgb_resulted[hw_points].blue; // All 3 color channels have same x corner_points[0].red.x = dc_fixpt_pow(dc_fixpt_from_int(2), @@ -220,34 +219,16 @@ bool cm3_helper_translate_curve_to_hw_format( /* see comment above, m_arrPoints[1].y should be the Y value for the * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1) */ - corner_points[1].red.y = rgb_resulted[hw_points - 1].red; - corner_points[1].green.y = rgb_resulted[hw_points - 1].green; - corner_points[1].blue.y = rgb_resulted[hw_points - 1].blue; + corner_points[1].red.y = rgb_resulted[hw_points].red; + corner_points[1].green.y = rgb_resulted[hw_points].green; + corner_points[1].blue.y = rgb_resulted[hw_points].blue; corner_points[1].red.slope = dc_fixpt_zero; corner_points[1].green.slope = dc_fixpt_zero; corner_points[1].blue.slope = dc_fixpt_zero; - if (output_tf->tf == TRANSFER_FUNCTION_PQ || output_tf->tf == TRANSFER_FUNCTION_HLG) { - /* for PQ/HLG, we want to have a straight line from last HW X point, - * and the slope to be such that we hit 1.0 at 10000/1000 nits. - */ - - if (output_tf->tf == TRANSFER_FUNCTION_PQ) - end_value = dc_fixpt_from_int(125); - else - end_value = dc_fixpt_from_fraction(125, 10); - - corner_points[1].red.slope = dc_fixpt_div( - dc_fixpt_sub(dc_fixpt_one, corner_points[1].red.y), - dc_fixpt_sub(end_value, corner_points[1].red.x)); - corner_points[1].green.slope = dc_fixpt_div( - dc_fixpt_sub(dc_fixpt_one, corner_points[1].green.y), - dc_fixpt_sub(end_value, corner_points[1].green.x)); - corner_points[1].blue.slope = dc_fixpt_div( - dc_fixpt_sub(dc_fixpt_one, corner_points[1].blue.y), - dc_fixpt_sub(end_value, corner_points[1].blue.x)); - } - lut_params->hw_points_num = hw_points; + // DCN3+ have 257 pts in lieu of no separate slope registers + // Prior HW had 256 base+slope pairs + lut_params->hw_points_num = hw_points + 1; k = 0; for (i = 1; i < MAX_REGIONS_NUMBER; i++) { @@ -267,38 +248,37 @@ bool cm3_helper_translate_curve_to_hw_format( rgb_plus_1 = rgb_resulted + 1; rgb_minus_1 = rgb; - i = 1; - while (i != hw_points + 1) { - if (i >= hw_points - 1) { - if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) - rgb_plus_1->red = dc_fixpt_add(rgb->red, rgb_minus_1->delta_red); - if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) - rgb_plus_1->green = dc_fixpt_add(rgb->green, rgb_minus_1->delta_green); - if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) - rgb_plus_1->blue = dc_fixpt_add(rgb->blue, rgb_minus_1->delta_blue); - } - - rgb->delta_red = dc_fixpt_sub(rgb_plus_1->red, rgb->red); - rgb->delta_green = dc_fixpt_sub(rgb_plus_1->green, rgb->green); - rgb->delta_blue = dc_fixpt_sub(rgb_plus_1->blue, rgb->blue); + if (fixpoint == true) { + i = 1; + while (i != hw_points + 2) { + if (i >= hw_points) { + if (dc_fixpt_lt(rgb_plus_1->red, rgb->red)) + rgb_plus_1->red = dc_fixpt_add(rgb->red, + rgb_minus_1->delta_red); + if (dc_fixpt_lt(rgb_plus_1->green, rgb->green)) + rgb_plus_1->green = dc_fixpt_add(rgb->green, + rgb_minus_1->delta_green); + if (dc_fixpt_lt(rgb_plus_1->blue, rgb->blue)) + rgb_plus_1->blue = dc_fixpt_add(rgb->blue, + rgb_minus_1->delta_blue); + } - if (fixpoint == true) { rgb->delta_red_reg = dc_fixpt_clamp_u0d10(rgb->delta_red); rgb->delta_green_reg = dc_fixpt_clamp_u0d10(rgb->delta_green); rgb->delta_blue_reg = dc_fixpt_clamp_u0d10(rgb->delta_blue); rgb->red_reg = dc_fixpt_clamp_u0d14(rgb->red); rgb->green_reg = dc_fixpt_clamp_u0d14(rgb->green); rgb->blue_reg = dc_fixpt_clamp_u0d14(rgb->blue); - } - ++rgb_plus_1; - rgb_minus_1 = rgb; - ++rgb; - ++i; + ++rgb_plus_1; + rgb_minus_1 = rgb; + ++rgb; + ++i; + } } cm3_helper_convert_to_custom_float(rgb_resulted, lut_params->corner_points, - hw_points, fixpoint); + hw_points+1, fixpoint); return true; } @@ -603,24 +583,6 @@ bool cm3_helper_convert_to_custom_float( return false; } - if (!convert_to_custom_float_format(rgb->delta_red, &fmt, - &rgb->delta_red_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format(rgb->delta_green, &fmt, - &rgb->delta_green_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - - if (!convert_to_custom_float_format(rgb->delta_blue, &fmt, - &rgb->delta_blue_reg)) { - BREAK_TO_DEBUGGER(); - return false; - } - ++rgb; ++i; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c index 6cf40c1332bc37..d1500b2238580b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c @@ -278,22 +278,10 @@ static void mpc3_program_ogam_pwl( { uint32_t i; struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); - uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg; - uint32_t last_base_value_green = rgb[num-1].green_reg + rgb[num-1].delta_green_reg; - uint32_t last_base_value_blue = rgb[num-1].blue_reg + rgb[num-1].delta_blue_reg; - - /*the entries of DCN3AG gamma LUTs take 18bit base values as opposed to - *38 base+delta values per entry in earlier DCN architectures - *last base value for our lut is compute by adding the last base value - *in our data + last delta - */ if (is_rgb_equal(rgb, num)) { for (i = 0 ; i < num; i++) REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg); - - REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_red); - } else { REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id], @@ -302,8 +290,6 @@ static void mpc3_program_ogam_pwl( for (i = 0 ; i < num; i++) REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].red_reg); - REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_red); - REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0); REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id], @@ -312,8 +298,6 @@ static void mpc3_program_ogam_pwl( for (i = 0 ; i < num; i++) REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].green_reg); - REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_green); - REG_SET(MPCC_OGAM_LUT_INDEX[mpcc_id], 0, MPCC_OGAM_LUT_INDEX, 0); REG_UPDATE(MPCC_OGAM_LUT_CONTROL[mpcc_id], @@ -322,7 +306,6 @@ static void mpc3_program_ogam_pwl( for (i = 0 ; i < num; i++) REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].blue_reg); - REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, last_base_value_blue); } } From 1edf3fbbeb36440e1222c2fe0e8127fb804c5278 Mon Sep 17 00:00:00 2001 From: Hamza Mahfooz Date: Fri, 4 Aug 2023 11:13:04 -0400 Subject: [PATCH] drm/amd/display: ensure async flips are only accepted for fast updates We should be checking to see if async flips are supported in amdgpu_dm_atomic_check() (i.e. not dm_crtc_helper_atomic_check()). Also, async flipping isn't supported if a plane's framebuffer changes memory domains during an atomic commit. So, move the check from dm_crtc_helper_atomic_check() to amdgpu_dm_atomic_check() and check if the memory domain has changed in amdgpu_dm_atomic_check(). Cc: stable@vger.kernel.org Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2733 Fixes: c1e18c44dc7f ("drm/amd/display: only accept async flips for fast updates") Reviewed-by: Harry Wentland Signed-off-by: Hamza Mahfooz Signed-off-by: Alex Deucher (cherry picked from commit a7c0cad0dc060bb77e9c9d235d68441b0fc69507) Signed-off-by: Cristian Ciocaltea --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 12 ------------ 1 file changed, 12 deletions(-) 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 be1ebe826442a4..4b223db0cf2fe8 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 @@ -473,18 +473,6 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, return -EINVAL; } - /* - * Only allow async flips for fast updates that don't change the FB - * pitch, the DCC state, rotation, etc. - */ - if (crtc_state->async_flip && - dm_crtc_state->update_type != UPDATE_TYPE_FAST) { - drm_dbg_atomic(crtc->dev, - "[CRTC:%d:%s] async flips are only supported for fast updates\n", - crtc->base.id, crtc->name); - return -EINVAL; - } - /* In some use cases, like reset, no stream is attached */ if (!dm_crtc_state->stream) return 0;