Skip to content

Commit 4465dd0

Browse files
Dillon Varonealexdeucher
authored andcommitted
drm/amd/display: Refactor SubVP cursor limiting logic
[WHY] There are several gaps that can result in SubVP being enabled with incompatible HW cursor sizes, and unjust restrictions to cursor size due to wrong predictions on future usage of SubVP. [HOW] - remove "prediction" logic in favor of tagging based on previous SubVP usage - block SubVP if current HW cursor settings are incompatible - provide interface for DM to determine if HW cursor should be disabled due to an attempt to enable SubVP Reviewed-by: Alvin Lee <[email protected]> Signed-off-by: Dillon Varone <[email protected]> Signed-off-by: Ray Wu <[email protected]> Tested-by: Daniel Wheeler <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent fe3250f commit 4465dd0

39 files changed

+418
-135
lines changed

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

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "dc_state.h"
3838
#include "dc_state_priv.h"
3939
#include "dc_plane_priv.h"
40+
#include "dc_stream_priv.h"
4041

4142
#include "gpio_service_interface.h"
4243
#include "clk_mgr.h"
@@ -2886,7 +2887,7 @@ static enum surface_update_type check_update_surfaces_for_stream(
28862887
int i;
28872888
enum surface_update_type overall_type = UPDATE_TYPE_FAST;
28882889

2889-
if (dc->idle_optimizations_allowed)
2890+
if (dc->idle_optimizations_allowed || dc_can_clear_cursor_limit(dc))
28902891
overall_type = UPDATE_TYPE_FULL;
28912892

28922893
if (stream_status == NULL || stream_status->plane_count != surface_count)
@@ -3290,7 +3291,7 @@ static void copy_stream_update_to_stream(struct dc *dc,
32903291
if (dsc_validate_context) {
32913292
stream->timing.dsc_cfg = *update->dsc_config;
32923293
stream->timing.flags.DSC = enable_dsc;
3293-
if (!dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true)) {
3294+
if (dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true) != DC_OK) {
32943295
stream->timing.dsc_cfg = old_dsc_cfg;
32953296
stream->timing.flags.DSC = old_dsc_enabled;
32963297
update->dsc_config = NULL;
@@ -3515,7 +3516,7 @@ static bool update_planes_and_stream_state(struct dc *dc,
35153516
}
35163517

35173518
if (update_type == UPDATE_TYPE_FULL) {
3518-
if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
3519+
if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK) {
35193520
BREAK_TO_DEBUGGER();
35203521
goto fail;
35213522
}
@@ -4608,7 +4609,7 @@ static struct dc_state *create_minimal_transition_state(struct dc *dc,
46084609

46094610
backup_and_set_minimal_pipe_split_policy(dc, base_context, policy);
46104611
/* commit minimal state */
4611-
if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false)) {
4612+
if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false) == DC_OK) {
46124613
/* prevent underflow and corruption when reconfiguring pipes */
46134614
force_vsync_flip_in_minimal_transition_context(minimal_transition_context);
46144615
} else {
@@ -5043,6 +5044,9 @@ static bool full_update_required(struct dc *dc,
50435044
if (dc->idle_optimizations_allowed)
50445045
return true;
50455046

5047+
if (dc_can_clear_cursor_limit(dc))
5048+
return true;
5049+
50465050
return false;
50475051
}
50485052

@@ -5128,7 +5132,7 @@ static bool update_planes_and_stream_v1(struct dc *dc,
51285132
copy_stream_update_to_stream(dc, context, stream, stream_update);
51295133

51305134
if (update_type >= UPDATE_TYPE_FULL) {
5131-
if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
5135+
if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK) {
51325136
DC_ERROR("Mode validation failed for stream update!\n");
51335137
dc_state_release(context);
51345138
return false;
@@ -6272,15 +6276,22 @@ bool dc_abm_save_restore(
62726276
void dc_query_current_properties(struct dc *dc, struct dc_current_properties *properties)
62736277
{
62746278
unsigned int i;
6275-
bool subvp_sw_cursor_req = false;
6279+
unsigned int max_cursor_size = dc->caps.max_cursor_size;
6280+
unsigned int stream_cursor_size;
62766281

6277-
for (i = 0; i < dc->current_state->stream_count; i++) {
6278-
if (check_subvp_sw_cursor_fallback_req(dc, dc->current_state->streams[i]) && !dc->current_state->streams[i]->hw_cursor_req) {
6279-
subvp_sw_cursor_req = true;
6280-
break;
6282+
if (dc->debug.allow_sw_cursor_fallback && dc->res_pool->funcs->get_max_hw_cursor_size) {
6283+
for (i = 0; i < dc->current_state->stream_count; i++) {
6284+
stream_cursor_size = dc->res_pool->funcs->get_max_hw_cursor_size(dc,
6285+
dc->current_state,
6286+
dc->current_state->streams[i]);
6287+
6288+
if (stream_cursor_size < max_cursor_size) {
6289+
max_cursor_size = stream_cursor_size;
6290+
}
62816291
}
62826292
}
6283-
properties->cursor_size_limit = subvp_sw_cursor_req ? 64 : dc->caps.max_cursor_size;
6293+
6294+
properties->cursor_size_limit = max_cursor_size;
62846295
}
62856296

62866297
/**
@@ -6346,3 +6357,27 @@ unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context)
63466357
else
63476358
return 0;
63486359
}
6360+
6361+
bool dc_is_cursor_limit_pending(struct dc *dc)
6362+
{
6363+
uint32_t i;
6364+
6365+
for (i = 0; i < dc->current_state->stream_count; i++) {
6366+
if (dc_stream_is_cursor_limit_pending(dc, dc->current_state->streams[i]))
6367+
return true;
6368+
}
6369+
6370+
return false;
6371+
}
6372+
6373+
bool dc_can_clear_cursor_limit(struct dc *dc)
6374+
{
6375+
uint32_t i;
6376+
6377+
for (i = 0; i < dc->current_state->stream_count; i++) {
6378+
if (dc_state_can_clear_stream_cursor_subvp_limit(dc->current_state->streams[i], dc->current_state))
6379+
return true;
6380+
}
6381+
6382+
return false;
6383+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ char *dc_status_to_str(enum dc_status status)
266266
return "Fail dp payload allocation";
267267
case DC_FAIL_DP_LINK_BANDWIDTH:
268268
return "Insufficient DP link bandwidth";
269+
case DC_FAIL_HW_CURSOR_SUPPORT:
270+
return "HW Cursor not supported";
269271
case DC_ERROR_UNEXPECTED:
270272
return "Unexpected error";
271273
}

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

Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,32 +1342,6 @@ static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx)
13421342
data->viewport_c.y += src.y / vpc_div;
13431343
}
13441344

1345-
static bool is_subvp_high_refresh_candidate(struct dc_stream_state *stream)
1346-
{
1347-
uint32_t refresh_rate;
1348-
struct dc *dc = stream->ctx->dc;
1349-
1350-
refresh_rate = (stream->timing.pix_clk_100hz * (uint64_t)100 +
1351-
stream->timing.v_total * stream->timing.h_total - (uint64_t)1);
1352-
refresh_rate = div_u64(refresh_rate, stream->timing.v_total);
1353-
refresh_rate = div_u64(refresh_rate, stream->timing.h_total);
1354-
1355-
/* If there's any stream that fits the SubVP high refresh criteria,
1356-
* we must return true. This is because cursor updates are asynchronous
1357-
* with full updates, so we could transition into a SubVP config and
1358-
* remain in HW cursor mode if there's no cursor update which will
1359-
* then cause corruption.
1360-
*/
1361-
if ((refresh_rate >= 120 && refresh_rate <= 175 &&
1362-
stream->timing.v_addressable >= 1080 &&
1363-
stream->timing.v_addressable <= 2160) &&
1364-
(dc->current_state->stream_count > 1 ||
1365-
(dc->current_state->stream_count == 1 && !stream->allow_freesync)))
1366-
return true;
1367-
1368-
return false;
1369-
}
1370-
13711345
static enum controller_dp_test_pattern convert_dp_to_controller_test_pattern(
13721346
enum dp_test_pattern test_pattern)
13731347
{
@@ -4259,6 +4233,11 @@ enum dc_status dc_validate_with_context(struct dc *dc,
42594233
}
42604234
}
42614235

4236+
/* clear subvp cursor limitations */
4237+
for (i = 0; i < context->stream_count; i++) {
4238+
dc_state_set_stream_subvp_cursor_limit(context->streams[i], context, false);
4239+
}
4240+
42624241
res = dc_validate_global_state(dc, context, fast_validate);
42634242

42644243
/* calculate pixel rate divider after deciding pxiel clock & odm combine */
@@ -4385,8 +4364,7 @@ enum dc_status dc_validate_global_state(
43854364
result = resource_build_scaling_params_for_context(dc, new_ctx);
43864365

43874366
if (result == DC_OK)
4388-
if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate))
4389-
result = DC_FAIL_BANDWIDTH_VALIDATE;
4367+
result = dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate);
43904368

43914369
return result;
43924370
}
@@ -5538,20 +5516,6 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc,
55385516
return DC_OK;
55395517
}
55405518

5541-
bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_state *stream)
5542-
{
5543-
if (!dc->debug.disable_subvp_high_refresh && is_subvp_high_refresh_candidate(stream))
5544-
return true;
5545-
if (dc->current_state->stream_count == 1 && stream->timing.v_addressable >= 2880 &&
5546-
((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120)
5547-
return true;
5548-
else if (dc->current_state->stream_count > 1 && stream->timing.v_addressable >= 1080 &&
5549-
((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120)
5550-
return true;
5551-
5552-
return false;
5553-
}
5554-
55555519
struct dscl_prog_data *resource_get_dscl_prog_data(struct pipe_ctx *pipe_ctx)
55565520
{
55575521
return &pipe_ctx->plane_res.scl_data.dscl_prog_data;

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

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* Authors: AMD
2323
*
2424
*/
25+
#include "dc_types.h"
2526
#include "core_types.h"
2627
#include "core_status.h"
2728
#include "dc_state.h"
@@ -812,8 +813,12 @@ enum dc_status dc_state_add_phantom_stream(const struct dc *dc,
812813
if (phantom_stream_status) {
813814
phantom_stream_status->mall_stream_config.type = SUBVP_PHANTOM;
814815
phantom_stream_status->mall_stream_config.paired_stream = main_stream;
816+
phantom_stream_status->mall_stream_config.subvp_limit_cursor_size = false;
817+
phantom_stream_status->mall_stream_config.cursor_size_limit_subvp = false;
815818
}
816819

820+
dc_state_set_stream_subvp_cursor_limit(main_stream, state, true);
821+
817822
return res;
818823
}
819824

@@ -939,13 +944,20 @@ void dc_state_release_phantom_streams_and_planes(
939944
const struct dc *dc,
940945
struct dc_state *state)
941946
{
947+
unsigned int phantom_count;
948+
struct dc_stream_state *phantom_streams[MAX_PHANTOM_PIPES];
949+
struct dc_plane_state *phantom_planes[MAX_PHANTOM_PIPES];
942950
int i;
943951

944-
for (i = 0; i < state->phantom_stream_count; i++)
945-
dc_state_release_phantom_stream(dc, state, state->phantom_streams[i]);
952+
phantom_count = state->phantom_stream_count;
953+
memcpy(phantom_streams, state->phantom_streams, sizeof(struct dc_stream_state *) * MAX_PHANTOM_PIPES);
954+
for (i = 0; i < phantom_count; i++)
955+
dc_state_release_phantom_stream(dc, state, phantom_streams[i]);
946956

947-
for (i = 0; i < state->phantom_plane_count; i++)
948-
dc_state_release_phantom_plane(dc, state, state->phantom_planes[i]);
957+
phantom_count = state->phantom_plane_count;
958+
memcpy(phantom_planes, state->phantom_planes, sizeof(struct dc_plane_state *) * MAX_PHANTOM_PIPES);
959+
for (i = 0; i < phantom_count; i++)
960+
dc_state_release_phantom_plane(dc, state, phantom_planes[i]);
949961
}
950962

951963
struct dc_stream_state *dc_state_get_stream_from_id(const struct dc_state *state, unsigned int id)
@@ -977,3 +989,94 @@ bool dc_state_is_fams2_in_use(
977989

978990
return is_fams2_in_use;
979991
}
992+
993+
void dc_state_set_stream_subvp_cursor_limit(const struct dc_stream_state *stream,
994+
struct dc_state *state,
995+
bool limit)
996+
{
997+
struct dc_stream_status *stream_status;
998+
999+
stream_status = dc_state_get_stream_status(state, stream);
1000+
1001+
if (stream_status) {
1002+
stream_status->mall_stream_config.subvp_limit_cursor_size = limit;
1003+
}
1004+
}
1005+
1006+
bool dc_state_get_stream_subvp_cursor_limit(const struct dc_stream_state *stream,
1007+
struct dc_state *state)
1008+
{
1009+
bool limit = false;
1010+
1011+
struct dc_stream_status *stream_status;
1012+
1013+
stream_status = dc_state_get_stream_status(state, stream);
1014+
1015+
if (stream_status) {
1016+
limit = stream_status->mall_stream_config.subvp_limit_cursor_size;
1017+
}
1018+
1019+
return limit;
1020+
}
1021+
1022+
void dc_state_set_stream_cursor_subvp_limit(const struct dc_stream_state *stream,
1023+
struct dc_state *state,
1024+
bool limit)
1025+
{
1026+
struct dc_stream_status *stream_status;
1027+
1028+
stream_status = dc_state_get_stream_status(state, stream);
1029+
1030+
if (stream_status) {
1031+
stream_status->mall_stream_config.cursor_size_limit_subvp = limit;
1032+
}
1033+
}
1034+
1035+
bool dc_state_get_stream_cursor_subvp_limit(const struct dc_stream_state *stream,
1036+
struct dc_state *state)
1037+
{
1038+
bool limit = false;
1039+
1040+
struct dc_stream_status *stream_status;
1041+
1042+
stream_status = dc_state_get_stream_status(state, stream);
1043+
1044+
if (stream_status) {
1045+
limit = stream_status->mall_stream_config.cursor_size_limit_subvp;
1046+
}
1047+
1048+
return limit;
1049+
}
1050+
1051+
bool dc_state_can_clear_stream_cursor_subvp_limit(const struct dc_stream_state *stream,
1052+
struct dc_state *state)
1053+
{
1054+
bool can_clear_limit = false;
1055+
1056+
struct dc_stream_status *stream_status;
1057+
1058+
stream_status = dc_state_get_stream_status(state, stream);
1059+
1060+
if (stream_status) {
1061+
can_clear_limit = dc_state_get_stream_cursor_subvp_limit(stream, state) &&
1062+
(stream_status->mall_stream_config.type == SUBVP_PHANTOM ||
1063+
stream->hw_cursor_req ||
1064+
!stream_status->mall_stream_config.subvp_limit_cursor_size ||
1065+
!stream->cursor_position.enable ||
1066+
dc_stream_check_cursor_attributes(stream, state, &stream->cursor_attributes));
1067+
}
1068+
1069+
return can_clear_limit;
1070+
}
1071+
1072+
bool dc_state_is_subvp_in_use(struct dc_state *state)
1073+
{
1074+
uint32_t i;
1075+
1076+
for (i = 0; i < state->stream_count; i++) {
1077+
if (dc_state_get_stream_subvp_type(state, state->streams[i]) != SUBVP_NONE)
1078+
return true;
1079+
}
1080+
1081+
return false;
1082+
}

0 commit comments

Comments
 (0)