Skip to content

Commit 6dd8931

Browse files
Wenjing Liualexdeucher
authored andcommitted
drm/amd/display: support dynamic HPO DP link encoder allocation
[why] When there are more DP2.0 RXs connected than the number HPO DP link encoders we have, we need to dynamically allocate HPO DP link encoder to the port that needs it. [how] Only allocate HPO DP link encoder when it is needed. Tested-by: Daniel Wheeler <[email protected]> Reviewed-by: Jun Lei <[email protected]> Acked-by: Rodrigo Siqueira <[email protected]> Signed-off-by: Wenjing Liu <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 3d38a58 commit 6dd8931

File tree

12 files changed

+134
-76
lines changed

12 files changed

+134
-76
lines changed

drivers/gpu/drm/amd/display/dc/core/dc.c

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -274,24 +274,6 @@ static bool create_links(
274274
goto failed_alloc;
275275
}
276276

277-
#if defined(CONFIG_DRM_AMD_DC_DCN)
278-
if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) &&
279-
dc->caps.dp_hpo &&
280-
link->dc->res_pool->res_cap->num_hpo_dp_link_encoder > 0) {
281-
/* FPGA case - Allocate HPO DP link encoder */
282-
if (i < link->dc->res_pool->res_cap->num_hpo_dp_link_encoder) {
283-
link->hpo_dp_link_enc = link->dc->res_pool->hpo_dp_link_enc[i];
284-
285-
if (link->hpo_dp_link_enc == NULL) {
286-
BREAK_TO_DEBUGGER();
287-
goto failed_alloc;
288-
}
289-
link->hpo_dp_link_enc->hpd_source = link->link_enc->hpd_source;
290-
link->hpo_dp_link_enc->transmitter = link->link_enc->transmitter;
291-
}
292-
}
293-
#endif
294-
295277
link->link_status.dpcd_caps = &link->dpcd_caps;
296278

297279
enc_init.ctx = dc->ctx;

drivers/gpu/drm/amd/display/dc/core/dc_debug.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,8 @@ char *dc_status_to_str(enum dc_status status)
422422
return "The operation is not supported.";
423423
case DC_UNSUPPORTED_VALUE:
424424
return "The value specified is not supported.";
425+
case DC_NO_LINK_ENC_RESOURCE:
426+
return "No link encoder resource";
425427
case DC_ERROR_UNEXPECTED:
426428
return "Unexpected error";
427429
}

drivers/gpu/drm/amd/display/dc/core/dc_link.c

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -66,31 +66,6 @@
6666
/*******************************************************************************
6767
* Private functions
6868
******************************************************************************/
69-
#if defined(CONFIG_DRM_AMD_DC_DCN)
70-
static bool add_dp_hpo_link_encoder_to_link(struct dc_link *link)
71-
{
72-
struct hpo_dp_link_encoder *enc = resource_get_unused_hpo_dp_link_encoder(
73-
link->dc->res_pool);
74-
75-
if (!link->hpo_dp_link_enc && enc) {
76-
link->hpo_dp_link_enc = enc;
77-
link->hpo_dp_link_enc->transmitter = link->link_enc->transmitter;
78-
link->hpo_dp_link_enc->hpd_source = link->link_enc->hpd_source;
79-
}
80-
81-
return (link->hpo_dp_link_enc != NULL);
82-
}
83-
84-
static void remove_dp_hpo_link_encoder_from_link(struct dc_link *link)
85-
{
86-
if (link->hpo_dp_link_enc) {
87-
link->hpo_dp_link_enc->hpd_source = HPD_SOURCEID_UNKNOWN;
88-
link->hpo_dp_link_enc->transmitter = TRANSMITTER_UNKNOWN;
89-
link->hpo_dp_link_enc = NULL;
90-
}
91-
}
92-
#endif
93-
9469
static void dc_link_destruct(struct dc_link *link)
9570
{
9671
int i;
@@ -118,12 +93,6 @@ static void dc_link_destruct(struct dc_link *link)
11893
link->link_enc->funcs->destroy(&link->link_enc);
11994
}
12095

