/* Check whether stream is supported by DIG link encoders. */ staticbool is_dig_link_enc_stream(struct dc_stream_state *stream)
{ bool is_dig_stream = false; struct link_encoder *link_enc = NULL; int i;
/* Loop over created link encoder objects. */ if (stream) { for (i = 0; i < stream->ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) {
link_enc = stream->ctx->dc->res_pool->link_encoders[i];
/* Need to check link signal type rather than stream signal type which may not *yetmatch.
*/ if (link_enc && ((uint32_t)stream->link->connector_signal & link_enc->output_signals)) {
is_dig_stream = true; break;
}
}
} return is_dig_stream;
}
staticstruct link_enc_assignment get_assignment(struct dc *dc, int i)
{ struct link_enc_assignment assignment;
staticvoid remove_link_enc_assignment( struct dc_state *state, struct dc_stream_state *stream, enum engine_id eng_id)
{ int eng_idx; int i;
if (eng_id != ENGINE_ID_UNKNOWN) {
eng_idx = eng_id - ENGINE_ID_DIGA;
/* stream ptr of stream in dc_state used to update correct entry in *link_enc_assignmentstable.
*/ for (i = 0; i < MAX_PIPES; i++) { struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i];
if (assignment.valid && assignment.stream == stream) {
state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].valid = false; /* Only add link encoder back to availability pool if not being *usedbyanyotherstream(i.e.removingSSTstreamorlastMSTstream).
*/ if (get_stream_using_link_enc(state, eng_id) == NULL)
state->res_ctx.link_enc_cfg_ctx.link_enc_avail[eng_idx] = eng_id;
staticvoid add_link_enc_assignment( struct dc_state *state, struct dc_stream_state *stream, enum engine_id eng_id)
{ int eng_idx; int i;
if (eng_id != ENGINE_ID_UNKNOWN) {
eng_idx = eng_id - ENGINE_ID_DIGA;
/* stream ptr of stream in dc_state used to update correct entry in *link_enc_assignmentstable.
*/ for (i = 0; i < state->stream_count; i++) { if (stream == state->streams[i]) {
state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i] = (struct link_enc_assignment){
.valid = true,
.ep_id = (struct display_endpoint_id) {
.link_id = stream->link->link_id,
.ep_type = stream->link->ep_type},
.eng_id = eng_id,
.stream = stream};
dc_stream_retain(stream);
state->res_ctx.link_enc_cfg_ctx.link_enc_avail[eng_idx] = ENGINE_ID_UNKNOWN;
stream->link_enc = stream->ctx->dc->res_pool->link_encoders[eng_idx]; break;
}
}
/* Attempted to add an encoder assignment for a stream not in dc_state. */
ASSERT(i != state->stream_count);
}
}
/* Return first available DIG link encoder. */ staticenum engine_id find_first_avail_link_enc( conststruct dc_context *ctx, conststruct dc_state *state, enum engine_id eng_id_requested)
{ enum engine_id eng_id = ENGINE_ID_UNKNOWN; int i;
if (eng_id_requested != ENGINE_ID_UNKNOWN) {
for (i = 0; i < ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) {
eng_id = state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i]; if (eng_id == eng_id_requested) return eng_id;
}
}
eng_id = ENGINE_ID_UNKNOWN;
for (i = 0; i < ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) {
eng_id = state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i]; if (eng_id != ENGINE_ID_UNKNOWN) break;
}
return eng_id;
}
/* Check for availability of link encoder eng_id. */ staticbool is_avail_link_enc(struct dc_state *state, enum engine_id eng_id, struct dc_stream_state *stream)
{ bool is_avail = false; int eng_idx = eng_id - ENGINE_ID_DIGA;
/* An encoder is available if it is still in the availability pool. */ if (eng_id != ENGINE_ID_UNKNOWN && state->res_ctx.link_enc_cfg_ctx.link_enc_avail[eng_idx] != ENGINE_ID_UNKNOWN) {
is_avail = true;
} else { struct dc_stream_state *stream_assigned = NULL;
/* MST streams share the same link and should share the same encoder. *Ifastreamthathasalreadybeenassignedalinkencoderusesasthe *samelinkasthestreamcheckingforavailability,itisanMSTstream *andshouldusethesamelinkencoder.
*/
stream_assigned = get_stream_using_link_enc(state, eng_id); if (stream_assigned && stream != stream_assigned && stream->link == stream_assigned->link)
is_avail = true;
}
return is_avail;
}
/* Test for display_endpoint_id equality. */ staticbool are_ep_ids_equal(struct display_endpoint_id *lhs, struct display_endpoint_id *rhs)
{ bool are_equal = false;
for (i = 0; i < MAX_PIPES; i++) { struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; if (assignment.eng_id == ENGINE_ID_UNKNOWN) continue;
/* Release DIG link encoder resources before running assignment algorithm. */ for (i = 0; i < dc->current_state->stream_count; i++)
dc->res_pool->funcs->link_enc_unassign(state, dc->current_state->streams[i]);
for (i = 0; i < MAX_PIPES; i++)
ASSERT(state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].valid == false);
/* (a) Assign DIG link encoders to physical (unmappable) endpoints first. */ for (i = 0; i < stream_count; i++) { struct dc_stream_state *stream = streams[i];
/* skip it if the link is mappable endpoint. */ if (stream->link->is_dig_mapping_flexible) continue;
/* Skip stream if not supported by DIG link encoder. */ if (!is_dig_link_enc_stream(stream)) continue;
/* Physical endpoints have a fixed mapping to DIG link encoders. */
eng_id = stream->link->eng_id;
add_link_enc_assignment(state, stream, eng_id);
}
/* (b) Retain previous assignments for mappable endpoints if encoders still available. */
eng_id = ENGINE_ID_UNKNOWN;
if (state != dc->current_state) { struct dc_state *prev_state = dc->current_state;
for (i = 0; i < stream_count; i++) { struct dc_stream_state *stream = state->streams[i];
/* Skip it if the link is NOT mappable endpoint. */ if (!stream->link->is_dig_mapping_flexible) continue;
/* Skip stream if not supported by DIG link encoder. */ if (!is_dig_link_enc_stream(stream)) continue;
/* (c) Then assign encoders to remaining mappable endpoints. */
eng_id = ENGINE_ID_UNKNOWN;
for (i = 0; i < stream_count; i++) { struct dc_stream_state *stream = streams[i]; struct link_encoder *link_enc = NULL;
/* Skip it if the link is NOT mappable endpoint. */ if (!stream->link->is_dig_mapping_flexible) continue;
/* Skip if encoder assignment retained in step (b) above. */ if (stream->link_enc) continue;
/* Skip stream if not supported by DIG link encoder. */ if (!is_dig_link_enc_stream(stream)) {
ASSERT(stream->link->is_dig_mapping_flexible != true); continue;
}
/* Mappable endpoints have a flexible mapping to DIG link encoders. */
/* For MST, multiple streams will share the same link / display *endpoint.Thesestreamsshouldusethesamelinkencoder *assignedtothatendpoint.
*/
link_enc = get_link_enc_used_by_link(state, stream->link); if (link_enc == NULL) {
bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id, struct dc_link *link)
{ bool is_avail = true; int i;
/* An encoder is not available if it has already been assigned to a different endpoint. */ for (i = 0; i < MAX_PIPES; i++) { struct link_enc_assignment assignment = get_assignment(dc, i); struct display_endpoint_id ep_id = (struct display_endpoint_id) {
.link_id = link->link_id,
.ep_type = link->ep_type};
bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state)
{ bool is_valid = false; bool valid_entries = true; bool valid_stream_ptrs = true; bool valid_uniqueness = true; bool valid_avail = true; bool valid_streams = true; int i, j;
uint8_t valid_count = 0;
uint8_t dig_stream_count = 0; int eng_ids_per_ep_id[MAX_PIPES] = {0}; int ep_ids_per_eng_id[MAX_PIPES] = {0}; int valid_bitmap = 0;
/* (1) No. valid entries same as stream count. */ for (i = 0; i < MAX_PIPES; i++) { struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i];
if (assignment.valid)
valid_count++;
if (is_dig_link_enc_stream(state->streams[i]))
dig_stream_count++;
} if (valid_count != dig_stream_count)
valid_entries = false;
/* (2) Matching stream ptrs. */ for (i = 0; i < MAX_PIPES; i++) { struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i];
if (assignment.valid) { if (assignment.stream != state->streams[i])
valid_stream_ptrs = false;
}
}
/* (3) Each endpoint assigned unique encoder. */ for (i = 0; i < MAX_PIPES; i++) { struct link_enc_assignment assignment_i = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i];
if (assignment_i.valid) { struct display_endpoint_id ep_id_i = assignment_i.ep_id;
/* (4) Assigned encoders not in available pool. */ for (i = 0; i < MAX_PIPES; i++) { struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i];
if (assignment.valid) { for (j = 0; j < dc->res_pool->res_cap->num_dig_link_enc; j++) { if (state->res_ctx.link_enc_cfg_ctx.link_enc_avail[j] == assignment.eng_id) {
valid_avail = false; break;
}
}
}
}
/* (5) All streams have valid link encoders. */ for (i = 0; i < state->stream_count; i++) { struct dc_stream_state *stream = state->streams[i];
void link_enc_cfg_set_transient_mode(struct dc *dc, struct dc_state *current_state, struct dc_state *new_state)
{ int i = 0; int num_transient_assignments = 0;
for (i = 0; i < MAX_PIPES; i++) { if (current_state->res_ctx.link_enc_cfg_ctx.transient_assignments[i].valid)
num_transient_assignments++;
}
/* Only enter transient mode if the new encoder assignments are valid. */ if (new_state->stream_count == num_transient_assignments) {
current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_TRANSIENT;
DC_LOG_DEBUG("%s: current_state(%p) mode(%d)\n", __func__, current_state, LINK_ENC_CFG_TRANSIENT);
}
}
Messung V0.5 in Prozent
¤ 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.0.3Bemerkung:
(vorverarbeitet am 2026-10-12)
¤
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.