Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <daniel.wheeler@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Wenjing Liu and committed by
Alex Deucher
6dd8931b 3d38a583

+134 -76
-18
drivers/gpu/drm/amd/display/dc/core/dc.c
··· 274 274 goto failed_alloc; 275 275 } 276 276 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 - 295 277 link->link_status.dpcd_caps = &link->dpcd_caps; 296 278 297 279 enc_init.ctx = dc->ctx;
+2
drivers/gpu/drm/amd/display/dc/core/dc_debug.c
··· 422 422 return "The operation is not supported."; 423 423 case DC_UNSUPPORTED_VALUE: 424 424 return "The value specified is not supported."; 425 + case DC_NO_LINK_ENC_RESOURCE: 426 + return "No link encoder resource"; 425 427 case DC_ERROR_UNEXPECTED: 426 428 return "Unexpected error"; 427 429 }
+7 -36
drivers/gpu/drm/amd/display/dc/core/dc_link.c
··· 66 66 /******************************************************************************* 67 67 * Private functions 68 68 ******************************************************************************/ 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 - 94 69 static void dc_link_destruct(struct dc_link *link) 95 70 { 96 71 int i; ··· 92 117 } 93 118 link->link_enc->funcs->destroy(&link->link_enc); 94 119 } 95 - 96 - #if defined(CONFIG_DRM_AMD_DC_DCN) 97 - if (link->hpo_dp_link_enc) { 98 - remove_dp_hpo_link_encoder_from_link(link); 99 - } 100 - #endif 101 120 102 121 if (link->local_sink) 103 122 dc_sink_release(link->local_sink); ··· 944 975 } 945 976 946 977 #if defined(CONFIG_DRM_AMD_DC_DCN) 947 - if (dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING) { 948 - add_dp_hpo_link_encoder_to_link(link); 949 - link_res.hpo_dp_link_enc = link->hpo_dp_link_enc; 950 - } 978 + if (dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING) 979 + link_res.hpo_dp_link_enc = resource_get_hpo_dp_link_enc_for_det_lt( 980 + &link->dc->current_state->res_ctx, 981 + link->dc->res_pool, 982 + link); 951 983 #endif 952 984 953 985 if (link->type == dc_connection_mst_branch) { ··· 4053 4083 config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A; 4054 4084 if (is_dp_128b_132b_signal(pipe_ctx)) { 4055 4085 config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0; 4056 - config.link_enc_idx = pipe_ctx->stream->link->hpo_dp_link_enc->inst; 4086 + 4087 + config.link_enc_idx = pipe_ctx->link_res.hpo_dp_link_enc->inst; 4057 4088 config.dp2_enabled = 1; 4058 4089 } 4059 4090 #endif
+106 -13
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
··· 1724 1724 res_ctx->is_hpo_dp_stream_enc_acquired[i] = acquired; 1725 1725 } 1726 1726 } 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 + } 1727 1815 #endif 1728 1816 1729 1817 /* TODO: release audio object */ ··· 1974 1886 &new_ctx->res_ctx, dc->res_pool, 1975 1887 del_pipe->stream_res.hpo_dp_stream_enc, 1976 1888 false); 1889 + remove_hpo_dp_link_enc_from_ctx(&new_ctx->res_ctx, del_pipe, del_pipe->stream); 1977 1890 } 1978 1891 #endif 1979 1892 ··· 2250 2161 &context->res_ctx, pool, 2251 2162 pipe_ctx->stream_res.hpo_dp_stream_enc, 2252 2163 true); 2253 - pipe_ctx->link_res.hpo_dp_link_enc = stream->link->hpo_dp_link_enc; 2164 + if (!add_hpo_dp_link_enc_to_ctx(&context->res_ctx, pool, pipe_ctx, stream)) 2165 + return DC_NO_LINK_ENC_RESOURCE; 2254 2166 } 2255 2167 } 2256 2168 #endif ··· 2927 2837 #if defined(CONFIG_DRM_AMD_DC_DCN) 2928 2838 if (pipe_ctx_old->stream_res.hpo_dp_stream_enc != pipe_ctx->stream_res.hpo_dp_stream_enc) 2929 2839 return true; 2840 + if (pipe_ctx_old->link_res.hpo_dp_link_enc != pipe_ctx->link_res.hpo_dp_link_enc) 2841 + return true; 2930 2842 #endif 2931 2843 2932 2844 /* DIG link encoder resource assignment for stream changed. */ ··· 3197 3105 } 3198 3106 3199 3107 #if defined(CONFIG_DRM_AMD_DC_DCN) 3200 - struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder( 3201 - const struct resource_pool *pool) 3108 + struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( 3109 + const struct resource_context *res_ctx, 3110 + const struct resource_pool *pool, 3111 + const struct dc_link *link) 3202 3112 { 3203 - uint8_t i; 3204 - struct hpo_dp_link_encoder *enc = NULL; 3113 + struct hpo_dp_link_encoder *hpo_dp_link_enc = NULL; 3114 + int enc_index; 3205 3115 3206 - ASSERT(pool->hpo_dp_link_enc_count <= MAX_HPO_DP2_LINK_ENCODERS); 3116 + enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, link); 3207 3117 3208 - for (i = 0; i < pool->hpo_dp_link_enc_count; i++) { 3209 - if (pool->hpo_dp_link_enc[i]->transmitter == TRANSMITTER_UNKNOWN) { 3210 - enc = pool->hpo_dp_link_enc[i]; 3211 - break; 3212 - } 3213 - } 3118 + if (enc_index < 0) 3119 + enc_index = find_free_hpo_dp_link_enc(res_ctx, pool); 3214 3120 3215 - return enc; 3121 + if (enc_index >= 0) 3122 + hpo_dp_link_enc = pool->hpo_dp_link_enc[enc_index]; 3123 + 3124 + return hpo_dp_link_enc; 3216 3125 } 3217 3126 #endif 3218 3127
-3
drivers/gpu/drm/amd/display/dc/dc_link.h
··· 162 162 163 163 struct panel_cntl *panel_cntl; 164 164 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 168 165 struct graphics_object_id link_id; 169 166 /* Endpoint type distinguishes display endpoints which do not have entries 170 167 * in the BIOS connector table from those that do. Helps when tracking link
+2
drivers/gpu/drm/amd/display/dc/inc/core_status.h
··· 53 53 DC_NOT_SUPPORTED = 24, 54 54 DC_UNSUPPORTED_VALUE = 25, 55 55 56 + DC_NO_LINK_ENC_RESOURCE = 26, 57 + 56 58 DC_ERROR_UNEXPECTED = -1 57 59 }; 58 60
+2
drivers/gpu/drm/amd/display/dc/inc/core_types.h
··· 422 422 struct link_enc_cfg_context link_enc_cfg_ctx; 423 423 #if defined(CONFIG_DRM_AMD_DC_DCN) 424 424 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]; 425 427 #endif 426 428 #if defined(CONFIG_DRM_AMD_DC_DCN) 427 429 bool is_mpc_3dlut_acquired[MAX_PIPES];
+4 -2
drivers/gpu/drm/amd/display/dc/inc/resource.h
··· 206 206 int get_num_odm_splits(struct pipe_ctx *pipe); 207 207 208 208 #if defined(CONFIG_DRM_AMD_DC_DCN) 209 - struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder( 210 - const struct resource_pool *pool); 209 + struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( 210 + const struct resource_context *res_ctx, 211 + const struct resource_pool *pool, 212 + const struct dc_link *link); 211 213 #endif 212 214 213 215 void reset_syncd_pipes_from_disabled_pipes(struct dc *dc,