121-
#if defined(CONFIG_DRM_AMD_DC_DCN)
122-
if (link->hpo_dp_link_enc) {
123-
remove_dp_hpo_link_encoder_from_link(link);
124-
}
125-
#endif
126-
12796
if (link->local_sink)
12897
dc_sink_release(link->local_sink);
12998

@@ -975,10 +944,11 @@ static bool dc_link_detect_helper(struct dc_link *link,
975944
}
976945

977946
#if defined(CONFIG_DRM_AMD_DC_DCN)
978-
if (dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING) {
979-
add_dp_hpo_link_encoder_to_link(link);
980-
link_res.hpo_dp_link_enc = link->hpo_dp_link_enc;
981-
}
947+
if (dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING)
948+
link_res.hpo_dp_link_enc = resource_get_hpo_dp_link_enc_for_det_lt(
949+
&link->dc->current_state->res_ctx,
950+
link->dc->res_pool,
951+
link);
982952
#endif
983953

984954
if (link->type == dc_connection_mst_branch) {
@@ -4083,7 +4053,8 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
40834053
config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
40844054
if (is_dp_128b_132b_signal(pipe_ctx)) {
40854055
config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0;
4086-
config.link_enc_idx = pipe_ctx->stream->link->hpo_dp_link_enc->inst;
4056+
4057+
config.link_enc_idx = pipe_ctx->link_res.hpo_dp_link_enc->inst;
40874058
config.dp2_enabled = 1;
40884059
}
40894060
#endif

drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,8 @@ void enable_dp_hpo_output(struct dc_link *link,
800800
link_res->hpo_dp_link_enc->funcs->enable_link_phy(
801801
link_res->hpo_dp_link_enc,
802802
link_settings,
803-
link->link_enc->transmitter);
803+
link->link_enc->transmitter,
804+
link->link_enc->hpd_source);
804805
}
805806

806807
/* DCCG muxing and DTBCLK DTO */

drivers/gpu/drm/amd/display/dc/core/dc_resource.c

Lines changed: 106 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,94 @@ static void update_hpo_dp_stream_engine_usage(
17241724
res_ctx->is_hpo_dp_stream_enc_acquired[i] = acquired;
17251725
}
17261726
}
1727+
1728+
static inline int find_acquired_hpo_dp_link_enc_for_link(
1729+
const struct resource_context *res_ctx,
1730+
const struct dc_link *link)
1731+
{
1732+
int i;
1733+
1734+
for (i = 0; i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_to_link_idx); i++)
1735+
if (res_ctx->hpo_dp_link_enc_ref_cnts[i] > 0 &&
1736+
res_ctx->hpo_dp_link_enc_to_link_idx[i] == link->link_index)
1737+
return i;
1738+
1739+
return -1;
1740+
}
1741+
1742+
static inline int find_free_hpo_dp_link_enc(const struct resource_context *res_ctx,
1743+
const struct resource_pool *pool)
1744+
{
1745+
int i;
1746+
1747+
for (i = 0; i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_ref_cnts); i++)
1748+
if (res_ctx->hpo_dp_link_enc_ref_cnts[i] == 0)
1749+
break;
1750+
1751+
return (i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_ref_cnts) &&
1752+
i < pool->hpo_dp_link_enc_count) ? i : -1;
1753+
}
1754+
1755+
static inline void acquire_hpo_dp_link_enc(
1756+
struct resource_context *res_ctx,
1757+
unsigned int link_index,
1758+
int enc_index)
1759+
{
1760+
res_ctx->hpo_dp_link_enc_to_link_idx[enc_index] = link_index;
1761+
res_ctx->hpo_dp_link_enc_ref_cnts[enc_index] = 1;
1762+
}
1763+
1764+
static inline void retain_hpo_dp_link_enc(
1765+
struct resource_context *res_ctx,
1766+
int enc_index)
1767+
{
1768+
res_ctx->hpo_dp_link_enc_ref_cnts[enc_index]++;
1769+
}
1770+
1771+
static inline void release_hpo_dp_link_enc(
1772+
struct resource_context *res_ctx,
1773+
int enc_index)
1774+
{
1775+
ASSERT(res_ctx->hpo_dp_link_enc_ref_cnts[enc_index] > 0);
1776+
res_ctx->hpo_dp_link_enc_ref_cnts[enc_index]--;
1777+
}
1778+
1779+
static bool add_hpo_dp_link_enc_to_ctx(struct resource_context *res_ctx,
1780+
const struct resource_pool *pool,
1781+
struct pipe_ctx *pipe_ctx,
1782+
struct dc_stream_state *stream)
1783+
{
1784+
int enc_index;
1785+
1786+
enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, stream->link);
1787+
1788+
if (enc_index >= 0) {
1789+
retain_hpo_dp_link_enc(res_ctx, enc_index);
1790+
} else {
1791+
enc_index = find_free_hpo_dp_link_enc(res_ctx, pool);
1792+
if (enc_index >= 0)
1793+
acquire_hpo_dp_link_enc(res_ctx, stream->link->link_index, enc_index);
1794+
}
1795+
1796+
if (enc_index >= 0)
1797+
pipe_ctx->link_res.hpo_dp_link_enc = pool->hpo_dp_link_enc[enc_index];
1798+
1799+
return pipe_ctx->link_res.hpo_dp_link_enc != NULL;
1800+
}
1801+
1802+
static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx,
1803+
struct pipe_ctx *pipe_ctx,
1804+
struct dc_stream_state *stream)
1805+
{
1806+
int enc_index;
1807+
1808+
enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, stream->link);
1809+
1810+
if (enc_index >= 0) {
1811+
release_hpo_dp_link_enc(res_ctx, enc_index);
1812+
pipe_ctx->link_res.hpo_dp_link_enc = NULL;
1813+
}
1814+
}
17271815
#endif
17281816

