diff options
Diffstat (limited to 'SOURCES/amdgpu-bug-fix.patch')
-rw-r--r-- | SOURCES/amdgpu-bug-fix.patch | 617 |
1 files changed, 617 insertions, 0 deletions
diff --git a/SOURCES/amdgpu-bug-fix.patch b/SOURCES/amdgpu-bug-fix.patch new file mode 100644 index 0000000..1e48174 --- /dev/null +++ b/SOURCES/amdgpu-bug-fix.patch @@ -0,0 +1,617 @@ +From 0af59135c2a9e05af87bc82f492fab13fff52fbd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Andr=C3=A9=20Almeida?= <andrealmeid@igalia.com> +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 <andrealmeid@igalia.com> +Reviewed-by: Simon Ser <contact@emersion.fr> +--- + 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 <contact@emersion.fr> +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 <contact@emersion.fr> +Reviewed-by: Alex Deucher <alexander.deucher@amd.com> +Co-developed-by: André Almeida <andrealmeid@igalia.com> +Signed-off-by: André Almeida <andrealmeid@igalia.com> +--- + 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 <contact@emersion.fr> +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 <contact@emersion.fr> +Reviewed-by: André Almeida <andrealmeid@igalia.com> +Reviewed-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: André Almeida <andrealmeid@igalia.com> +--- + 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 <krunoslav.kovac@amd.com> +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 <anthony.koo@amd.com> +Acked-by: Wayne Lin <wayne.lin@amd.com> +Signed-off-by: Krunoslav Kovac <krunoslav.kovac@amd.com> +Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +(cherry picked from commit 4d5fd3d08ea9926fb2031ff7cfb4d72b7c950301) +Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> +--- + .../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 <hamza.mahfooz@amd.com> +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 <harry.wentland@amd.com> +Signed-off-by: Hamza Mahfooz <hamza.mahfooz@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +(cherry picked from commit a7c0cad0dc060bb77e9c9d235d68441b0fc69507) +Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> +--- + .../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; |