drm/amd/display: Refactor phantom resource allocation
authorDillon Varone <dillon.varone@amd.com>
Tue, 21 Nov 2023 20:07:01 +0000 (15:07 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 19 Dec 2023 19:59:02 +0000 (14:59 -0500)
[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>
33 files changed:
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/core/dc_state.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
drivers/gpu/drm/amd/display/dc/dc_state.h
drivers/gpu/drm/amd/display/dc/dc_state_priv.h
drivers/gpu/drm/amd/display/dc/dc_stream.h
drivers/gpu/drm/amd/display/dc/dc_stream_priv.h
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c
drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h
drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c

index b3ffb25dc6b116f5cff565bd8309266aa3981752..fc230ecc71805dadde2ddaee389c938586c83508 100644 (file)
@@ -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,
index f5250022b98e561d9ec88718caa81765f3b5d2a8..630a55b2c1d481dfc7c4ccb9e90de985706d917a 100644 (file)
@@ -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,7 +1183,11 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
                                        tg->funcs->enable_crtc(tg);
                                }
                        }
-                       dc_state_rem_all_planes_for_stream(dc, old_stream, dangling_context);
+
+                       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);
 
                        if (pipe->stream && pipe->plane_state)
@@ -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;
        }
index 170bad6f33c7b1c8bf56d1bf7a5951442e4c4ac1..48fdfacc413aa3549ebfe2b885f7f4971e63a1d8 100644 (file)
@@ -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 = &current_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)++;
        }
index 4a6a7d7557e0747bb9ac6b514d197066c567597f..716b59bd03b65b1d0fa4c83f4673f44a93d9c9ba 100644 (file)
@@ -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_rem_all_planes_for_stream(dc, del_streams[i], context)) {
-                       res = DC_FAIL_DETACH_SURFACES;
-                       goto fail;
+               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]);
                }
 
-               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)
index ec5b0d114c7c21e95d55616f59b091eabfa149ce..66a70a60c479a16ab77bde91b9a01e92e6507935 100644 (file)
@@ -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"
        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];
+       kref_init(&new_state->refcount);
 
-               if (cur_pipe->top_pipe)
-                       cur_pipe->top_pipe =  &new_state->res_ctx.pipe_ctx[cur_pipe->top_pipe->pipe_idx];
+       return new_state;
+}
 
-               if (cur_pipe->bottom_pipe)
-                       cur_pipe->bottom_pipe = &new_state->res_ctx.pipe_ctx[cur_pipe->bottom_pipe->pipe_idx];
+void dc_state_copy_current(struct dc *dc, struct dc_state *dst_state)
+{
+       dc_state_copy(dst_state, dc->current_state);
+}
 
-               if (cur_pipe->prev_odm_pipe)
-                       cur_pipe->prev_odm_pipe =  &new_state->res_ctx.pipe_ctx[cur_pipe->prev_odm_pipe->pipe_idx];
+struct dc_state *dc_state_create_current_copy(struct dc *dc)
+{
+       return dc_state_create_copy(dc->current_state);
+}
 
-               if (cur_pipe->next_odm_pipe)
-                       cur_pipe->next_odm_pipe = &new_state->res_ctx.pipe_ctx[cur_pipe->next_odm_pipe->pipe_idx];
-       }
+void dc_state_construct(struct dc *dc, struct dc_state *state)
+{
+       state->clk_mgr = dc->clk_mgr;
 
-       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]);
+       /* 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;
 
-       kref_init(&new_state->refcount);
+       /* release tracked phantoms */
+       for (i = 0; i < state->phantom_stream_count; i++) {
+               dc_stream_release(state->phantom_streams[i]);
+               state->phantom_streams[i] = NULL;
+       }
 
-       return new_state;
+       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 *context)
+void dc_state_retain(struct dc_state *state)
 {
-       kref_get(&context->refcount);
+       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,35 +594,65 @@ 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) {
-               phantom_stream->signal = SIGNAL_TYPE_VIRTUAL;
-               phantom_stream->dpms_off = true;
+       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,8 +676,17 @@ 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)
-               phantom_plane->is_phantom = true;
+       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]);
+}
index 86de4bf2ce1385f122f0e332ebfe7deaa447d948..f2b265ed7fc21599f82b35a20aa5c51e4732481d 100644 (file)
@@ -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)
index d638679cf31ae3e48fffa7daae7ac59ceb933579..a270b4bf7b95c32636fddd243d26e7290f5b77db 100644 (file)
@@ -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,
index 704d4ff722f02972004604196cc95fb898ebdd3b..1d315f7cdce381ef09ca7e632bf3a7ef20b4ee70 100644 (file)
@@ -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) &&
index df1a8b85a6523908acf1ec04aef46ab3c2fd6679..d167fdbfa8a970dfb3b1c4f1827963f04897e22e 100644 (file)
 #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);
 
index 16c09caa131761218df306b310409323c1a4cb26..c1f44e09a6c1bf79841882d0e1ea0a41ce1e5ca5 100644 (file)
 #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_ */
index f617428c6a57684b9b44ec2d5c9809c800b31bf0..a23eebd9933b72ea5c1c2a951a560232250bf34c 100644 (file)
@@ -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
index 710d3b04c7e86252bc72c5368ad762181c32c088..7476fd52ce2b55da66f987be4194c852cdc8f3d3 100644 (file)
@@ -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_
index b3d3607411756dc4fddafc3d29746c3f337fea6c..1743ebcd6b2ee1c75882cb44ee2c7750f13b8c43 100644 (file)
@@ -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
index 50d223fa1e49887d13636a78e297920fbc0d98db..10c890a9cb7c274256811e785769b3a4aadb7a60 100644 (file)
@@ -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);
 
