diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2749-drm-amd-display-Add-update-flags-in-to-determine-sur.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2749-drm-amd-display-Add-update-flags-in-to-determine-sur.patch | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2749-drm-amd-display-Add-update-flags-in-to-determine-sur.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2749-drm-amd-display-Add-update-flags-in-to-determine-sur.patch new file mode 100644 index 00000000..6b54c351 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/2749-drm-amd-display-Add-update-flags-in-to-determine-sur.patch @@ -0,0 +1,364 @@ +From 855ad09a761f3d1b244358ff1a270be4768f648c Mon Sep 17 00:00:00 2001 +From: Andrew Jiang <Andrew.Jiang@amd.com> +Date: Mon, 6 Nov 2017 17:00:07 -0500 +Subject: [PATCH 2749/4131] drm/amd/display: Add update flags in to determine + surface update type + +This way, we can know exactly what triggered the update type we're +looking at, and we can simplify the logic for determining what exactly +needs to be updated in the future. + +Also allow a dst rect size increase to go through a medium update, +since that does not require us to increase clock or bandwidth. + +Signed-off-by: Andrew Jiang <Andrew.Jiang@amd.com> +Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 123 ++++++++++++++++++++----------- + drivers/gpu/drm/amd/display/dc/dc.h | 93 +++++++++++++++-------- + 2 files changed, 140 insertions(+), 76 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index fddca38..b0d4927 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -54,6 +54,13 @@ + /******************************************************************************* + * Private functions + ******************************************************************************/ ++ ++static inline void elevate_update_type(enum surface_update_type *original, enum surface_update_type new) ++{ ++ if (new > *original) ++ *original = new; ++} ++ + static void destroy_links(struct dc *dc) + { + uint32_t i; +@@ -1122,77 +1129,88 @@ static unsigned int pixel_format_to_bpp(enum surface_pixel_format format) + + static enum surface_update_type get_plane_info_update_type(const struct dc_surface_update *u) + { +- struct dc_plane_info temp_plane_info; +- memset(&temp_plane_info, 0, sizeof(temp_plane_info)); ++ union surface_update_flags *update_flags = &u->surface->update_flags; + + if (!u->plane_info) + return UPDATE_TYPE_FAST; + +- temp_plane_info = *u->plane_info; ++ if (u->plane_info->color_space != u->surface->color_space) ++ update_flags->bits.color_space_change = 1; + +- /* Copy all parameters that will cause a full update +- * from current surface, the rest of the parameters +- * from provided plane configuration. +- * Perform memory compare and special validation +- * for those that can cause fast/medium updates +- */ ++ if (u->plane_info->input_tf != u->surface->input_tf) ++ update_flags->bits.input_tf_change = 1; + +- /* Full update parameters */ +- temp_plane_info.color_space = u->surface->color_space; +- temp_plane_info.input_tf = u->surface->input_tf; +- temp_plane_info.horizontal_mirror = u->surface->horizontal_mirror; +- temp_plane_info.rotation = u->surface->rotation; +- temp_plane_info.stereo_format = u->surface->stereo_format; ++ if (u->plane_info->horizontal_mirror != u->surface->horizontal_mirror) ++ update_flags->bits.horizontal_mirror_change = 1; + +- if (memcmp(u->plane_info, &temp_plane_info, +- sizeof(struct dc_plane_info)) != 0) +- return UPDATE_TYPE_FULL; ++ if (u->plane_info->rotation != u->surface->rotation) ++ update_flags->bits.rotation_change = 1; ++ ++ if (u->plane_info->stereo_format != u->surface->stereo_format) ++ update_flags->bits.stereo_format_change = 1; ++ ++ if (u->plane_info->per_pixel_alpha != u->surface->per_pixel_alpha) ++ update_flags->bits.per_pixel_alpha_change = 1; + + if (pixel_format_to_bpp(u->plane_info->format) != +- pixel_format_to_bpp(u->surface->format)) { ++ pixel_format_to_bpp(u->surface->format)) + /* different bytes per element will require full bandwidth + * and DML calculation + */ +- return UPDATE_TYPE_FULL; +- } ++ update_flags->bits.bpp_change = 1; + + if (memcmp(&u->plane_info->tiling_info, &u->surface->tiling_info, + sizeof(union dc_tiling_info)) != 0) { ++ update_flags->bits.swizzle_change = 1; + /* todo: below are HW dependent, we should add a hook to + * DCE/N resource and validated there. + */ +- if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) { ++ if (u->plane_info->tiling_info.gfx9.swizzle != DC_SW_LINEAR) + /* swizzled mode requires RQ to be setup properly, + * thus need to run DML to calculate RQ settings + */ +- return UPDATE_TYPE_FULL; +- } ++ update_flags->bits.bandwidth_change = 1; + } + ++ if (update_flags->bits.rotation_change ++ || update_flags->bits.stereo_format_change ++ || update_flags->bits.bpp_change ++ || update_flags->bits.bandwidth_change) ++ return UPDATE_TYPE_FULL; ++ + return UPDATE_TYPE_MED; + } + +-static enum surface_update_type get_scaling_info_update_type( ++static enum surface_update_type get_scaling_info_update_type( + const struct dc_surface_update *u) + { ++ union surface_update_flags *update_flags = &u->surface->update_flags; ++ + if (!u->scaling_info) + return UPDATE_TYPE_FAST; + + if (u->scaling_info->clip_rect.width != u->surface->clip_rect.width + || u->scaling_info->clip_rect.height != u->surface->clip_rect.height + || u->scaling_info->dst_rect.width != u->surface->dst_rect.width +- || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) +- return UPDATE_TYPE_FULL; ++ || u->scaling_info->dst_rect.height != u->surface->dst_rect.height) { ++ update_flags->bits.scaling_change = 1; ++ ++ if ((u->scaling_info->dst_rect.width < u->surface->dst_rect.width ++ || u->scaling_info->dst_rect.height < u->surface->dst_rect.height) ++ && (u->scaling_info->dst_rect.width < u->surface->src_rect.width ++ || u->scaling_info->dst_rect.height < u->surface->src_rect.height)) ++ /* Making dst rect smaller requires a bandwidth change */ ++ update_flags->bits.bandwidth_change = 1; ++ } + + if (u->scaling_info->src_rect.width != u->surface->src_rect.width + || u->scaling_info->src_rect.height != u->surface->src_rect.height) { + ++ update_flags->bits.scaling_change = 1; + if (u->scaling_info->src_rect.width > u->surface->src_rect.width + && u->scaling_info->src_rect.height > u->surface->src_rect.height) +- return UPDATE_TYPE_FULL; +- +- /* Upscaling does not require a full update */ +- return UPDATE_TYPE_MED; ++ /* Making src rect bigger requires a bandwidth change */ ++ update_flags->bits.clock_change = 1; + } + + if (u->scaling_info->src_rect.x != u->surface->src_rect.x +@@ -1201,33 +1219,50 @@ static enum surface_update_type get_scaling_info_update_type( + || u->scaling_info->clip_rect.y != u->surface->clip_rect.y + || u->scaling_info->dst_rect.x != u->surface->dst_rect.x + || u->scaling_info->dst_rect.y != u->surface->dst_rect.y) ++ update_flags->bits.position_change = 1; ++ ++ if (update_flags->bits.clock_change ++ || update_flags->bits.bandwidth_change) ++ return UPDATE_TYPE_FULL; ++ ++ if (update_flags->bits.scaling_change ++ || update_flags->bits.position_change) + return UPDATE_TYPE_MED; + + return UPDATE_TYPE_FAST; + } + + static enum surface_update_type det_surface_update(const struct dc *dc, +- const struct dc_surface_update *u) ++ const struct dc_surface_update *u) + { + const struct dc_state *context = dc->current_state; +- enum surface_update_type type = UPDATE_TYPE_FAST; ++ enum surface_update_type type; + enum surface_update_type overall_type = UPDATE_TYPE_FAST; ++ union surface_update_flags *update_flags = &u->surface->update_flags; ++ ++ update_flags->raw = 0; // Reset all flags + +- if (!is_surface_in_context(context, u->surface)) ++ if (!is_surface_in_context(context, u->surface)) { ++ update_flags->bits.new_plane = 1; + return UPDATE_TYPE_FULL; ++ } + + type = get_plane_info_update_type(u); +- if (overall_type < type) +- overall_type = type; ++ elevate_update_type(&overall_type, type); + + type = get_scaling_info_update_type(u); +- if (overall_type < type) +- overall_type = type; ++ elevate_update_type(&overall_type, type); ++ ++ if (u->in_transfer_func) ++ update_flags->bits.in_transfer_func = 1; ++ ++ if (u->input_csc_color_matrix) ++ update_flags->bits.input_csc_change = 1; + +- if (u->in_transfer_func || +- u->input_csc_color_matrix) { +- if (overall_type < UPDATE_TYPE_MED) +- overall_type = UPDATE_TYPE_MED; ++ if (update_flags->bits.in_transfer_func ++ || update_flags->bits.input_csc_change) { ++ type = UPDATE_TYPE_MED; ++ elevate_update_type(&overall_type, type); + } + + return overall_type; +@@ -1253,11 +1288,11 @@ enum surface_update_type dc_check_update_surfaces_for_stream( + enum surface_update_type type = + det_surface_update(dc, &updates[i]); + ++ updates[i].surface->update_type = type; + if (type == UPDATE_TYPE_FULL) + return type; + +- if (overall_type < type) +- overall_type = type; ++ elevate_update_type(&overall_type, type); + } + + return overall_type; +diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h +index ae78770..effffda 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc.h ++++ b/drivers/gpu/drm/amd/display/dc/dc.h +@@ -99,6 +99,39 @@ struct dc_static_screen_events { + bool overlay_update; + }; + ++ ++/* Surface update type is used by dc_update_surfaces_and_stream ++ * The update type is determined at the very beginning of the function based ++ * on parameters passed in and decides how much programming (or updating) is ++ * going to be done during the call. ++ * ++ * UPDATE_TYPE_FAST is used for really fast updates that do not require much ++ * logical calculations or hardware register programming. This update MUST be ++ * ISR safe on windows. Currently fast update will only be used to flip surface ++ * address. ++ * ++ * UPDATE_TYPE_MED is used for slower updates which require significant hw ++ * re-programming however do not affect bandwidth consumption or clock ++ * requirements. At present, this is the level at which front end updates ++ * that do not require us to run bw_calcs happen. These are in/out transfer func ++ * updates, viewport offset changes, recout size changes and pixel depth changes. ++ * This update can be done at ISR, but we want to minimize how often this happens. ++ * ++ * UPDATE_TYPE_FULL is slow. Really slow. This requires us to recalculate our ++ * bandwidth and clocks, possibly rearrange some pipes and reprogram anything front ++ * end related. Any time viewport dimensions, recout dimensions, scaling ratios or ++ * gamma need to be adjusted or pipe needs to be turned on (or disconnected) we do ++ * a full update. This cannot be done at ISR level and should be a rare event. ++ * Unless someone is stress testing mpo enter/exit, playing with colour or adjusting ++ * underscan we don't expect to see this call at all. ++ */ ++ ++enum surface_update_type { ++ UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ ++ UPDATE_TYPE_MED, /* ISR safe, most of programming needed, no bw/clk change*/ ++ UPDATE_TYPE_FULL, /* may need to shuffle resources */ ++}; ++ + /* Forward declaration*/ + struct dc; + struct dc_plane_state; +@@ -399,6 +432,32 @@ struct dc_plane_status { + bool is_right_eye; + }; + ++union surface_update_flags { ++ ++ struct { ++ /* Medium updates */ ++ uint32_t color_space_change:1; ++ uint32_t input_tf_change:1; ++ uint32_t horizontal_mirror_change:1; ++ uint32_t per_pixel_alpha_change:1; ++ uint32_t rotation_change:1; ++ uint32_t swizzle_change:1; ++ uint32_t scaling_change:1; ++ uint32_t position_change:1; ++ uint32_t in_transfer_func:1; ++ uint32_t input_csc_change:1; ++ ++ /* Full updates */ ++ uint32_t new_plane:1; ++ uint32_t bpp_change:1; ++ uint32_t bandwidth_change:1; ++ uint32_t clock_change:1; ++ uint32_t stereo_format_change:1; ++ } bits; ++ ++ uint32_t raw; ++}; ++ + struct dc_plane_state { + struct dc_plane_address address; + struct scaling_taps scaling_quality; +@@ -432,6 +491,8 @@ struct dc_plane_state { + bool flip_immediate; + bool horizontal_mirror; + ++ union surface_update_flags update_flags; ++ enum surface_update_type update_type; + /* private to DC core */ + struct dc_plane_status status; + struct dc_context *ctx; +@@ -528,38 +589,6 @@ void dc_flip_plane_addrs(struct dc *dc, + bool dc_post_update_surfaces_to_stream( + struct dc *dc); + +-/* Surface update type is used by dc_update_surfaces_and_stream +- * The update type is determined at the very beginning of the function based +- * on parameters passed in and decides how much programming (or updating) is +- * going to be done during the call. +- * +- * UPDATE_TYPE_FAST is used for really fast updates that do not require much +- * logical calculations or hardware register programming. This update MUST be +- * ISR safe on windows. Currently fast update will only be used to flip surface +- * address. +- * +- * UPDATE_TYPE_MED is used for slower updates which require significant hw +- * re-programming however do not affect bandwidth consumption or clock +- * requirements. At present, this is the level at which front end updates +- * that do not require us to run bw_calcs happen. These are in/out transfer func +- * updates, viewport offset changes, recout size changes and pixel depth changes. +- * This update can be done at ISR, but we want to minimize how often this happens. +- * +- * UPDATE_TYPE_FULL is slow. Really slow. This requires us to recalculate our +- * bandwidth and clocks, possibly rearrange some pipes and reprogram anything front +- * end related. Any time viewport dimensions, recout dimensions, scaling ratios or +- * gamma need to be adjusted or pipe needs to be turned on (or disconnected) we do +- * a full update. This cannot be done at ISR level and should be a rare event. +- * Unless someone is stress testing mpo enter/exit, playing with colour or adjusting +- * underscan we don't expect to see this call at all. +- */ +- +-enum surface_update_type { +- UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ +- UPDATE_TYPE_MED, /* ISR safe, most of programming needed, no bw/clk change*/ +- UPDATE_TYPE_FULL, /* may need to shuffle resources */ +-}; +- + /******************************************************************************* + * Stream Interfaces + ******************************************************************************/ +-- +2.7.4 + |