drm/amd/display: Refactor phantom resource allocation
[WHY?] Phantom streams and planes were previously not referenced explcitly on creation. [HOW?] To reduce memory management complexity, add an additional phantom streams and planes reference into dc_state, and move mall_stream_config to stream_status inside the state to make it safe to modify in shallow copies. Also consildates any logic that is affected by this change to dc_state. Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Reviewed-by: Jun Lei <jun.lei@amd.com> Acked-by: Wayne Lin <wayne.lin@amd.com> Signed-off-by: Dillon Varone <dillon.varone@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
09a4ec5da9
commit
012a04b1d6
33 changed files with 583 additions and 554 deletions
|
@ -2608,12 +2608,10 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc)
|
|||
|
||||
memset(del_streams, 0, sizeof(del_streams));
|
||||
|
||||
context = dc_state_create(dc);
|
||||
context = dc_state_create_current_copy(dc);
|
||||
if (context == NULL)
|
||||
goto context_alloc_fail;
|
||||
|
||||
dc_resource_state_copy_construct_current(dc, context);
|
||||
|
||||
/* First remove from context all streams */
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
struct dc_stream_state *stream = context->streams[i];
|
||||
|
@ -2923,7 +2921,6 @@ static int dm_resume(void *handle)
|
|||
dc_state_release(dm_state->context);
|
||||
dm_state->context = dc_state_create(dm->dc);
|
||||
/* TODO: Remove dc_state->dccg, use dc->dccg directly. */
|
||||
dc_resource_state_construct(dm->dc, dm_state->context);
|
||||
|
||||
/* Before powering on DC we need to re-initialize DMUB. */
|
||||
dm_dmub_hw_resume(adev);
|
||||
|
@ -4051,14 +4048,12 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
|
|||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->context = dc_state_create(adev->dm.dc);
|
||||
state->context = dc_state_create_current_copy(adev->dm.dc);
|
||||
if (!state->context) {
|
||||
kfree(state);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dc_resource_state_copy_construct_current(adev->dm.dc, state->context);
|
||||
|
||||
drm_atomic_private_obj_init(adev_to_drm(adev),
|
||||
&adev->dm.atomic_obj,
|
||||
&state->base,
|
||||
|
|
|
@ -1046,8 +1046,6 @@ static bool dc_construct(struct dc *dc,
|
|||
if (!create_link_encoders(dc))
|
||||
goto fail;
|
||||
|
||||
dc_resource_state_construct(dc, dc->current_state);
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
|
@ -1120,7 +1118,7 @@ static void dc_update_viusal_confirm_color(struct dc *dc, struct dc_state *conte
|
|||
static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
||||
{
|
||||
int i, j;
|
||||
struct dc_state *dangling_context = dc_state_create(dc);
|
||||
struct dc_state *dangling_context = dc_state_create_current_copy(dc);
|
||||
struct dc_state *current_ctx;
|
||||
struct pipe_ctx *pipe;
|
||||
struct timing_generator *tg;
|
||||
|
@ -1128,8 +1126,6 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
|||
if (dangling_context == NULL)
|
||||
return;
|
||||
|
||||
dc_resource_state_copy_construct(dc->current_state, dangling_context);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct dc_stream_state *old_stream =
|
||||
dc->current_state->res_ctx.pipe_ctx[i].stream;
|
||||
|
@ -1187,6 +1183,10 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
|
|||
tg->funcs->enable_crtc(tg);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_phantom)
|
||||
dc_state_rem_all_phantom_planes_for_stream(dc, old_stream, dangling_context, true);
|
||||
else
|
||||
dc_state_rem_all_planes_for_stream(dc, old_stream, dangling_context);
|
||||
disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
|
||||
|
||||
|
@ -1562,7 +1562,7 @@ static void program_timing_sync(
|
|||
if (group_size > 1) {
|
||||
if (sync_type == TIMING_SYNCHRONIZABLE) {
|
||||
dc->hwss.enable_timing_synchronization(
|
||||
dc, group_index, group_size, pipe_set);
|
||||
dc, ctx, group_index, group_size, pipe_set);
|
||||
} else
|
||||
if (sync_type == VBLANK_SYNCHRONIZABLE) {
|
||||
dc->hwss.enable_vblanks_synchronization(
|
||||
|
@ -2075,12 +2075,10 @@ enum dc_status dc_commit_streams(struct dc *dc,
|
|||
if (handle_exit_odm2to1)
|
||||
res = commit_minimal_transition_state(dc, dc->current_state);
|
||||
|
||||
context = dc_state_create(dc);
|
||||
context = dc_state_create_current_copy(dc);
|
||||
if (!context)
|
||||
goto context_alloc_fail;
|
||||
|
||||
dc_resource_state_copy_construct_current(dc, context);
|
||||
|
||||
res = dc_validate_with_context(dc, set, stream_count, context, false);
|
||||
if (res != DC_OK) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
|
@ -2218,7 +2216,7 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
|
|||
if (context->res_ctx.pipe_ctx[i].stream == NULL ||
|
||||
context->res_ctx.pipe_ctx[i].plane_state == NULL) {
|
||||
context->res_ctx.pipe_ctx[i].pipe_idx = i;
|
||||
dc->hwss.disable_plane(dc, &context->res_ctx.pipe_ctx[i]);
|
||||
dc->hwss.disable_plane(dc, context, &context->res_ctx.pipe_ctx[i]);
|
||||
}
|
||||
|
||||
process_deferred_updates(dc);
|
||||
|
@ -2899,11 +2897,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
|
|||
update->dsc_config->num_slices_v != 0);
|
||||
|
||||
/* Use temporarry context for validating new DSC config */
|
||||
struct dc_state *dsc_validate_context = dc_state_create(dc);
|
||||
struct dc_state *dsc_validate_context = dc_state_create_copy(dc->current_state);
|
||||
|
||||
if (dsc_validate_context) {
|
||||
dc_resource_state_copy_construct(dc->current_state, 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)) {
|
||||
|
@ -3011,20 +3007,17 @@ static bool update_planes_and_stream_state(struct dc *dc,
|
|||
new_planes[i] = srf_updates[i].surface;
|
||||
|
||||
/* initialize scratch memory for building context */
|
||||
context = dc_state_create(dc);
|
||||
context = dc_state_create_copy(dc->current_state);
|
||||
if (context == NULL) {
|
||||
DC_ERROR("Failed to allocate new validate context!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
dc_resource_state_copy_construct(
|
||||
dc->current_state, context);
|
||||
|
||||
/* For each full update, remove all existing phantom pipes first.
|
||||
* Ensures that we have enough pipes for newly added MPO planes
|
||||
*/
|
||||
if (dc->res_pool->funcs->remove_phantom_pipes)
|
||||
dc->res_pool->funcs->remove_phantom_pipes(dc, context, false);
|
||||
dc_state_remove_phantom_streams_and_planes(dc, context);
|
||||
dc_state_release_phantom_streams_and_planes(dc, context);
|
||||
|
||||
/*remove old surfaces from context */
|
||||
if (!dc_state_rem_all_planes_for_stream(dc, stream, context)) {
|
||||
|
@ -3059,19 +3052,6 @@ static bool update_planes_and_stream_state(struct dc *dc,
|
|||
|
||||
if (update_type == UPDATE_TYPE_FULL) {
|
||||
if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
|
||||
/* For phantom pipes we remove and create a new set of phantom pipes
|
||||
* for each full update (because we don't know if we'll need phantom
|
||||
* pipes until after the first round of validation). However, if validation
|
||||
* fails we need to keep the existing phantom pipes (because we don't update
|
||||
* the dc->current_state).
|
||||
*
|
||||
* The phantom stream/plane refcount is decremented for validation because
|
||||
* we assume it'll be removed (the free comes when the dc_state is freed),
|
||||
* but if validation fails we have to increment back the refcount so it's
|
||||
* consistent.
|
||||
*/
|
||||
if (dc->res_pool->funcs->retain_phantom_pipes)
|
||||
dc->res_pool->funcs->retain_phantom_pipes(dc, dc->current_state);
|
||||
BREAK_TO_DEBUGGER();
|
||||
goto fail;
|
||||
}
|
||||
|
@ -3390,6 +3370,7 @@ static void commit_planes_for_stream_fast(struct dc *dc,
|
|||
{
|
||||
int i, j;
|
||||
struct pipe_ctx *top_pipe_to_program = NULL;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
dc_z10_restore(dc);
|
||||
|
||||
top_pipe_to_program = resource_get_otg_master_for_stream(
|
||||
|
@ -3425,6 +3406,8 @@ static void commit_planes_for_stream_fast(struct dc *dc,
|
|||
}
|
||||
}
|
||||
|
||||
stream_status = dc_state_get_stream_status(context, stream);
|
||||
|
||||
build_dmub_cmd_list(dc,
|
||||
srf_updates,
|
||||
surface_count,
|
||||
|
@ -3437,7 +3420,8 @@ static void commit_planes_for_stream_fast(struct dc *dc,
|
|||
context->dmub_cmd_count,
|
||||
context->block_sequence,
|
||||
&(context->block_sequence_steps),
|
||||
top_pipe_to_program);
|
||||
top_pipe_to_program,
|
||||
stream_status);
|
||||
hwss_execute_sequence(dc,
|
||||
context->block_sequence,
|
||||
context->block_sequence_steps);
|
||||
|
@ -3974,7 +3958,7 @@ static void release_minimal_transition_state(struct dc *dc,
|
|||
static struct dc_state *create_minimal_transition_state(struct dc *dc,
|
||||
struct dc_state *base_context, struct pipe_split_policy_backup *policy)
|
||||
{
|
||||
struct dc_state *minimal_transition_context = dc_state_create(dc);
|
||||
struct dc_state *minimal_transition_context = NULL;
|
||||
unsigned int i, j;
|
||||
|
||||
if (!dc->config.is_vmin_only_asic) {
|
||||
|
@ -3986,7 +3970,7 @@ static struct dc_state *create_minimal_transition_state(struct dc *dc,
|
|||
policy->subvp_policy = dc->debug.force_disable_subvp;
|
||||
dc->debug.force_disable_subvp = true;
|
||||
|
||||
dc_resource_state_copy_construct(base_context, minimal_transition_context);
|
||||
minimal_transition_context = dc_state_create_copy(base_context);
|
||||
|
||||
/* commit minimal state */
|
||||
if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false)) {
|
||||
|
@ -4018,7 +4002,6 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc,
|
|||
bool success = false;
|
||||
struct dc_state *minimal_transition_context;
|
||||
struct pipe_split_policy_backup policy;
|
||||
struct mall_temp_config mall_temp_config;
|
||||
|
||||
/* commit based on new context */
|
||||
/* Since all phantom pipes are removed in full validation,
|
||||
|
@ -4027,8 +4010,6 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc,
|
|||
* pipe as subvp/phantom will be cleared (dc copy constructor
|
||||
* creates a shallow copy).
|
||||
*/
|
||||
if (dc->res_pool->funcs->save_mall_state)
|
||||
dc->res_pool->funcs->save_mall_state(dc, context, &mall_temp_config);
|
||||
minimal_transition_context = create_minimal_transition_state(dc,
|
||||
context, &policy);
|
||||
if (minimal_transition_context) {
|
||||
|
@ -4041,16 +4022,6 @@ static bool commit_minimal_transition_state_for_windowed_mpo_odm(struct dc *dc,
|
|||
success = dc_commit_state_no_check(dc, minimal_transition_context) == DC_OK;
|
||||
}
|
||||
release_minimal_transition_state(dc, minimal_transition_context, &policy);
|
||||
if (dc->res_pool->funcs->restore_mall_state)
|
||||
dc->res_pool->funcs->restore_mall_state(dc, context, &mall_temp_config);
|
||||
/* If we do a minimal transition with plane removal and the context
|
||||
* has subvp we also have to retain back the phantom stream / planes
|
||||
* since the refcount is decremented as part of the min transition
|
||||
* (we commit a state with no subvp, so the phantom streams / planes
|
||||
* had to be removed).
|
||||
*/
|
||||
if (dc->res_pool->funcs->retain_phantom_pipes)
|
||||
dc->res_pool->funcs->retain_phantom_pipes(dc, context);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
|
@ -4383,7 +4354,6 @@ bool dc_update_planes_and_stream(struct dc *dc,
|
|||
struct dc_state *context;
|
||||
enum surface_update_type update_type;
|
||||
int i;
|
||||
struct mall_temp_config mall_temp_config;
|
||||
struct dc_fast_update fast_update[MAX_SURFACES] = {0};
|
||||
|
||||
/* In cases where MPO and split or ODM are used transitions can
|
||||
|
@ -4427,23 +4397,10 @@ bool dc_update_planes_and_stream(struct dc *dc,
|
|||
* pipe as subvp/phantom will be cleared (dc copy constructor
|
||||
* creates a shallow copy).
|
||||
*/
|
||||
if (dc->res_pool->funcs->save_mall_state)
|
||||
dc->res_pool->funcs->save_mall_state(dc, context, &mall_temp_config);
|
||||
if (!commit_minimal_transition_state(dc, context)) {
|
||||
dc_state_release(context);
|
||||
return false;
|
||||
}
|
||||
if (dc->res_pool->funcs->restore_mall_state)
|
||||
dc->res_pool->funcs->restore_mall_state(dc, context, &mall_temp_config);
|
||||
|
||||
/* If we do a minimal transition with plane removal and the context
|
||||
* has subvp we also have to retain back the phantom stream / planes
|
||||
* since the refcount is decremented as part of the min transition
|
||||
* (we commit a state with no subvp, so the phantom streams / planes
|
||||
* had to be removed).
|
||||
*/
|
||||
if (dc->res_pool->funcs->retain_phantom_pipes)
|
||||
dc->res_pool->funcs->retain_phantom_pipes(dc, context);
|
||||
update_type = UPDATE_TYPE_FULL;
|
||||
}
|
||||
|
||||
|
@ -4559,14 +4516,12 @@ void dc_commit_updates_for_stream(struct dc *dc,
|
|||
if (update_type >= UPDATE_TYPE_FULL) {
|
||||
|
||||
/* initialize scratch memory for building context */
|
||||
context = dc_state_create(dc);
|
||||
context = dc_state_create_copy(state);
|
||||
if (context == NULL) {
|
||||
DC_ERROR("Failed to allocate new validate context!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dc_resource_state_copy_construct(state, context);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
|
||||
struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
|
||||
|
@ -4711,7 +4666,7 @@ void dc_set_power_state(
|
|||
|
||||
switch (power_state) {
|
||||
case DC_ACPI_CM_POWER_STATE_D0:
|
||||
dc_resource_state_construct(dc, dc->current_state);
|
||||
dc_state_construct(dc, dc->current_state);
|
||||
|
||||
dc_z10_restore(dc);
|
||||
|
||||
|
@ -4726,7 +4681,7 @@ void dc_set_power_state(
|
|||
default:
|
||||
ASSERT(dc->current_state->stream_count == 0);
|
||||
|
||||
dc_resource_state_destruct(dc->current_state);
|
||||
dc_state_destruct(dc->current_state);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -473,7 +473,8 @@ void hwss_build_fast_sequence(struct dc *dc,
|
|||
unsigned int dmub_cmd_count,
|
||||
struct block_sequence block_sequence[],
|
||||
int *num_steps,
|
||||
struct pipe_ctx *pipe_ctx)
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_stream_status *stream_status)
|
||||
{
|
||||
struct dc_plane_state *plane = pipe_ctx->plane_state;
|
||||
struct dc_stream_state *stream = pipe_ctx->stream;
|
||||
|
@ -490,7 +491,8 @@ void hwss_build_fast_sequence(struct dc *dc,
|
|||
if (dc->hwss.subvp_pipe_control_lock_fast) {
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = true;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.subvp_immediate_flip =
|
||||
plane->flip_immediate && stream_status->mall_stream_config.type == SUBVP_MAIN;
|
||||
block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
|
||||
(*num_steps)++;
|
||||
}
|
||||
|
@ -529,7 +531,7 @@ void hwss_build_fast_sequence(struct dc *dc,
|
|||
}
|
||||
if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) {
|
||||
if (resource_is_pipe_type(current_mpc_pipe, OTG_MASTER) &&
|
||||
dc_state_get_pipe_subvp_type(NULL, pipe_ctx) == SUBVP_MAIN) {
|
||||
stream_status->mall_stream_config.type == SUBVP_MAIN) {
|
||||
block_sequence[*num_steps].params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv;
|
||||
block_sequence[*num_steps].params.subvp_save_surf_addr.addr = ¤t_mpc_pipe->plane_state->address;
|
||||
block_sequence[*num_steps].params.subvp_save_surf_addr.subvp_index = current_mpc_pipe->subvp_index;
|
||||
|
@ -612,7 +614,8 @@ void hwss_build_fast_sequence(struct dc *dc,
|
|||
if (dc->hwss.subvp_pipe_control_lock_fast) {
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = false;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx;
|
||||
block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.subvp_immediate_flip =
|
||||
plane->flip_immediate && stream_status->mall_stream_config.type == SUBVP_MAIN;
|
||||
block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
|
||||
(*num_steps)++;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "link_enc_cfg.h"
|
||||
#include "link.h"
|
||||
#include "clk_mgr.h"
|
||||
#include "dc_state_priv.h"
|
||||
#include "virtual/virtual_link_hwss.h"
|
||||
#include "link/hwss/link_hwss_dio.h"
|
||||
#include "link/hwss/link_hwss_dpia.h"
|
||||
|
@ -3523,34 +3524,6 @@ enum dc_status resource_map_pool_resources(
|
|||
return DC_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state
|
||||
*
|
||||
* @dc: copy out of dc->current_state
|
||||
* @dst_ctx: copy into this
|
||||
*
|
||||
* This function makes a shallow copy of the current DC state and increments
|
||||
* refcounts on existing streams and planes.
|
||||
*/
|
||||
void dc_resource_state_copy_construct_current(
|
||||
const struct dc *dc,
|
||||
struct dc_state *dst_ctx)
|
||||
{
|
||||
dc_resource_state_copy_construct(dc->current_state, dst_ctx);
|
||||
}
|
||||
|
||||
|
||||
void dc_resource_state_construct(
|
||||
const struct dc *dc,
|
||||
struct dc_state *dst_ctx)
|
||||
{
|
||||
dst_ctx->clk_mgr = dc->clk_mgr;
|
||||
|
||||
/* Initialise DIG link encoder resource tracking variables. */
|
||||
link_enc_cfg_init(dc, dst_ctx);
|
||||
}
|
||||
|
||||
|
||||
bool dc_resource_is_dsc_encoding_supported(const struct dc *dc)
|
||||
{
|
||||
if (dc->res_pool == NULL)
|
||||
|
@ -3724,6 +3697,7 @@ enum dc_status dc_validate_with_context(struct dc *dc,
|
|||
unchanged_streams[i],
|
||||
set,
|
||||
set_count)) {
|
||||
|
||||
if (!dc_state_rem_all_planes_for_stream(dc,
|
||||
unchanged_streams[i],
|
||||
context)) {
|
||||
|
@ -3746,12 +3720,24 @@ enum dc_status dc_validate_with_context(struct dc *dc,
|
|||
}
|
||||
}
|
||||
|
||||
if (dc_state_get_stream_subvp_type(context, del_streams[i]) == SUBVP_PHANTOM) {
|
||||
/* remove phantoms specifically */
|
||||
if (!dc_state_rem_all_phantom_planes_for_stream(dc, del_streams[i], context, true)) {
|
||||
res = DC_FAIL_DETACH_SURFACES;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = dc_state_remove_phantom_stream(dc, context, del_streams[i]);
|
||||
dc_state_release_phantom_stream(dc, context, del_streams[i]);
|
||||
} else {
|
||||
if (!dc_state_rem_all_planes_for_stream(dc, del_streams[i], context)) {
|
||||
res = DC_FAIL_DETACH_SURFACES;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = dc_state_remove_stream(dc, context, del_streams[i]);
|
||||
}
|
||||
|
||||
if (res != DC_OK)
|
||||
goto fail;
|
||||
}
|
||||
|
@ -4280,84 +4266,6 @@ static void set_vtem_info_packet(
|
|||
*info_packet = stream->vtem_infopacket;
|
||||
}
|
||||
|
||||
void dc_resource_state_destruct(struct dc_state *context)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
for (j = 0; j < context->stream_status[i].plane_count; j++)
|
||||
dc_plane_state_release(
|
||||
context->stream_status[i].plane_states[j]);
|
||||
|
||||
context->stream_status[i].plane_count = 0;
|
||||
dc_stream_release(context->streams[i]);
|
||||
context->streams[i] = NULL;
|
||||
}
|
||||
context->stream_count = 0;
|
||||
context->stream_mask = 0;
|
||||
memset(&context->res_ctx, 0, sizeof(context->res_ctx));
|
||||
memset(&context->pp_display_cfg, 0, sizeof(context->pp_display_cfg));
|
||||
memset(&context->dcn_bw_vars, 0, sizeof(context->dcn_bw_vars));
|
||||
context->clk_mgr = NULL;
|
||||
memset(&context->bw_ctx.bw, 0, sizeof(context->bw_ctx.bw));
|
||||
memset(context->block_sequence, 0, sizeof(context->block_sequence));
|
||||
context->block_sequence_steps = 0;
|
||||
memset(context->dc_dmub_cmd, 0, sizeof(context->dc_dmub_cmd));
|
||||
context->dmub_cmd_count = 0;
|
||||
memset(&context->perf_params, 0, sizeof(context->perf_params));
|
||||
memset(&context->scratch, 0, sizeof(context->scratch));
|
||||
}
|
||||
|
||||
void dc_resource_state_copy_construct(
|
||||
const struct dc_state *src_ctx,
|
||||
struct dc_state *dst_ctx)
|
||||
{
|
||||
int i, j;
|
||||
struct kref refcount = dst_ctx->refcount;
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
struct dml2_context *dml2 = NULL;
|
||||
|
||||
// Need to preserve allocated dml2 context
|
||||
if (src_ctx->clk_mgr && src_ctx->clk_mgr->ctx->dc->debug.using_dml2)
|
||||
dml2 = dst_ctx->bw_ctx.dml2;
|
||||
#endif
|
||||
|
||||
*dst_ctx = *src_ctx;
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
// Preserve allocated dml2 context
|
||||
if (src_ctx->clk_mgr && src_ctx->clk_mgr->ctx->dc->debug.using_dml2)
|
||||
dst_ctx->bw_ctx.dml2 = dml2;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
struct pipe_ctx *cur_pipe = &dst_ctx->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (cur_pipe->top_pipe)
|
||||
cur_pipe->top_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->bottom_pipe)
|
||||
cur_pipe->bottom_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->next_odm_pipe)
|
||||
cur_pipe->next_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->prev_odm_pipe)
|
||||
cur_pipe->prev_odm_pipe = &dst_ctx->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
|
||||
}
|
||||
|
||||
for (i = 0; i < dst_ctx->stream_count; i++) {
|
||||
dc_stream_retain(dst_ctx->streams[i]);
|
||||
for (j = 0; j < dst_ctx->stream_status[i].plane_count; j++)
|
||||
dc_plane_state_retain(
|
||||
dst_ctx->stream_status[i].plane_states[j]);
|
||||
}
|
||||
|
||||
/* context refcount should not be overridden */
|
||||
dst_ctx->refcount = refcount;
|
||||
|
||||
}
|
||||
|
||||
struct clock_source *dc_resource_find_first_free_pll(
|
||||
struct resource_context *res_ctx,
|
||||
const struct resource_pool *pool)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "dm_services.h"
|
||||
#include "resource.h"
|
||||
#include "link_enc_cfg.h"
|
||||
|
||||
#include "dml2/dml2_wrapper.h"
|
||||
#include "dml2/dml2_internal_types.h"
|
||||
|
@ -39,7 +40,144 @@
|
|||
dc->ctx->logger
|
||||
#define DC_LOGGER_INIT(logger)
|
||||
|
||||
/* Public dc_state functions */
|
||||
/* Private dc_state helper functions */
|
||||
static bool dc_state_track_phantom_stream(struct dc_state *state,
|
||||
struct dc_stream_state *phantom_stream)
|
||||
{
|
||||
if (state->phantom_stream_count >= MAX_PHANTOM_PIPES)
|
||||
return false;
|
||||
|
||||
state->phantom_streams[state->phantom_stream_count++] = phantom_stream;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dc_state_untrack_phantom_stream(struct dc_state *state, struct dc_stream_state *phantom_stream)
|
||||
{
|
||||
bool res = false;
|
||||
int i;
|
||||
|
||||
/* first find phantom stream in the dc_state */
|
||||
for (i = 0; i < state->phantom_stream_count; i++) {
|
||||
if (state->phantom_streams[i] == phantom_stream) {
|
||||
state->phantom_streams[i] = NULL;
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* failed to find stream in state */
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
/* trim back phantom streams */
|
||||
state->phantom_stream_count--;
|
||||
for (; i < state->phantom_stream_count; i++)
|
||||
state->phantom_streams[i] = state->phantom_streams[i + 1];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool dc_state_is_phantom_stream_tracked(struct dc_state *state, struct dc_stream_state *phantom_stream)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < state->phantom_stream_count; i++) {
|
||||
if (state->phantom_streams[i] == phantom_stream)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool dc_state_track_phantom_plane(struct dc_state *state,
|
||||
struct dc_plane_state *phantom_plane)
|
||||
{
|
||||
if (state->phantom_plane_count >= MAX_PHANTOM_PIPES)
|
||||
return false;
|
||||
|
||||
state->phantom_planes[state->phantom_plane_count++] = phantom_plane;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dc_state_untrack_phantom_plane(struct dc_state *state, struct dc_plane_state *phantom_plane)
|
||||
{
|
||||
bool res = false;
|
||||
int i;
|
||||
|
||||
/* first find phantom plane in the dc_state */
|
||||
for (i = 0; i < state->phantom_plane_count; i++) {
|
||||
if (state->phantom_planes[i] == phantom_plane) {
|
||||
state->phantom_planes[i] = NULL;
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* failed to find plane in state */
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
/* trim back phantom planes */
|
||||
state->phantom_plane_count--;
|
||||
for (; i < state->phantom_plane_count; i++)
|
||||
state->phantom_planes[i] = state->phantom_planes[i + 1];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool dc_state_is_phantom_plane_tracked(struct dc_state *state, struct dc_plane_state *phantom_plane)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < state->phantom_plane_count; i++) {
|
||||
if (state->phantom_planes[i] == phantom_plane)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void dc_state_copy_internal(struct dc_state *dst_state, struct dc_state *src_state)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
memcpy(dst_state, src_state, sizeof(struct dc_state));
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
struct pipe_ctx *cur_pipe = &dst_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (cur_pipe->top_pipe)
|
||||
cur_pipe->top_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->bottom_pipe)
|
||||
cur_pipe->bottom_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->prev_odm_pipe)
|
||||
cur_pipe->prev_odm_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->next_odm_pipe)
|
||||
cur_pipe->next_odm_pipe = &dst_state->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
|
||||
}
|
||||
|
||||
/* retain phantoms */
|
||||
for (i = 0; i < dst_state->phantom_stream_count; i++)
|
||||
dc_stream_retain(dst_state->phantom_streams[i]);
|
||||
|
||||
for (i = 0; i < dst_state->phantom_plane_count; i++)
|
||||
dc_plane_state_retain(dst_state->phantom_planes[i]);
|
||||
|
||||
/* retain streams and planes */
|
||||
for (i = 0; i < dst_state->stream_count; i++) {
|
||||
dc_stream_retain(dst_state->streams[i]);
|
||||
for (j = 0; j < dst_state->stream_status[i].plane_count; j++)
|
||||
dc_plane_state_retain(
|
||||
dst_state->stream_status[i].plane_states[j]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void init_state(struct dc *dc, struct dc_state *state)
|
||||
{
|
||||
/* Each context must have their own instance of VBA and in order to
|
||||
|
@ -49,6 +187,7 @@ static void init_state(struct dc *dc, struct dc_state *state)
|
|||
memcpy(&state->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib));
|
||||
}
|
||||
|
||||
/* Public dc_state functions */
|
||||
struct dc_state *dc_state_create(struct dc *dc)
|
||||
{
|
||||
struct dc_state *state = kvzalloc(sizeof(struct dc_state),
|
||||
|
@ -58,6 +197,7 @@ struct dc_state *dc_state_create(struct dc *dc)
|
|||
return NULL;
|
||||
|
||||
init_state(dc, state);
|
||||
dc_state_construct(dc, state);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
if (dc->debug.using_dml2)
|
||||
|
@ -69,61 +209,112 @@ struct dc_state *dc_state_create(struct dc *dc)
|
|||
return state;
|
||||
}
|
||||
|
||||
void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state)
|
||||
{
|
||||
struct kref refcount = dst_state->refcount;
|
||||
|
||||
dc_state_copy_internal(dst_state, src_state);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
if (src_state->bw_ctx.dml2)
|
||||
dml2_copy(dst_state->bw_ctx.dml2, src_state->bw_ctx.dml2);
|
||||
#endif
|
||||
|
||||
/* context refcount should not be overridden */
|
||||
dst_state->refcount = refcount;
|
||||
}
|
||||
|
||||
struct dc_state *dc_state_create_copy(struct dc_state *src_state)
|
||||
{
|
||||
int i, j;
|
||||
struct dc_state *new_state = kvmalloc(sizeof(struct dc_state), GFP_KERNEL);
|
||||
struct dc_state *new_state;
|
||||
|
||||
new_state = kvmalloc(sizeof(struct dc_state),
|
||||
GFP_KERNEL);
|
||||
if (!new_state)
|
||||
return NULL;
|
||||
|
||||
memcpy(new_state, src_state, sizeof(struct dc_state));
|
||||
dc_state_copy_internal(new_state, src_state);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
if (new_state->bw_ctx.dml2 && !dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2)) {
|
||||
if (src_state->bw_ctx.dml2 &&
|
||||
!dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2)) {
|
||||
dc_state_release(new_state);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
struct pipe_ctx *cur_pipe = &new_state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (cur_pipe->top_pipe)
|
||||
cur_pipe->top_pipe = &new_state->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->bottom_pipe)
|
||||
cur_pipe->bottom_pipe = &new_state->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->prev_odm_pipe)
|
||||
cur_pipe->prev_odm_pipe = &new_state->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
|
||||
|
||||
if (cur_pipe->next_odm_pipe)
|
||||
cur_pipe->next_odm_pipe = &new_state->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
|
||||
}
|
||||
|
||||
for (i = 0; i < new_state->stream_count; i++) {
|
||||
dc_stream_retain(new_state->streams[i]);
|
||||
for (j = 0; j < new_state->stream_status[i].plane_count; j++)
|
||||
dc_plane_state_retain(
|
||||
new_state->stream_status[i].plane_states[j]);
|
||||
}
|
||||
|
||||
kref_init(&new_state->refcount);
|
||||
|
||||
return new_state;
|
||||
}
|
||||
|
||||
void dc_state_retain(struct dc_state *context)
|
||||
void dc_state_copy_current(struct dc *dc, struct dc_state *dst_state)
|
||||
{
|
||||
kref_get(&context->refcount);
|
||||
dc_state_copy(dst_state, dc->current_state);
|
||||
}
|
||||
|
||||
struct dc_state *dc_state_create_current_copy(struct dc *dc)
|
||||
{
|
||||
return dc_state_create_copy(dc->current_state);
|
||||
}
|
||||
|
||||
void dc_state_construct(struct dc *dc, struct dc_state *state)
|
||||
{
|
||||
state->clk_mgr = dc->clk_mgr;
|
||||
|
||||
/* Initialise DIG link encoder resource tracking variables. */
|
||||
link_enc_cfg_init(dc, state);
|
||||
}
|
||||
|
||||
void dc_state_destruct(struct dc_state *state)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
for (j = 0; j < state->stream_status[i].plane_count; j++)
|
||||
dc_plane_state_release(
|
||||
state->stream_status[i].plane_states[j]);
|
||||
|
||||
state->stream_status[i].plane_count = 0;
|
||||
dc_stream_release(state->streams[i]);
|
||||
state->streams[i] = NULL;
|
||||
}
|
||||
state->stream_count = 0;
|
||||
|
||||
/* release tracked phantoms */
|
||||
for (i = 0; i < state->phantom_stream_count; i++) {
|
||||
dc_stream_release(state->phantom_streams[i]);
|
||||
state->phantom_streams[i] = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < state->phantom_plane_count; i++) {
|
||||
dc_plane_state_release(state->phantom_planes[i]);
|
||||
state->phantom_planes[i] = NULL;
|
||||
}
|
||||
state->stream_mask = 0;
|
||||
memset(&state->res_ctx, 0, sizeof(state->res_ctx));
|
||||
memset(&state->pp_display_cfg, 0, sizeof(state->pp_display_cfg));
|
||||
memset(&state->dcn_bw_vars, 0, sizeof(state->dcn_bw_vars));
|
||||
state->clk_mgr = NULL;
|
||||
memset(&state->bw_ctx.bw, 0, sizeof(state->bw_ctx.bw));
|
||||
memset(state->block_sequence, 0, sizeof(state->block_sequence));
|
||||
state->block_sequence_steps = 0;
|
||||
memset(state->dc_dmub_cmd, 0, sizeof(state->dc_dmub_cmd));
|
||||
state->dmub_cmd_count = 0;
|
||||
memset(&state->perf_params, 0, sizeof(state->perf_params));
|
||||
memset(&state->scratch, 0, sizeof(state->scratch));
|
||||
}
|
||||
|
||||
void dc_state_retain(struct dc_state *state)
|
||||
{
|
||||
kref_get(&state->refcount);
|
||||
}
|
||||
|
||||
static void dc_state_free(struct kref *kref)
|
||||
{
|
||||
struct dc_state *state = container_of(kref, struct dc_state, refcount);
|
||||
|
||||
dc_resource_state_destruct(state);
|
||||
dc_state_destruct(state);
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC_FP
|
||||
dml2_destroy(state->bw_ctx.dml2);
|
||||
|
@ -403,34 +594,64 @@ struct dc_stream_status *dc_state_get_stream_status(
|
|||
enum mall_stream_type dc_state_get_pipe_subvp_type(const struct dc_state *state,
|
||||
const struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
if (pipe_ctx->stream == NULL)
|
||||
return SUBVP_NONE;
|
||||
|
||||
return pipe_ctx->stream->mall_stream_config.type;
|
||||
return dc_state_get_stream_subvp_type(state, pipe_ctx->stream);
|
||||
}
|
||||
|
||||
enum mall_stream_type dc_state_get_stream_subvp_type(const struct dc_state *state,
|
||||
const struct dc_stream_state *stream)
|
||||
{
|
||||
return stream->mall_stream_config.type;
|
||||
int i;
|
||||
|
||||
enum mall_stream_type type = SUBVP_NONE;
|
||||
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
if (state->streams[i] == stream) {
|
||||
type = state->stream_status[i].mall_stream_config.type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
struct dc_stream_state *dc_state_get_paired_subvp_stream(const struct dc_state *state,
|
||||
const struct dc_stream_state *stream)
|
||||
{
|
||||
return stream->mall_stream_config.paired_stream;
|
||||
int i;
|
||||
|
||||
struct dc_stream_state *paired_stream = NULL;
|
||||
|
||||
for (i = 0; i < state->stream_count; i++) {
|
||||
if (state->streams[i] == stream) {
|
||||
paired_stream = state->stream_status[i].mall_stream_config.paired_stream;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return paired_stream;
|
||||
}
|
||||
|
||||
struct dc_stream_state *dc_state_create_phantom_stream(const struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *main_stream)
|
||||
{
|
||||
struct dc_stream_state *phantom_stream = dc_create_stream_for_sink(main_stream->sink);
|
||||
struct dc_stream_state *phantom_stream;
|
||||
|
||||
if (phantom_stream != NULL) {
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
phantom_stream = dc_create_stream_for_sink(main_stream->sink);
|
||||
|
||||
if (!phantom_stream) {
|
||||
DC_LOG_ERROR("Failed to allocate phantom stream.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* track phantom stream in dc_state */
|
||||
dc_state_track_phantom_stream(state, phantom_stream);
|
||||
|
||||
phantom_stream->is_phantom = true;
|
||||
phantom_stream->signal = SIGNAL_TYPE_VIRTUAL;
|
||||
phantom_stream->dpms_off = true;
|
||||
}
|
||||
|
||||
return phantom_stream;
|
||||
}
|
||||
|
@ -439,6 +660,13 @@ void dc_state_release_phantom_stream(const struct dc *dc,
|
|||
struct dc_state *state,
|
||||
struct dc_stream_state *phantom_stream)
|
||||
{
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (!dc_state_untrack_phantom_stream(state, phantom_stream)) {
|
||||
DC_LOG_ERROR("Failed to free phantom stream %p in dc state %p.\n", phantom_stream, state);
|
||||
return;
|
||||
}
|
||||
|
||||
dc_stream_release(phantom_stream);
|
||||
}
|
||||
|
||||
|
@ -448,7 +676,16 @@ struct dc_plane_state *dc_state_create_phantom_plane(struct dc *dc,
|
|||
{
|
||||
struct dc_plane_state *phantom_plane = dc_create_plane_state(dc);
|
||||
|
||||
if (phantom_plane != NULL)
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (!phantom_plane) {
|
||||
DC_LOG_ERROR("Failed to allocate phantom plane.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* track phantom inside dc_state */
|
||||
dc_state_track_phantom_plane(state, phantom_plane);
|
||||
|
||||
phantom_plane->is_phantom = true;
|
||||
|
||||
return phantom_plane;
|
||||
|
@ -458,6 +695,13 @@ void dc_state_release_phantom_plane(const struct dc *dc,
|
|||
struct dc_state *state,
|
||||
struct dc_plane_state *phantom_plane)
|
||||
{
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
if (!dc_state_untrack_phantom_plane(state, phantom_plane)) {
|
||||
DC_LOG_ERROR("Failed to free phantom plane %p in dc state %p.\n", phantom_plane, state);
|
||||
return;
|
||||
}
|
||||
|
||||
dc_plane_state_release(phantom_plane);
|
||||
}
|
||||
|
||||
|
@ -467,13 +711,23 @@ enum dc_status dc_state_add_phantom_stream(struct dc *dc,
|
|||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_stream_state *main_stream)
|
||||
{
|
||||
struct dc_stream_status *main_stream_status;
|
||||
struct dc_stream_status *phantom_stream_status;
|
||||
enum dc_status res = dc_state_add_stream(dc, state, phantom_stream);
|
||||
|
||||
/* check if stream is tracked */
|
||||
if (res == DC_OK && !dc_state_is_phantom_stream_tracked(state, phantom_stream)) {
|
||||
/* stream must be tracked if added to state */
|
||||
dc_state_track_phantom_stream(state, phantom_stream);
|
||||
}
|
||||
|
||||
/* setup subvp meta */
|
||||
phantom_stream->mall_stream_config.type = SUBVP_PHANTOM;
|
||||
phantom_stream->mall_stream_config.paired_stream = main_stream;
|
||||
main_stream->mall_stream_config.type = SUBVP_MAIN;
|
||||
main_stream->mall_stream_config.paired_stream = phantom_stream;
|
||||
main_stream_status = dc_state_get_stream_status(state, main_stream);
|
||||
phantom_stream_status = dc_state_get_stream_status(state, phantom_stream);
|
||||
phantom_stream_status->mall_stream_config.type = SUBVP_PHANTOM;
|
||||
phantom_stream_status->mall_stream_config.paired_stream = main_stream;
|
||||
main_stream_status->mall_stream_config.type = SUBVP_MAIN;
|
||||
main_stream_status->mall_stream_config.paired_stream = phantom_stream;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -482,9 +736,18 @@ enum dc_status dc_state_remove_phantom_stream(struct dc *dc,
|
|||
struct dc_state *state,
|
||||
struct dc_stream_state *phantom_stream)
|
||||
{
|
||||
struct dc_stream_status *main_stream_status;
|
||||
struct dc_stream_status *phantom_stream_status;
|
||||
|
||||
/* reset subvp meta */
|
||||
phantom_stream->mall_stream_config.paired_stream->mall_stream_config.type = SUBVP_NONE;
|
||||
phantom_stream->mall_stream_config.paired_stream->mall_stream_config.paired_stream = NULL;
|
||||
phantom_stream_status = dc_state_get_stream_status(state, phantom_stream);
|
||||
main_stream_status = dc_state_get_stream_status(state, phantom_stream_status->mall_stream_config.paired_stream);
|
||||
phantom_stream_status->mall_stream_config.type = SUBVP_NONE;
|
||||
phantom_stream_status->mall_stream_config.paired_stream = NULL;
|
||||
if (main_stream_status) {
|
||||
main_stream_status->mall_stream_config.type = SUBVP_NONE;
|
||||
main_stream_status->mall_stream_config.paired_stream = NULL;
|
||||
}
|
||||
|
||||
/* remove stream from state */
|
||||
return dc_state_remove_stream(dc, state, phantom_stream);
|
||||
|
@ -496,7 +759,15 @@ bool dc_state_add_phantom_plane(
|
|||
struct dc_plane_state *phantom_plane,
|
||||
struct dc_state *state)
|
||||
{
|
||||
return dc_state_add_plane(dc, phantom_stream, phantom_plane, state);
|
||||
bool res = dc_state_add_plane(dc, phantom_stream, phantom_plane, state);
|
||||
|
||||
/* check if stream is tracked */
|
||||
if (res && !dc_state_is_phantom_plane_tracked(state, phantom_plane)) {
|
||||
/* stream must be tracked if added to state */
|
||||
dc_state_track_phantom_plane(state, phantom_plane);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool dc_state_remove_phantom_plane(
|
||||
|
@ -511,9 +782,37 @@ bool dc_state_remove_phantom_plane(
|
|||
bool dc_state_rem_all_phantom_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_state *state)
|
||||
struct dc_state *state,
|
||||
bool should_release_planes)
|
||||
{
|
||||
return dc_state_rem_all_planes_for_stream(dc, phantom_stream, state);
|
||||
int i, old_plane_count;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
struct dc_plane_state *del_planes[MAX_SURFACE_NUM] = { 0 };
|
||||
|
||||
for (i = 0; i < state->stream_count; i++)
|
||||
if (state->streams[i] == phantom_stream) {
|
||||
stream_status = &state->stream_status[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream_status == NULL) {
|
||||
dm_error("Existing stream %p not found!\n", phantom_stream);
|
||||
return false;
|
||||
}
|
||||
|
||||
old_plane_count = stream_status->plane_count;
|
||||
|
||||
for (i = 0; i < old_plane_count; i++)
|
||||
del_planes[i] = stream_status->plane_states[i];
|
||||
|
||||
for (i = 0; i < old_plane_count; i++) {
|
||||
if (!dc_state_remove_plane(dc, phantom_stream, del_planes[i], state))
|
||||
return false;
|
||||
if (should_release_planes)
|
||||
dc_state_release_phantom_plane(dc, state, del_planes[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_state_add_all_phantom_planes_for_stream(
|
||||
|
@ -525,3 +824,38 @@ bool dc_state_add_all_phantom_planes_for_stream(
|
|||
{
|
||||
return dc_state_add_all_planes_for_stream(dc, phantom_stream, phantom_planes, plane_count, state);
|
||||
}
|
||||
|
||||
bool dc_state_remove_phantom_streams_and_planes(
|
||||
struct dc *dc,
|
||||
struct dc_state *state)
|
||||
{
|
||||
int i;
|
||||
bool removed_phantom = false;
|
||||
struct dc_stream_state *phantom_stream = NULL;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &state->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->plane_state && pipe->stream && dc_state_get_pipe_subvp_type(state, pipe) == SUBVP_PHANTOM) {
|
||||
phantom_stream = pipe->stream;
|
||||
|
||||
dc_state_rem_all_phantom_planes_for_stream(dc, phantom_stream, state, false);
|
||||
dc_state_remove_phantom_stream(dc, state, phantom_stream);
|
||||
removed_phantom = true;
|
||||
}
|
||||
}
|
||||
return removed_phantom;
|
||||
}
|
||||
|
||||
void dc_state_release_phantom_streams_and_planes(
|
||||
struct dc *dc,
|
||||
struct dc_state *state)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < state->phantom_stream_count; i++)
|
||||
dc_state_release_phantom_stream(dc, state, state->phantom_streams[i]);
|
||||
|
||||
for (i = 0; i < state->phantom_plane_count; i++)
|
||||
dc_state_release_phantom_plane(dc, state, state->phantom_planes[i]);
|
||||
}
|
||||
|
|
|
@ -123,8 +123,7 @@ bool dc_stream_construct(struct dc_stream_state *stream,
|
|||
}
|
||||
stream->out_transfer_func->type = TF_TYPE_BYPASS;
|
||||
|
||||
stream->stream_id = stream->ctx->dc_stream_id_count;
|
||||
stream->ctx->dc_stream_id_count++;
|
||||
dc_stream_assign_stream_id(stream);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -138,6 +137,13 @@ void dc_stream_destruct(struct dc_stream_state *stream)
|
|||
}
|
||||
}
|
||||
|
||||
void dc_stream_assign_stream_id(struct dc_stream_state *stream)
|
||||
{
|
||||
/* MSB is reserved to indicate phantoms */
|
||||
stream->stream_id = stream->ctx->dc_stream_id_count;
|
||||
stream->ctx->dc_stream_id_count++;
|
||||
}
|
||||
|
||||
void dc_stream_retain(struct dc_stream_state *stream)
|
||||
{
|
||||
kref_get(&stream->refcount);
|
||||
|
@ -198,8 +204,7 @@ struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream)
|
|||
if (new_stream->out_transfer_func)
|
||||
dc_transfer_func_retain(new_stream->out_transfer_func);
|
||||
|
||||
new_stream->stream_id = new_stream->ctx->dc_stream_id_count;
|
||||
new_stream->ctx->dc_stream_id_count++;
|
||||
dc_stream_assign_stream_id(new_stream);
|
||||
|
||||
/* If using dynamic encoder assignment, wait till stream committed to assign encoder. */
|
||||
if (new_stream->ctx->dc->res_pool->funcs->link_encs_assign)
|
||||
|
|
|
@ -1388,6 +1388,9 @@ struct dc_surface_update {
|
|||
const struct colorspace_transform *gamut_remap_matrix;
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new surface with default parameters;
|
||||
*/
|
||||
void dc_gamma_retain(struct dc_gamma *dc_gamma);
|
||||
void dc_gamma_release(struct dc_gamma **dc_gamma);
|
||||
struct dc_gamma *dc_create_gamma(void);
|
||||
|
@ -1451,27 +1454,12 @@ enum dc_status dc_validate_global_state(
|
|||
struct dc_state *new_ctx,
|
||||
bool fast_validate);
|
||||
|
||||
|
||||
void dc_resource_state_construct(
|
||||
const struct dc *dc,
|
||||
struct dc_state *dst_ctx);
|
||||
|
||||
bool dc_acquire_release_mpc_3dlut(
|
||||
struct dc *dc, bool acquire,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_3dlut **lut,
|
||||
struct dc_transfer_func **shaper);
|
||||
|
||||
void dc_resource_state_copy_construct(
|
||||
const struct dc_state *src_ctx,
|
||||
struct dc_state *dst_ctx);
|
||||
|
||||
void dc_resource_state_copy_construct_current(
|
||||
const struct dc *dc,
|
||||
struct dc_state *dst_ctx);
|
||||
|
||||
void dc_resource_state_destruct(struct dc_state *context);
|
||||
|
||||
bool dc_resource_is_dsc_encoding_supported(const struct dc *dc);
|
||||
|
||||
enum dc_status dc_commit_streams(struct dc *dc,
|
||||
|
|
|
@ -672,12 +672,14 @@ static void update_subvp_prefetch_end_to_mall_start(struct dc *dc,
|
|||
uint32_t prefetch_delta_us = 0;
|
||||
struct dc_stream_state *phantom_stream0 = NULL;
|
||||
struct dc_stream_state *phantom_stream1 = NULL;
|
||||
struct dc_crtc_timing *phantom_timing0 = &phantom_stream0->timing;
|
||||
struct dc_crtc_timing *phantom_timing1 = &phantom_stream1->timing;
|
||||
struct dc_crtc_timing *phantom_timing0 = NULL;
|
||||
struct dc_crtc_timing *phantom_timing1 = NULL;
|
||||
struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 *pipe_data = NULL;
|
||||
|
||||
phantom_stream0 = dc_state_get_paired_subvp_stream(context, subvp_pipes[0]->stream);
|
||||
phantom_stream1 = dc_state_get_paired_subvp_stream(context, subvp_pipes[1]->stream);
|
||||
phantom_timing0 = &phantom_stream0->timing;
|
||||
phantom_timing1 = &phantom_stream1->timing;
|
||||
|
||||
subvp0_prefetch_us = div64_u64(((uint64_t)(phantom_timing0->v_total - phantom_timing0->v_front_porch) *
|
||||
(uint64_t)phantom_timing0->h_total * 1000000),
|
||||
|
@ -853,7 +855,6 @@ void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
|
|||
*/
|
||||
if (resource_is_pipe_type(pipe, OTG_MASTER) &&
|
||||
resource_is_pipe_type(pipe, DPP_PIPE) &&
|
||||
pipe->stream->mall_stream_config.paired_stream &&
|
||||
pipe_mall_type == SUBVP_MAIN) {
|
||||
populate_subvp_cmd_pipe_info(dc, context, &cmd, pipe, cmd_pipe_index++);
|
||||
} else if (resource_is_pipe_type(pipe, OTG_MASTER) &&
|
||||
|
|
|
@ -29,9 +29,13 @@
|
|||
#include "dc.h"
|
||||
#include "inc/core_status.h"
|
||||
|
||||
|
||||
struct dc_state *dc_state_create(struct dc *dc);
|
||||
void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state);
|
||||
struct dc_state *dc_state_create_copy(struct dc_state *src_state);
|
||||
void dc_state_copy_current(struct dc *dc, struct dc_state *dst_state);
|
||||
struct dc_state *dc_state_create_current_copy(struct dc *dc);
|
||||
void dc_state_construct(struct dc *dc, struct dc_state *state);
|
||||
void dc_state_destruct(struct dc_state *state);
|
||||
void dc_state_retain(struct dc_state *state);
|
||||
void dc_state_release(struct dc_state *state);
|
||||
|
||||
|
|
|
@ -29,10 +29,6 @@
|
|||
#include "dc_state.h"
|
||||
#include "dc_stream.h"
|
||||
|
||||
struct dc_stream_status *dc_state_get_stream_status(
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *stream);
|
||||
|
||||
/* Get the type of the provided resource (none, phantom, main) based on the provided
|
||||
* context. If the context is unavailable, determine only if phantom or not.
|
||||
*/
|
||||
|
@ -85,7 +81,8 @@ bool dc_state_remove_phantom_plane(
|
|||
bool dc_state_rem_all_phantom_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_state *state);
|
||||
struct dc_state *state,
|
||||
bool should_release_planes);
|
||||
|
||||
bool dc_state_add_all_phantom_planes_for_stream(
|
||||
const struct dc *dc,
|
||||
|
@ -94,4 +91,12 @@ bool dc_state_add_all_phantom_planes_for_stream(
|
|||
int plane_count,
|
||||
struct dc_state *state);
|
||||
|
||||
bool dc_state_remove_phantom_streams_and_planes(
|
||||
struct dc *dc,
|
||||
struct dc_state *state);
|
||||
|
||||
void dc_state_release_phantom_streams_and_planes(
|
||||
struct dc *dc,
|
||||
struct dc_state *state);
|
||||
|
||||
#endif /* _DC_STATE_PRIV_H_ */
|
||||
|
|
|
@ -38,6 +38,14 @@ struct timing_sync_info {
|
|||
bool master;
|
||||
};
|
||||
|
||||
struct mall_stream_config {
|
||||
/* MALL stream config to indicate if the stream is phantom or not.
|
||||
* We will use a phantom stream to indicate that the pipe is phantom.
|
||||
*/
|
||||
enum mall_stream_type type;
|
||||
struct dc_stream_state *paired_stream; // master / slave stream
|
||||
};
|
||||
|
||||
struct dc_stream_status {
|
||||
int primary_otg_inst;
|
||||
int stream_enc_inst;
|
||||
|
@ -50,6 +58,7 @@ struct dc_stream_status {
|
|||
struct timing_sync_info timing_sync_info;
|
||||
struct dc_plane_state *plane_states[MAX_SURFACE_NUM];
|
||||
bool is_abm_supported;
|
||||
struct mall_stream_config mall_stream_config;
|
||||
};
|
||||
|
||||
enum hubp_dmdata_mode {
|
||||
|
@ -146,25 +155,6 @@ struct test_pattern {
|
|||
|
||||
#define SUBVP_DRR_MARGIN_US 100 // 100us for DRR margin (SubVP + DRR)
|
||||
|
||||
struct mall_stream_config {
|
||||
/* MALL stream config to indicate if the stream is phantom or not.
|
||||
* We will use a phantom stream to indicate that the pipe is phantom.
|
||||
*/
|
||||
enum mall_stream_type type;
|
||||
struct dc_stream_state *paired_stream; // master / slave stream
|
||||
};
|
||||
|
||||
/* Temp struct used to save and restore MALL config
|
||||
* during validation.
|
||||
*
|
||||
* TODO: Move MALL config into dc_state instead of stream struct
|
||||
* to avoid needing to save/restore.
|
||||
*/
|
||||
struct mall_temp_config {
|
||||
struct mall_stream_config mall_stream_config[MAX_PIPES];
|
||||
bool is_phantom_plane[MAX_PIPES];
|
||||
};
|
||||
|
||||
struct dc_stream_debug_options {
|
||||
char force_odm_combine_segments;
|
||||
};
|
||||
|
@ -294,7 +284,7 @@ struct dc_stream_state {
|
|||
bool has_non_synchronizable_pclk;
|
||||
bool vblank_synchronized;
|
||||
bool fpo_in_use;
|
||||
struct mall_stream_config mall_stream_config;
|
||||
bool is_phantom;
|
||||
};
|
||||
|
||||
#define ABM_LEVEL_IMMEDIATE_DISABLE 255
|
||||
|
|
|
@ -32,4 +32,6 @@ bool dc_stream_construct(struct dc_stream_state *stream,
|
|||
struct dc_sink *dc_sink_data);
|
||||
void dc_stream_destruct(struct dc_stream_state *stream);
|
||||
|
||||
void dc_stream_assign_stream_id(struct dc_stream_state *stream);
|
||||
|
||||
#endif // _DC_STREAM_PRIV_H_
|
||||
|
|
|
@ -430,71 +430,6 @@ void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
|
|||
dcn32_determine_det_override(dc, context, pipes);
|
||||
}
|
||||
|
||||
/**
|
||||
* dcn32_save_mall_state(): Save MALL (SubVP) state for fast validation cases
|
||||
*
|
||||
* This function saves the MALL (SubVP) case for fast validation cases. For fast validation,
|
||||
* there are situations where a shallow copy of the dc->current_state is created for the
|
||||
* validation. In this case we want to save and restore the mall config because we always
|
||||
* teardown subvp at the beginning of validation (and don't attempt to add it back if it's
|
||||
* fast validation). If we don't restore the subvp config in cases of fast validation +
|
||||
* shallow copy of the dc->current_state, the dc->current_state will have a partially
|
||||
* removed subvp state when we did not intend to remove it.
|
||||
*
|
||||
* NOTE: This function ONLY works if the streams are not moved to a different pipe in the
|
||||
* validation. We don't expect this to happen in fast_validation=1 cases.
|
||||
*
|
||||
* @dc: Current DC state
|
||||
* @context: New DC state to be programmed
|
||||
* @temp_config: struct used to cache the existing MALL state
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void dcn32_save_mall_state(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct mall_temp_config *temp_config)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream)
|
||||
temp_config->mall_stream_config[i] = pipe->stream->mall_stream_config;
|
||||
|
||||
if (pipe->plane_state)
|
||||
temp_config->is_phantom_plane[i] = pipe->plane_state->is_phantom;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dcn32_restore_mall_state(): Restore MALL (SubVP) state for fast validation cases
|
||||
*
|
||||
* Restore the MALL state based on the previously saved state from dcn32_save_mall_state
|
||||
*
|
||||
* @dc: Current DC state
|
||||
* @context: New DC state to be programmed, restore MALL state into here
|
||||
* @temp_config: struct that has the cached MALL state
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
void dcn32_restore_mall_state(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct mall_temp_config *temp_config)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream)
|
||||
pipe->stream->mall_stream_config = temp_config->mall_stream_config[i];
|
||||
|
||||
if (pipe->plane_state)
|
||||
pipe->plane_state->is_phantom = temp_config->is_phantom_plane[i];
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_STRETCHED_V_BLANK 1000 // in micro-seconds (must ensure to match value in FW)
|
||||
/*
|
||||
* Scaling factor for v_blank stretch calculations considering timing in
|
||||
|
|
|
@ -1539,7 +1539,8 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
|
|||
// If SubVP pipe config is unsupported (or cannot be used for UCLK switching)
|
||||
// remove phantom pipes and repopulate dml pipes
|
||||
if (!found_supported_config) {
|
||||
dc->res_pool->funcs->remove_phantom_pipes(dc, context, false);
|
||||
dc_state_remove_phantom_streams_and_planes(dc, context);
|
||||
dc_state_release_phantom_streams_and_planes(dc, context);
|
||||
vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] = dm_dram_clock_change_unsupported;
|
||||
*pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, false);
|
||||
|
||||
|
@ -1937,7 +1938,8 @@ bool dcn32_internal_validate_bw(struct dc *dc,
|
|||
return false;
|
||||
|
||||
// For each full update, remove all existing phantom pipes first
|
||||
dc->res_pool->funcs->remove_phantom_pipes(dc, context, fast_validate);
|
||||
dc_state_remove_phantom_streams_and_planes(dc, context);
|
||||
dc_state_release_phantom_streams_and_planes(dc, context);
|
||||
|
||||
dc->res_pool->funcs->update_soc_for_wm_a(dc, context);
|
||||
|
||||
|
|
|
@ -807,7 +807,7 @@ static void add_phantom_pipes_for_main_pipe(struct dml2_context *ctx, struct dc_
|
|||
}
|
||||
}
|
||||
|
||||
static bool remove_all_planes_for_stream(struct dml2_context *ctx, struct dc_stream_state *stream, struct dc_state *context)
|
||||
static bool remove_all_phantom_planes_for_stream(struct dml2_context *ctx, struct dc_stream_state *stream, struct dc_state *context)
|
||||
{
|
||||
int i, old_plane_count;
|
||||
struct dc_stream_status *stream_status = NULL;
|
||||
|
@ -828,9 +828,11 @@ static bool remove_all_planes_for_stream(struct dml2_context *ctx, struct dc_str
|
|||
for (i = 0; i < old_plane_count; i++)
|
||||
del_planes[i] = stream_status->plane_states[i];
|
||||
|
||||
for (i = 0; i < old_plane_count; i++)
|
||||
for (i = 0; i < old_plane_count; i++) {
|
||||
if (!ctx->config.svp_pstate.callbacks.remove_phantom_plane(ctx->config.svp_pstate.callbacks.dc, stream, del_planes[i], context))
|
||||
return false;
|
||||
ctx->config.svp_pstate.callbacks.release_phantom_plane(ctx->config.svp_pstate.callbacks.dc, context, del_planes[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -839,39 +841,21 @@ bool dml2_svp_remove_all_phantom_pipes(struct dml2_context *ctx, struct dc_state
|
|||
{
|
||||
int i;
|
||||
bool removed_pipe = false;
|
||||
struct dc_plane_state *phantom_plane = NULL;
|
||||
struct dc_stream_state *phantom_stream = NULL;
|
||||
|
||||
for (i = 0; i < ctx->config.dcn_pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &state->res_ctx.pipe_ctx[i];
|
||||
// build scaling params for phantom pipes
|
||||
if (pipe->plane_state && pipe->stream && ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(state, pipe) == SUBVP_PHANTOM) {
|
||||
phantom_plane = pipe->plane_state;
|
||||
phantom_stream = pipe->stream;
|
||||
|
||||
remove_all_planes_for_stream(ctx, pipe->stream, state);
|
||||
ctx->config.svp_pstate.callbacks.remove_phantom_stream(ctx->config.svp_pstate.callbacks.dc, state, pipe->stream);
|
||||
|
||||
/* Ref count is incremented on allocation and also when added to the context.
|
||||
* Therefore we must call release for the the phantom plane and stream once
|
||||
* they are removed from the ctx to finally decrement the refcount to 0 to free.
|
||||
*/
|
||||
ctx->config.svp_pstate.callbacks.release_phantom_plane(ctx->config.svp_pstate.callbacks.dc,
|
||||
state,
|
||||
phantom_plane);
|
||||
ctx->config.svp_pstate.callbacks.release_phantom_stream(ctx->config.svp_pstate.callbacks.dc,
|
||||
state,
|
||||
phantom_stream);
|
||||
remove_all_phantom_planes_for_stream(ctx, phantom_stream, state);
|
||||
ctx->config.svp_pstate.callbacks.remove_phantom_stream(ctx->config.svp_pstate.callbacks.dc, state, phantom_stream);
|
||||
ctx->config.svp_pstate.callbacks.release_phantom_stream(ctx->config.svp_pstate.callbacks.dc, state, phantom_stream);
|
||||
|
||||
removed_pipe = true;
|
||||
}
|
||||
|
||||
// Clear all phantom stream info
|
||||
if (pipe->stream) {
|
||||
pipe->stream->mall_stream_config.type = SUBVP_NONE;
|
||||
pipe->stream->mall_stream_config.paired_stream = NULL;
|
||||
}
|
||||
|
||||
if (pipe->plane_state) {
|
||||
pipe->plane_state->is_phantom = false;
|
||||
}
|
||||
|
|
|
@ -104,7 +104,10 @@ struct dml2_dc_svp_callbacks {
|
|||
struct dc_stream_state *phantom_stream,
|
||||
struct dc_stream_state *main_stream);
|
||||
bool (*add_phantom_plane)(const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, struct dc_state *context);
|
||||
bool (*remove_phantom_plane)(const struct dc *dc, struct dc_stream_state *stream, struct dc_plane_state *plane_state, struct dc_state *context);
|
||||
bool (*remove_phantom_plane)(const struct dc *dc,
|
||||
struct dc_stream_state *stream,
|
||||
struct dc_plane_state *plane_state,
|
||||
struct dc_state *context);
|
||||
enum dc_status (*remove_phantom_stream)(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct dc_stream_state *stream);
|
||||
|
|
|
@ -1685,7 +1685,7 @@ static void disable_vga_and_power_gate_all_controllers(
|
|||
true);
|
||||
|
||||
dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i;
|
||||
dc->hwss.disable_plane(dc,
|
||||
dc->hwss.disable_plane(dc, dc->current_state,
|
||||
&dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
}
|
||||
}
|
||||
|
@ -2134,7 +2134,7 @@ static void dce110_reset_hw_ctx_wrap(
|
|||
old_clk))
|
||||
old_clk->funcs->cs_power_down(old_clk);
|
||||
|
||||
dc->hwss.disable_plane(dc, pipe_ctx_old);
|
||||
dc->hwss.disable_plane(dc, dc->current_state, pipe_ctx_old);
|
||||
|
||||
pipe_ctx_old->stream = NULL;
|
||||
}
|
||||
|
@ -2498,6 +2498,7 @@ static bool wait_for_reset_trigger_to_occur(
|
|||
/* Enable timing synchronization for a group of Timing Generators. */
|
||||
static void dce110_enable_timing_synchronization(
|
||||
struct dc *dc,
|
||||
struct dc_state *state,
|
||||
int group_index,
|
||||
int group_size,
|
||||
struct pipe_ctx *grouped_pipes[])
|
||||
|
@ -2843,7 +2844,7 @@ static void dce110_post_unlock_program_front_end(
|
|||
{
|
||||
}
|
||||
|
||||
static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
||||
static void dce110_power_down_fe(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
int fe_idx = pipe_ctx->plane_res.mi ?
|
||||
|
|
|
@ -1181,7 +1181,9 @@ void dcn10_verify_allow_pstate_change_high(struct dc *dc)
|
|||
}
|
||||
|
||||
/* trigger HW to start disconnect plane from stream on the next vsync */
|
||||
void dcn10_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
||||
void dcn10_plane_atomic_disconnect(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
struct hubp *hubp = pipe_ctx->plane_res.hubp;
|
||||
|
@ -1201,7 +1203,7 @@ void dcn10_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
|||
mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove);
|
||||
// Phantom pipes have OTG disabled by default, so MPCC_STATUS will never assert idle,
|
||||
// so don't wait for MPCC_IDLE in the programming sequence
|
||||
if (opp != NULL && dc_state_get_pipe_subvp_type(NULL, pipe_ctx) != SUBVP_PHANTOM)
|
||||
if (opp != NULL && dc_state_get_pipe_subvp_type(state, pipe_ctx) != SUBVP_PHANTOM)
|
||||
opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
|
||||
|
||||
dc->optimized_required = true;
|
||||
|
@ -1291,7 +1293,7 @@ void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
|||
pipe_ctx->plane_state = NULL;
|
||||
}
|
||||
|
||||
void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
||||
void dcn10_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
@ -1417,12 +1419,12 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
|
|||
dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
|
||||
pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
|
||||
|
||||
hws->funcs.plane_atomic_disconnect(dc, pipe_ctx);
|
||||
hws->funcs.plane_atomic_disconnect(dc, context, pipe_ctx);
|
||||
|
||||
if (tg->funcs->is_tg_enabled(tg))
|
||||
tg->funcs->unlock(tg);
|
||||
|
||||
dc->hwss.disable_plane(dc, pipe_ctx);
|
||||
dc->hwss.disable_plane(dc, context, pipe_ctx);
|
||||
|
||||
pipe_ctx->stream_res.tg = NULL;
|
||||
pipe_ctx->plane_res.hubp = NULL;
|
||||
|
@ -2263,6 +2265,7 @@ void dcn10_enable_vblanks_synchronization(
|
|||
|
||||
void dcn10_enable_timing_synchronization(
|
||||
struct dc *dc,
|
||||
struct dc_state *state,
|
||||
int group_index,
|
||||
int group_size,
|
||||
struct pipe_ctx *grouped_pipes[])
|
||||
|
@ -2277,7 +2280,7 @@ void dcn10_enable_timing_synchronization(
|
|||
DC_SYNC_INFO("Setting up OTG reset trigger\n");
|
||||
|
||||
for (i = 1; i < group_size; i++) {
|
||||
if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(NULL, grouped_pipes[i]) == SUBVP_PHANTOM)
|
||||
if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(state, grouped_pipes[i]) == SUBVP_PHANTOM)
|
||||
continue;
|
||||
|
||||
opp = grouped_pipes[i]->stream_res.opp;
|
||||
|
@ -2297,14 +2300,14 @@ void dcn10_enable_timing_synchronization(
|
|||
if (grouped_pipes[i]->stream == NULL)
|
||||
continue;
|
||||
|
||||
if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(NULL, grouped_pipes[i]) == SUBVP_PHANTOM)
|
||||
if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(state, grouped_pipes[i]) == SUBVP_PHANTOM)
|
||||
continue;
|
||||
|
||||
grouped_pipes[i]->stream->vblank_synchronized = false;
|
||||
}
|
||||
|
||||
for (i = 1; i < group_size; i++) {
|
||||
if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(NULL, grouped_pipes[i]) == SUBVP_PHANTOM)
|
||||
if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(state, grouped_pipes[i]) == SUBVP_PHANTOM)
|
||||
continue;
|
||||
|
||||
grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
|
||||
|
@ -2318,11 +2321,11 @@ void dcn10_enable_timing_synchronization(
|
|||
* synchronized. Look at last pipe programmed to reset.
|
||||
*/
|
||||
|
||||
if (grouped_pipes[1]->stream && dc_state_get_pipe_subvp_type(NULL, grouped_pipes[1]) != SUBVP_PHANTOM)
|
||||
if (grouped_pipes[1]->stream && dc_state_get_pipe_subvp_type(state, grouped_pipes[1]) != SUBVP_PHANTOM)
|
||||
wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg);
|
||||
|
||||
for (i = 1; i < group_size; i++) {
|
||||
if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(NULL, grouped_pipes[i]) == SUBVP_PHANTOM)
|
||||
if (grouped_pipes[i]->stream && dc_state_get_pipe_subvp_type(state, grouped_pipes[i]) == SUBVP_PHANTOM)
|
||||
continue;
|
||||
|
||||
grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
|
||||
|
@ -3022,7 +3025,7 @@ void dcn10_post_unlock_program_front_end(
|
|||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
|
||||
dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
dc->hwss.disable_plane(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) {
|
||||
|
|
|
@ -75,7 +75,7 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
|||
void dcn10_reset_hw_ctx_wrap(
|
||||
struct dc *dc,
|
||||
struct dc_state *context);
|
||||
void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
||||
void dcn10_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx);
|
||||
void dcn10_lock_all_pipes(
|
||||
struct dc *dc,
|
||||
struct dc_state *context,
|
||||
|
@ -108,13 +108,16 @@ void dcn10_power_down_on_boot(struct dc *dc);
|
|||
enum dc_status dce110_apply_ctx_to_hw(
|
||||
struct dc *dc,
|
||||
struct dc_state *context);
|
||||
void dcn10_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
||||
void dcn10_plane_atomic_disconnect(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct pipe_ctx *pipe_ctx);
|
||||
void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data);
|
||||
void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx);
|
||||
void dce110_power_down(struct dc *dc);
|
||||
void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context);
|
||||
void dcn10_enable_timing_synchronization(
|
||||
struct dc *dc,
|
||||
struct dc_state *state,
|
||||
int group_index,
|
||||
int group_size,
|
||||
struct pipe_ctx *grouped_pipes[]);
|
||||
|
|
|
@ -624,9 +624,9 @@ void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
|||
}
|
||||
|
||||
|
||||
void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
||||
void dcn20_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
bool is_phantom = dc_state_get_pipe_subvp_type(NULL, pipe_ctx) == SUBVP_PHANTOM;
|
||||
bool is_phantom = dc_state_get_pipe_subvp_type(state, pipe_ctx) == SUBVP_PHANTOM;
|
||||
struct timing_generator *tg = is_phantom ? pipe_ctx->stream_res.tg : NULL;
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
@ -1369,10 +1369,13 @@ void dcn20_pipe_control_lock(
|
|||
}
|
||||
}
|
||||
|
||||
static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe)
|
||||
static void dcn20_detect_pipe_changes(struct dc_state *old_state,
|
||||
struct dc_state *new_state,
|
||||
struct pipe_ctx *old_pipe,
|
||||
struct pipe_ctx *new_pipe)
|
||||
{
|
||||
bool old_is_phantom = dc_state_get_pipe_subvp_type(NULL, old_pipe) == SUBVP_PHANTOM;
|
||||
bool new_is_phantom = dc_state_get_pipe_subvp_type(NULL, new_pipe) == SUBVP_PHANTOM;
|
||||
bool old_is_phantom = dc_state_get_pipe_subvp_type(old_state, old_pipe) == SUBVP_PHANTOM;
|
||||
bool new_is_phantom = dc_state_get_pipe_subvp_type(new_state, new_pipe) == SUBVP_PHANTOM;
|
||||
|
||||
new_pipe->update_flags.raw = 0;
|
||||
|
||||
|
@ -1420,7 +1423,7 @@ static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx
|
|||
* The remove-add sequence of the phantom pipe always results in the pipe
|
||||
* being blanked in enable_stream_timing (DPG).
|
||||
*/
|
||||
if (new_pipe->stream && dc_state_get_pipe_subvp_type(NULL, new_pipe) == SUBVP_PHANTOM)
|
||||
if (new_pipe->stream && dc_state_get_pipe_subvp_type(new_state, new_pipe) == SUBVP_PHANTOM)
|
||||
new_pipe->update_flags.bits.enable = 1;
|
||||
|
||||
/* Phantom pipes are effectively disabled, if the pipe was previously phantom
|
||||
|
@ -1782,7 +1785,7 @@ static void dcn20_program_pipe(
|
|||
pipe_ctx->pipe_dlg_param.vupdate_offset,
|
||||
pipe_ctx->pipe_dlg_param.vupdate_width);
|
||||
|
||||
if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM)
|
||||
if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM)
|
||||
pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
|
||||
|
@ -1921,7 +1924,7 @@ void dcn20_program_front_end_for_ctx(
|
|||
|
||||
/* Set pipe update flags and lock pipes */
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i],
|
||||
dcn20_detect_pipe_changes(dc->current_state, context, &dc->current_state->res_ctx.pipe_ctx[i],
|
||||
&context->res_ctx.pipe_ctx[i]);
|
||||
|
||||
/* When disabling phantom pipes, turn on phantom OTG first (so we can get double
|
||||
|
@ -1971,7 +1974,7 @@ void dcn20_program_front_end_for_ctx(
|
|||
if (hubbub->funcs->program_det_size && (context->res_ctx.pipe_ctx[i].update_flags.bits.disable ||
|
||||
(context->res_ctx.pipe_ctx[i].plane_state && dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM)))
|
||||
hubbub->funcs->program_det_size(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
|
||||
hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
hws->funcs.plane_atomic_disconnect(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx);
|
||||
}
|
||||
|
||||
|
@ -2044,7 +2047,7 @@ void dcn20_post_unlock_program_front_end(
|
|||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++)
|
||||
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
|
||||
dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
dc->hwss.disable_plane(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
|
||||
|
||||
/*
|
||||
* If we are enabling a pipe, we need to wait for pending clear as this is a critical
|
||||
|
@ -2954,7 +2957,7 @@ void dcn20_fpga_init_hw(struct dc *dc)
|
|||
dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
|
||||
pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
|
||||
/*to do*/
|
||||
hws->funcs.plane_atomic_disconnect(dc, pipe_ctx);
|
||||
hws->funcs.plane_atomic_disconnect(dc, context, pipe_ctx);
|
||||
}
|
||||
|
||||
/* initialize DWB pointer to MCIF_WB */
|
||||
|
@ -2971,7 +2974,7 @@ void dcn20_fpga_init_hw(struct dc *dc)
|
|||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
dc->hwss.disable_plane(dc, pipe_ctx);
|
||||
dc->hwss.disable_plane(dc, context, pipe_ctx);
|
||||
|
||||
pipe_ctx->stream_res.tg = NULL;
|
||||
pipe_ctx->plane_res.hubp = NULL;
|
||||
|
|
|
@ -52,7 +52,7 @@ void dcn20_program_output_csc(struct dc *dc,
|
|||
void dcn20_enable_stream(struct pipe_ctx *pipe_ctx);
|
||||
void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
|
||||
struct dc_link_settings *link_settings);
|
||||
void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
||||
void dcn20_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx);
|
||||
void dcn20_disable_pixel_data(
|
||||
struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
|
|
|
@ -320,7 +320,7 @@ void dcn201_init_hw(struct dc *dc)
|
|||
res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
|
||||
pipe_ctx->stream_res.opp = res_pool->opps[i];
|
||||
/*To do: number of MPCC != number of opp*/
|
||||
hws->funcs.plane_atomic_disconnect(dc, pipe_ctx);
|
||||
hws->funcs.plane_atomic_disconnect(dc, context, pipe_ctx);
|
||||
}
|
||||
|
||||
/* initialize DWB pointer to MCIF_WB */
|
||||
|
@ -337,7 +337,7 @@ void dcn201_init_hw(struct dc *dc)
|
|||
for (i = 0; i < res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
dc->hwss.disable_plane(dc, pipe_ctx);
|
||||
dc->hwss.disable_plane(dc, context, pipe_ctx);
|
||||
|
||||
pipe_ctx->stream_res.tg = NULL;
|
||||
pipe_ctx->plane_res.hubp = NULL;
|
||||
|
@ -369,7 +369,9 @@ void dcn201_init_hw(struct dc *dc)
|
|||
}
|
||||
|
||||
/* trigger HW to start disconnect plane from stream on the next vsync */
|
||||
void dcn201_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
||||
void dcn201_plane_atomic_disconnect(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
struct hubp *hubp = pipe_ctx->plane_res.hubp;
|
||||
|
|
|
@ -33,7 +33,7 @@ void dcn201_init_hw(struct dc *dc);
|
|||
void dcn201_unblank_stream(struct pipe_ctx *pipe_ctx,
|
||||
struct dc_link_settings *link_settings);
|
||||
void dcn201_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx);
|
||||
void dcn201_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
||||
void dcn201_plane_atomic_disconnect(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx);
|
||||
void dcn201_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
||||
void dcn201_set_cursor_attribute(struct pipe_ctx *pipe_ctx);
|
||||
void dcn201_pipe_control_lock(
|
||||
|
|
|
@ -349,8 +349,7 @@ void dcn32_commit_subvp_config(struct dc *dc, struct dc_state *context)
|
|||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe_ctx->stream && pipe_ctx->stream->mall_stream_config.paired_stream &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_MAIN) {
|
||||
if (pipe_ctx->stream && dc_state_get_pipe_subvp_type(context, pipe_ctx) == SUBVP_MAIN) {
|
||||
// There is at least 1 SubVP pipe, so enable SubVP
|
||||
enable_subvp = true;
|
||||
break;
|
||||
|
@ -419,14 +418,7 @@ void dcn32_subvp_pipe_control_lock_fast(union block_sequence_params *params)
|
|||
{
|
||||
struct dc *dc = params->subvp_pipe_control_lock_fast_params.dc;
|
||||
bool lock = params->subvp_pipe_control_lock_fast_params.lock;
|
||||
struct pipe_ctx *pipe_ctx = params->subvp_pipe_control_lock_fast_params.pipe_ctx;
|
||||
bool subvp_immediate_flip = false;
|
||||
|
||||
if (pipe_ctx && pipe_ctx->stream && pipe_ctx->plane_state) {
|
||||
if (dc_state_get_pipe_subvp_type(NULL, pipe_ctx) == SUBVP_MAIN &&
|
||||
pipe_ctx->plane_state->flip_immediate)
|
||||
subvp_immediate_flip = true;
|
||||
}
|
||||
bool subvp_immediate_flip = params->subvp_pipe_control_lock_fast_params.subvp_immediate_flip;
|
||||
|
||||
// Don't need to lock for DRR VSYNC flips -- FW will wait for DRR pending update cleared.
|
||||
if (subvp_immediate_flip) {
|
||||
|
@ -1382,7 +1374,7 @@ void dcn32_update_phantom_vp_position(struct dc *dc,
|
|||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_MAIN &&
|
||||
pipe->stream->mall_stream_config.paired_stream == phantom_pipe->stream) {
|
||||
dc_state_get_paired_subvp_stream(context, pipe->stream) == phantom_pipe->stream) {
|
||||
if (pipe->plane_state && pipe->plane_state->update_flags.bits.position_change) {
|
||||
|
||||
phantom_plane->src_rect.x = pipe->plane_state->src_rect.x;
|
||||
|
@ -1407,7 +1399,6 @@ void dcn32_update_phantom_vp_position(struct dc *dc,
|
|||
void dcn32_apply_update_flags_for_phantom(struct pipe_ctx *phantom_pipe)
|
||||
{
|
||||
phantom_pipe->update_flags.raw = 0;
|
||||
if (dc_state_get_pipe_subvp_type(NULL, phantom_pipe) == SUBVP_PHANTOM) {
|
||||
if (resource_is_pipe_type(phantom_pipe, DPP_PIPE)) {
|
||||
phantom_pipe->update_flags.bits.enable = 1;
|
||||
phantom_pipe->update_flags.bits.mpcc = 1;
|
||||
|
@ -1423,7 +1414,6 @@ void dcn32_apply_update_flags_for_phantom(struct pipe_ctx *phantom_pipe)
|
|||
phantom_pipe->update_flags.bits.global_sync = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool dcn32_dsc_pg_status(
|
||||
|
|
|
@ -814,12 +814,12 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context)
|
|||
dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
|
||||
pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
|
||||
|
||||
hws->funcs.plane_atomic_disconnect(dc, pipe_ctx);
|
||||
hws->funcs.plane_atomic_disconnect(dc, context, pipe_ctx);
|
||||
|
||||
if (tg->funcs->is_tg_enabled(tg))
|
||||
tg->funcs->unlock(tg);
|
||||
|
||||
dc->hwss.disable_plane(dc, pipe_ctx);
|
||||
dc->hwss.disable_plane(dc, context, pipe_ctx);
|
||||
|
||||
pipe_ctx->stream_res.tg = NULL;
|
||||
pipe_ctx->plane_res.hubp = NULL;
|
||||
|
@ -946,10 +946,10 @@ void dcn35_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
|||
pipe_ctx->plane_state = NULL;
|
||||
}
|
||||
|
||||
void dcn35_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
||||
void dcn35_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx)
|
||||
{
|
||||
struct dce_hwseq *hws = dc->hwseq;
|
||||
bool is_phantom = dc_state_get_pipe_subvp_type(NULL, pipe_ctx) == SUBVP_PHANTOM;
|
||||
bool is_phantom = dc_state_get_pipe_subvp_type(state, pipe_ctx) == SUBVP_PHANTOM;
|
||||
struct timing_generator *tg = is_phantom ? pipe_ctx->stream_res.tg : NULL;
|
||||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
|
|
@ -57,7 +57,7 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context);
|
|||
void dcn35_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
||||
void dcn35_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
|
||||
struct dc_state *context);
|
||||
void dcn35_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
||||
void dcn35_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx);
|
||||
|
||||
void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
|
||||
struct pg_block_update *update_state);
|
||||
|
|
|
@ -50,7 +50,7 @@ struct pg_block_update;
|
|||
struct subvp_pipe_control_lock_fast_params {
|
||||
struct dc *dc;
|
||||
bool lock;
|
||||
struct pipe_ctx *pipe_ctx;
|
||||
bool subvp_immediate_flip;
|
||||
};
|
||||
|
||||
struct pipe_control_lock_params {
|
||||
|
@ -200,7 +200,7 @@ struct hw_sequencer_funcs {
|
|||
struct dc_state *context);
|
||||
enum dc_status (*apply_ctx_to_hw)(struct dc *dc,
|
||||
struct dc_state *context);
|
||||
void (*disable_plane)(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
||||
void (*disable_plane)(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx);
|
||||
void (*disable_pixel_data)(struct dc *dc, struct pipe_ctx *pipe_ctx, bool blank);
|
||||
void (*apply_ctx_for_surface)(struct dc *dc,
|
||||
const struct dc_stream_state *stream,
|
||||
|
@ -248,6 +248,7 @@ struct hw_sequencer_funcs {
|
|||
void (*enable_per_frame_crtc_position_reset)(struct dc *dc,
|
||||
int group_size, struct pipe_ctx *grouped_pipes[]);
|
||||
void (*enable_timing_synchronization)(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
int group_index, int group_size,
|
||||
struct pipe_ctx *grouped_pipes[]);
|
||||
void (*enable_vblanks_synchronization)(struct dc *dc,
|
||||
|
@ -474,7 +475,8 @@ void hwss_build_fast_sequence(struct dc *dc,
|
|||
unsigned int dmub_cmd_count,
|
||||
struct block_sequence block_sequence[],
|
||||
int *num_steps,
|
||||
struct pipe_ctx *pipe_ctx);
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_stream_status *stream_status);
|
||||
|
||||
void hwss_send_dmcub_cmd(union block_sequence_params *params);
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ struct hwseq_private_funcs {
|
|||
void (*update_plane_addr)(const struct dc *dc,
|
||||
struct pipe_ctx *pipe_ctx);
|
||||
void (*plane_atomic_disconnect)(struct dc *dc,
|
||||
struct dc_state *state,
|
||||
struct pipe_ctx *pipe_ctx);
|
||||
void (*update_mpcc)(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
||||
bool (*set_input_transfer_func)(struct dc *dc,
|
||||
|
|
|
@ -200,11 +200,7 @@ struct resource_funcs {
|
|||
unsigned int pipe_cnt,
|
||||
unsigned int index);
|
||||
|
||||
bool (*remove_phantom_pipes)(struct dc *dc, struct dc_state *context, bool fast_update);
|
||||
void (*retain_phantom_pipes)(struct dc *dc, struct dc_state *context);
|
||||
void (*get_panel_config_defaults)(struct dc_panel_config *panel_config);
|
||||
void (*save_mall_state)(struct dc *dc, struct dc_state *context, struct mall_temp_config *temp_config);
|
||||
void (*restore_mall_state)(struct dc *dc, struct dc_state *context, struct mall_temp_config *temp_config);
|
||||
void (*build_pipe_pix_clk_params)(struct pipe_ctx *pipe_ctx);
|
||||
};
|
||||
|
||||
|
@ -526,6 +522,14 @@ struct dc_state {
|
|||
* @stream_status: Planes status on a given stream
|
||||
*/
|
||||
struct dc_stream_status stream_status[MAX_PIPES];
|
||||
/**
|
||||
* @phantom_streams: Stream state properties for phantoms
|
||||
*/
|
||||
struct dc_stream_state *phantom_streams[MAX_PHANTOM_PIPES];
|
||||
/**
|
||||
* @phantom_planes: Planes state properties for phantoms
|
||||
*/
|
||||
struct dc_plane_state *phantom_planes[MAX_PHANTOM_PIPES];
|
||||
|
||||
/**
|
||||
* @stream_count: Total of streams in use
|
||||
|
@ -533,6 +537,14 @@ struct dc_state {
|
|||
uint8_t stream_count;
|
||||
uint8_t stream_mask;
|
||||
|
||||
/**
|
||||
* @stream_count: Total phantom streams in use
|
||||
*/
|
||||
uint8_t phantom_stream_count;
|
||||
/**
|
||||
* @stream_count: Total phantom planes in use
|
||||
*/
|
||||
uint8_t phantom_plane_count;
|
||||
/**
|
||||
* @res_ctx: Persistent state of resources
|
||||
*/
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
* to be used inside loops and for determining array sizes.
|
||||
*/
|
||||
#define MAX_PIPES 6
|
||||
#define MAX_PHANTOM_PIPES (MAX_PIPES / 2)
|
||||
#define MAX_DIG_LINK_ENCODERS 7
|
||||
#define MAX_DWB_PIPES 1
|
||||
#define MAX_HPO_DP2_ENCODERS 4
|
||||
|
|
|
@ -1697,69 +1697,6 @@ static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc,
|
|||
return phantom_stream;
|
||||
}
|
||||
|
||||
void dcn32_retain_phantom_pipes(struct dc *dc, struct dc_state *context)
|
||||
{
|
||||
int i;
|
||||
struct dc_plane_state *phantom_plane = NULL;
|
||||
struct dc_stream_state *phantom_stream = NULL;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (resource_is_pipe_type(pipe, OTG_MASTER) &&
|
||||
resource_is_pipe_type(pipe, DPP_PIPE) &&
|
||||
dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {
|
||||
phantom_plane = pipe->plane_state;
|
||||
phantom_stream = pipe->stream;
|
||||
|
||||
dc_plane_state_retain(phantom_plane);
|
||||
dc_stream_retain(phantom_stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return true if removed piped from ctx, false otherwise
|
||||
bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context, bool fast_update)
|
||||
{
|
||||
int i;
|
||||
bool removed_pipe = false;
|
||||
struct dc_plane_state *phantom_plane = NULL;
|
||||
struct dc_stream_state *phantom_stream = NULL;
|
||||
|
||||
for (i = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
|
||||
// build scaling params for phantom pipes
|
||||
if (pipe->plane_state && pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {
|
||||
phantom_plane = pipe->plane_state;
|
||||
phantom_stream = pipe->stream;
|
||||
|
||||
dc_state_rem_all_planes_for_stream(dc, pipe->stream, context);
|
||||
|
||||
/* For non-full updates, a shallow copy of the current state
|
||||
* is created. In this case we don't want to erase the current
|
||||
* state (there can be 2 HIRQL threads, one in flip, and one in
|
||||
* checkMPO) that can cause a race condition.
|
||||
*
|
||||
* This is just a workaround, needs a proper fix.
|
||||
*/
|
||||
if (!fast_update)
|
||||
dc_state_remove_phantom_stream(dc, context, pipe->stream);
|
||||
else
|
||||
dc_state_remove_stream(dc, context, pipe->stream);
|
||||
|
||||
/* Ref count is incremented on allocation and also when added to the context.
|
||||
* Therefore we must call release for the the phantom plane and stream once
|
||||
* they are removed from the ctx to finally decrement the refcount to 0 to free.
|
||||
*/
|
||||
dc_state_release_phantom_plane(dc, context, phantom_plane);
|
||||
dc_state_release_phantom_stream(dc, context, phantom_stream);
|
||||
|
||||
removed_pipe = true;
|
||||
}
|
||||
}
|
||||
return removed_pipe;
|
||||
}
|
||||
|
||||
/* TODO: Input to this function should indicate which pipe indexes (or streams)
|
||||
* require a phantom pipe / stream
|
||||
*/
|
||||
|
@ -1803,7 +1740,6 @@ static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_val
|
|||
int vlevel = 0;
|
||||
int pipe_cnt = 0;
|
||||
display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
|
||||
struct mall_temp_config mall_temp_config;
|
||||
|
||||
/* To handle Freesync properly, setting FreeSync DML parameters
|
||||
* to its default state for the first stage of validation
|
||||
|
@ -1813,29 +1749,12 @@ static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_val
|
|||
|
||||
DC_LOGGER_INIT(dc->ctx->logger);
|
||||
|
||||
/* For fast validation, there are situations where a shallow copy of
|
||||
* of the dc->current_state is created for the validation. In this case
|
||||
* we want to save and restore the mall config because we always
|
||||
* teardown subvp at the beginning of validation (and don't attempt
|
||||
* to add it back if it's fast validation). If we don't restore the
|
||||
* subvp config in cases of fast validation + shallow copy of the
|
||||
* dc->current_state, the dc->current_state will have a partially
|
||||
* removed subvp state when we did not intend to remove it.
|
||||
*/
|
||||
if (fast_validate) {
|
||||
memset(&mall_temp_config, 0, sizeof(mall_temp_config));
|
||||
dcn32_save_mall_state(dc, context, &mall_temp_config);
|
||||
}
|
||||
|
||||
BW_VAL_TRACE_COUNT();
|
||||
|
||||
DC_FP_START();
|
||||
out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate);
|
||||
DC_FP_END();
|
||||
|
||||
if (fast_validate)
|
||||
dcn32_restore_mall_state(dc, context, &mall_temp_config);
|
||||
|
||||
if (pipe_cnt == 0)
|
||||
goto validate_out;
|
||||
|
||||
|
@ -2023,10 +1942,6 @@ static struct resource_funcs dcn32_res_pool_funcs = {
|
|||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
|
||||
.add_phantom_pipes = dcn32_add_phantom_pipes,
|
||||
.remove_phantom_pipes = dcn32_remove_phantom_pipes,
|
||||
.retain_phantom_pipes = dcn32_retain_phantom_pipes,
|
||||
.save_mall_state = dcn32_save_mall_state,
|
||||
.restore_mall_state = dcn32_restore_mall_state,
|
||||
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
|
||||
};
|
||||
|
||||
|
|
|
@ -91,12 +91,6 @@ bool dcn32_release_post_bldn_3dlut(
|
|||
struct dc_3dlut **lut,
|
||||
struct dc_transfer_func **shaper);
|
||||
|
||||
bool dcn32_remove_phantom_pipes(struct dc *dc,
|
||||
struct dc_state *context, bool fast_update);
|
||||
|
||||
void dcn32_retain_phantom_pipes(struct dc *dc,
|
||||
struct dc_state *context);
|
||||
|
||||
void dcn32_add_phantom_pipes(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
|
@ -169,14 +163,6 @@ void dcn32_determine_det_override(struct dc *dc,
|
|||
void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes);
|
||||
|
||||
void dcn32_save_mall_state(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct mall_temp_config *temp_config);
|
||||
|
||||
void dcn32_restore_mall_state(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
struct mall_temp_config *temp_config);
|
||||
|
||||
struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, const struct dc_state *context);
|
||||
|
||||
bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe);
|
||||
|
|
|
@ -1607,10 +1607,6 @@ static struct resource_funcs dcn321_res_pool_funcs = {
|
|||
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
|
||||
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
|
||||
.add_phantom_pipes = dcn32_add_phantom_pipes,
|
||||
.remove_phantom_pipes = dcn32_remove_phantom_pipes,
|
||||
.retain_phantom_pipes = dcn32_retain_phantom_pipes,
|
||||
.save_mall_state = dcn32_save_mall_state,
|
||||
.restore_mall_state = dcn32_restore_mall_state,
|
||||
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue