linux/drivers/gpu/drm/amd/display/dc/dml2/dml2_mall_phantom.c

/* SPDX-License-Identifier: MIT */
/*
 * Copyright 2023 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: AMD
 *
 */

#include "dml2_dc_types.h"
#include "dml2_internal_types.h"
#include "dml2_utils.h"
#include "dml2_mall_phantom.h"

unsigned int dml2_helper_calculate_num_ways_for_subvp(struct dml2_context *ctx, struct dc_state *context)
{}

static void merge_pipes_for_subvp(struct dml2_context *ctx, struct dc_state *context)
{}

static bool all_pipes_have_stream_and_plane(struct dml2_context *ctx, const struct dc_state *context)
{}

static bool mpo_in_use(const struct dc_state *context)
{}

/*
 * dcn32_get_num_free_pipes: Calculate number of free pipes
 *
 * This function assumes that a "used" pipe is a pipe that has
 * both a stream and a plane assigned to it.
 *
 * @dc: current dc state
 * @context: new dc state
 *
 * Return:
 * Number of free pipes available in the context
 */
static unsigned int get_num_free_pipes(struct dml2_context *ctx, struct dc_state *state)
{}

/*
 * dcn32_assign_subvp_pipe: Function to decide which pipe will use Sub-VP.
 *
 * We enter this function if we are Sub-VP capable (i.e. enough pipes available)
 * and regular P-State switching (i.e. VACTIVE/VBLANK) is not supported, or if
 * we are forcing SubVP P-State switching on the current config.
 *
 * The number of pipes used for the chosen surface must be less than or equal to the
 * number of free pipes available.
 *
 * In general we choose surfaces with the longest frame time first (better for SubVP + VBLANK).
 * For multi-display cases the ActiveDRAMClockChangeMargin doesn't provide enough info on its own
 * for determining which should be the SubVP pipe (need a way to determine if a pipe / plane doesn't
 * support MCLK switching naturally [i.e. ACTIVE or VBLANK]).
 *
 * @param dc: current dc state
 * @param context: new dc state
 * @param index: [out] dc pipe index for the pipe chosen to have phantom pipes assigned
 *
 * Return:
 * True if a valid pipe assignment was found for Sub-VP. Otherwise false.
 */
static bool assign_subvp_pipe(struct dml2_context *ctx, struct dc_state *context, unsigned int *index)
{}

/*
 * enough_pipes_for_subvp: Function to check if there are "enough" pipes for SubVP.
 *
 * This function returns true if there are enough free pipes
 * to create the required phantom pipes for any given stream
 * (that does not already have phantom pipe assigned).
 *
 * e.g. For a 2 stream config where the first stream uses one
 * pipe and the second stream uses 2 pipes (i.e. pipe split),
 * this function will return true because there is 1 remaining
 * pipe which can be used as the phantom pipe for the non pipe
 * split pipe.
 *
 * @dc: current dc state
 * @context: new dc state
 *
 * Return:
 * True if there are enough free pipes to assign phantom pipes to at least one
 * stream that does not already have phantom pipes assigned. Otherwise false.
 */
static bool enough_pipes_for_subvp(struct dml2_context *ctx, struct dc_state *state)
{}

/*
 * subvp_subvp_schedulable: Determine if SubVP + SubVP config is schedulable
 *
 * High level algorithm:
 * 1. Find longest microschedule length (in us) between the two SubVP pipes
 * 2. Check if the worst case overlap (VBLANK in middle of ACTIVE) for both
 * pipes still allows for the maximum microschedule to fit in the active
 * region for both pipes.
 *
 * @dc: current dc state
 * @context: new dc state
 *
 * Return:
 * bool - True if the SubVP + SubVP config is schedulable, false otherwise
 */
static bool subvp_subvp_schedulable(struct dml2_context *ctx, struct dc_state *context)
{}

