/* 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 *
*/
/* If this assert is hit then we have a link encoder dynamic management issue */
ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true);
bool is_dtbclk_required(conststruct dc *dc, struct dc_state *context)
{ int i;
for (i = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) continue; if (is_dp2p0_output_encoder(&context->res_ctx.pipe_ctx[i])) returntrue;
} returnfalse;
}
int dml2_helper_find_dml_pipe_idx_by_stream_id(struct dml2_context *ctx, unsignedintstream_id)
{ int i; for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) { if (ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[i] && ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[i] == stream_id) return i;
}
return -1;
}
staticint find_dml_pipe_idx_by_plane_id(struct dml2_context *ctx, unsignedint plane_id)
{ int i; for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) { if (ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id_valid[i] && ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_id[i] == plane_id) return i;
}
for (dc_pipe_ctx_index = 0; dc_pipe_ctx_index < pipe_cnt; dc_pipe_ctx_index++) { if (!context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream) continue; /* The DML2 and the DC logic of determining pipe indices are different from each other so * there is a need to know which DML pipe index maps to which DC pipe. The code below * finds a dml_pipe_index from the plane id if a plane is valid. If a plane is not valid then
* it finds a dml_pipe_index from the stream id. */ if (get_plane_id(in_ctx, context, context->res_ctx.pipe_ctx[dc_pipe_ctx_index].plane_state,
context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->stream_id,
in_ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[context->res_ctx.pipe_ctx[dc_pipe_ctx_index].pipe_idx], &plane_id)) {
dml_pipe_idx = find_dml_pipe_idx_by_plane_id(in_ctx, plane_id);
} else {
dml_pipe_idx = dml2_helper_find_dml_pipe_idx_by_stream_id(in_ctx, context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->stream_id);
}
if (dml_pipe_idx == 0xFFFFFFFF) continue;
ASSERT(in_ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[dml_pipe_idx]);
ASSERT(in_ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[dml_pipe_idx] == context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->stream_id);
/* Use the dml_pipe_index here for the getters to fetch the correct values and dc_pipe_index in the pipe_ctx to populate them * at the right locations.
*/
populate_pipe_ctx_dlg_params_from_dml(&context->res_ctx.pipe_ctx[dc_pipe_ctx_index], &context->bw_ctx.dml2->v20.dml_core_ctx, dml_pipe_idx);
pipe_mall_type = dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[dc_pipe_ctx_index]); if (pipe_mall_type == SUBVP_PHANTOM) { // Phantom pipe requires that DET_SIZE = 0 and no unbounded requests
context->res_ctx.pipe_ctx[dc_pipe_ctx_index].det_buffer_size_kb = 0;
context->res_ctx.pipe_ctx[dc_pipe_ctx_index].unbounded_req = false;
} else {
context->res_ctx.pipe_ctx[dc_pipe_ctx_index].det_buffer_size_kb = dml_get_det_buffer_size_kbytes(&context->bw_ctx.dml2->v20.dml_core_ctx, dml_pipe_idx); // Unbounded requesting should not ever be used when more than 1 pipe is enabled.
context->res_ctx.pipe_ctx[dc_pipe_ctx_index].unbounded_req = in_ctx->v20.dml_core_ctx.ms.UnboundedRequestEnabledThisState;
}
if (context->stream_count != 0) { for (i = 0; i < context->stream_count; i++) { if (context->streams[i]->num_wb_info != 0)
j++;
}
} if (j == 0) /*no dwb */ return; for (i = 0; i < __DML_NUM_DMB__; i++) {
bw_writeback = &context->bw_ctx.bw.dcn.bw_writeback;
wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[i];
for (j = 0 ; j < 4; j++) { /*current dml only has one set of watermark, need to follow up*/
bw_writeback->mcif_wb_arb[i].cli_watermark[j] =
dml_get_wm_writeback_urgent(dml_core_ctx) * 1000;
bw_writeback->mcif_wb_arb[i].pstate_watermark[j] =
dml_get_wm_writeback_dram_clock_change(dml_core_ctx) * 1000;
} if (context->res_ctx.pipe_ctx[i].stream->phy_pix_clk != 0) { /* time_per_pixel should be in u6.6 format */
bw_writeback->mcif_wb_arb[i].time_per_pixel =
(1000000 << 6) / context->res_ctx.pipe_ctx[i].stream->phy_pix_clk;
}
bw_writeback->mcif_wb_arb[i].slice_lines = 32;
bw_writeback->mcif_wb_arb[i].arbitration_slice = 2;
bw_writeback->mcif_wb_arb[i].max_scaled_time =
dml2_calc_max_scaled_time(wb_arb_params->time_per_pixel,
wbif_mode, wb_arb_params->cli_watermark[0]); /*not required any more*/
bw_writeback->mcif_wb_arb[i].dram_speed_change_duration =
dml_get_wm_writeback_dram_clock_change(dml_core_ctx) * 1000;
}
} void dml2_initialize_det_scratch(struct dml2_context *in_ctx)
{ int i;
for (i = 0; i < MAX_PLANES; i++) {
in_ctx->det_helper_scratch.dpps_per_surface[i] = 1;
}
}
for (plane_index = 0; plane_index < dml_dispcfg->num_surfaces; plane_index++) { /* Number of planes per stream */
num_of_planes_per_stream[stream_index] += 1;
/* If the override size is not divisible by det_segment_size then round off to nearest number divisible by det_segment_size as * this is a requirement.
*/ if (dml_dispcfg->plane.DETSizeOverride[plane_index] % in_ctx->config.det_segment_size != 0) {
dml_dispcfg->plane.DETSizeOverride[plane_index] = dml_dispcfg->plane.DETSizeOverride[plane_index] & ~0x3F;
}
for (i = 0; i < MAX_PIPES; i++) { if (!display_state->res_ctx.pipe_ctx[i].stream) continue; if (get_plane_id(in_ctx, display_state, display_state->res_ctx.pipe_ctx[i].plane_state,
display_state->res_ctx.pipe_ctx[i].stream->stream_id,
in_ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[display_state->res_ctx.pipe_ctx[i].pipe_idx], &plane_id))
dml_pipe_idx = find_dml_pipe_idx_by_plane_id(in_ctx, plane_id); else
dml_pipe_idx = dml2_helper_find_dml_pipe_idx_by_stream_id(in_ctx, display_state->res_ctx.pipe_ctx[i].stream->stream_id);
if (dml_pipe_idx == 0xFFFFFFFF) continue;
total_det_allocated += dml_get_det_buffer_size_kbytes(&in_ctx->v20.dml_core_ctx, dml_pipe_idx); if (total_det_allocated > max_det_size) {
need_recalculation = true;
}
}
/* Store the DPPPerSurface for correctly determining the number of planes in the next call. */ for (i = 0; i < MAX_PLANES; i++) {
det_scratch->dpps_per_surface[i] = in_ctx->v20.scratch.cur_display_config.hw.DPPPerSurface[i];
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.