mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-04 02:34:10 -04:00
drm/amd/display: refactor dio link encoder assigning
[WHY] We would like to have new dio encoder assigning flow. Which should be aligned with hpo assigning and have simple logic and data representation. [HOW} 1. A new config option to enable/disable the new code. 2. Encoder-link mapping is in res_ctx and assigned encoder. is accessed through pipe_ctx. 3. assign dio encoder when add stream to ctx Reviewed-by: Jun Lei <jun.lei@amd.com> Reviewed-by: Meenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com> Signed-off-by: Peichen Huang <PeiChen.Huang@amd.com> Signed-off-by: Zaeem Mohamed <zaeem.mohamed@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
c87d202692
commit
a1d79eae96
@@ -2325,7 +2325,7 @@ enum dc_status dc_commit_streams(struct dc *dc, struct dc_commit_streams_params
|
||||
/*
|
||||
* Only update link encoder to stream assignment after bandwidth validation passed.
|
||||
*/
|
||||
if (res == DC_OK && dc->res_pool->funcs->link_encs_assign)
|
||||
if (res == DC_OK && dc->res_pool->funcs->link_encs_assign && !dc->config.unify_link_enc_assignment)
|
||||
dc->res_pool->funcs->link_encs_assign(
|
||||
dc, context, context->streams, context->stream_count);
|
||||
|
||||
|
||||
@@ -2683,6 +2683,162 @@ static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static inline int find_acquired_dio_link_enc_for_link(
|
||||
const struct resource_context *res_ctx,
|
||||
const struct dc_link *link)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(res_ctx->dio_link_enc_ref_cnts); i++)
|
||||
if (res_ctx->dio_link_enc_ref_cnts[i] > 0 &&
|
||||
res_ctx->dio_link_enc_to_link_idx[i] == link->link_index)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int find_fixed_dio_link_enc(const struct dc_link *link)
|
||||
{
|
||||
/* the 8b10b dp phy can only use fixed link encoder */
|
||||
return link->eng_id;
|
||||
}
|
||||
|
||||
static inline int find_free_dio_link_enc(const struct resource_context *res_ctx,
|
||||
const struct dc_link *link, const struct resource_pool *pool)
|
||||
{
|
||||
int i;
|
||||
int enc_count = pool->dig_link_enc_count;
|
||||
|
||||
/* for dpia, check preferred encoder first and then the next one */
|
||||
for (i = 0; i < enc_count; i++)
|
||||
if (res_ctx->dio_link_enc_ref_cnts[(link->dpia_preferred_eng_id + i) % enc_count] == 0)
|
||||
break;
|
||||
|
||||
return (i >= 0 && i < enc_count) ? (link->dpia_preferred_eng_id + i) % enc_count : -1;
|
||||
}
|
||||
|
||||
static inline void acquire_dio_link_enc(
|
||||
struct resource_context *res_ctx,
|
||||
unsigned int link_index,
|
||||
int enc_index)
|
||||
{
|
||||
res_ctx->dio_link_enc_to_link_idx[enc_index] = link_index;
|
||||
res_ctx->dio_link_enc_ref_cnts[enc_index] = 1;
|
||||
}
|
||||
|
||||
static inline void retain_dio_link_enc(
|
||||
struct resource_context *res_ctx,
|
||||
int enc_index)
|
||||
{
|
||||
res_ctx->dio_link_enc_ref_cnts[enc_index]++;
|
||||
}
|
||||
|
||||
static inline void release_dio_link_enc(
|
||||
struct resource_context *res_ctx,
|
||||
int enc_index)
|
||||
{
|
||||
ASSERT(res_ctx->dio_link_enc_ref_cnts[enc_index] > 0);
|
||||
res_ctx->dio_link_enc_ref_cnts[enc_index]--;
|
||||
}
|
||||
|
||||
static bool is_dio_enc_acquired_by_other_link(const struct dc_link *link,
|
||||
int enc_index,
|
||||
int *link_index)
|
||||
{
|
||||
const struct dc *dc = link->dc;
|
||||
const struct resource_context *res_ctx = &dc->current_state->res_ctx;
|
||||
|
||||
/* pass the link_index that acquired the enc_index */
|
||||
if (res_ctx->dio_link_enc_ref_cnts[enc_index] > 0 &&
|
||||
res_ctx->dio_link_enc_to_link_idx[enc_index] != link->link_index) {
|
||||
*link_index = res_ctx->dio_link_enc_to_link_idx[enc_index];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void swap_dio_link_enc_to_muxable_ctx(struct dc_state *context,
|
||||
const struct resource_pool *pool,
|
||||
int new_encoder,
|
||||
int old_encoder)
|
||||
{
|
||||
struct resource_context *res_ctx = &context->res_ctx;
|
||||
int stream_count = context->stream_count;
|
||||
int i = 0;
|
||||
|
||||
res_ctx->dio_link_enc_ref_cnts[new_encoder] = res_ctx->dio_link_enc_ref_cnts[old_encoder];
|
||||
res_ctx->dio_link_enc_to_link_idx[new_encoder] = res_ctx->dio_link_enc_to_link_idx[old_encoder];
|
||||
res_ctx->dio_link_enc_ref_cnts[old_encoder] = 0;
|
||||
|
||||
for (i = 0; i < stream_count; i++) {
|
||||
struct dc_stream_state *stream = context->streams[i];
|
||||
struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
|
||||
|
||||
if (pipe_ctx && pipe_ctx->link_res.dio_link_enc == pool->link_encoders[old_encoder])
|
||||
pipe_ctx->link_res.dio_link_enc = pool->link_encoders[new_encoder];
|
||||
}
|
||||
}
|
||||
|
||||
static bool add_dio_link_enc_to_ctx(const struct dc *dc,
|
||||
struct dc_state *context,
|
||||
const struct resource_pool *pool,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
struct resource_context *res_ctx = &context->res_ctx;
|
||||
int enc_index;
|
||||
|
||||
enc_index = find_acquired_dio_link_enc_for_link(res_ctx, stream->link);
|
||||
|
||||
if (enc_index >= 0) {
|
||||
retain_dio_link_enc(res_ctx, enc_index);
|
||||
} else {
|
||||
if (stream->link->is_dig_mapping_flexible)
|
||||
enc_index = find_free_dio_link_enc(res_ctx, stream->link, pool);
|
||||
else {
|
||||
int link_index = 0;
|
||||
|
||||
enc_index = find_fixed_dio_link_enc(stream->link);
|
||||
/* Fixed mapping link can only use its fixed link encoder.
|
||||
* If the encoder is acquired by other link then get a new free encoder and swap the new
|
||||
* one into the acquiring link.
|
||||
*/
|
||||
if (enc_index >= 0 && is_dio_enc_acquired_by_other_link(stream->link, enc_index, &link_index)) {
|
||||
int new_enc_index = find_free_dio_link_enc(res_ctx, dc->links[link_index], pool);
|
||||
|
||||
if (new_enc_index >= 0)
|
||||
swap_dio_link_enc_to_muxable_ctx(context, pool, new_enc_index, enc_index);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (enc_index >= 0)
|
||||
acquire_dio_link_enc(res_ctx, stream->link->link_index, enc_index);
|
||||
}
|
||||
|
||||
if (enc_index >= 0)
|
||||
pipe_ctx->link_res.dio_link_enc = pool->link_encoders[enc_index];
|
||||
|
||||
return pipe_ctx->link_res.dio_link_enc != NULL;
|
||||
}
|
||||
|
||||
static void remove_dio_link_enc_from_ctx(struct resource_context *res_ctx,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct dc_stream_state *stream)
|
||||
{
|
||||
int enc_index = -1;
|
||||
|
||||
if (stream->link)
|
||||
enc_index = find_acquired_dio_link_enc_for_link(res_ctx, stream->link);
|
||||
|
||||
if (enc_index >= 0) {
|
||||
release_dio_link_enc(res_ctx, enc_index);
|
||||
pipe_ctx->link_res.dio_link_enc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int get_num_of_free_pipes(const struct resource_pool *pool, const struct dc_state *context)
|
||||
{
|
||||
int i;
|
||||
@@ -2730,6 +2886,10 @@ void resource_remove_otg_master_for_stream_output(struct dc_state *context,
|
||||
remove_hpo_dp_link_enc_from_ctx(
|
||||
&context->res_ctx, otg_master, stream);
|
||||
}
|
||||
|
||||
if (stream->ctx->dc->config.unify_link_enc_assignment)
|
||||
remove_dio_link_enc_from_ctx(&context->res_ctx, otg_master, stream);
|
||||
|
||||
if (otg_master->stream_res.audio)
|
||||
update_audio_usage(
|
||||
&context->res_ctx,
|
||||
@@ -2744,6 +2904,7 @@ void resource_remove_otg_master_for_stream_output(struct dc_state *context,
|
||||
if (pool->funcs->remove_stream_from_ctx)
|
||||
pool->funcs->remove_stream_from_ctx(
|
||||
stream->ctx->dc, context, stream);
|
||||
|
||||
memset(otg_master, 0, sizeof(*otg_master));
|
||||
}
|
||||
|
||||
@@ -3716,6 +3877,7 @@ enum dc_status resource_map_pool_resources(
|
||||
struct pipe_ctx *pipe_ctx = NULL;
|
||||
int pipe_idx = -1;
|
||||
bool acquired = false;
|
||||
bool is_dio_encoder = true;
|
||||
|
||||
calculate_phy_pix_clks(stream);
|
||||
|
||||
@@ -3781,6 +3943,10 @@ enum dc_status resource_map_pool_resources(
|
||||
}
|
||||
}
|
||||
|
||||
if (dc->config.unify_link_enc_assignment && is_dio_encoder)
|
||||
if (!add_dio_link_enc_to_ctx(dc, context, pool, pipe_ctx, stream))
|
||||
return DC_NO_LINK_ENC_RESOURCE;
|
||||
|
||||
/* TODO: Add check if ASIC support and EDID audio */
|
||||
if (!stream->converter_disable_audio &&
|
||||
dc_is_audio_capable_signal(pipe_ctx->stream->signal) &&
|
||||
@@ -5017,6 +5183,28 @@ void get_audio_check(struct audio_info *aud_modes,
|
||||
}
|
||||
}
|
||||
|
||||
static struct link_encoder *get_temp_dio_link_enc(
|
||||
const struct resource_context *res_ctx,
|
||||
const struct resource_pool *const pool,
|
||||
const struct dc_link *link)
|
||||
{
|
||||
struct link_encoder *link_enc = NULL;
|
||||
int enc_index;
|
||||
|
||||
if (link->is_dig_mapping_flexible)
|
||||
enc_index = find_acquired_dio_link_enc_for_link(res_ctx, link);
|
||||
else
|
||||
enc_index = link->eng_id;
|
||||
|
||||
if (enc_index < 0)
|
||||
enc_index = find_free_dio_link_enc(res_ctx, link, pool);
|
||||
|
||||
if (enc_index >= 0)
|
||||
link_enc = pool->link_encoders[enc_index];
|
||||
|
||||
return link_enc;
|
||||
}
|
||||
|
||||
static struct hpo_dp_link_encoder *get_temp_hpo_dp_link_enc(
|
||||
const struct resource_context *res_ctx,
|
||||
const struct resource_pool *const pool,
|
||||
@@ -5046,11 +5234,17 @@ bool get_temp_dp_link_res(struct dc_link *link,
|
||||
memset(link_res, 0, sizeof(*link_res));
|
||||
|
||||
if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
|
||||
link_res->hpo_dp_link_enc = get_temp_hpo_dp_link_enc(res_ctx,
|
||||
dc->res_pool, link);
|
||||
link_res->hpo_dp_link_enc = get_temp_hpo_dp_link_enc(res_ctx, dc->res_pool, link);
|
||||
if (!link_res->hpo_dp_link_enc)
|
||||
return false;
|
||||
} else if (dc->link_srv->dp_get_encoding_format(link_settings) == DP_8b_10b_ENCODING &&
|
||||
dc->config.unify_link_enc_assignment) {
|
||||
link_res->dio_link_enc = get_temp_dio_link_enc(res_ctx,
|
||||
dc->res_pool, link);
|
||||
if (!link_res->dio_link_enc)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5322,6 +5516,10 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc,
|
||||
remove_hpo_dp_link_enc_from_ctx(&context->res_ctx, pipe_ctx, pipe_ctx->stream);
|
||||
}
|
||||
|
||||
if (pipe_ctx->link_res.dio_link_enc == NULL && dc->config.unify_link_enc_assignment)
|
||||
if (!add_dio_link_enc_to_ctx(dc, context, dc->res_pool, pipe_ctx, pipe_ctx->stream))
|
||||
return DC_NO_LINK_ENC_RESOURCE;
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -473,6 +473,7 @@ struct dc_config {
|
||||
bool consolidated_dpia_dp_lt;
|
||||
bool set_pipe_unlock_order;
|
||||
bool enable_dpia_pre_training;
|
||||
bool unify_link_enc_assignment;
|
||||
};
|
||||
|
||||
enum visual_confirm {
|
||||
@@ -778,6 +779,7 @@ union dpia_debug_options {
|
||||
uint32_t disable_usb4_pm_support:1; /* bit 5 */
|
||||
uint32_t enable_consolidated_dpia_dp_lt:1; /* bit 6 */
|
||||
uint32_t enable_dpia_pre_training:1; /* bit 7 */
|
||||
uint32_t unify_link_enc_assignment:1; /* bit 8 */
|
||||
uint32_t reserved:24;
|
||||
} bits;
|
||||
uint32_t raw;
|
||||
|
||||
@@ -376,6 +376,7 @@ struct plane_resource {
|
||||
|
||||
/* all mappable hardware resources used to enable a link */
|
||||
struct link_resource {
|
||||
struct link_encoder *dio_link_enc;
|
||||
struct hpo_dp_link_encoder *hpo_dp_link_enc;
|
||||
};
|
||||
|
||||
@@ -500,6 +501,8 @@ struct resource_context {
|
||||
uint8_t dp_clock_source_ref_count;
|
||||
bool is_dsc_acquired[MAX_PIPES];
|
||||
struct link_enc_cfg_context link_enc_cfg_ctx;
|
||||
unsigned int dio_link_enc_to_link_idx[MAX_DIG_LINK_ENCODERS];
|
||||
int dio_link_enc_ref_cnts[MAX_DIG_LINK_ENCODERS];
|
||||
bool is_hpo_dp_stream_enc_acquired[MAX_HPO_DP2_ENCODERS];
|
||||
unsigned int hpo_dp_link_enc_to_link_idx[MAX_HPO_DP2_LINK_ENCODERS];
|
||||
int hpo_dp_link_enc_ref_cnts[MAX_HPO_DP2_LINK_ENCODERS];
|
||||
|
||||
Reference in New Issue
Block a user