/*
 * dml2_svp_drr_schedulable: Determine if SubVP + DRR config is schedulable
 *
 * High level algorithm:
 * 1. Get timing for SubVP pipe, phantom pipe, and DRR pipe
 * 2. Determine the frame time for the DRR display when adding required margin for MCLK switching
 * (the margin is equal to the MALL region + DRR margin (500us))
 * 3.If (SubVP Active - Prefetch > Stretched DRR frame + max(MALL region, Stretched DRR frame))
 * then report the configuration as supported
 *
 * @dc: current dc state
 * @context: new dc state
 * @drr_pipe: DRR pipe_ctx for the SubVP + DRR config
 *
 * Return:
 * bool - True if the SubVP + DRR config is schedulable, false otherwise
 */
bool dml2_svp_drr_schedulable(struct dml2_context *ctx, struct dc_state *context, struct dc_crtc_timing *drr_timing)
{}


/*
 * subvp_vblank_schedulable: Determine if SubVP + VBLANK config is schedulable
 *
 * High level algorithm:
 * 1. Get timing for SubVP pipe, phantom pipe, and VBLANK pipe
 * 2. If (SubVP Active - Prefetch > Vblank Frame Time + max(MALL region, Vblank blanking time))
 * then report the configuration as supported
 * 3. If the VBLANK display is DRR, then take the DRR static schedulability path
 *
 * @dc: current dc state
 * @context: new dc state
 *
 * Return:
 * bool - True if the SubVP + VBLANK/DRR config is schedulable, false otherwise
 */
static bool subvp_vblank_schedulable(struct dml2_context *ctx, struct dc_state *context)
{}

/*
 * subvp_validate_static_schedulability: Check which SubVP case is calculated and handle
 * static analysis based on the case.
 *
 * Three cases:
 * 1. SubVP + SubVP
 * 2. SubVP + VBLANK (DRR checked internally)
 * 3. SubVP + VACTIVE (currently unsupported)
 *
 * @dc: current dc state
 * @context: new dc state
 * @vlevel: Voltage level calculated by DML
 *
 * Return:
 * bool - True if statically schedulable, false otherwise
 */
bool dml2_svp_validate_static_schedulability(struct dml2_context *ctx, struct dc_state *context, enum dml_dram_clock_change_support pstate_change_type)
{}

static void set_phantom_stream_timing(struct dml2_context *ctx, struct dc_state *state,
				     struct pipe_ctx *ref_pipe,
				     struct dc_stream_state *phantom_stream,
				     unsigned int dc_pipe_idx,
				     unsigned int svp_height,
				     unsigned int svp_vstartup)
{}

static struct dc_stream_state *enable_phantom_stream(struct dml2_context *ctx, struct dc_state *state, unsigned int dc_pipe_idx, unsigned int svp_height, unsigned int vstartup)
{}

static void enable_phantom_plane(struct dml2_context *ctx,
		struct dc_state *state,
		struct dc_stream_state *phantom_stream,
		unsigned int dc_pipe_idx)
{}

static void add_phantom_pipes_for_main_pipe(struct dml2_context *ctx, struct dc_state *state, unsigned int main_pipe_idx, unsigned int svp_height, unsigned int vstartup)
{}

static bool remove_all_phantom_planes_for_stream(struct dml2_context *ctx, struct dc_stream_state *stream, struct dc_state *context)
{}

bool dml2_svp_remove_all_phantom_pipes(struct dml2_context *ctx, struct dc_state *state)
{}


/* Conditions for setting up phantom pipes for SubVP:
 * 1. Not force disable SubVP
 * 2. Full update (i.e. !fast_validate)
 * 3. Enough pipes are available to support SubVP (TODO: Which pipes will use VACTIVE / VBLANK / SUBVP?)
 * 4. Display configuration passes validation
 * 5. (Config doesn't support MCLK in VACTIVE/VBLANK || dc->debug.force_subvp_mclk_switch)
 */
bool dml2_svp_add_phantom_pipe_to_dc_state(struct dml2_context *ctx, struct dc_state *state, struct dml_mode_support_info_st *mode_support_info)
{}