2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

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 <alvin.lee2@amd.com>
Signed-off-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com>
Tested-by: Mark Broadworth <mark.broadworth@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Dillon Varone 2025-04-01 12:06:35 -04:00 committed by Alex Deucher
parent 11772eb73b
commit 19e743f0fb
39 changed files with 400 additions and 129 deletions

View File

@ -37,6 +37,7 @@
#include "dc_state.h"
#include "dc_state_priv.h"
#include "dc_plane_priv.h"
#include "dc_stream_priv.h"
#include "gpio_service_interface.h"
#include "clk_mgr.h"
@ -2886,7 +2887,7 @@ static enum surface_update_type check_update_surfaces_for_stream(
int i;
enum surface_update_type overall_type = UPDATE_TYPE_FAST;
if (dc->idle_optimizations_allowed)
if (dc->idle_optimizations_allowed || dc_can_clear_cursor_limit(dc))
overall_type = UPDATE_TYPE_FULL;
if (stream_status == NULL || stream_status->plane_count != surface_count)
@ -3290,7 +3291,7 @@ static void copy_stream_update_to_stream(struct dc *dc,
if (dsc_validate_context) {
stream->timing.dsc_cfg = *update->dsc_config;
stream->timing.flags.DSC = enable_dsc;
if (!dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true)) {
if (dc->res_pool->funcs->validate_bandwidth(dc, dsc_validate_context, true) != DC_OK) {
stream->timing.dsc_cfg = old_dsc_cfg;
stream->timing.flags.DSC = old_dsc_enabled;
update->dsc_config = NULL;
@ -4608,7 +4609,7 @@ static struct dc_state *create_minimal_transition_state(struct dc *dc,
backup_and_set_minimal_pipe_split_policy(dc, base_context, policy);
/* commit minimal state */
if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false)) {
if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false) == DC_OK) {
/* prevent underflow and corruption when reconfiguring pipes */
force_vsync_flip_in_minimal_transition_context(minimal_transition_context);
} else {
@ -5128,7 +5129,7 @@ static bool update_planes_and_stream_v1(struct dc *dc,
copy_stream_update_to_stream(dc, context, stream, stream_update);
if (update_type >= UPDATE_TYPE_FULL) {
if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK) {
DC_ERROR("Mode validation failed for stream update!\n");
dc_state_release(context);
return false;
@ -6272,15 +6273,22 @@ bool dc_abm_save_restore(
void dc_query_current_properties(struct dc *dc, struct dc_current_properties *properties)
{
unsigned int i;
bool subvp_sw_cursor_req = false;
unsigned int max_cursor_size = dc->caps.max_cursor_size;
unsigned int stream_cursor_size;
for (i = 0; i < dc->current_state->stream_count; i++) {
if (check_subvp_sw_cursor_fallback_req(dc, dc->current_state->streams[i]) && !dc->current_state->streams[i]->hw_cursor_req) {
subvp_sw_cursor_req = true;
break;
if (dc->debug.allow_sw_cursor_fallback && dc->res_pool->funcs->get_max_hw_cursor_size) {
for (i = 0; i < dc->current_state->stream_count; i++) {
stream_cursor_size = dc->res_pool->funcs->get_max_hw_cursor_size(dc,
dc->current_state,
dc->current_state->streams[i]);
if (stream_cursor_size < max_cursor_size) {
max_cursor_size = stream_cursor_size;
}
}
}
properties->cursor_size_limit = subvp_sw_cursor_req ? 64 : dc->caps.max_cursor_size;
properties->cursor_size_limit = max_cursor_size;
}
/**
@ -6346,3 +6354,27 @@ unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context)
else
return 0;
}
bool dc_is_cursor_limit_pending(struct dc *dc)
{
uint32_t i;
for (i = 0; i < dc->current_state->stream_count; i++) {
if (dc_stream_is_cursor_limit_pending(dc, dc->current_state->streams[i]))
return true;
}
return false;
}
bool dc_can_clear_cursor_limit(struct dc *dc)
{
uint32_t i;
for (i = 0; i < dc->current_state->stream_count; i++) {
if (dc_state_can_clear_stream_cursor_subvp_limit(dc->current_state->streams[i], dc->current_state))
return true;
}
return false;
}

View File

@ -266,6 +266,8 @@ char *dc_status_to_str(enum dc_status status)
return "Fail dp payload allocation";
case DC_FAIL_DP_LINK_BANDWIDTH:
return "Insufficient DP link bandwidth";
case DC_FAIL_HW_CURSOR_SUPPORT:
return "HW Cursor not supported";
case DC_ERROR_UNEXPECTED:
return "Unexpected error";
}

View File

@ -1342,32 +1342,6 @@ static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx)
data->viewport_c.y += src.y / vpc_div;
}
static bool is_subvp_high_refresh_candidate(struct dc_stream_state *stream)
{
uint32_t refresh_rate;
struct dc *dc = stream->ctx->dc;
refresh_rate = (stream->timing.pix_clk_100hz * (uint64_t)100 +
stream->timing.v_total * stream->timing.h_total - (uint64_t)1);
refresh_rate = div_u64(refresh_rate, stream->timing.v_total);
refresh_rate = div_u64(refresh_rate, stream->timing.h_total);
/* If there's any stream that fits the SubVP high refresh criteria,
* we must return true. This is because cursor updates are asynchronous
* with full updates, so we could transition into a SubVP config and
* remain in HW cursor mode if there's no cursor update which will
* then cause corruption.
*/
if ((refresh_rate >= 120 && refresh_rate <= 175 &&
stream->timing.v_addressable >= 1080 &&
stream->timing.v_addressable <= 2160) &&
(dc->current_state->stream_count > 1 ||
(dc->current_state->stream_count == 1 && !stream->allow_freesync)))
return true;
return false;
}
static enum controller_dp_test_pattern convert_dp_to_controller_test_pattern(
enum dp_test_pattern test_pattern)
{
@ -4259,6 +4233,11 @@ enum dc_status dc_validate_with_context(struct dc *dc,
}
}
/* clear subvp cursor limitations */
for (i = 0; i < context->stream_count; i++) {
dc_state_set_stream_subvp_cursor_limit(context->streams[i], context, false);
}
res = dc_validate_global_state(dc, context, fast_validate);
/* calculate pixel rate divider after deciding pxiel clock & odm combine */
@ -4385,8 +4364,7 @@ enum dc_status dc_validate_global_state(
result = resource_build_scaling_params_for_context(dc, new_ctx);
if (result == DC_OK)
if (!dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate))
result = DC_FAIL_BANDWIDTH_VALIDATE;
result = dc->res_pool->funcs->validate_bandwidth(dc, new_ctx, fast_validate);
return result;
}
@ -5538,20 +5516,6 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc,
return DC_OK;
}
bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_state *stream)
{
if (!dc->debug.disable_subvp_high_refresh && is_subvp_high_refresh_candidate(stream))
return true;
if (dc->current_state->stream_count == 1 && stream->timing.v_addressable >= 2880 &&
((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120)
return true;
else if (dc->current_state->stream_count > 1 && stream->timing.v_addressable >= 1080 &&
((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120)
return true;
return false;
}
struct dscl_prog_data *resource_get_dscl_prog_data(struct pipe_ctx *pipe_ctx)
{
return &pipe_ctx->plane_res.scl_data.dscl_prog_data;

View File

@ -22,6 +22,7 @@
* Authors: AMD
*
*/
#include "dc_types.h"
#include "core_types.h"
#include "core_status.h"
#include "dc_state.h"
@ -812,8 +813,12 @@ enum dc_status dc_state_add_phantom_stream(const struct dc *dc,
if (phantom_stream_status) {
phantom_stream_status->mall_stream_config.type = SUBVP_PHANTOM;
phantom_stream_status->mall_stream_config.paired_stream = main_stream;
phantom_stream_status->mall_stream_config.subvp_limit_cursor_size = false;
phantom_stream_status->mall_stream_config.cursor_size_limit_subvp = false;
}
dc_state_set_stream_subvp_cursor_limit(main_stream, state, true);
return res;
}
@ -977,3 +982,94 @@ bool dc_state_is_fams2_in_use(
return is_fams2_in_use;
}
void dc_state_set_stream_subvp_cursor_limit(const struct dc_stream_state *stream,
struct dc_state *state,
bool limit)
{
struct dc_stream_status *stream_status;
stream_status = dc_state_get_stream_status(state, stream);
if (stream_status) {
stream_status->mall_stream_config.subvp_limit_cursor_size = limit;
}
}
bool dc_state_get_stream_subvp_cursor_limit(const struct dc_stream_state *stream,
struct dc_state *state)
{
bool limit = false;
struct dc_stream_status *stream_status;
stream_status = dc_state_get_stream_status(state, stream);
if (stream_status) {
limit = stream_status->mall_stream_config.subvp_limit_cursor_size;
}
return limit;
}
void dc_state_set_stream_cursor_subvp_limit(const struct dc_stream_state *stream,
struct dc_state *state,
bool limit)
{
struct dc_stream_status *stream_status;
stream_status = dc_state_get_stream_status(state, stream);
if (stream_status) {
stream_status->mall_stream_config.cursor_size_limit_subvp = limit;
}
}
bool dc_state_get_stream_cursor_subvp_limit(const struct dc_stream_state *stream,
struct dc_state *state)
{
bool limit = false;
struct dc_stream_status *stream_status;
stream_status = dc_state_get_stream_status(state, stream);
if (stream_status) {
limit = stream_status->mall_stream_config.cursor_size_limit_subvp;
}
return limit;
}
bool dc_state_can_clear_stream_cursor_subvp_limit(const struct dc_stream_state *stream,
struct dc_state *state)
{
bool can_clear_limit = false;
struct dc_stream_status *stream_status;
stream_status = dc_state_get_stream_status(state, stream);
if (stream_status) {
can_clear_limit = dc_state_get_stream_cursor_subvp_limit(stream, state) &&
(stream_status->mall_stream_config.type == SUBVP_PHANTOM ||
stream->hw_cursor_req ||
!stream_status->mall_stream_config.subvp_limit_cursor_size ||
!stream->cursor_position.enable ||
dc_stream_check_cursor_attributes(stream, state, &stream->cursor_attributes));
}
return can_clear_limit;
}
bool dc_state_is_subvp_in_use(struct dc_state *state)
{
uint32_t i;
for (i = 0; i < state->stream_count; i++) {
if (dc_state_get_stream_subvp_type(state, state->streams[i]) != SUBVP_NONE)
return true;
}
return false;
}

View File

@ -265,13 +265,16 @@ void program_cursor_attributes(
}
/*
* dc_stream_set_cursor_attributes() - Update cursor attributes and set cursor surface address
* dc_stream_check_cursor_attributes() - Check validitity of cursor attributes and surface address
*/
bool dc_stream_set_cursor_attributes(
struct dc_stream_state *stream,
bool dc_stream_check_cursor_attributes(
const struct dc_stream_state *stream,
struct dc_state *state,
const struct dc_cursor_attributes *attributes)
{
struct dc *dc;
const struct dc *dc;
unsigned int max_cursor_size;
if (NULL == stream) {
dm_error("DC: dc_stream is NULL!\n");
@ -289,24 +292,38 @@ bool dc_stream_set_cursor_attributes(
dc = stream->ctx->dc;
/* SubVP is not compatible with HW cursor larger than 64 x 64 x 4.
* Therefore, if cursor is greater than 64 x 64 x 4, fallback to SW cursor in the following case:
* 1. If the config is a candidate for SubVP high refresh (both single an dual display configs)
* 2. If not subvp high refresh, for single display cases, if resolution is >= 5K and refresh rate < 120hz
* 3. If not subvp high refresh, for multi display cases, if resolution is >= 4K and refresh rate < 120hz
/* SubVP is not compatible with HW cursor larger than what can fit in cursor SRAM.
* Therefore, if cursor is greater than this, fallback to SW cursor.
*/
if (dc->debug.allow_sw_cursor_fallback &&
attributes->height * attributes->width * 4 > 16384 &&
!stream->hw_cursor_req) {
if (check_subvp_sw_cursor_fallback_req(dc, stream))
if (dc->debug.allow_sw_cursor_fallback && dc->res_pool->funcs->get_max_hw_cursor_size) {
max_cursor_size = dc->res_pool->funcs->get_max_hw_cursor_size(dc, state, stream);
max_cursor_size = max_cursor_size * max_cursor_size * 4;
if (attributes->height * attributes->width * 4 > max_cursor_size) {
return false;
}
}
stream->cursor_attributes = *attributes;
return true;
}
/*
* dc_stream_set_cursor_attributes() - Update cursor attributes and set cursor surface address
*/
bool dc_stream_set_cursor_attributes(
struct dc_stream_state *stream,
const struct dc_cursor_attributes *attributes)
{
bool result = false;
if (dc_stream_check_cursor_attributes(stream, stream->ctx->dc->current_state, attributes)) {
stream->cursor_attributes = *attributes;
result = true;
}
return result;
}
bool dc_stream_program_cursor_attributes(
struct dc_stream_state *stream,
const struct dc_cursor_attributes *attributes)
@ -1109,3 +1126,26 @@ unsigned int dc_stream_get_max_flickerless_instant_vtotal_increase(struct dc_str
return dc_stream_get_max_flickerless_instant_vtotal_delta(stream, is_gaming, false);
}
bool dc_stream_is_cursor_limit_pending(struct dc *dc, struct dc_stream_state *stream)
{
bool is_limit_pending = false;
if (dc->current_state)
is_limit_pending = dc_state_get_stream_cursor_subvp_limit(stream, dc->current_state);
return is_limit_pending;
}
bool dc_stream_can_clear_cursor_limit(struct dc *dc, struct dc_stream_state *stream)
{
bool can_clear_limit = false;
if (dc->current_state)
can_clear_limit = dc_state_get_stream_cursor_subvp_limit(stream, dc->current_state) &&
(stream->hw_cursor_req ||
!stream->cursor_position.enable ||
dc_stream_check_cursor_attributes(stream, dc->current_state, &stream->cursor_attributes));
return can_clear_limit;
}

View File

@ -249,6 +249,7 @@ struct dc_caps {
uint32_t i2c_speed_in_khz_hdcp;
uint32_t dmdata_alloc_size;
unsigned int max_cursor_size;
unsigned int max_buffered_cursor_size;
unsigned int max_video_width;
/*
* max video plane width that can be safely assumed to be always
@ -2607,4 +2608,7 @@ void dc_disable_accelerated_mode(struct dc *dc);
bool dc_is_timing_changed(struct dc_stream_state *cur_stream,
struct dc_stream_state *new_stream);
bool dc_is_cursor_limit_pending(struct dc *dc);
bool dc_can_clear_cursor_limit(struct dc *dc);
#endif /* DC_INTERFACE_H_ */

View File

@ -105,4 +105,24 @@ bool dc_state_is_fams2_in_use(
const struct dc *dc,
const struct dc_state *state);
void dc_state_set_stream_subvp_cursor_limit(const struct dc_stream_state *stream,
struct dc_state *state,
bool limit);
bool dc_state_get_stream_subvp_cursor_limit(const struct dc_stream_state *stream,
struct dc_state *state);
void dc_state_set_stream_cursor_subvp_limit(const struct dc_stream_state *stream,
struct dc_state *state,
bool limit);
bool dc_state_get_stream_cursor_subvp_limit(const struct dc_stream_state *stream,
struct dc_state *state);
bool dc_state_can_clear_stream_cursor_subvp_limit(const struct dc_stream_state *stream,
struct dc_state *state);
bool dc_state_is_subvp_in_use(struct dc_state *state);
#endif /* _DC_STATE_PRIV_H_ */

View File

@ -44,6 +44,8 @@ struct mall_stream_config {
*/
enum mall_stream_type type;
struct dc_stream_state *paired_stream; // master / slave stream
bool subvp_limit_cursor_size; /* stream has/is using subvp limiting hw cursor support */
bool cursor_size_limit_subvp; /* stream is using hw cursor config preventing subvp */
};
struct dc_stream_status {
@ -503,6 +505,11 @@ void program_cursor_position(
struct dc *dc,
struct dc_stream_state *stream);
bool dc_stream_check_cursor_attributes(
const struct dc_stream_state *stream,
struct dc_state *state,
const struct dc_cursor_attributes *attributes);
bool dc_stream_set_cursor_attributes(
struct dc_stream_state *stream,
const struct dc_cursor_attributes *attributes);
@ -579,4 +586,8 @@ void dc_dmub_update_dirty_rect(struct dc *dc,
struct dc_stream_state *stream,
struct dc_surface_update *srf_updates,
struct dc_state *context);
bool dc_stream_is_cursor_limit_pending(struct dc *dc, struct dc_stream_state *stream);
bool dc_stream_can_clear_cursor_limit(struct dc *dc, struct dc_stream_state *stream);
#endif /* DC_STREAM_H_ */

View File

@ -627,6 +627,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
*/
if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && !dcn32_is_center_timing(pipe) &&
!pipe->stream->hw_cursor_req &&
!dc_state_get_stream_cursor_subvp_limit(pipe->stream, context) &&
!(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) &&
(!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) &&
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE &&

View File

@ -526,7 +526,8 @@ static void populate_dml21_output_config_from_stream_state(struct dml2_link_outp
static void populate_dml21_stream_overrides_from_stream_state(
struct dml2_stream_parameters *stream_desc,
struct dc_stream_state *stream)
struct dc_stream_state *stream,
struct dc_stream_status *stream_status)
{
switch (stream->debug.force_odm_combine_segments) {
case 0:
@ -551,7 +552,9 @@ static void populate_dml21_stream_overrides_from_stream_state(
if (!stream->ctx->dc->debug.enable_single_display_2to1_odm_policy ||
stream->debug.force_odm_combine_segments > 0)
stream_desc->overrides.disable_dynamic_odm = true;
stream_desc->overrides.disable_subvp = stream->ctx->dc->debug.force_disable_subvp || stream->hw_cursor_req;
stream_desc->overrides.disable_subvp = stream->ctx->dc->debug.force_disable_subvp ||
stream->hw_cursor_req ||
stream_status->mall_stream_config.cursor_size_limit_subvp;
}
static enum dml2_swizzle_mode gfx_addr3_to_dml2_swizzle_mode(enum swizzle_mode_addr3_values addr3_mode)
@ -1024,7 +1027,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s
populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], dml_ctx);
adjust_dml21_hblank_timing_config_from_pipe_ctx(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, &context->res_ctx.pipe_ctx[stream_index]);
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]);
populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location], context->streams[stream_index]);
populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location], context->streams[stream_index], &context->stream_status[stream_index]);
dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.fclk_pstate = dml2_twait_budgeting_setting_if_needed;
dml_dispcfg->stream_descriptors[disp_cfg_stream_location].overrides.hw.twait_budgeting.uclk_pstate = dml2_twait_budgeting_setting_if_needed;

View File

@ -2482,7 +2482,7 @@ bool dcn20_update_bandwidth(
struct dce_hwseq *hws = dc->hwseq;
/* recalculate DML parameters */
if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false))
if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK)
return false;
/* apply updated bandwidth parameters */

View File

@ -2650,7 +2650,7 @@ bool dcn401_update_bandwidth(
struct dce_hwseq *hws = dc->hwseq;
/* recalculate DML parameters */
if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false))
if (dc->res_pool->funcs->validate_bandwidth(dc, context, false) != DC_OK)
return false;
/* apply updated bandwidth parameters */

View File

@ -26,6 +26,8 @@
#ifndef _CORE_STATUS_H_
#define _CORE_STATUS_H_
#include "dc_hw_types.h"
enum dc_status {
DC_OK = 1,
@ -56,6 +58,7 @@ enum dc_status {
DC_NO_LINK_ENC_RESOURCE = 26,
DC_FAIL_DP_PAYLOAD_ALLOCATION = 27,
DC_FAIL_DP_LINK_BANDWIDTH = 28,
DC_FAIL_HW_CURSOR_SUPPORT = 29,
DC_ERROR_UNEXPECTED = -1
};

View File

@ -79,7 +79,7 @@ struct resource_funcs {
* associated with it. */
struct link_encoder *(*link_enc_create_minimal)(struct dc_context *ctx, enum engine_id eng_id);
bool (*validate_bandwidth)(
enum dc_status (*validate_bandwidth)(
struct dc *dc,
struct dc_state *context,
bool fast_validate);
@ -218,6 +218,9 @@ struct resource_funcs {
int (*get_power_profile)(const struct dc_state *context);
unsigned int (*get_det_buffer_size)(const struct dc_state *context);
unsigned int (*get_vstartup_for_pipe)(struct pipe_ctx *pipe_ctx);
unsigned int (*get_max_hw_cursor_size)(const struct dc *dc,
struct dc_state *state,
const struct dc_stream_state *stream);
};
struct audio_support{

View File

@ -628,8 +628,6 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc,
struct dc_state *context,
struct pipe_ctx *pipe_ctx);
bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_state *stream);
/* Get hw programming parameters container from pipe context
* @pipe_ctx: pipe context
* @dscl_prog_data: struct to hold programmable hw reg values

View File

@ -836,7 +836,7 @@ static enum dc_status build_mapped_resource(
return DC_OK;
}
static bool dce100_validate_bandwidth(
static enum dc_status dce100_validate_bandwidth(
struct dc *dc,
struct dc_state *context,
bool fast_validate)
@ -858,7 +858,7 @@ static bool dce100_validate_bandwidth(
context->bw_ctx.bw.dce.yclk_khz = 0;
}
return true;
return DC_OK;
}
static bool dce100_validate_surface_sets(

View File

@ -960,7 +960,7 @@ static enum dc_status build_mapped_resource(
return DC_OK;
}
static bool dce110_validate_bandwidth(
static enum dc_status dce110_validate_bandwidth(
struct dc *dc,
struct dc_state *context,
bool fast_validate)
@ -1031,7 +1031,7 @@ static bool dce110_validate_bandwidth(
context->bw_ctx.bw.dce.yclk_khz,
context->bw_ctx.bw.dce.blackout_recovery_time_us);
}
return result;
return result ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
static enum dc_status dce110_validate_plane(const struct dc_plane_state *plane_state,

View File

@ -883,7 +883,7 @@ static enum dc_status build_mapped_resource(
return DC_OK;
}
bool dce112_validate_bandwidth(
enum dc_status dce112_validate_bandwidth(
struct dc *dc,
struct dc_state *context,
bool fast_validate)
@ -952,7 +952,7 @@ bool dce112_validate_bandwidth(
context->bw_ctx.bw.dce.yclk_khz,
context->bw_ctx.bw.dce.blackout_recovery_time_us);
}
return result;
return result ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
enum dc_status resource_map_phy_clock_resources(

View File

@ -42,7 +42,7 @@ enum dc_status dce112_validate_with_context(
struct dc_state *context,
struct dc_state *old_context);
bool dce112_validate_bandwidth(
enum dc_status dce112_validate_bandwidth(
struct dc *dc,
struct dc_state *context,
bool fast_validate);

View File

@ -863,7 +863,7 @@ static void dce60_resource_destruct(struct dce110_resource_pool *pool)
}
}
static bool dce60_validate_bandwidth(
static enum dc_status dce60_validate_bandwidth(
struct dc *dc,
struct dc_state *context,
bool fast_validate)
@ -885,7 +885,7 @@ static bool dce60_validate_bandwidth(
context->bw_ctx.bw.dce.yclk_khz = 0;
}
return true;
return DC_OK;
}
static bool dce60_validate_surface_sets(

View File

@ -869,7 +869,7 @@ static void dce80_resource_destruct(struct dce110_resource_pool *pool)
}
}
static bool dce80_validate_bandwidth(
static enum dc_status dce80_validate_bandwidth(
struct dc *dc,
struct dc_state *context,
bool fast_validate)
@ -891,7 +891,7 @@ static bool dce80_validate_bandwidth(
context->bw_ctx.bw.dce.yclk_khz = 0;
}
return true;
return DC_OK;
}
static bool dce80_validate_surface_sets(

View File

@ -23,6 +23,7 @@
*
*/
#include "core_status.h"
#include "dm_services.h"
#include "dc.h"
@ -1125,7 +1126,7 @@ static void dcn10_destroy_resource_pool(struct resource_pool **pool)
*pool = NULL;
}
static bool dcn10_validate_bandwidth(
static enum dc_status dcn10_validate_bandwidth(
struct dc *dc,
struct dc_state *context,
bool fast_validate)
@ -1136,7 +1137,7 @@ static bool dcn10_validate_bandwidth(
voltage_supported = dcn_validate_bandwidth(dc, context, fast_validate);
DC_FP_END();
return voltage_supported;
return voltage_supported ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
static enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps)

View File

@ -2124,7 +2124,7 @@ validate_out:
return out;
}
bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
enum dc_status dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
bool fast_validate)
{
bool voltage_supported;
@ -2132,14 +2132,14 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
if (!pipes)
return false;
return DC_FAIL_BANDWIDTH_VALIDATE;
DC_FP_START();
voltage_supported = dcn20_validate_bandwidth_fp(dc, context, fast_validate, pipes);
DC_FP_END();
kfree(pipes);
return voltage_supported;
return voltage_supported ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
struct pipe_ctx *dcn20_acquire_free_pipe_for_layer(

View File

@ -119,7 +119,7 @@ void dcn20_set_mcif_arb_params(
struct dc_state *context,
display_e2e_pipe_params_st *pipes,
int pipe_cnt);
bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate);
enum dc_status dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate);
void dcn20_merge_pipes_for_validate(
struct dc *dc,
struct dc_state *context);

View File

@ -923,7 +923,7 @@ validate_out:
* with DC_FP_START()/DC_FP_END(). Use the same approach as for
* dcn20_validate_bandwidth in dcn20_resource.c.
*/
static bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context,
static enum dc_status dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context,
bool fast_validate)
{
bool voltage_supported;
@ -931,14 +931,14 @@ static bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context,
pipes = kcalloc(dc->res_pool->pipe_count, sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
if (!pipes)
return false;
return DC_FAIL_BANDWIDTH_VALIDATE;
DC_FP_START();
voltage_supported = dcn21_validate_bandwidth_fp(dc, context, fast_validate, pipes);
DC_FP_END();
kfree(pipes);
return voltage_supported;
return voltage_supported ? DC_OK : DC_NOT_SUPPORTED;
}
static void dcn21_destroy_resource_pool(struct resource_pool **pool)

View File

@ -2035,7 +2035,7 @@ void dcn30_calculate_wm_and_dlg(
DC_FP_END();
}
bool dcn30_validate_bandwidth(struct dc *dc,
enum dc_status dcn30_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate)
{
@ -2092,7 +2092,7 @@ validate_out:
BW_VAL_TRACE_FINISH();
return out;
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)

View File

@ -56,7 +56,7 @@ unsigned int dcn30_calc_max_scaled_time(
enum mmhubbub_wbif_mode mode,
unsigned int urgent_watermark);
bool dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context,
enum dc_status dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context,
bool fast_validate);
bool dcn30_internal_validate_bw(
struct dc *dc,

View File

@ -1758,7 +1758,7 @@ dcn31_set_mcif_arb_params(struct dc *dc,
DC_FP_END();
}
bool dcn31_validate_bandwidth(struct dc *dc,
enum dc_status dcn31_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate)
{
@ -1813,7 +1813,7 @@ validate_out:
BW_VAL_TRACE_FINISH();
return out;
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
static void dcn31_get_panel_config_defaults(struct dc_panel_config *panel_config)

View File

@ -37,7 +37,7 @@ struct dcn31_resource_pool {
struct resource_pool base;
};
bool dcn31_validate_bandwidth(struct dc *dc,
enum dc_status dcn31_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate);
void dcn31_calculate_wm_and_dlg(

View File

@ -1694,7 +1694,7 @@ static void dcn314_get_panel_config_defaults(struct dc_panel_config *panel_confi
*panel_config = panel_config_defaults;
}
bool dcn314_validate_bandwidth(struct dc *dc,
enum dc_status dcn314_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate)
{
@ -1750,7 +1750,7 @@ validate_out:
BW_VAL_TRACE_FINISH();
return out;
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
static struct resource_funcs dcn314_res_pool_funcs = {

View File

@ -39,7 +39,7 @@ struct dcn314_resource_pool {
struct resource_pool base;
};
bool dcn314_validate_bandwidth(struct dc *dc,
enum dc_status dcn314_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate);

View File

@ -24,6 +24,7 @@
*
*/
#include "dc_types.h"
#include "dm_services.h"
#include "dc.h"
@ -1806,19 +1807,56 @@ validate_out:
return out;
}
bool dcn32_validate_bandwidth(struct dc *dc,
enum dc_status dcn32_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate)
{
bool out = false;
unsigned int i;
enum dc_status status;
const struct dc_stream_state *stream;
/* reset cursor limitations on subvp */
for (i = 0; i < context->stream_count; i++) {
stream = context->streams[i];
if (dc_state_can_clear_stream_cursor_subvp_limit(stream, context)) {
dc_state_set_stream_cursor_subvp_limit(stream, context, false);
}
}
if (dc->debug.using_dml2)
out = dml2_validate(dc, context,
status = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
fast_validate);
fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
else
out = dml1_validate(dc, context, fast_validate);
return out;
status = dml1_validate(dc, context, fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
if (!fast_validate && status == DC_OK && dc_state_is_subvp_in_use(context)) {
/* check new stream configuration still supports cursor if subvp used */
for (i = 0; i < context->stream_count; i++) {
stream = context->streams[i];
if (dc_state_get_stream_subvp_type(context, stream) != SUBVP_PHANTOM &&
stream->cursor_position.enable &&
!dc_stream_check_cursor_attributes(stream, context, &stream->cursor_attributes)) {
/* hw cursor cannot be supported with subvp active, so disable subvp for now */
dc_state_set_stream_cursor_subvp_limit(stream, context, true);
status = DC_FAIL_HW_CURSOR_SUPPORT;
}
};
}
if (!fast_validate && status == DC_FAIL_HW_CURSOR_SUPPORT) {
/* attempt to validate again with subvp disabled due to cursor */
if (dc->debug.using_dml2)
status = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
else
status = dml1_validate(dc, context, fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
return status;
}
int dcn32_populate_dml_pipes_from_context(
@ -2042,6 +2080,18 @@ static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw
DC_FP_END();
}
unsigned int dcn32_get_max_hw_cursor_size(const struct dc *dc,
struct dc_state *state,
const struct dc_stream_state *stream)
{
bool limit_cur_to_buf;
limit_cur_to_buf = dc_state_get_stream_subvp_cursor_limit(stream, state) &&
!stream->hw_cursor_req;
return limit_cur_to_buf ? dc->caps.max_buffered_cursor_size : dc->caps.max_cursor_size;
}
static struct resource_funcs dcn32_res_pool_funcs = {
.destroy = dcn32_destroy_resource_pool,
.link_enc_create = dcn32_link_encoder_create,
@ -2067,7 +2117,8 @@ static struct resource_funcs dcn32_res_pool_funcs = {
.add_phantom_pipes = dcn32_add_phantom_pipes,
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size,
};
static uint32_t read_pipe_fuses(struct dc_context *ctx)

View File

@ -98,7 +98,7 @@ void dcn32_add_phantom_pipes(struct dc *dc,
unsigned int pipe_cnt,
unsigned int index);
bool dcn32_validate_bandwidth(struct dc *dc,
enum dc_status dcn32_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate);
@ -188,6 +188,10 @@ void dcn32_override_min_req_dcfclk(struct dc *dc, struct dc_state *context);
unsigned int dcn32_calculate_mall_ways_from_bytes(const struct dc *dc, unsigned int total_size_in_mall_bytes);
unsigned int dcn32_get_max_hw_cursor_size(const struct dc *dc,
struct dc_state *state,
const struct dc_stream_state *stream);
/* definitions for run time init of reg offsets */
/* CLK SRC */

View File

@ -1624,7 +1624,8 @@ static struct resource_funcs dcn321_res_pool_funcs = {
.add_phantom_pipes = dcn32_add_phantom_pipes,
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size,
};
static uint32_t read_pipe_fuses(struct dc_context *ctx)

View File

@ -1732,7 +1732,7 @@ static void dcn35_get_panel_config_defaults(struct dc_panel_config *panel_config
}
static bool dcn35_validate_bandwidth(struct dc *dc,
static enum dc_status dcn35_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate)
{
@ -1743,13 +1743,13 @@ static bool dcn35_validate_bandwidth(struct dc *dc,
fast_validate);
if (fast_validate)
return out;
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
DC_FP_START();
dcn35_decide_zstate_support(dc, context);
DC_FP_END();
return out;
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
enum dc_status dcn35_patch_unknown_plane_state(struct dc_plane_state *plane_state)

View File

@ -1712,7 +1712,7 @@ static void dcn35_get_panel_config_defaults(struct dc_panel_config *panel_config
}
static bool dcn351_validate_bandwidth(struct dc *dc,
static enum dc_status dcn351_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate)
{
@ -1723,13 +1723,13 @@ static bool dcn351_validate_bandwidth(struct dc *dc,
fast_validate);
if (fast_validate)
return out;
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
DC_FP_START();
dcn35_decide_zstate_support(dc, context);
DC_FP_END();
return out;
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
static struct resource_funcs dcn351_res_pool_funcs = {

View File

@ -1713,7 +1713,7 @@ static void dcn35_get_panel_config_defaults(struct dc_panel_config *panel_config
}
static bool dcn35_validate_bandwidth(struct dc *dc,
static enum dc_status dcn35_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate)
{
@ -1724,13 +1724,13 @@ static bool dcn35_validate_bandwidth(struct dc *dc,
fast_validate);
if (fast_validate)
return out;
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
DC_FP_START();
dcn35_decide_zstate_support(dc, context);
DC_FP_END();
return out;
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}

View File

@ -1642,16 +1642,52 @@ enum dc_status dcn401_patch_unknown_plane_state(struct dc_plane_state *plane_sta
return DC_OK;
}
bool dcn401_validate_bandwidth(struct dc *dc,
enum dc_status dcn401_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate)
{
bool out = false;
unsigned int i;
enum dc_status status = DC_OK;
const struct dc_stream_state *stream;
/* reset cursor limitations on subvp */
for (i = 0; i < context->stream_count; i++) {
stream = context->streams[i];
if (dc_state_can_clear_stream_cursor_subvp_limit(stream, context)) {
dc_state_set_stream_cursor_subvp_limit(stream, context, false);
}
}
if (dc->debug.using_dml2)
out = dml2_validate(dc, context,
status = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
fast_validate);
return out;
fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
if (!fast_validate && status == DC_OK && dc_state_is_subvp_in_use(context)) {
/* check new stream configuration still supports cursor if subvp used */
for (i = 0; i < context->stream_count; i++) {
stream = context->streams[i];
if (dc_state_get_stream_subvp_type(context, stream) != SUBVP_PHANTOM &&
stream->cursor_position.enable &&
!dc_stream_check_cursor_attributes(stream, context, &stream->cursor_attributes)) {
/* hw cursor cannot be supported with subvp active, so disable subvp for now */
dc_state_set_stream_cursor_subvp_limit(stream, context, true);
status = DC_FAIL_HW_CURSOR_SUPPORT;
}
};
}
if (!fast_validate && status == DC_FAIL_HW_CURSOR_SUPPORT) {
/* attempt to validate again with subvp disabled due to cursor */
if (dc->debug.using_dml2)
status = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
fast_validate) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
}
return status;
}
void dcn401_prepare_mcache_programming(struct dc *dc,
@ -1770,7 +1806,8 @@ static struct resource_funcs dcn401_res_pool_funcs = {
.build_pipe_pix_clk_params = dcn401_build_pipe_pix_clk_params,
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
.get_power_profile = dcn401_get_power_profile,
.get_vstartup_for_pipe = dcn401_get_vstartup_for_pipe
.get_vstartup_for_pipe = dcn401_get_vstartup_for_pipe,
.get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size
};
static uint32_t read_pipe_fuses(struct dc_context *ctx)

View File

@ -22,7 +22,7 @@ struct resource_pool *dcn401_create_resource_pool(
enum dc_status dcn401_patch_unknown_plane_state(struct dc_plane_state *plane_state);
bool dcn401_validate_bandwidth(struct dc *dc,
enum dc_status dcn401_validate_bandwidth(struct dc *dc,
struct dc_state *context,
bool fast_validate);