17291817
/* TODO: release audio object */
@@ -1886,6 +1974,7 @@ enum dc_status dc_remove_stream_from_ctx(
18861974
&new_ctx->res_ctx, dc->res_pool,
18871975
del_pipe->stream_res.hpo_dp_stream_enc,
18881976
false);
1977+
remove_hpo_dp_link_enc_from_ctx(&new_ctx->res_ctx, del_pipe, del_pipe->stream);
18891978
}
18901979
#endif
18911980

@@ -2161,7 +2250,8 @@ enum dc_status resource_map_pool_resources(
21612250
&context->res_ctx, pool,
21622251
pipe_ctx->stream_res.hpo_dp_stream_enc,
21632252
true);
2164-
pipe_ctx->link_res.hpo_dp_link_enc = stream->link->hpo_dp_link_enc;
2253+
if (!add_hpo_dp_link_enc_to_ctx(&context->res_ctx, pool, pipe_ctx, stream))
2254+
return DC_NO_LINK_ENC_RESOURCE;
21652255
}
21662256
}
21672257
#endif
@@ -2837,6 +2927,8 @@ bool pipe_need_reprogram(
28372927
#if defined(CONFIG_DRM_AMD_DC_DCN)
28382928
if (pipe_ctx_old->stream_res.hpo_dp_stream_enc != pipe_ctx->stream_res.hpo_dp_stream_enc)
28392929
return true;
2930+
if (pipe_ctx_old->link_res.hpo_dp_link_enc != pipe_ctx->link_res.hpo_dp_link_enc)
2931+
return true;
28402932
#endif
28412933

28422934
/* DIG link encoder resource assignment for stream changed. */
@@ -3105,22 +3197,23 @@ void get_audio_check(struct audio_info *aud_modes,
31053197
}
31063198

31073199
#if defined(CONFIG_DRM_AMD_DC_DCN)
3108-
struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder(
3109-
const struct resource_pool *pool)
3200+
struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt(
3201+
const struct resource_context *res_ctx,
3202+
const struct resource_pool *pool,
3203+
const struct dc_link *link)
31103204
{
3111-
uint8_t i;
3112-
struct hpo_dp_link_encoder *enc = NULL;
3205+
struct hpo_dp_link_encoder *hpo_dp_link_enc = NULL;
3206+
int enc_index;
31133207

3114-
ASSERT(pool->hpo_dp_link_enc_count <= MAX_HPO_DP2_LINK_ENCODERS);
3208+
enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, link);
31153209

3116-
for (i = 0; i < pool->hpo_dp_link_enc_count; i++) {
3117-
if (pool->hpo_dp_link_enc[i]->transmitter == TRANSMITTER_UNKNOWN) {
3118-
enc = pool->hpo_dp_link_enc[i];
3119-
break;
3120-
}
3121-
}
3210+
if (enc_index < 0)
3211+
enc_index = find_free_hpo_dp_link_enc(res_ctx, pool);
3212+
3213+
if (enc_index >= 0)
3214+
hpo_dp_link_enc = pool->hpo_dp_link_enc[enc_index];
31223215

3123-
return enc;
3216+
return hpo_dp_link_enc;
31243217
}
31253218
#endif
31263219

