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

drm/amd/display: Blank HUBP during pixel data blank for DCN30

[Why]
There are some timings for which we support p-state
switching in active, but not in blank. There was a
previous issue where a timing that had active-only
support would hang a p-state request when we were in
an extended blanking period. The workaround for that
issue was to block active-only p-state switching,
but that resulted in a lack of p-state support for
some common timings such as 1440p60. We want to fix
that issue properly by un-blocking p-state requests
while the display is blanked, so that we can re-enable
active-only p-state switching.

[How]
- new version of blank_pixel_data for DCN30
- call hubp->set_blank from dcn30_blank_pixel_data
- blank every hubp in the mpcc tree, and odm tree
- on blank enable, wait until the next frame before blanking HUBP

Signed-off-by: Joshua Aberback <joshua.aberback@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Joshua Aberback and committed by
Alex Deucher
36f87850 e748b59f

+87 -2
+83
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
··· 809 809 dc->res_pool->hubbub->funcs->force_pstate_change_control( 810 810 dc->res_pool->hubbub, true, true); 811 811 } 812 + 813 + void dcn30_blank_pixel_data(struct dc *dc, struct pipe_ctx *pipe_ctx, bool blank) 814 + { 815 + struct tg_color black_color = {0}; 816 + struct stream_resource *stream_res = &pipe_ctx->stream_res; 817 + struct dc_stream_state *stream = pipe_ctx->stream; 818 + enum dc_color_space color_space = stream->output_color_space; 819 + enum controller_dp_test_pattern test_pattern = CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR; 820 + enum controller_dp_color_space test_pattern_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED; 821 + struct pipe_ctx *odm_pipe; 822 + struct pipe_ctx *mpcc_pipe; 823 + int odm_cnt = 1; 824 + 825 + int width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; 826 + int height = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top; 827 + 828 + if (stream->link->test_pattern_enabled) 829 + return; 830 + 831 + /* get opp dpg blank color */ 832 + color_space_to_black_color(dc, color_space, &black_color); 833 + 834 + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) 835 + odm_cnt++; 836 + 837 + width = width / odm_cnt; 838 + 839 + if (blank) { 840 + dc->hwss.set_abm_immediate_disable(pipe_ctx); 841 + 842 + if (dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) { 843 + test_pattern = CONTROLLER_DP_TEST_PATTERN_COLORSQUARES; 844 + test_pattern_color_space = CONTROLLER_DP_COLOR_SPACE_RGB; 845 + } 846 + } else { 847 + test_pattern = CONTROLLER_DP_TEST_PATTERN_VIDEOMODE; 848 + } 849 + 850 + stream_res->opp->funcs->opp_set_disp_pattern_generator( 851 + stream_res->opp, 852 + test_pattern, 853 + test_pattern_color_space, 854 + stream->timing.display_color_depth, 855 + &black_color, 856 + width, 857 + height, 858 + 0); 859 + 860 + /* wait for the next frame when enabling DPG */ 861 + if (blank && stream_res->tg->funcs->is_tg_enabled(stream_res->tg)) 862 + dc->hwseq->funcs.wait_for_blank_complete(pipe_ctx->stream_res.opp); 863 + 864 + /* Blank HUBP to allow p-state during blank on all timings */ 865 + pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, blank); 866 + for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe) 867 + mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, blank); 868 + 869 + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { 870 + odm_pipe->stream_res.opp->funcs->opp_set_disp_pattern_generator( 871 + odm_pipe->stream_res.opp, 872 + dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE && blank ? 873 + CONTROLLER_DP_TEST_PATTERN_COLORRAMP : test_pattern, 874 + test_pattern_color_space, 875 + stream->timing.display_color_depth, 876 + &black_color, 877 + width, 878 + height, 879 + 0); 880 + 881 + if (blank && stream_res->tg->funcs->is_tg_enabled(stream_res->tg)) 882 + dc->hwseq->funcs.wait_for_blank_complete(pipe_ctx->stream_res.opp); 883 + 884 + odm_pipe->plane_res.hubp->funcs->set_blank(odm_pipe->plane_res.hubp, blank); 885 + for (mpcc_pipe = odm_pipe->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe) 886 + mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, blank); 887 + } 888 + 889 + if (!blank) 890 + if (stream_res->abm) { 891 + dc->hwss.set_pipe(pipe_ctx); 892 + stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level); 893 + } 894 + }
+2
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.h
··· 69 69 70 70 void dcn30_hardware_release(struct dc *dc); 71 71 72 + void dcn30_blank_pixel_data(struct dc *dc, struct pipe_ctx *pipe_ctx, bool blank); 73 + 72 74 #endif /* __DC_HWSS_DCN30_H__ */
+1 -1
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c
··· 106 106 .set_output_transfer_func = dcn30_set_output_transfer_func, 107 107 .power_down = dce110_power_down, 108 108 .enable_display_power_gating = dcn10_dummy_display_power_gating, 109 - .blank_pixel_data = dcn20_blank_pixel_data, 109 + .blank_pixel_data = dcn30_blank_pixel_data, 110 110 .reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap, 111 111 .enable_stream_timing = dcn20_enable_stream_timing, 112 112 .edp_backlight_control = dce110_edp_backlight_control,
+1 -1
drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
··· 5558 5558 } 5559 5559 } 5560 5560 5561 - if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0 && PrefetchMode == 0) { 5561 + if (mode_lib->vba.MinActiveDRAMClockChangeMargin > 0) { 5562 5562 *DRAMClockChangeSupport = dm_dram_clock_change_vactive; 5563 5563 } else if (((mode_lib->vba.SynchronizedVBlank == true || mode_lib->vba.TotalNumberOfActiveOTG == 1 || SecondMinActiveDRAMClockChangeMarginOneDisplayInVBLank > 0) && PrefetchMode == 0)) { 5564 5564 *DRAMClockChangeSupport = dm_dram_clock_change_vblank;