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

drm/amd/display: Add hblank borrowing support

[WHY]
Some DSC timing failed at bandwidth validation due to hactive
can't be evenly divided on each ODM segment.

[HOW]
Borrow from hblank to increase hactive to support these timing.

Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Chris Park <chris.park@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Chris Park and committed by
Alex Deucher
0c0a1943 a29997b7

+75 -7
+41 -1
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
··· 2094 2094 count = resource_get_odm_slice_count(otg_master); 2095 2095 h_active = timing->h_addressable + 2096 2096 timing->h_border_left + 2097 - timing->h_border_right; 2097 + timing->h_border_right + 2098 + otg_master->hblank_borrow; 2098 2099 width = h_active / count; 2099 2100 2100 2101 if (otg_master->stream_res.tg) ··· 4028 4027 } 4029 4028 4030 4029 /** 4030 + * decide_hblank_borrow - Decides the horizontal blanking borrow value for a given pipe context. 4031 + * @pipe_ctx: Pointer to the pipe context structure. 4032 + * 4033 + * This function calculates the horizontal blanking borrow value for a given pipe context based on the 4034 + * display stream compression (DSC) configuration. If the horizontal active pixels (hactive) are less 4035 + * than the total width of the DSC slices, it sets the hblank_borrow value to the difference. If the 4036 + * total horizontal timing minus the hblank_borrow value is less than 32, it resets the hblank_borrow 4037 + * value to 0. 4038 + */ 4039 + static void decide_hblank_borrow(struct pipe_ctx *pipe_ctx) 4040 + { 4041 + uint32_t hactive; 4042 + uint32_t ceil_slice_width; 4043 + struct dc_stream_state *stream = NULL; 4044 + 4045 + if (!pipe_ctx) 4046 + return; 4047 + 4048 + stream = pipe_ctx->stream; 4049 + 4050 + if (stream->timing.flags.DSC) { 4051 + hactive = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; 4052 + 4053 + /* Assume if determined slices does not divide Hactive evenly, Hborrow is needed for padding*/ 4054 + if (hactive % stream->timing.dsc_cfg.num_slices_h != 0) { 4055 + ceil_slice_width = (hactive / stream->timing.dsc_cfg.num_slices_h) + 1; 4056 + pipe_ctx->hblank_borrow = ceil_slice_width * stream->timing.dsc_cfg.num_slices_h - hactive; 4057 + 4058 + if (stream->timing.h_total - hactive - pipe_ctx->hblank_borrow < 32) 4059 + pipe_ctx->hblank_borrow = 0; 4060 + } 4061 + } 4062 + } 4063 + 4064 + /** 4031 4065 * dc_validate_global_state() - Determine if hardware can support a given state 4032 4066 * 4033 4067 * @dc: dc struct for this driver ··· 4099 4063 4100 4064 if (pipe_ctx->stream != stream) 4101 4065 continue; 4066 + 4067 + /* Decide whether hblank borrow is needed and save it in pipe_ctx */ 4068 + if (dc->debug.enable_hblank_borrow) 4069 + decide_hblank_borrow(pipe_ctx); 4102 4070 4103 4071 if (dc->res_pool->funcs->patch_unknown_plane_state && 4104 4072 pipe_ctx->plane_state &&
+1
drivers/gpu/drm/amd/display/dc/dc.h
··· 1069 1069 unsigned int scale_to_sharpness_policy; 1070 1070 bool skip_full_updated_if_possible; 1071 1071 unsigned int enable_oled_edp_power_up_opt; 1072 + bool enable_hblank_borrow; 1072 1073 }; 1073 1074 1074 1075
+1 -1
drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
··· 120 120 spl_in->odm_slice_index = resource_get_odm_slice_index(pipe_ctx); 121 121 // Make spl input basic out info output_size width point to stream h active 122 122 spl_in->basic_out.output_size.width = 123 - stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; 123 + stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right + pipe_ctx->hblank_borrow; 124 124 // Make spl input basic out info output_size height point to v active 125 125 spl_in->basic_out.output_size.height = 126 126 stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
+19 -2
drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
··· 445 445 timing->vblank_nom = timing->v_total - timing->v_active; 446 446 } 447 447 448 + /** 449 + * adjust_dml21_hblank_timing_config_from_pipe_ctx - Adjusts the horizontal blanking timing configuration 450 + * based on the pipe context. 451 + * @timing: Pointer to the dml2_timing_cfg structure to be adjusted. 452 + * @pipe: Pointer to the pipe_ctx structure containing the horizontal blanking borrow value. 453 + * 454 + * This function modifies the horizontal active and blank end timings by adding and subtracting 455 + * the horizontal blanking borrow value from the pipe context, respectively. 456 + */ 457 + static void adjust_dml21_hblank_timing_config_from_pipe_ctx(struct dml2_timing_cfg *timing, struct pipe_ctx *pipe) 458 + { 459 + timing->h_active += pipe->hblank_borrow; 460 + timing->h_blank_end -= pipe->hblank_borrow; 461 + } 462 + 448 463 static void populate_dml21_output_config_from_stream_state(struct dml2_link_output_cfg *output, 449 464 struct dc_stream_state *stream, const struct pipe_ctx *pipe) 450 465 { ··· 747 732 temp_pipe->plane_state = pipe->plane_state; 748 733 temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps; 749 734 temp_pipe->stream_res = pipe->stream_res; 735 + temp_pipe->hblank_borrow = pipe->hblank_borrow; 750 736 dml_ctx->config.callbacks.build_scaling_params(temp_pipe); 751 737 break; 752 738 } ··· 1012 996 1013 997 ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__); 1014 998 populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], dml_ctx); 999 + adjust_dml21_hblank_timing_config_from_pipe_ctx(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, &context->res_ctx.pipe_ctx[stream_index]); 1015 1000 populate_dml21_output_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].output, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index]); 1016 1001 populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location], context->streams[stream_index]); 1017 1002 ··· 1151 1134 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 1152 1135 union dml2_global_sync_programming *global_sync = &stream_programming->global_sync; 1153 1136 1154 - hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right; 1137 + hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right + pipe_ctx->hblank_borrow; 1155 1138 vactive = timing->v_addressable + timing->v_border_bottom + timing->v_border_top; 1156 1139 hblank_start = pipe_ctx->stream->timing.h_total - pipe_ctx->stream->timing.h_front_porch; 1157 1140 vblank_start = pipe_ctx->stream->timing.v_total - pipe_ctx->stream->timing.v_front_porch; 1158 1141 1159 - hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right; 1142 + hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right - pipe_ctx->hblank_borrow; 1160 1143 vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom; 1161 1144 1162 1145 if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
+2 -1
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
··· 1049 1049 } 1050 1050 1051 1051 /* Enable DSC hw block */ 1052 - dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; 1052 + dsc_cfg.pic_width = (stream->timing.h_addressable + pipe_ctx->hblank_borrow + 1053 + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt; 1053 1054 dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; 1054 1055 dsc_cfg.pixel_encoding = stream->timing.pixel_encoding; 1055 1056 dsc_cfg.color_depth = stream->timing.display_color_depth;
+6 -1
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
··· 820 820 int opp_cnt = 1; 821 821 int opp_inst[MAX_PIPES] = {0}; 822 822 struct pipe_ctx *opp_heads[MAX_PIPES] = {0}; 823 + struct dc_crtc_timing patched_crtc_timing = stream->timing; 823 824 bool manual_mode; 824 825 unsigned int tmds_div = PIXEL_RATE_DIV_NA; 825 826 unsigned int unused_div = PIXEL_RATE_DIV_NA; ··· 875 874 if (dc->hwseq->funcs.PLAT_58856_wa && (!dc_is_dp_signal(stream->signal))) 876 875 dc->hwseq->funcs.PLAT_58856_wa(context, pipe_ctx); 877 876 877 + /* if we are borrowing from hblank, h_addressable needs to be adjusted */ 878 + if (dc->debug.enable_hblank_borrow) 879 + patched_crtc_timing.h_addressable = patched_crtc_timing.h_addressable + pipe_ctx->hblank_borrow; 880 + 878 881 pipe_ctx->stream_res.tg->funcs->program_timing( 879 882 pipe_ctx->stream_res.tg, 880 - &stream->timing, 883 + &patched_crtc_timing, 881 884 pipe_ctx->pipe_dlg_param.vready_offset, 882 885 pipe_ctx->pipe_dlg_param.vstartup_start, 883 886 pipe_ctx->pipe_dlg_param.vupdate_offset,
+2
drivers/gpu/drm/amd/display/dc/inc/core_types.h
··· 478 478 /* subvp_index: only valid if the pipe is a SUBVP_MAIN*/ 479 479 uint8_t subvp_index; 480 480 struct pixel_rate_divider pixel_rate_divider; 481 + /* pixels borrowed from hblank to hactive */ 482 + uint8_t hblank_borrow; 481 483 }; 482 484 483 485 /* Data used for dynamic link encoder assignment.
+1
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
··· 2804 2804 free_pipe->plane_res.xfm = pool->transforms[free_pipe_idx]; 2805 2805 free_pipe->plane_res.dpp = pool->dpps[free_pipe_idx]; 2806 2806 free_pipe->plane_res.mpcc_inst = pool->dpps[free_pipe_idx]->inst; 2807 + free_pipe->hblank_borrow = otg_master->hblank_borrow; 2807 2808 if (free_pipe->stream->timing.flags.DSC == 1) { 2808 2809 dcn20_acquire_dsc(free_pipe->stream->ctx->dc, 2809 2810 &new_ctx->res_ctx,