Skip to content

Commit e5fc782

Browse files
Gabe Teegeralexdeucher
authored andcommitted
drm/amd/display: Add support for zstate during extended vblank
[why] When we enter FREESYNC_STATE_VIDEO, we want to use the extra vblank portion to enter zstate if possible. [how] When we enter freesync, a full update is triggered and the new vtotal with extra lines is passed to dml in a stream update. The time gained from extra vblank lines is calculated in microseconds. We allow zstate entry if the time gained is greater than 5 ms, which is the current policy. Furthermore, an optimized value for min_dst_y_next_start is calculated and written to its register. When exiting freesync, another full update is triggered and default values are restored. Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Acked-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Gabe Teeger <gabe.teeger@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 02fc996 commit e5fc782

10 files changed

Lines changed: 80 additions & 4 deletions

File tree

drivers/gpu/drm/amd/display/dc/core/dc.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2393,6 +2393,8 @@ static enum surface_update_type check_update_surfaces_for_stream(
23932393

23942394
if (stream_update->mst_bw_update)
23952395
su_flags->bits.mst_bw = 1;
2396+
if (stream_update->crtc_timing_adjust && dc_extended_blank_supported(dc))
2397+
su_flags->bits.crtc_timing_adjust = 1;
23962398

23972399
if (su_flags->raw != 0)
23982400
overall_type = UPDATE_TYPE_FULL;
@@ -2654,6 +2656,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
26542656
if (update->vrr_infopacket)
26552657
stream->vrr_infopacket = *update->vrr_infopacket;
26562658

2659+
if (update->crtc_timing_adjust)
2660+
stream->adjust = *update->crtc_timing_adjust;
2661+
26572662
if (update->dpms_off)
26582663
stream->dpms_off = *update->dpms_off;
26592664

@@ -4055,3 +4060,17 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo
40554060
if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause)
40564061
pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst);
40574062
}
4063+
/*
4064+
* dc_extended_blank_supported: Decide whether extended blank is supported
4065+
*
4066+
* Extended blank is a freesync optimization feature to be enabled in the future.
4067+
* During the extra vblank period gained from freesync, we have the ability to enter z9/z10.
4068+
*
4069+
* @param [in] dc: Current DC state
4070+
* @return: Indicate whether extended blank is supported (true or false)
4071+
*/
4072+
bool dc_extended_blank_supported(struct dc *dc)
4073+
{
4074+
return dc->debug.extended_blank_optimization && !dc->debug.disable_z10
4075+
&& dc->caps.zstate_support && dc->caps.is_apu;
4076+
}

drivers/gpu/drm/amd/display/dc/dc.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ struct dc_caps {
188188
bool psp_setup_panel_mode;
189189
bool extended_aux_timeout_support;
190190
bool dmcub_support;
191+
bool zstate_support;
191192
uint32_t num_of_internal_disp;
192193
enum dp_protocol_version max_dp_protocol_version;
193194
unsigned int mall_size_per_mem_channel;
@@ -703,13 +704,14 @@ struct dc_debug_options {
703704
bool enable_driver_sequence_debug;
704705
enum det_size crb_alloc_policy;
705706
int crb_alloc_policy_min_disp_count;
706-
#if defined(CONFIG_DRM_AMD_DC_DCN)
707707
bool disable_z10;
708+
#if defined(CONFIG_DRM_AMD_DC_DCN)
708709
bool enable_z9_disable_interface;
709710
bool enable_sw_cntl_psr;
710711
union dpia_debug_options dpia_debug;
711712
#endif
712713
bool apply_vendor_specific_lttpr_wa;
714+
bool extended_blank_optimization;
713715
bool ignore_dpref_ss;
714716
uint8_t psr_power_use_phy_fsm;
715717
};
@@ -1369,6 +1371,8 @@ struct dc_sink_init_data {
13691371
bool converter_disable_audio;
13701372
};
13711373

1374+
bool dc_extended_blank_supported(struct dc *dc);
1375+
13721376
struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params);
13731377

13741378
/* Newer interfaces */

drivers/gpu/drm/amd/display/dc/dc_stream.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ union stream_update_flags {
131131
uint32_t wb_update:1;
132132
uint32_t dsc_changed : 1;
133133
uint32_t mst_bw : 1;
134+
uint32_t crtc_timing_adjust : 1;
134135
} bits;
135136

136137
uint32_t raw;
@@ -289,6 +290,7 @@ struct dc_stream_update {
289290
struct dc_3dlut *lut3d_func;
290291

291292
struct test_pattern *pending_test_pattern;
293+
struct dc_crtc_timing_adjust *crtc_timing_adjust;
292294
};
293295

