aboutsummaryrefslogtreecommitdiffstats
path: root/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0174-drm-amd-display-refactor-dc_update_surfaces_for_stre.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0174-drm-amd-display-refactor-dc_update_surfaces_for_stre.patch')
-rw-r--r--meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0174-drm-amd-display-refactor-dc_update_surfaces_for_stre.patch483
1 files changed, 483 insertions, 0 deletions
diff --git a/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0174-drm-amd-display-refactor-dc_update_surfaces_for_stre.patch b/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0174-drm-amd-display-refactor-dc_update_surfaces_for_stre.patch
new file mode 100644
index 00000000..5d810cc7
--- /dev/null
+++ b/meta-v1000/recipes-kernel/linux/linux-yocto-4.14.71/0174-drm-amd-display-refactor-dc_update_surfaces_for_stre.patch
@@ -0,0 +1,483 @@
+From 12d9f6f100e0ec2876f0b88ef4bcfb5ef2b15e23 Mon Sep 17 00:00:00 2001
+From: Tony Cheng <tony.cheng@amd.com>
+Date: Thu, 19 Jan 2017 23:57:09 -0500
+Subject: [PATCH 0174/4131] drm/amd/display: refactor
+ dc_update_surfaces_for_stream
+
+- reuse existing helper functions
+- helper function to make it more obvious which cases we can do optimize programming
+
+Signed-off-by: Tony Cheng <tony.cheng@amd.com>
+Reviewed-by: Yongqiang Sun <yongqiang.sun@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 | 367 ++++++++++++++++++-------------
+ 1 file changed, 212 insertions(+), 155 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index de6ef87..170936b 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -1007,7 +1007,7 @@ bool dc_commit_streams(
+ struct dc_bios *dcb = core_dc->ctx->dc_bios;
+ enum dc_status result = DC_ERROR_UNEXPECTED;
+ struct validate_context *context;
+- struct dc_validation_set set[MAX_STREAMS] = { 0 };
++ struct dc_validation_set set[MAX_STREAMS] = { {0, {0} } };
+ int i, j, k;
+
+ if (false == streams_changed(core_dc, streams, stream_count))
+@@ -1321,80 +1321,167 @@ bool dc_commit_surfaces_to_stream(
+ return dc_post_update_surfaces_to_stream(dc);
+ }
+
+-void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates,
+- int surface_count, const struct dc_stream *dc_stream)
++static bool is_surface_in_context(
++ const struct validate_context *context,
++ const struct dc_surface *surface)
+ {
+- struct core_dc *core_dc = DC_TO_CORE(dc);
+- struct validate_context *context = core_dc->temp_flip_context;
+- int i, j;
+- bool is_new_pipe_surface[MAX_PIPES];
+- const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 };
+- bool need_apply_clk_constraints = false;
+- bool can_skip_context_building = true;
++ int j;
+
+- update_surface_trace(dc, updates, surface_count);
++ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
++ const struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+- *context = *core_dc->current_context;
++ if (surface == &pipe_ctx->surface->public) {
++ return true;
++ }
++ }
+
+- for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
+- struct pipe_ctx *cur_pipe = &context->res_ctx.pipe_ctx[i];
++ return false;
++}
+
+- if (cur_pipe->top_pipe)
+- cur_pipe->top_pipe =
+- &context->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
++enum surface_update_type {
++ UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */
++ UPDATE_TYPE_MED, /* a lot of programming needed. may need to alloc */
++ UPDATE_TYPE_FULL, /* may need to shuffle resources */
++};
+
+- if (cur_pipe->bottom_pipe)
+- cur_pipe->bottom_pipe =
+- &context->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
+- }
++static enum surface_update_type det_surface_update(
++ const struct core_dc *dc,
++ const struct dc_surface_update *u)
++{
++ const struct validate_context *context = dc->current_context;
+
+- for (j = 0; j < MAX_PIPES; j++)
+- is_new_pipe_surface[j] = true;
++ if (u->scaling_info || u->plane_info)
++ /* todo: not all scale and plane_info update need full update
++ * ie. check if following is the same
++ * scale ratio, view port, surface bpp etc
++ */
++ return UPDATE_TYPE_FULL; /* may need bandwidth update */
+
+- for (i = 0 ; i < surface_count; i++) {
+- struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface);
+- bool existing_surface = false;
++ if (!is_surface_in_context(context, u->surface))
++ return UPDATE_TYPE_FULL;
+
+- new_surfaces[i] = updates[i].surface;
++ if (u->in_transfer_func ||
++ u->out_transfer_func ||
++ u->hdr_static_metadata)
++ return UPDATE_TYPE_MED;
+
+- for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
+- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
++ return UPDATE_TYPE_FAST;
++}
+
+- if (surface == pipe_ctx->surface) {
+- existing_surface = true;
+- is_new_pipe_surface[j] = false;
+- }
+- }
++static enum surface_update_type check_update_surfaces_for_stream(
++ struct core_dc *dc,
++ struct dc_surface_update *updates,
++ int surface_count,
++ const struct dc_stream_status *stream_status)
++{
++ int i;
++ enum surface_update_type overall_type = UPDATE_TYPE_FAST;
+
+- if (updates[i].plane_info ||
+- updates[i].scaling_info ||
+- !existing_surface)
+- can_skip_context_building = false;
++ if (stream_status->surface_count != surface_count)
++ return UPDATE_TYPE_FULL;
++
++ for (i = 0 ; i < surface_count; i++) {
++ enum surface_update_type type =
++ det_surface_update(dc, &updates[i]);
++
++ if (type == UPDATE_TYPE_FULL)
++ return type;
++
++ if (overall_type < type)
++ overall_type = type;
+ }
+
+- if (!can_skip_context_building && dc_stream) {
+- const struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
++ return overall_type;
++}
+
+- if (core_dc->current_context->stream_count == 0)
+- return;
++enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL;
+
+- /* Cannot commit surface to a stream that is not commited */
+- for (i = 0; i < core_dc->current_context->stream_count; i++)
+- if (stream == core_dc->current_context->streams[i])
+- break;
+- if (i == core_dc->current_context->stream_count)
+- return;
++void dc_update_surfaces_for_stream(struct dc *dc,
++ struct dc_surface_update *updates, int surface_count,
++ const struct dc_stream *dc_stream)
++{
++ struct core_dc *core_dc = DC_TO_CORE(dc);
++ struct validate_context *context;
++ int i, j;
++
++ enum surface_update_type update_type;
++ const struct dc_stream_status *stream_status;
++
++ stream_status = dc_stream_get_status(dc_stream);
++ ASSERT(stream_status);
++ if (!stream_status)
++ return; /* Cannot commit surface to stream that is not committed */
++
++ update_type = check_update_surfaces_for_stream(
++ core_dc, updates, surface_count, stream_status);
++
++ if (update_type >= update_surface_trace_level)
++ update_surface_trace(dc, updates, surface_count);
+
++ if (update_type >= UPDATE_TYPE_FULL) {
++ const struct dc_surface *new_surfaces[MAX_SURFACES] = { 0 };
++
++ for (i = 0; i < surface_count; i++)
++ new_surfaces[i] = updates[i].surface;
++
++ /* initialize scratch memory for building context */
++ context = core_dc->temp_flip_context;
++ resource_validate_ctx_copy_construct(
++ core_dc->current_context, context);
++
++ /* add surface to context */
+ if (!resource_attach_surfaces_to_context(
+ new_surfaces, surface_count, dc_stream, context)) {
+ BREAK_TO_DEBUGGER();
+ return;
+ }
++ } else {
++ context = core_dc->current_context;
+ }
+-
+ for (i = 0; i < surface_count; i++) {
++ /* save update param into surface */
+ struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface);
++ struct core_stream *stream = DC_STREAM_TO_CORE(dc_stream);
+
++ if (updates[i].flip_addr) {
++ surface->public.address = updates[i].flip_addr->address;
++ surface->public.flip_immediate =
++ updates[i].flip_addr->flip_immediate;
++ }
++
++ if (updates[i].scaling_info) {
++ surface->public.scaling_quality =
++ updates[i].scaling_info->scaling_quality;
++ surface->public.dst_rect =
++ updates[i].scaling_info->dst_rect;
++ surface->public.src_rect =
++ updates[i].scaling_info->src_rect;
++ surface->public.clip_rect =
++ updates[i].scaling_info->clip_rect;
++ }
++
++ if (updates[i].plane_info) {
++ surface->public.color_space =
++ updates[i].plane_info->color_space;
++ surface->public.format =
++ updates[i].plane_info->format;
++ surface->public.plane_size =
++ updates[i].plane_info->plane_size;
++ surface->public.rotation =
++ updates[i].plane_info->rotation;
++ surface->public.horizontal_mirror =
++ updates[i].plane_info->horizontal_mirror;
++ surface->public.stereo_format =
++ updates[i].plane_info->stereo_format;
++ surface->public.tiling_info =
++ updates[i].plane_info->tiling_info;
++ surface->public.visible =
++ updates[i].plane_info->visible;
++ surface->public.dcc =
++ updates[i].plane_info->dcc;
++ }
++
++ /* not sure if we still need this */
+ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+ struct core_stream *stream = pipe_ctx->stream;
+@@ -1402,133 +1489,101 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda
+ if (pipe_ctx->surface != surface)
+ continue;
+
+- if (updates[i].flip_addr) {
+- surface->public.address = updates[i].flip_addr->address;
+- surface->public.flip_immediate =
+- updates[i].flip_addr->flip_immediate;
+- }
+-
+- if (updates[i].plane_info || updates[i].scaling_info
+- || is_new_pipe_surface[j]) {
+- need_apply_clk_constraints = true;
+-
+- if (updates[i].plane_info) {
+- surface->public.color_space =
+- updates[i].plane_info->color_space;
+- surface->public.format =
+- updates[i].plane_info->format;
+- surface->public.plane_size =
+- updates[i].plane_info->plane_size;
+- surface->public.rotation =
+- updates[i].plane_info->rotation;
+- surface->public.horizontal_mirror =
+- updates[i].plane_info->horizontal_mirror;
+- surface->public.stereo_format =
+- updates[i].plane_info->stereo_format;
+- surface->public.tiling_info =
+- updates[i].plane_info->tiling_info;
+- surface->public.visible =
+- updates[i].plane_info->visible;
+- surface->public.dcc =
+- updates[i].plane_info->dcc;
+- }
+-
+- if (updates[i].scaling_info) {
+- surface->public.scaling_quality =
+- updates[i].scaling_info->scaling_quality;
+- surface->public.dst_rect =
+- updates[i].scaling_info->dst_rect;
+- surface->public.src_rect =
+- updates[i].scaling_info->src_rect;
+- surface->public.clip_rect =
+- updates[i].scaling_info->clip_rect;
+- }
+-
+- resource_build_scaling_params(updates[i].surface, pipe_ctx);
+- if (dc->debug.surface_visual_confirm) {
+- pipe_ctx->scl_data.recout.height -= 2;
+- pipe_ctx->scl_data.recout.width -= 2;
+- }
++ resource_build_scaling_params(updates[i].surface, pipe_ctx);
++ if (dc->debug.surface_visual_confirm) {
++ pipe_ctx->scl_data.recout.height -= 2;
++ pipe_ctx->scl_data.recout.width -= 2;
+ }
++ }
+
+- if (dc->debug.disable_color_module)
+- continue; /* skip below color updates */
++ if (dc->debug.disable_color_module)
++ continue; /* skip below color updates */
+
+- if (updates[i].gamma &&
+- updates[i].gamma != surface->public.gamma_correction) {
+- if (surface->public.gamma_correction != NULL)
+- dc_gamma_release(&surface->public.
+- gamma_correction);
++ if (updates[i].gamma &&
++ updates[i].gamma != surface->public.gamma_correction) {
++ if (surface->public.gamma_correction != NULL)
++ dc_gamma_release(&surface->public.
++ gamma_correction);
+
+- dc_gamma_retain(updates[i].gamma);
+- surface->public.gamma_correction =
+- updates[i].gamma;
+- }
++ dc_gamma_retain(updates[i].gamma);
++ surface->public.gamma_correction =
++ updates[i].gamma;
++ }
+
+- if (updates[i].in_transfer_func &&
+- updates[i].in_transfer_func != surface->public.in_transfer_func) {
+- if (surface->public.in_transfer_func != NULL)
+- dc_transfer_func_release(
+- surface->public.
+- in_transfer_func);
+-
+- dc_transfer_func_retain(
+- updates[i].in_transfer_func);
+- surface->public.in_transfer_func =
+- updates[i].in_transfer_func;
+- }
++ if (updates[i].in_transfer_func &&
++ updates[i].in_transfer_func != surface->public.in_transfer_func) {
++ if (surface->public.in_transfer_func != NULL)
++ dc_transfer_func_release(
++ surface->public.
++ in_transfer_func);
++
++ dc_transfer_func_retain(
++ updates[i].in_transfer_func);
++ surface->public.in_transfer_func =
++ updates[i].in_transfer_func;
++ }
+
+- if (updates[i].out_transfer_func &&
+- updates[i].out_transfer_func != stream->public.out_transfer_func) {
+- if (stream->public.out_transfer_func != NULL)
+- dc_transfer_func_release(
+- stream->public.
+- out_transfer_func);
+- dc_transfer_func_retain(
+- updates[i].out_transfer_func);
+- stream->public.out_transfer_func =
+- updates[i].out_transfer_func;
+- }
+- if (updates[i].hdr_static_metadata)
+- surface->public.hdr_static_ctx =
+- *(updates[i].hdr_static_metadata);
++ if (updates[i].out_transfer_func &&
++ updates[i].out_transfer_func != dc_stream->out_transfer_func) {
++ if (dc_stream->out_transfer_func != NULL)
++ dc_transfer_func_release(dc_stream->out_transfer_func);
++ dc_transfer_func_retain(updates[i].out_transfer_func);
++ stream->public.out_transfer_func = updates[i].out_transfer_func;
+ }
++ if (updates[i].hdr_static_metadata)
++ surface->public.hdr_static_ctx =
++ *(updates[i].hdr_static_metadata);
+ }
+
++
++ if (!surface_count) /* reset */
++ core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context);
++
+ for (i = 0; i < surface_count; i++) {
+ struct core_surface *surface = DC_SURFACE_TO_CORE(updates[i].surface);
+
+ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
++ struct pipe_ctx *cur_pipe_ctx;
++ bool is_new_pipe_surface = true;
+
+ if (pipe_ctx->surface != surface)
+ continue;
+
+- if (updates[i].flip_addr && can_skip_context_building) {
+- core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
+- } else {
++ if (update_type != UPDATE_TYPE_FAST &&
++ !pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
++ core_dc->hwss.pipe_control_lock(
++ core_dc->hwseq,
++ pipe_ctx->pipe_idx,
++ PIPE_LOCK_CONTROL_GRAPHICS |
++ PIPE_LOCK_CONTROL_SCL |
++ PIPE_LOCK_CONTROL_BLENDER |
++ PIPE_LOCK_CONTROL_MODE,
++ true);
++ }
+
+- if (!pipe_ctx->tg->funcs->is_blanked(pipe_ctx->tg)) {
+- core_dc->hwss.pipe_control_lock(
+- core_dc->hwseq,
+- pipe_ctx->pipe_idx,
+- PIPE_LOCK_CONTROL_GRAPHICS |
+- PIPE_LOCK_CONTROL_SCL |
+- PIPE_LOCK_CONTROL_BLENDER |
+- PIPE_LOCK_CONTROL_MODE,
+- true);
+- }
++ if (update_type == UPDATE_TYPE_FULL) {
++ core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context);
++ } else if (updates[i].flip_addr) {
++ core_dc->hwss.update_plane_addr(core_dc, pipe_ctx);
+ }
+
++ if (update_type == UPDATE_TYPE_FAST)
++ continue;
++
++ cur_pipe_ctx = &core_dc->current_context->res_ctx.pipe_ctx[j];
++ if (cur_pipe_ctx->surface == pipe_ctx->surface)
++ is_new_pipe_surface = false;
++
+ if (dc->debug.disable_color_module)
+ continue; /* skip below color updates */
+
+- if (is_new_pipe_surface[j] ||
++ if (is_new_pipe_surface ||
+ updates[i].in_transfer_func)
+ core_dc->hwss.set_input_transfer_func(
+ pipe_ctx, pipe_ctx->surface);
+
+- if (is_new_pipe_surface[j] ||
++ if (is_new_pipe_surface ||
+ updates[i].out_transfer_func)
+ core_dc->hwss.set_output_transfer_func(
+ pipe_ctx,
+@@ -1539,14 +1594,12 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda
+ resource_build_info_frame(pipe_ctx);
+ core_dc->hwss.update_info_frame(pipe_ctx);
+ }
+-
+- }
+- if (!can_skip_context_building) {
+- core_dc->hwss.apply_ctx_for_surface(core_dc, surface, context);
+- context_timing_trace(dc, &context->res_ctx);
+ }
+ }
+
++ if (update_type == UPDATE_TYPE_FAST)
++ return;
++
+ for (i = context->res_ctx.pool->pipe_count - 1; i >= 0; i--) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+@@ -1566,8 +1619,12 @@ void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *upda
+ }
+ }
+
+- core_dc->temp_flip_context = core_dc->current_context;
+- core_dc->current_context = context;
++ if (core_dc->current_context != context) {
++ resource_validate_ctx_destruct(core_dc->current_context);
++ core_dc->temp_flip_context = core_dc->current_context;
++
++ core_dc->current_context = context;
++ }
+ }
+
+ uint8_t dc_get_current_stream_count(const struct dc *dc)
+--
+2.7.4
+