drivers/gpu/drm/amd/display/dc/dc_link.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,6 @@ struct dc_link {
162162

163163
struct panel_cntl *panel_cntl;
164164
struct link_encoder *link_enc;
165-
#if defined(CONFIG_DRM_AMD_DC_DCN)
166-
struct hpo_dp_link_encoder *hpo_dp_link_enc;
167-
#endif
168165
struct graphics_object_id link_id;
169166
/* Endpoint type distinguishes display endpoints which do not have entries
170167
* in the BIOS connector table from those that do. Helps when tracking link

drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,8 @@ static enum bp_result link_transmitter_control(
499499
void dcn31_hpo_dp_link_enc_enable_dp_output(
500500
struct hpo_dp_link_encoder *enc,
501501
const struct dc_link_settings *link_settings,
502-
enum transmitter transmitter)
502+
enum transmitter transmitter,
503+
enum hpd_source_id hpd_source)
503504
{
504505
struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
505506
struct bp_transmitter_control cntl = { 0 };
@@ -508,6 +509,9 @@ void dcn31_hpo_dp_link_enc_enable_dp_output(
508509
/* Set the transmitter */
509510
enc3->base.transmitter = transmitter;
510511

512+
/* Set the hpd source */
513+
enc3->base.hpd_source = hpd_source;
514+
511515
/* Enable the PHY */
512516
cntl.action = TRANSMITTER_CONTROL_ENABLE;
513517
cntl.engine_id = ENGINE_ID_UNKNOWN;

drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ void hpo_dp_link_encoder31_construct(struct dcn31_hpo_dp_link_encoder *enc31,
184184
void dcn31_hpo_dp_link_enc_enable_dp_output(
185185
struct hpo_dp_link_encoder *enc,
186186
const struct dc_link_settings *link_settings,
187-
enum transmitter transmitter);
187+
enum transmitter transmitter,
188+
enum hpd_source_id hpd_source);
188189

189190
void dcn31_hpo_dp_link_enc_disable_output(
190191
struct hpo_dp_link_encoder *enc,

drivers/gpu/drm/amd/display/dc/inc/core_status.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ enum dc_status {
5353
DC_NOT_SUPPORTED = 24,
5454
DC_UNSUPPORTED_VALUE = 25,
5555

56+
DC_NO_LINK_ENC_RESOURCE = 26,
57+
5658
DC_ERROR_UNEXPECTED = -1
5759
};
5860

drivers/gpu/drm/amd/display/dc/inc/core_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,8 @@ struct resource_context {
422422
struct link_enc_cfg_context link_enc_cfg_ctx;
423423
#if defined(CONFIG_DRM_AMD_DC_DCN)
424424
bool is_hpo_dp_stream_enc_acquired[MAX_HPO_DP2_ENCODERS];
425+
unsigned int hpo_dp_link_enc_to_link_idx[MAX_HPO_DP2_LINK_ENCODERS];
426+
int hpo_dp_link_enc_ref_cnts[MAX_HPO_DP2_LINK_ENCODERS];
425427
#endif
426428
#if defined(CONFIG_DRM_AMD_DC_DCN)
427429
bool is_mpc_3dlut_acquired[MAX_PIPES];

0 commit comments

Comments
 (0)