Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/display: update DCN to use new surface programming

[Why]
The split pipe config is updated due to antoher stream bandwidth
validataion. Driver doesn't reprogram the split pipe config
to signle pipe cause SW use signel pipe but HW still use pipe split.

[How]
track global updates and update any hw that isn't
related to current stream being updated.

Signed-off-by: Paul Hsieh <paul.hsieh@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Acked-by: Wayne Lin <Wayne.Lin@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Paul Hsieh and committed by
Alex Deucher
7f63d8a1 4462bca7

+27 -149
+19 -142
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
··· 2956 2956 { 2957 2957 struct dce_hwseq *hws = dc->hwseq; 2958 2958 2959 + if (pipe_ctx->top_pipe == NULL) { 2960 + bool blank = !is_pipe_tree_visible(pipe_ctx); 2961 + 2962 + pipe_ctx->stream_res.tg->funcs->program_global_sync( 2963 + pipe_ctx->stream_res.tg, 2964 + pipe_ctx->pipe_dlg_param.vready_offset, 2965 + pipe_ctx->pipe_dlg_param.vstartup_start, 2966 + pipe_ctx->pipe_dlg_param.vupdate_offset, 2967 + pipe_ctx->pipe_dlg_param.vupdate_width); 2968 + 2969 + pipe_ctx->stream_res.tg->funcs->set_vtg_params( 2970 + pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true); 2971 + 2972 + if (hws->funcs.setup_vupdate_interrupt) 2973 + hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx); 2974 + 2975 + hws->funcs.blank_pixel_data(dc, pipe_ctx, blank); 2976 + } 2977 + 2959 2978 if (pipe_ctx->plane_state->update_flags.bits.full_update) 2960 2979 dcn10_enable_plane(dc, pipe_ctx, context); 2961 2980 ··· 2995 2976 */ 2996 2977 if (pipe_ctx->plane_state->update_flags.bits.full_update) 2997 2978 hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream); 2998 - } 2999 - 3000 - static void dcn10_program_all_pipe_in_tree( 3001 - struct dc *dc, 3002 - struct pipe_ctx *pipe_ctx, 3003 - struct dc_state *context) 3004 - { 3005 - struct dce_hwseq *hws = dc->hwseq; 3006 - 3007 - if (pipe_ctx->top_pipe == NULL) { 3008 - bool blank = !is_pipe_tree_visible(pipe_ctx); 3009 - 3010 - pipe_ctx->stream_res.tg->funcs->program_global_sync( 3011 - pipe_ctx->stream_res.tg, 3012 - pipe_ctx->pipe_dlg_param.vready_offset, 3013 - pipe_ctx->pipe_dlg_param.vstartup_start, 3014 - pipe_ctx->pipe_dlg_param.vupdate_offset, 3015 - pipe_ctx->pipe_dlg_param.vupdate_width); 3016 - 3017 - pipe_ctx->stream_res.tg->funcs->set_vtg_params( 3018 - pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true); 3019 - 3020 - if (hws->funcs.setup_vupdate_interrupt) 3021 - hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx); 3022 - 3023 - hws->funcs.blank_pixel_data(dc, pipe_ctx, blank); 3024 - } 3025 - 3026 - if (pipe_ctx->plane_state != NULL) 3027 - hws->funcs.program_pipe(dc, pipe_ctx, context); 3028 - 3029 - if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) 3030 - dcn10_program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context); 3031 - } 3032 - 3033 - static struct pipe_ctx *dcn10_find_top_pipe_for_stream( 3034 - struct dc *dc, 3035 - struct dc_state *context, 3036 - const struct dc_stream_state *stream) 3037 - { 3038 - int i; 3039 - 3040 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 3041 - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 3042 - struct pipe_ctx *old_pipe_ctx = 3043 - &dc->current_state->res_ctx.pipe_ctx[i]; 3044 - 3045 - if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) 3046 - continue; 3047 - 3048 - if (pipe_ctx->stream != stream) 3049 - continue; 3050 - 3051 - if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe) 3052 - return pipe_ctx; 3053 - } 3054 - return NULL; 3055 2979 } 3056 2980 3057 2981 void dcn10_wait_for_pending_cleared(struct dc *dc, ··· 3026 3064 */ 3027 3065 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); 3028 3066 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); 3029 - } 3030 - } 3031 - 3032 - void dcn10_apply_ctx_for_surface( 3033 - struct dc *dc, 3034 - const struct dc_stream_state *stream, 3035 - int num_planes, 3036 - struct dc_state *context) 3037 - { 3038 - struct dce_hwseq *hws = dc->hwseq; 3039 - int i; 3040 - struct timing_generator *tg; 3041 - uint32_t underflow_check_delay_us; 3042 - bool interdependent_update = false; 3043 - struct pipe_ctx *top_pipe_to_program = 3044 - dcn10_find_top_pipe_for_stream(dc, context, stream); 3045 - DC_LOGGER_INIT(dc->ctx->logger); 3046 - 3047 - // Clear pipe_ctx flag 3048 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 3049 - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 3050 - pipe_ctx->update_flags.raw = 0; 3051 - } 3052 - 3053 - if (!top_pipe_to_program) 3054 - return; 3055 - 3056 - tg = top_pipe_to_program->stream_res.tg; 3057 - 3058 - interdependent_update = top_pipe_to_program->plane_state && 3059 - top_pipe_to_program->plane_state->update_flags.bits.full_update; 3060 - 3061 - underflow_check_delay_us = dc->debug.underflow_assert_delay_us; 3062 - 3063 - if (underflow_check_delay_us != 0xFFFFFFFF && hws->funcs.did_underflow_occur) 3064 - ASSERT(hws->funcs.did_underflow_occur(dc, top_pipe_to_program)); 3065 - 3066 - if (underflow_check_delay_us != 0xFFFFFFFF) 3067 - udelay(underflow_check_delay_us); 3068 - 3069 - if (underflow_check_delay_us != 0xFFFFFFFF && hws->funcs.did_underflow_occur) 3070 - ASSERT(hws->funcs.did_underflow_occur(dc, top_pipe_to_program)); 3071 - 3072 - if (num_planes == 0) { 3073 - /* OTG blank before remove all front end */ 3074 - hws->funcs.blank_pixel_data(dc, top_pipe_to_program, true); 3075 - } 3076 - 3077 - /* Disconnect unused mpcc */ 3078 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 3079 - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 3080 - struct pipe_ctx *old_pipe_ctx = 3081 - &dc->current_state->res_ctx.pipe_ctx[i]; 3082 - 3083 - if ((!pipe_ctx->plane_state || 3084 - pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) && 3085 - old_pipe_ctx->plane_state && 3086 - old_pipe_ctx->stream_res.tg == tg) { 3087 - 3088 - hws->funcs.plane_atomic_disconnect(dc, old_pipe_ctx); 3089 - pipe_ctx->update_flags.bits.disable = 1; 3090 - 3091 - DC_LOG_DC("Reset mpcc for pipe %d\n", 3092 - old_pipe_ctx->pipe_idx); 3093 - } 3094 - } 3095 - 3096 - if (num_planes > 0) 3097 - dcn10_program_all_pipe_in_tree(dc, top_pipe_to_program, context); 3098 - 3099 - /* Program secondary blending tree and writeback pipes */ 3100 - if ((stream->num_wb_info > 0) && (hws->funcs.program_all_writeback_pipes_in_tree)) 3101 - hws->funcs.program_all_writeback_pipes_in_tree(dc, stream, context); 3102 - if (interdependent_update) 3103 - for (i = 0; i < dc->res_pool->pipe_count; i++) { 3104 - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; 3105 - /* Skip inactive pipes and ones already updated */ 3106 - if (!pipe_ctx->stream || pipe_ctx->stream == stream || 3107 - !pipe_ctx->plane_state || !tg->funcs->is_tg_enabled(tg)) 3108 - continue; 3109 - 3110 - pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent( 3111 - pipe_ctx->plane_res.hubp, 3112 - &pipe_ctx->dlg_regs, 3113 - &pipe_ctx->ttu_regs); 3114 3067 } 3115 3068 } 3116 3069
-5
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h
··· 80 80 struct dc *dc, 81 81 struct dc_state *context, 82 82 bool lock); 83 - void dcn10_apply_ctx_for_surface( 84 - struct dc *dc, 85 - const struct dc_stream_state *stream, 86 - int num_planes, 87 - struct dc_state *context); 88 83 void dcn10_post_unlock_program_front_end( 89 84 struct dc *dc, 90 85 struct dc_state *context);
+3 -1
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c
··· 26 26 #include "hw_sequencer_private.h" 27 27 #include "dce110/dce110_hw_sequencer.h" 28 28 #include "dcn10_hw_sequencer.h" 29 + #include "dcn20/dcn20_hwseq.h" 29 30 30 31 static const struct hw_sequencer_funcs dcn10_funcs = { 31 32 .program_gamut_remap = dcn10_program_gamut_remap, 32 33 .init_hw = dcn10_init_hw, 33 34 .power_down_on_boot = dcn10_power_down_on_boot, 34 35 .apply_ctx_to_hw = dce110_apply_ctx_to_hw, 35 - .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, 36 + .apply_ctx_for_surface = NULL, 37 + .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, 36 38 .post_unlock_program_front_end = dcn10_post_unlock_program_front_end, 37 39 .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, 38 40 .update_plane_addr = dcn10_update_plane_addr,
+5 -1
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
··· 1700 1700 1701 1701 if (pipe->plane_state && !pipe->top_pipe) { 1702 1702 while (pipe) { 1703 - dcn20_program_pipe(dc, pipe, context); 1703 + if (hws->funcs.program_pipe) 1704 + hws->funcs.program_pipe(dc, pipe, context); 1705 + else 1706 + dcn20_program_pipe(dc, pipe, context); 1707 + 1704 1708 pipe = pipe->bottom_pipe; 1705 1709 } 1706 1710 /* Program secondary blending tree and writeback pipes */