index 0c146af34d82a5b97ead1c3ff201beedd994edb7..282d70e2b18ab8a2da54346562eb7b79fb451b43 100644 (file)
@@ -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;
                }
index 505a5d7ae20ddbd2b8ba8132d3611a80808dd006..ee0eb184eb6d7ea23bec303133cfaa76dc40854a 100644 (file)
@@ -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);
index 968f6ba7ccf61fac91be1bdce9238c585f5cae73..762e674f9998c2dc4d819740f5f072696f64cdd9 100644 (file)
@@ -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 ?
index 96fb563b100902799501e15a631b706a715cd9db..d0247cd7833f0f739f26d56116c71339fc899cc6 100644 (file)
@@ -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) {
index ef6d56da417cdffb6b15de4529972d8ef3795bc4..bc5dd68a2408801d0e9f46373e523e1dab01c461 100644 (file)
@@ -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[]);
index 0c9f4ea109cb122e0552270127db8987ffc6c2b3..88fe102f8288226aa9d9ad9d50a12cdf32bb4cd0 100644 (file)
@@ -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;
index ab02e4e9c8c292fa051b9a4cd2a63f1881767586..b94c85340abff7c02f3ec59025b04c8417d77bd6 100644 (file)
@@ -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,
index d3fe6092f50e8f8a1ff72f59c79f17a2f6167bf6..d5769f38874fd4d1d9bd72d988f9e53bfa966c92 100644 (file)
@@ -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;
index 26cd62be64181e643a79e8a2788ce2d8499236c1..6a50a9894be6ae3caff35eb303efc7178f74acd9 100644 (file)
@@ -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(
index d3d16c7af38c326de0bb14c747281e352149b46a..6f360f008f67a0c76d69ef4dc9e033e3e2d9e5d9 100644 (file)
@@ -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,21 +1399,19 @@ 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;
-                       phantom_pipe->update_flags.bits.dppclk = 1;
-                       phantom_pipe->update_flags.bits.hubp_interdependent = 1;
-                       phantom_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
-                       phantom_pipe->update_flags.bits.gamut_remap = 1;
-                       phantom_pipe->update_flags.bits.scaler = 1;
-                       phantom_pipe->update_flags.bits.viewport = 1;
-                       phantom_pipe->update_flags.bits.det_size = 1;
-                       if (resource_is_pipe_type(phantom_pipe, OTG_MASTER)) {
-                               phantom_pipe->update_flags.bits.odm = 1;
-                               phantom_pipe->update_flags.bits.global_sync = 1;
-                       }
+       if (resource_is_pipe_type(phantom_pipe, DPP_PIPE)) {
+               phantom_pipe->update_flags.bits.enable = 1;
+               phantom_pipe->update_flags.bits.mpcc = 1;
+               phantom_pipe->update_flags.bits.dppclk = 1;
+               phantom_pipe->update_flags.bits.hubp_interdependent = 1;
+               phantom_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
+               phantom_pipe->update_flags.bits.gamut_remap = 1;
+               phantom_pipe->update_flags.bits.scaler = 1;
+               phantom_pipe->update_flags.bits.viewport = 1;
+               phantom_pipe->update_flags.bits.det_size = 1;
+               if (resource_is_pipe_type(phantom_pipe, OTG_MASTER)) {
+                       phantom_pipe->update_flags.bits.odm = 1;
+                       phantom_pipe->update_flags.bits.global_sync = 1;
                }
        }
 }
index 56a4bc476684596c47d984fe3efd88529f0774c0..582852ed21fbf6e7cbbfb2dd33f0c5d7157211d4 100644 (file)
@@ -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);
index 3837038dc4a8f4a35645dc932401937aa7f32c6a..b7bafe7fe2fdb4dda44649a785a4c87fe7065300 100644 (file)
@@ -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);
index 45dc6d4e956273240f954af6730b6986d24f7cc9..6ca8c5488d507aadafcd11a9589effd187fcf277 100644 (file)
@@ -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);
 
index 82c5921668754c54a9379f0a6cb5bd4a780bab66..6137cf09aa54d25750246e86583c5938e557501b 100644 (file)
@@ -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,
index 10397d4dfb0753fb81f971b6280a0f9d817e5f23..c3b973abb89a73ea4139af0318840af37b608245 100644 (file)
@@ -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
         */
index b95ae9596c3b1e541535291d5c09f04132512574..dcae23faeee3d322b64ba4d0bb7fcb1ad7a3c65c 100644 (file)
@@ -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
index dbcb9c5ea9af2a1804a9b77a82649ce028980681..c4d71e7f18af47ba47dbc89e1a9098a0a4eade04 100644 (file)
@@ -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,
 };
 
index 9ca799da1a56e0e38466440c14251fa25ec64ca1..b27fadd452bb856b1397ea6cd44260030d5e1e8c 100644 (file)
@@ -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);
index 8c278c2fd2870e3b9fecb8126110e7f33ed5c661..74412e5f03fefbaa9350982ac92bc528cc8e80e8 100644 (file)
@@ -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,
 };