294296
bool dc_is_stream_unchanged(

drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,7 @@ void dcn20_optimize_bandwidth(
18571857
struct dc_state *context)
18581858
{
18591859
struct hubbub *hubbub = dc->res_pool->hubbub;
1860+
int i;
18601861

18611862
/* program dchubbub watermarks */
18621863
hubbub->funcs->program_watermarks(hubbub,
@@ -1873,6 +1874,17 @@ void dcn20_optimize_bandwidth(
18731874
dc->clk_mgr,
18741875
context,
18751876
true);
1877+
if (dc_extended_blank_supported(dc) && context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW) {
1878+
for (i = 0; i < dc->res_pool->pipe_count; ++i) {
1879+
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1880+
1881+
if (pipe_ctx->stream && pipe_ctx->plane_res.hubp->funcs->program_extended_blank
1882+
&& pipe_ctx->stream->adjust.v_total_min == pipe_ctx->stream->adjust.v_total_max
1883+
&& pipe_ctx->stream->adjust.v_total_max > pipe_ctx->stream->timing.v_total)
1884+
pipe_ctx->plane_res.hubp->funcs->program_extended_blank(pipe_ctx->plane_res.hubp,
1885+
pipe_ctx->dlg_regs.optimized_min_dst_y_next_start);
1886+
}
1887+
}
18761888
/* increase compbuf size */
18771889
if (hubbub->funcs->program_compbuf_size)
18781890
hubbub->funcs->program_compbuf_size(hubbub, context->bw_ctx.bw.dcn.compbuf_size_kb, true);

drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubp.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ void hubp31_soft_reset(struct hubp *hubp, bool reset)
5454
REG_UPDATE(DCHUBP_CNTL, HUBP_SOFT_RESET, reset);
5555
}
5656

57+
void hubp31_program_extended_blank(struct hubp *hubp, unsigned int min_dst_y_next_start_optimized)
58+
{
59+
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
60+
61+
REG_SET(BLANK_OFFSET_1, 0, MIN_DST_Y_NEXT_START, min_dst_y_next_start_optimized);
62+
}
63+
5764
static struct hubp_funcs dcn31_hubp_funcs = {
5865
.hubp_enable_tripleBuffer = hubp2_enable_triplebuffer,
5966
.hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled,
@@ -80,6 +87,7 @@ static struct hubp_funcs dcn31_hubp_funcs = {
8087
.set_unbounded_requesting = hubp31_set_unbounded_requesting,
8188
.hubp_soft_reset = hubp31_soft_reset,
8289
.hubp_in_blank = hubp1_in_blank,
90+
.program_extended_blank = hubp31_program_extended_blank,
8391
};
8492

8593
bool hubp31_construct(

drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2232,6 +2232,7 @@ static bool dcn31_resource_construct(
22322232
dc->caps.extended_aux_timeout_support = true;
22332233
dc->caps.dmcub_support = true;
22342234
dc->caps.is_apu = true;
2235+
dc->caps.zstate_support = true;
22352236

22362237
/* Color pipeline capabilities */
22372238
dc->caps.color.dpp.dcn_arch = 1;

drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -722,8 +722,10 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
722722
{
723723
int plane_count;
724724
int i;
725+
unsigned int optimized_min_dst_y_next_start_us;
725726

726727
plane_count = 0;
728+
optimized_min_dst_y_next_start_us = 0;
727729
for (i = 0; i < dc->res_pool->pipe_count; i++) {
728730
if (context->res_ctx.pipe_ctx[i].plane_state)
729731
plane_count++;
@@ -744,11 +746,22 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
744746
struct dc_link *link = context->streams[0]->sink->link;
745747
struct dc_stream_status *stream_status = &context->stream_status[0];
746748

749+
if (dc_extended_blank_supported(dc)) {
750+
for (i = 0; i < dc->res_pool->pipe_count; i++) {
751+
if (context->res_ctx.pipe_ctx[i].stream == context->streams[0]
752+
&& context->res_ctx.pipe_ctx[i].stream->adjust.v_total_min == context->res_ctx.pipe_ctx[i].stream->adjust.v_total_max
753+
&& context->res_ctx.pipe_ctx[i].stream->adjust.v_total_min > context->res_ctx.pipe_ctx[i].stream->timing.v_total) {
754+
optimized_min_dst_y_next_start_us =
755+
context->res_ctx.pipe_ctx[i].dlg_regs.optimized_min_dst_y_next_start_us;
756+
break;
757+
}
758+
}
759+
}
747760
/* zstate only supported on PWRSEQ0 and when there's <2 planes*/
748761
if (link->link_index != 0 || stream_status->plane_count > 1)
749762
return DCN_ZSTATE_SUPPORT_DISALLOW;
750763

751-
if (context->bw_ctx.dml.vba.StutterPeriod > 5000.0)
764+
if (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || optimized_min_dst_y_next_start_us > 5000)
752765
return DCN_ZSTATE_SUPPORT_ALLOW;
753766
else if (link->psr_settings.psr_version == DC_PSR_VERSION_1 && !dc->debug.disable_psr)
754767
return DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY;
@@ -786,8 +799,6 @@ void dcn20_calculate_dlg_params(
786799
!= dm_dram_clock_change_unsupported;
787800
context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
788801

789-
context->bw_ctx.bw.dcn.clk.zstate_support = decide_zstate_support(dc, context);
790-
791802
context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(dc, context);
792803

793804
if (context->bw_ctx.bw.dcn.clk.dispclk_khz < dc->debug.min_disp_clk_khz)
@@ -843,6 +854,7 @@ void dcn20_calculate_dlg_params(
843854
&pipes[pipe_idx].pipe);
844855
pipe_idx++;
845856
}
857+
context->bw_ctx.bw.dcn.clk.zstate_support = decide_zstate_support(dc, context);
846858
}
847859

848860
static void swizzle_to_dml_params(

drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,7 @@ static void dml_rq_dlg_get_dlg_params(
10551055

10561056
float vba__refcyc_per_req_delivery_pre_l = get_refcyc_per_req_delivery_pre_l_in_us(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz; // From VBA
10571057
float vba__refcyc_per_req_delivery_l = get_refcyc_per_req_delivery_l_in_us(mode_lib, e2e_pipe_param, num_pipes, pipe_idx) * refclk_freq_in_mhz; // From VBA
1058+
int blank_lines;
10581059

10591060
memset(disp_dlg_regs, 0, sizeof(*disp_dlg_regs));
10601061
memset(disp_ttu_regs, 0, sizeof(*disp_ttu_regs));
@@ -1080,6 +1081,18 @@ static void dml_rq_dlg_get_dlg_params(
10801081
dlg_vblank_start = interlaced ? (vblank_start / 2) : vblank_start;
10811082

10821083
disp_dlg_regs->min_dst_y_next_start = (unsigned int) (((double) dlg_vblank_start) * dml_pow(2, 2));
1084+
blank_lines = (dst->vblank_end + dst->vtotal_min - dst->vblank_start - dst->vstartup_start - 1);
1085+
if (blank_lines < 0)
1086+
blank_lines = 0;
1087+
if (blank_lines != 0) {
1088+
disp_dlg_regs->optimized_min_dst_y_next_start_us =
1089+
((unsigned int) blank_lines * dst->hactive) / (unsigned int) dst->pixel_rate_mhz;
1090+
disp_dlg_regs->optimized_min_dst_y_next_start =
1091+
(unsigned int)(((double) (dlg_vblank_start + blank_lines)) * dml_pow(2, 2));
1092+
} else {
1093+
// use unoptimized value
1094+
disp_dlg_regs->optimized_min_dst_y_next_start = disp_dlg_regs->min_dst_y_next_start;
1095+
}
10831096
ASSERT(disp_dlg_regs->min_dst_y_next_start < (unsigned int)dml_pow(2, 18));
10841097

10851098
dml_print("DML_DLG: %s: min_ttu_vblank (us) = %3.2f\n", __func__, min_ttu_vblank);

drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,8 @@ struct _vcs_dpi_display_dlg_regs_st {
446446
unsigned int refcyc_h_blank_end;
447447
unsigned int dlg_vblank_end;
448448
unsigned int min_dst_y_next_start;
449+
unsigned int optimized_min_dst_y_next_start;
450+
unsigned int optimized_min_dst_y_next_start_us;
449451
unsigned int refcyc_per_htotal;
450452
unsigned int refcyc_x_after_scaler;
451453
unsigned int dst_y_after_scaler;

drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ struct hubp_funcs {
195195

196196
void (*hubp_set_flip_int)(struct hubp *hubp);
197197

198+
void (*program_extended_blank)(struct hubp *hubp,
199+
unsigned int min_dst_y_next_start_optimized);
200+
198201
void (*hubp_wait_pipe_read_start)(struct hubp *hubp);
199202
};
200203

0 commit comments

Comments
 (0)