1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "link_enc_cfg.h"
27#include "resource.h"
28#include "dc_link_dp.h"
29
30
31static bool is_dig_link_enc_stream(struct dc_stream_state *stream)
32{
33 bool is_dig_stream = false;
34 struct link_encoder *link_enc = NULL;
35 int i;
36
37
38 for (i = 0; i < stream->ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) {
39 link_enc = stream->ctx->dc->res_pool->link_encoders[i];
40
41 if (link_enc &&
42 ((uint32_t)stream->signal & link_enc->output_signals)) {
43 if (dc_is_dp_signal(stream->signal)) {
44
45 struct dc_link_settings link_settings = {0};
46
47 decide_link_settings(stream, &link_settings);
48 if ((link_settings.link_rate >= LINK_RATE_LOW) &&
49 link_settings.link_rate <= LINK_RATE_HIGH3) {
50 is_dig_stream = true;
51 break;
52 }
53 } else {
54 is_dig_stream = true;
55 break;
56 }
57 }
58 }
59
60 return is_dig_stream;
61}
62
63
64static void update_link_enc_assignment(
65 struct dc_state *state,
66 struct dc_stream_state *stream,
67 enum engine_id eng_id,
68 bool add_enc)
69{
70 int eng_idx;
71 int stream_idx;
72 int i;
73
74 if (eng_id != ENGINE_ID_UNKNOWN) {
75 eng_idx = eng_id - ENGINE_ID_DIGA;
76 stream_idx = -1;
77
78
79
80
81 for (i = 0; i < state->stream_count; i++) {
82 if (stream == state->streams[i]) {
83 stream_idx = i;
84 break;
85 }
86 }
87
88
89
90
91
92 if (stream_idx != -1) {
93 if (add_enc) {
94 state->res_ctx.link_enc_assignments[stream_idx] = (struct link_enc_assignment){
95 .valid = true,
96 .ep_id = (struct display_endpoint_id) {
97 .link_id = stream->link->link_id,
98 .ep_type = stream->link->ep_type},
99 .eng_id = eng_id};
100 state->res_ctx.link_enc_avail[eng_idx] = ENGINE_ID_UNKNOWN;
101 stream->link_enc = stream->ctx->dc->res_pool->link_encoders[eng_idx];
102 } else {
103 state->res_ctx.link_enc_assignments[stream_idx].valid = false;
104 state->res_ctx.link_enc_avail[eng_idx] = eng_id;
105 stream->link_enc = NULL;
106 }
107 } else {
108 dm_output_to_console("%s: Stream not found in dc_state.\n", __func__);
109 }
110 }
111}
112
113
114static enum engine_id find_first_avail_link_enc(
115 const struct dc_context *ctx,
116 const struct dc_state *state)
117{
118 enum engine_id eng_id = ENGINE_ID_UNKNOWN;
119 int i;
120
121 for (i = 0; i < ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) {
122 eng_id = state->res_ctx.link_enc_avail[i];
123 if (eng_id != ENGINE_ID_UNKNOWN)
124 break;
125 }
126
127 return eng_id;
128}
129
130
131static struct dc_stream_state *get_stream_using_link_enc(
132 struct dc_state *state,
133 enum engine_id eng_id)
134{
135 struct dc_stream_state *stream = NULL;
136 int stream_idx = -1;
137 int i;
138
139 for (i = 0; i < state->stream_count; i++) {
140 struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];
141
142 if (assignment.valid && (assignment.eng_id == eng_id)) {
143 stream_idx = i;
144 break;
145 }
146 }
147
148 if (stream_idx != -1)
149 stream = state->streams[stream_idx];
150 else
151 dm_output_to_console("%s: No stream using DIG(%d).\n", __func__, eng_id);
152
153 return stream;
154}
155
156void link_enc_cfg_init(
157 struct dc *dc,
158 struct dc_state *state)
159{
160 int i;
161
162 for (i = 0; i < dc->res_pool->res_cap->num_dig_link_enc; i++) {
163 if (dc->res_pool->link_encoders[i])
164 state->res_ctx.link_enc_avail[i] = (enum engine_id) i;
165 else
166 state->res_ctx.link_enc_avail[i] = ENGINE_ID_UNKNOWN;
167 }
168}
169
170void link_enc_cfg_link_encs_assign(
171 struct dc *dc,
172 struct dc_state *state,
173 struct dc_stream_state *streams[],
174 uint8_t stream_count)
175{
176 enum engine_id eng_id = ENGINE_ID_UNKNOWN;
177 int i;
178
179
180 for (i = 0; i < stream_count; i++)
181 dc->res_pool->funcs->link_enc_unassign(state, streams[i]);
182
183
184 for (i = 0; i < stream_count; i++) {
185 struct dc_stream_state *stream = streams[i];
186
187
188 if (!is_dig_link_enc_stream(stream))
189 continue;
190
191
192 if (!stream->link->is_dig_mapping_flexible) {
193 eng_id = stream->link->eng_id;
194 update_link_enc_assignment(state, stream, eng_id, true);
195 }
196 }
197
198
199 eng_id = ENGINE_ID_UNKNOWN;
200
201 for (i = 0; i < stream_count; i++) {
202 struct dc_stream_state *stream = streams[i];
203
204
205 if (!is_dig_link_enc_stream(stream))
206 continue;
207
208
209 if (stream->link->is_dig_mapping_flexible) {
210 eng_id = find_first_avail_link_enc(stream->ctx, state);
211 update_link_enc_assignment(state, stream, eng_id, true);
212 }
213 }
214}
215
216void link_enc_cfg_link_enc_unassign(
217 struct dc_state *state,
218 struct dc_stream_state *stream)
219{
220 enum engine_id eng_id = ENGINE_ID_UNKNOWN;
221
222
223 if (!is_dig_link_enc_stream(stream))
224 return;
225
226 if (stream->link_enc)
227 eng_id = stream->link_enc->preferred_engine;
228
229 update_link_enc_assignment(state, stream, eng_id, false);
230}
231
232bool link_enc_cfg_is_transmitter_mappable(
233 struct dc_state *state,
234 struct link_encoder *link_enc)
235{
236 bool is_mappable = false;
237 enum engine_id eng_id = link_enc->preferred_engine;
238 struct dc_stream_state *stream = get_stream_using_link_enc(state, eng_id);
239
240 if (stream)
241 is_mappable = stream->link->is_dig_mapping_flexible;
242
243 return is_mappable;
244}
245
246struct dc_link *link_enc_cfg_get_link_using_link_enc(
247 struct dc_state *state,
248 enum engine_id eng_id)
249{
250 struct dc_link *link = NULL;
251 int stream_idx = -1;
252 int i;
253
254 for (i = 0; i < state->stream_count; i++) {
255 struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];
256
257 if (assignment.valid && (assignment.eng_id == eng_id)) {
258 stream_idx = i;
259 break;
260 }
261 }
262
263 if (stream_idx != -1)
264 link = state->streams[stream_idx]->link;
265 else
266 dm_output_to_console("%s: No link using DIG(%d).\n", __func__, eng_id);
267
268 return link;
269}
270
271struct link_encoder *link_enc_cfg_get_link_enc_used_by_link(
272 struct dc_state *state,
273 const struct dc_link *link)
274{
275 struct link_encoder *link_enc = NULL;
276 struct display_endpoint_id ep_id;
277 int stream_idx = -1;
278 int i;
279
280 ep_id = (struct display_endpoint_id) {
281 .link_id = link->link_id,
282 .ep_type = link->ep_type};
283
284 for (i = 0; i < state->stream_count; i++) {
285 struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];
286
287 if (assignment.valid &&
288 assignment.ep_id.link_id.id == ep_id.link_id.id &&
289 assignment.ep_id.link_id.enum_id == ep_id.link_id.enum_id &&
290 assignment.ep_id.link_id.type == ep_id.link_id.type &&
291 assignment.ep_id.ep_type == ep_id.ep_type) {
292 stream_idx = i;
293 break;
294 }
295 }
296
297 if (stream_idx != -1)
298 link_enc = state->streams[stream_idx]->link_enc;
299
300 return link_enc;
301}
302
303struct link_encoder *link_enc_cfg_get_next_avail_link_enc(
304 const struct dc *dc,
305 const struct dc_state *state)
306{
307 struct link_encoder *link_enc = NULL;
308 enum engine_id eng_id;
309
310 eng_id = find_first_avail_link_enc(dc->ctx, state);
311 if (eng_id != ENGINE_ID_UNKNOWN)
312 link_enc = dc->res_pool->link_encoders[eng_id - ENGINE_ID_DIGA];
313
314 return link_enc;
315}
316