File: | dev/pci/drm/i915/display/intel_dp_mst.c |
Warning: | line 510, column 2 Value stored to 'ret' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright © 2008 Intel Corporation |
3 | * 2014 Red Hat Inc. |
4 | * |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * copy of this software and associated documentation files (the "Software"), |
7 | * to deal in the Software without restriction, including without limitation |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
9 | * and/or sell copies of the Software, and to permit persons to whom the |
10 | * Software is furnished to do so, subject to the following conditions: |
11 | * |
12 | * The above copyright notice and this permission notice (including the next |
13 | * paragraph) shall be included in all copies or substantial portions of the |
14 | * Software. |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
22 | * IN THE SOFTWARE. |
23 | * |
24 | */ |
25 | |
26 | #include <drm/drm_atomic_helper.h> |
27 | #include <drm/drm_edid.h> |
28 | #include <drm/drm_probe_helper.h> |
29 | |
30 | #include "i915_drv.h" |
31 | #include "intel_atomic.h" |
32 | #include "intel_audio.h" |
33 | #include "intel_connector.h" |
34 | #include "intel_ddi.h" |
35 | #include "intel_display_types.h" |
36 | #include "intel_hotplug.h" |
37 | #include "intel_dp.h" |
38 | #include "intel_dp_mst.h" |
39 | #include "intel_dpio_phy.h" |
40 | #include "intel_hdcp.h" |
41 | |
42 | static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, |
43 | struct intel_crtc_state *crtc_state, |
44 | struct drm_connector_state *conn_state, |
45 | struct link_config_limits *limits) |
46 | { |
47 | struct drm_atomic_state *state = crtc_state->uapi.state; |
48 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); |
49 | struct intel_dp *intel_dp = &intel_mst->primary->dp; |
50 | struct intel_connector *connector = |
51 | to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); |
52 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->base.dev); |
53 | const struct drm_display_mode *adjusted_mode = |
54 | &crtc_state->hw.adjusted_mode; |
55 | bool_Bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 0, |
56 | DP_DPCD_QUIRK_CONSTANT_N); |
57 | int bpp, slots = -EINVAL22; |
58 | |
59 | crtc_state->lane_count = limits->max_lane_count; |
60 | crtc_state->port_clock = limits->max_clock; |
61 | |
62 | for (bpp = limits->max_bpp; bpp >= limits->min_bpp; bpp -= 2 * 3) { |
63 | crtc_state->pipe_bpp = bpp; |
64 | |
65 | crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, |
66 | crtc_state->pipe_bpp, |
67 | false0); |
68 | |
69 | slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr, |
70 | connector->port, |
71 | crtc_state->pbn, |
72 | drm_dp_get_vc_payload_bw(crtc_state->port_clock, |
73 | crtc_state->lane_count)); |
74 | if (slots == -EDEADLK11) |
75 | return slots; |
76 | if (slots >= 0) |
77 | break; |
78 | } |
79 | |
80 | if (slots < 0) { |
81 | drm_dbg_kms(&i915->drm, "failed finding vcpi slots:%d\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "failed finding vcpi slots:%d\n" , slots) |
82 | slots)drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "failed finding vcpi slots:%d\n" , slots); |
83 | return slots; |
84 | } |
85 | |
86 | intel_link_compute_m_n(crtc_state->pipe_bpp, |
87 | crtc_state->lane_count, |
88 | adjusted_mode->crtc_clock, |
89 | crtc_state->port_clock, |
90 | &crtc_state->dp_m_n, |
91 | constant_n, crtc_state->fec_enable); |
92 | crtc_state->dp_m_n.tu = slots; |
93 | |
94 | return 0; |
95 | } |
96 | |
97 | static int intel_dp_mst_compute_config(struct intel_encoder *encoder, |
98 | struct intel_crtc_state *pipe_config, |
99 | struct drm_connector_state *conn_state) |
100 | { |
101 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
102 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); |
103 | struct intel_dp *intel_dp = &intel_mst->primary->dp; |
104 | struct intel_connector *connector = |
105 | to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); |
106 | struct intel_digital_connector_state *intel_conn_state = |
107 | to_intel_digital_connector_state(conn_state)({ const __typeof( ((struct intel_digital_connector_state *)0 )->base ) *__mptr = (conn_state); (struct intel_digital_connector_state *)( (char *)__mptr - __builtin_offsetof(struct intel_digital_connector_state , base) );}); |
108 | const struct drm_display_mode *adjusted_mode = |
109 | &pipe_config->hw.adjusted_mode; |
110 | struct link_config_limits limits; |
111 | int ret; |
112 | |
113 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN(1<<5)) |
114 | return -EINVAL22; |
115 | |
116 | pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; |
117 | pipe_config->has_pch_encoder = false0; |
118 | |
119 | if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) |
120 | pipe_config->has_audio = connector->port->has_audio; |
121 | else |
122 | pipe_config->has_audio = |
123 | intel_conn_state->force_audio == HDMI_AUDIO_ON; |
124 | |
125 | /* |
126 | * for MST we always configure max link bw - the spec doesn't |
127 | * seem to suggest we should do otherwise. |
128 | */ |
129 | limits.min_clock = |
130 | limits.max_clock = intel_dp_max_link_rate(intel_dp); |
131 | |
132 | limits.min_lane_count = |
133 | limits.max_lane_count = intel_dp_max_lane_count(intel_dp); |
134 | |
135 | limits.min_bpp = intel_dp_min_bpp(pipe_config); |
136 | /* |
137 | * FIXME: If all the streams can't fit into the link with |
138 | * their current pipe_bpp we should reduce pipe_bpp across |
139 | * the board until things start to fit. Until then we |
140 | * limit to <= 8bpc since that's what was hardcoded for all |
141 | * MST streams previously. This hack should be removed once |
142 | * we have the proper retry logic in place. |
143 | */ |
144 | limits.max_bpp = min(pipe_config->pipe_bpp, 24)(((pipe_config->pipe_bpp)<(24))?(pipe_config->pipe_bpp ):(24)); |
145 | |
146 | intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits); |
147 | |
148 | ret = intel_dp_mst_compute_link_config(encoder, pipe_config, |
149 | conn_state, &limits); |
150 | if (ret) |
151 | return ret; |
152 | |
153 | pipe_config->limited_color_range = |
154 | intel_dp_limited_color_range(pipe_config, conn_state); |
155 | |
156 | if (IS_GEN9_LP(dev_priv)((0 + (&(dev_priv)->__info)->gen == (9)) && ((&(dev_priv)->__info)->is_lp))) |
157 | pipe_config->lane_lat_optim_mask = |
158 | bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); |
159 | |
160 | intel_ddi_compute_min_voltage_level(dev_priv, pipe_config); |
161 | |
162 | return 0; |
163 | } |
164 | |
165 | /* |
166 | * Iterate over all connectors and return a mask of |
167 | * all CPU transcoders streaming over the same DP link. |
168 | */ |
169 | static unsigned int |
170 | intel_dp_mst_transcoder_mask(struct intel_atomic_state *state, |
171 | struct intel_dp *mst_port) |
172 | { |
173 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(state->base.dev); |
174 | const struct intel_digital_connector_state *conn_state; |
175 | struct intel_connector *connector; |
176 | u8 transcoders = 0; |
177 | int i; |
178 | |
179 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) < 12) |
180 | return 0; |
181 | |
182 | for_each_new_intel_connector_in_state(state, connector, conn_state, i)for ((i) = 0; (i) < (state)->base.num_connector; (i)++) if (!((state)->base.connectors[i].ptr && ((connector ) = ({ const __typeof( ((struct intel_connector *)0)->base ) *__mptr = ((state)->base.connectors[i].ptr); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}), (conn_state) = ({ const __typeof( ((struct intel_digital_connector_state *)0)->base ) *__mptr = ((state)->base.connectors[i].new_state ); (struct intel_digital_connector_state *)( (char *)__mptr - __builtin_offsetof(struct intel_digital_connector_state, base ) );}), 1))) {} else { |
183 | const struct intel_crtc_state *crtc_state; |
184 | struct intel_crtc *crtc; |
185 | |
186 | if (connector->mst_port != mst_port || !conn_state->base.crtc) |
187 | continue; |
188 | |
189 | crtc = to_intel_crtc(conn_state->base.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (conn_state->base.crtc); (struct intel_crtc *)( (char * )__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
190 | crtc_state = intel_atomic_get_new_crtc_state(state, crtc); |
191 | |
192 | if (!crtc_state->hw.active) |
193 | continue; |
194 | |
195 | transcoders |= BIT(crtc_state->cpu_transcoder)(1UL << (crtc_state->cpu_transcoder)); |
196 | } |
197 | |
198 | return transcoders; |
199 | } |
200 | |
201 | static int intel_dp_mst_compute_config_late(struct intel_encoder *encoder, |
202 | struct intel_crtc_state *crtc_state, |
203 | struct drm_connector_state *conn_state) |
204 | { |
205 | struct intel_atomic_state *state = to_intel_atomic_state(conn_state->state)({ const __typeof( ((struct intel_atomic_state *)0)->base ) *__mptr = (conn_state->state); (struct intel_atomic_state *)( (char *)__mptr - __builtin_offsetof(struct intel_atomic_state , base) );}); |
206 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); |
207 | struct intel_dp *intel_dp = &intel_mst->primary->dp; |
208 | |
209 | /* lowest numbered transcoder will be designated master */ |
210 | crtc_state->mst_master_transcoder = |
211 | ffs(intel_dp_mst_transcoder_mask(state, intel_dp)) - 1; |
212 | |
213 | return 0; |
214 | } |
215 | |
216 | /* |
217 | * If one of the connectors in a MST stream needs a modeset, mark all CRTCs |
218 | * that shares the same MST stream as mode changed, |
219 | * intel_modeset_pipe_config()+intel_crtc_check_fastset() will take care to do |
220 | * a fastset when possible. |
221 | */ |
222 | static int |
223 | intel_dp_mst_atomic_master_trans_check(struct intel_connector *connector, |
224 | struct intel_atomic_state *state) |
225 | { |
226 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(state->base.dev); |
227 | struct drm_connector_list_iter connector_list_iter; |
228 | struct intel_connector *connector_iter; |
229 | |
230 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) < 12) |
231 | return 0; |
232 | |
233 | if (!intel_connector_needs_modeset(state, &connector->base)) |
234 | return 0; |
235 | |
236 | drm_connector_list_iter_begin(&dev_priv->drm, &connector_list_iter); |
237 | for_each_intel_connector_iter(connector_iter, &connector_list_iter)while ((connector_iter = ({ const __typeof( ((struct intel_connector *)0)->base ) *__mptr = (drm_connector_list_iter_next(& connector_list_iter)); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );}))) { |
238 | struct intel_digital_connector_state *conn_iter_state; |
239 | struct intel_crtc_state *crtc_state; |
240 | struct intel_crtc *crtc; |
241 | int ret; |
242 | |
243 | if (connector_iter->mst_port != connector->mst_port || |
244 | connector_iter == connector) |
245 | continue; |
246 | |
247 | conn_iter_state = intel_atomic_get_digital_connector_state(state, |
248 | connector_iter); |
249 | if (IS_ERR(conn_iter_state)) { |
250 | drm_connector_list_iter_end(&connector_list_iter); |
251 | return PTR_ERR(conn_iter_state); |
252 | } |
253 | |
254 | if (!conn_iter_state->base.crtc) |
255 | continue; |
256 | |
257 | crtc = to_intel_crtc(conn_iter_state->base.crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (conn_iter_state->base.crtc); (struct intel_crtc *)( (char *)__mptr - __builtin_offsetof(struct intel_crtc, base) );}); |
258 | crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); |
259 | if (IS_ERR(crtc_state)) { |
260 | drm_connector_list_iter_end(&connector_list_iter); |
261 | return PTR_ERR(crtc_state); |
262 | } |
263 | |
264 | ret = drm_atomic_add_affected_planes(&state->base, &crtc->base); |
265 | if (ret) { |
266 | drm_connector_list_iter_end(&connector_list_iter); |
267 | return ret; |
268 | } |
269 | crtc_state->uapi.mode_changed = true1; |
270 | } |
271 | drm_connector_list_iter_end(&connector_list_iter); |
272 | |
273 | return 0; |
274 | } |
275 | |
276 | static int |
277 | intel_dp_mst_atomic_check(struct drm_connector *connector, |
278 | struct drm_atomic_state *_state) |
279 | { |
280 | struct intel_atomic_state *state = to_intel_atomic_state(_state)({ const __typeof( ((struct intel_atomic_state *)0)->base ) *__mptr = (_state); (struct intel_atomic_state *)( (char *)__mptr - __builtin_offsetof(struct intel_atomic_state, base) );}); |
281 | struct drm_connector_state *new_conn_state = |
282 | drm_atomic_get_new_connector_state(&state->base, connector); |
283 | struct drm_connector_state *old_conn_state = |
284 | drm_atomic_get_old_connector_state(&state->base, connector); |
285 | struct intel_connector *intel_connector = |
286 | to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );}); |
287 | struct drm_crtc *new_crtc = new_conn_state->crtc; |
288 | struct drm_dp_mst_topology_mgr *mgr; |
289 | int ret; |
290 | |
291 | ret = intel_digital_connector_atomic_check(connector, &state->base); |
292 | if (ret) |
293 | return ret; |
294 | |
295 | ret = intel_dp_mst_atomic_master_trans_check(intel_connector, state); |
296 | if (ret) |
297 | return ret; |
298 | |
299 | if (!old_conn_state->crtc) |
300 | return 0; |
301 | |
302 | /* We only want to free VCPI if this state disables the CRTC on this |
303 | * connector |
304 | */ |
305 | if (new_crtc) { |
306 | struct intel_crtc *intel_crtc = to_intel_crtc(new_crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (new_crtc); (struct intel_crtc *)( (char *)__mptr - __builtin_offsetof (struct intel_crtc, base) );}); |
307 | struct intel_crtc_state *crtc_state = |
308 | intel_atomic_get_new_crtc_state(state, intel_crtc); |
309 | |
310 | if (!crtc_state || |
311 | !drm_atomic_crtc_needs_modeset(&crtc_state->uapi) || |
312 | crtc_state->uapi.enable) |
313 | return 0; |
314 | } |
315 | |
316 | mgr = &enc_to_mst(to_intel_encoder(old_conn_state->best_encoder)({ const __typeof( ((struct intel_encoder *)0)->base ) *__mptr = (old_conn_state->best_encoder); (struct intel_encoder * )( (char *)__mptr - __builtin_offsetof(struct intel_encoder, base ) );}))->primary->dp.mst_mgr; |
317 | ret = drm_dp_atomic_release_vcpi_slots(&state->base, mgr, |
318 | intel_connector->port); |
319 | |
320 | return ret; |
321 | } |
322 | |
323 | static void clear_act_sent(struct intel_dp *intel_dp) |
324 | { |
325 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp); |
326 | |
327 | intel_de_write(i915, intel_dp->regs.dp_tp_status, |
328 | DP_TP_STATUS_ACT_SENT(1 << 24)); |
329 | } |
330 | |
331 | static void wait_for_act_sent(struct intel_dp *intel_dp) |
332 | { |
333 | struct drm_i915_privateinteldrm_softc *i915 = dp_to_i915(intel_dp); |
334 | |
335 | if (intel_de_wait_for_set(i915, intel_dp->regs.dp_tp_status, |
336 | DP_TP_STATUS_ACT_SENT(1 << 24), 1)) |
337 | drm_err(&i915->drm, "Timed out waiting for ACT sent\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Timed out waiting for ACT sent\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__); |
338 | |
339 | drm_dp_check_act_status(&intel_dp->mst_mgr); |
340 | } |
341 | |
342 | static void intel_mst_disable_dp(struct intel_atomic_state *state, |
343 | struct intel_encoder *encoder, |
344 | const struct intel_crtc_state *old_crtc_state, |
345 | const struct drm_connector_state *old_conn_state) |
346 | { |
347 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); |
348 | struct intel_digital_port *dig_port = intel_mst->primary; |
349 | struct intel_dp *intel_dp = &dig_port->dp; |
350 | struct intel_connector *connector = |
351 | to_intel_connector(old_conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (old_conn_state->connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); |
352 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->base.dev); |
353 | int ret; |
354 | |
355 | drm_dbg_kms(&i915->drm, "active links %d\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "active links %d\n" , intel_dp->active_mst_links) |
356 | intel_dp->active_mst_links)drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "active links %d\n" , intel_dp->active_mst_links); |
357 | |
358 | intel_hdcp_disable(intel_mst->connector); |
359 | |
360 | drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, connector->port); |
361 | |
362 | ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); |
363 | if (ret) { |
364 | drm_dbg_kms(&i915->drm, "failed to update payload %d\n", ret)drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "failed to update payload %d\n" , ret); |
365 | } |
366 | if (old_crtc_state->has_audio) |
367 | intel_audio_codec_disable(encoder, |
368 | old_crtc_state, old_conn_state); |
369 | } |
370 | |
371 | static void intel_mst_post_disable_dp(struct intel_atomic_state *state, |
372 | struct intel_encoder *encoder, |
373 | const struct intel_crtc_state *old_crtc_state, |
374 | const struct drm_connector_state *old_conn_state) |
375 | { |
376 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); |
377 | struct intel_digital_port *dig_port = intel_mst->primary; |
378 | struct intel_dp *intel_dp = &dig_port->dp; |
379 | struct intel_connector *connector = |
380 | to_intel_connector(old_conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (old_conn_state->connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); |
381 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->base.dev); |
382 | bool_Bool last_mst_stream; |
383 | u32 val; |
384 | |
385 | intel_dp->active_mst_links--; |
386 | last_mst_stream = intel_dp->active_mst_links == 0; |
387 | drm_WARN_ON(&dev_priv->drm,({ int __ret = !!((((&(dev_priv)->__info)->gen) >= 12 && last_mst_stream && !intel_dp_mst_is_master_trans (old_crtc_state))); if (__ret) printf("%s %s: " "%s", dev_driver_string (((&dev_priv->drm))->dev), "", "drm_WARN_ON(" "((&(dev_priv)->__info)->gen) >= 12 && last_mst_stream && !intel_dp_mst_is_master_trans(old_crtc_state)" ")"); __builtin_expect(!!(__ret), 0); }) |
388 | INTEL_GEN(dev_priv) >= 12 && last_mst_stream &&({ int __ret = !!((((&(dev_priv)->__info)->gen) >= 12 && last_mst_stream && !intel_dp_mst_is_master_trans (old_crtc_state))); if (__ret) printf("%s %s: " "%s", dev_driver_string (((&dev_priv->drm))->dev), "", "drm_WARN_ON(" "((&(dev_priv)->__info)->gen) >= 12 && last_mst_stream && !intel_dp_mst_is_master_trans(old_crtc_state)" ")"); __builtin_expect(!!(__ret), 0); }) |
389 | !intel_dp_mst_is_master_trans(old_crtc_state))({ int __ret = !!((((&(dev_priv)->__info)->gen) >= 12 && last_mst_stream && !intel_dp_mst_is_master_trans (old_crtc_state))); if (__ret) printf("%s %s: " "%s", dev_driver_string (((&dev_priv->drm))->dev), "", "drm_WARN_ON(" "((&(dev_priv)->__info)->gen) >= 12 && last_mst_stream && !intel_dp_mst_is_master_trans(old_crtc_state)" ")"); __builtin_expect(!!(__ret), 0); }); |
390 | |
391 | intel_crtc_vblank_off(old_crtc_state); |
392 | |
393 | intel_disable_pipe(old_crtc_state); |
394 | |
395 | drm_dp_update_payload_part2(&intel_dp->mst_mgr); |
396 | |
397 | clear_act_sent(intel_dp); |
398 | |
399 | val = intel_de_read(dev_priv, |
400 | TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder)((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> trans_offsets[(old_crtc_state->cpu_transcoder)] - (&(dev_priv )->__info)->trans_offsets[TRANSCODER_A] + (0x60400) + ( (&(dev_priv)->__info)->display_mmio_offset))) })); |
401 | val &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC(1 << 8); |
402 | intel_de_write(dev_priv, |
403 | TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder)((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> trans_offsets[(old_crtc_state->cpu_transcoder)] - (&(dev_priv )->__info)->trans_offsets[TRANSCODER_A] + (0x60400) + ( (&(dev_priv)->__info)->display_mmio_offset))) }), |
404 | val); |
405 | |
406 | wait_for_act_sent(intel_dp); |
407 | |
408 | drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port); |
409 | |
410 | intel_ddi_disable_transcoder_func(old_crtc_state); |
411 | |
412 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) >= 9) |
413 | skl_scaler_disable(old_crtc_state); |
414 | else |
415 | ilk_pfit_disable(old_crtc_state); |
416 | |
417 | /* |
418 | * Power down mst path before disabling the port, otherwise we end |
419 | * up getting interrupts from the sink upon detecting link loss. |
420 | */ |
421 | drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, |
422 | false0); |
423 | |
424 | /* |
425 | * BSpec 4287: disable DIP after the transcoder is disabled and before |
426 | * the transcoder clock select is set to none. |
427 | */ |
428 | if (last_mst_stream) |
429 | intel_dp_set_infoframes(&dig_port->base, false0, |
430 | old_crtc_state, NULL((void *)0)); |
431 | /* |
432 | * From TGL spec: "If multi-stream slave transcoder: Configure |
433 | * Transcoder Clock Select to direct no clock to the transcoder" |
434 | * |
435 | * From older GENs spec: "Configure Transcoder Clock Select to direct |
436 | * no clock to the transcoder" |
437 | */ |
438 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) < 12 || !last_mst_stream) |
439 | intel_ddi_disable_pipe_clock(old_crtc_state); |
440 | |
441 | |
442 | intel_mst->connector = NULL((void *)0); |
443 | if (last_mst_stream) |
444 | dig_port->base.post_disable(state, &dig_port->base, |
445 | old_crtc_state, NULL((void *)0)); |
446 | |
447 | drm_dbg_kms(&dev_priv->drm, "active links %d\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "active links %d\n" , intel_dp->active_mst_links) |
448 | intel_dp->active_mst_links)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "active links %d\n" , intel_dp->active_mst_links); |
449 | } |
450 | |
451 | static void intel_mst_pre_pll_enable_dp(struct intel_atomic_state *state, |
452 | struct intel_encoder *encoder, |
453 | const struct intel_crtc_state *pipe_config, |
454 | const struct drm_connector_state *conn_state) |
455 | { |
456 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); |
457 | struct intel_digital_port *dig_port = intel_mst->primary; |
458 | struct intel_dp *intel_dp = &dig_port->dp; |
459 | |
460 | if (intel_dp->active_mst_links == 0) |
461 | dig_port->base.pre_pll_enable(state, &dig_port->base, |
462 | pipe_config, NULL((void *)0)); |
463 | } |
464 | |
465 | static void intel_mst_pre_enable_dp(struct intel_atomic_state *state, |
466 | struct intel_encoder *encoder, |
467 | const struct intel_crtc_state *pipe_config, |
468 | const struct drm_connector_state *conn_state) |
469 | { |
470 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); |
471 | struct intel_digital_port *dig_port = intel_mst->primary; |
472 | struct intel_dp *intel_dp = &dig_port->dp; |
473 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
474 | struct intel_connector *connector = |
475 | to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}); |
476 | int ret; |
477 | bool_Bool first_mst_stream; |
478 | |
479 | /* MST encoders are bound to a crtc, not to a connector, |
480 | * force the mapping here for get_hw_state. |
481 | */ |
482 | connector->encoder = encoder; |
483 | intel_mst->connector = connector; |
484 | first_mst_stream = intel_dp->active_mst_links == 0; |
485 | drm_WARN_ON(&dev_priv->drm,({ int __ret = !!((((&(dev_priv)->__info)->gen) >= 12 && first_mst_stream && !intel_dp_mst_is_master_trans (pipe_config))); if (__ret) printf("%s %s: " "%s", dev_driver_string (((&dev_priv->drm))->dev), "", "drm_WARN_ON(" "((&(dev_priv)->__info)->gen) >= 12 && first_mst_stream && !intel_dp_mst_is_master_trans(pipe_config)" ")"); __builtin_expect(!!(__ret), 0); }) |
486 | INTEL_GEN(dev_priv) >= 12 && first_mst_stream &&({ int __ret = !!((((&(dev_priv)->__info)->gen) >= 12 && first_mst_stream && !intel_dp_mst_is_master_trans (pipe_config))); if (__ret) printf("%s %s: " "%s", dev_driver_string (((&dev_priv->drm))->dev), "", "drm_WARN_ON(" "((&(dev_priv)->__info)->gen) >= 12 && first_mst_stream && !intel_dp_mst_is_master_trans(pipe_config)" ")"); __builtin_expect(!!(__ret), 0); }) |
487 | !intel_dp_mst_is_master_trans(pipe_config))({ int __ret = !!((((&(dev_priv)->__info)->gen) >= 12 && first_mst_stream && !intel_dp_mst_is_master_trans (pipe_config))); if (__ret) printf("%s %s: " "%s", dev_driver_string (((&dev_priv->drm))->dev), "", "drm_WARN_ON(" "((&(dev_priv)->__info)->gen) >= 12 && first_mst_stream && !intel_dp_mst_is_master_trans(pipe_config)" ")"); __builtin_expect(!!(__ret), 0); }); |
488 | |
489 | drm_dbg_kms(&dev_priv->drm, "active links %d\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "active links %d\n" , intel_dp->active_mst_links) |
490 | intel_dp->active_mst_links)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "active links %d\n" , intel_dp->active_mst_links); |
491 | |
492 | if (first_mst_stream) |
493 | intel_dp_set_power(intel_dp, DP_SET_POWER_D00x1); |
494 | |
495 | drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, true1); |
496 | |
497 | if (first_mst_stream) |
498 | dig_port->base.pre_enable(state, &dig_port->base, |
499 | pipe_config, NULL((void *)0)); |
500 | |
501 | ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, |
502 | connector->port, |
503 | pipe_config->pbn, |
504 | pipe_config->dp_m_n.tu); |
505 | if (!ret) |
506 | drm_err(&dev_priv->drm, "failed to allocate vcpi\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "failed to allocate vcpi\n" , ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc->p_p->ps_pid, __func__); |
507 | |
508 | intel_dp->active_mst_links++; |
509 | |
510 | ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr); |
Value stored to 'ret' is never read | |
511 | |
512 | /* |
513 | * Before Gen 12 this is not done as part of |
514 | * dig_port->base.pre_enable() and should be done here. For |
515 | * Gen 12+ the step in which this should be done is different for the |
516 | * first MST stream, so it's done on the DDI for the first stream and |
517 | * here for the following ones. |
518 | */ |
519 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) < 12 || !first_mst_stream) |
520 | intel_ddi_enable_pipe_clock(encoder, pipe_config); |
521 | |
522 | intel_ddi_set_dp_msa(pipe_config, conn_state); |
523 | |
524 | intel_dp_set_m_n(pipe_config, M1_N1); |
525 | } |
526 | |
527 | static void intel_mst_enable_dp(struct intel_atomic_state *state, |
528 | struct intel_encoder *encoder, |
529 | const struct intel_crtc_state *pipe_config, |
530 | const struct drm_connector_state *conn_state) |
531 | { |
532 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); |
533 | struct intel_digital_port *dig_port = intel_mst->primary; |
534 | struct intel_dp *intel_dp = &dig_port->dp; |
535 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(encoder->base.dev); |
536 | u32 val; |
537 | |
538 | drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder)({ int __ret = !!((pipe_config->has_pch_encoder)); if (__ret ) printf("%s %s: " "%s", dev_driver_string(((&dev_priv-> drm))->dev), "", "drm_WARN_ON(" "pipe_config->has_pch_encoder" ")"); __builtin_expect(!!(__ret), 0); }); |
539 | |
540 | clear_act_sent(intel_dp); |
541 | |
542 | intel_ddi_enable_transcoder_func(encoder, pipe_config); |
543 | |
544 | val = intel_de_read(dev_priv, |
545 | TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder)((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> trans_offsets[(pipe_config->cpu_transcoder)] - (&(dev_priv )->__info)->trans_offsets[TRANSCODER_A] + (0x60400) + ( (&(dev_priv)->__info)->display_mmio_offset))) })); |
546 | val |= TRANS_DDI_DP_VC_PAYLOAD_ALLOC(1 << 8); |
547 | intel_de_write(dev_priv, |
548 | TRANS_DDI_FUNC_CTL(pipe_config->cpu_transcoder)((const i915_reg_t){ .reg = (((&(dev_priv)->__info)-> trans_offsets[(pipe_config->cpu_transcoder)] - (&(dev_priv )->__info)->trans_offsets[TRANSCODER_A] + (0x60400) + ( (&(dev_priv)->__info)->display_mmio_offset))) }), |
549 | val); |
550 | |
551 | drm_dbg_kms(&dev_priv->drm, "active links %d\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "active links %d\n" , intel_dp->active_mst_links) |
552 | intel_dp->active_mst_links)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "active links %d\n" , intel_dp->active_mst_links); |
553 | |
554 | wait_for_act_sent(intel_dp); |
555 | |
556 | drm_dp_update_payload_part2(&intel_dp->mst_mgr); |
557 | |
558 | intel_enable_pipe(pipe_config); |
559 | |
560 | intel_crtc_vblank_on(pipe_config); |
561 | |
562 | if (pipe_config->has_audio) |
563 | intel_audio_codec_enable(encoder, pipe_config, conn_state); |
564 | |
565 | /* Enable hdcp if it's desired */ |
566 | if (conn_state->content_protection == |
567 | DRM_MODE_CONTENT_PROTECTION_DESIRED1) |
568 | intel_hdcp_enable(to_intel_connector(conn_state->connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (conn_state->connector); (struct intel_connector * )( (char *)__mptr - __builtin_offsetof(struct intel_connector , base) );}), |
569 | pipe_config->cpu_transcoder, |
570 | (u8)conn_state->hdcp_content_type); |
571 | } |
572 | |
573 | static bool_Bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder, |
574 | enum pipe *pipe) |
575 | { |
576 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); |
577 | *pipe = intel_mst->pipe; |
578 | if (intel_mst->connector) |
579 | return true1; |
580 | return false0; |
581 | } |
582 | |
583 | static void intel_dp_mst_enc_get_config(struct intel_encoder *encoder, |
584 | struct intel_crtc_state *pipe_config) |
585 | { |
586 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); |
587 | struct intel_digital_port *dig_port = intel_mst->primary; |
588 | |
589 | intel_ddi_get_config(&dig_port->base, pipe_config); |
590 | } |
591 | |
592 | static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector) |
593 | { |
594 | struct intel_connector *intel_connector = to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );}); |
595 | struct intel_dp *intel_dp = intel_connector->mst_port; |
596 | struct edid *edid; |
597 | int ret; |
598 | |
599 | if (drm_connector_is_unregistered(connector)) |
600 | return intel_connector_update_modes(connector, NULL((void *)0)); |
601 | |
602 | edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port); |
603 | ret = intel_connector_update_modes(connector, edid); |
604 | kfree(edid); |
605 | |
606 | return ret; |
607 | } |
608 | |
609 | static int |
610 | intel_dp_mst_connector_late_register(struct drm_connector *connector) |
611 | { |
612 | struct intel_connector *intel_connector = to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );}); |
613 | int ret; |
614 | |
615 | ret = drm_dp_mst_connector_late_register(connector, |
616 | intel_connector->port); |
617 | if (ret < 0) |
618 | return ret; |
619 | |
620 | ret = intel_connector_register(connector); |
621 | if (ret < 0) |
622 | drm_dp_mst_connector_early_unregister(connector, |
623 | intel_connector->port); |
624 | |
625 | return ret; |
626 | } |
627 | |
628 | static void |
629 | intel_dp_mst_connector_early_unregister(struct drm_connector *connector) |
630 | { |
631 | struct intel_connector *intel_connector = to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );}); |
632 | |
633 | intel_connector_unregister(connector); |
634 | drm_dp_mst_connector_early_unregister(connector, |
635 | intel_connector->port); |
636 | } |
637 | |
638 | static const struct drm_connector_funcs intel_dp_mst_connector_funcs = { |
639 | .fill_modes = drm_helper_probe_single_connector_modes, |
640 | .atomic_get_property = intel_digital_connector_atomic_get_property, |
641 | .atomic_set_property = intel_digital_connector_atomic_set_property, |
642 | .late_register = intel_dp_mst_connector_late_register, |
643 | .early_unregister = intel_dp_mst_connector_early_unregister, |
644 | .destroy = intel_connector_destroy, |
645 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
646 | .atomic_duplicate_state = intel_digital_connector_duplicate_state, |
647 | }; |
648 | |
649 | static int intel_dp_mst_get_modes(struct drm_connector *connector) |
650 | { |
651 | return intel_dp_mst_get_ddc_modes(connector); |
652 | } |
653 | |
654 | static int |
655 | intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, |
656 | struct drm_display_mode *mode, |
657 | struct drm_modeset_acquire_ctx *ctx, |
658 | enum drm_mode_status *status) |
659 | { |
660 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(connector->dev); |
661 | struct intel_connector *intel_connector = to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );}); |
662 | struct intel_dp *intel_dp = intel_connector->mst_port; |
663 | struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst_mgr; |
664 | struct drm_dp_mst_port *port = intel_connector->port; |
665 | const int min_bpp = 18; |
666 | int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; |
667 | int max_rate, mode_rate, max_lanes, max_link_clock; |
668 | int ret; |
669 | |
670 | if (drm_connector_is_unregistered(connector)) { |
671 | *status = MODE_ERROR; |
672 | return 0; |
673 | } |
674 | |
675 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN(1<<5)) { |
676 | *status = MODE_NO_DBLESCAN; |
677 | return 0; |
678 | } |
679 | |
680 | max_link_clock = intel_dp_max_link_rate(intel_dp); |
681 | max_lanes = intel_dp_max_lane_count(intel_dp); |
682 | |
683 | max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); |
684 | mode_rate = intel_dp_link_required(mode->clock, min_bpp); |
685 | |
686 | ret = drm_modeset_lock(&mgr->base.lock, ctx); |
687 | if (ret) |
688 | return ret; |
689 | |
690 | if (mode_rate > max_rate || mode->clock > max_dotclk || |
691 | drm_dp_calc_pbn_mode(mode->clock, min_bpp, false0) > port->full_pbn) { |
692 | *status = MODE_CLOCK_HIGH; |
693 | return 0; |
694 | } |
695 | |
696 | if (mode->clock < 10000) { |
697 | *status = MODE_CLOCK_LOW; |
698 | return 0; |
699 | } |
700 | |
701 | if (mode->flags & DRM_MODE_FLAG_DBLCLK(1<<12)) { |
702 | *status = MODE_H_ILLEGAL; |
703 | return 0; |
704 | } |
705 | |
706 | *status = intel_mode_valid_max_plane_size(dev_priv, mode); |
707 | return 0; |
708 | } |
709 | |
710 | static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *connector, |
711 | struct drm_connector_state *state) |
712 | { |
713 | struct intel_connector *intel_connector = to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );}); |
714 | struct intel_dp *intel_dp = intel_connector->mst_port; |
715 | struct intel_crtc *crtc = to_intel_crtc(state->crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr = (state->crtc); (struct intel_crtc *)( (char *)__mptr - __builtin_offsetof (struct intel_crtc, base) );}); |
716 | |
717 | return &intel_dp->mst_encoders[crtc->pipe]->base.base; |
718 | } |
719 | |
720 | static int |
721 | intel_dp_mst_detect(struct drm_connector *connector, |
722 | struct drm_modeset_acquire_ctx *ctx, bool_Bool force) |
723 | { |
724 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(connector->dev); |
725 | struct intel_connector *intel_connector = to_intel_connector(connector)({ const __typeof( ((struct intel_connector *)0)->base ) * __mptr = (connector); (struct intel_connector *)( (char *)__mptr - __builtin_offsetof(struct intel_connector, base) );}); |
726 | struct intel_dp *intel_dp = intel_connector->mst_port; |
727 | |
728 | if (!INTEL_DISPLAY_ENABLED(i915)(({ int __ret = !!((!((&(i915)->__info)->pipe_mask != 0))); if (__ret) printf("%s %s: " "%s", dev_driver_string((( &(i915)->drm))->dev), "", "drm_WARN_ON(" "!((&(i915)->__info)->pipe_mask != 0)" ")"); __builtin_expect(!!(__ret), 0); }), !(i915)->params .disable_display)) |
729 | return connector_status_disconnected; |
730 | |
731 | if (drm_connector_is_unregistered(connector)) |
732 | return connector_status_disconnected; |
733 | |
734 | return drm_dp_mst_detect_port(connector, ctx, &intel_dp->mst_mgr, |
735 | intel_connector->port); |
736 | } |
737 | |
738 | static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = { |
739 | .get_modes = intel_dp_mst_get_modes, |
740 | .mode_valid_ctx = intel_dp_mst_mode_valid_ctx, |
741 | .atomic_best_encoder = intel_mst_atomic_best_encoder, |
742 | .atomic_check = intel_dp_mst_atomic_check, |
743 | .detect_ctx = intel_dp_mst_detect, |
744 | }; |
745 | |
746 | static void intel_dp_mst_encoder_destroy(struct drm_encoder *encoder) |
747 | { |
748 | struct intel_dp_mst_encoder *intel_mst = enc_to_mst(to_intel_encoder(encoder)({ const __typeof( ((struct intel_encoder *)0)->base ) *__mptr = (encoder); (struct intel_encoder *)( (char *)__mptr - __builtin_offsetof (struct intel_encoder, base) );})); |
749 | |
750 | drm_encoder_cleanup(encoder); |
751 | kfree(intel_mst); |
752 | } |
753 | |
754 | static const struct drm_encoder_funcs intel_dp_mst_enc_funcs = { |
755 | .destroy = intel_dp_mst_encoder_destroy, |
756 | }; |
757 | |
758 | static bool_Bool intel_dp_mst_get_hw_state(struct intel_connector *connector) |
759 | { |
760 | if (intel_attached_encoder(connector) && connector->base.state->crtc) { |
761 | enum pipe pipe; |
762 | if (!intel_attached_encoder(connector)->get_hw_state(intel_attached_encoder(connector), &pipe)) |
763 | return false0; |
764 | return true1; |
765 | } |
766 | return false0; |
767 | } |
768 | |
769 | static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *pathprop) |
770 | { |
771 | struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr)({ const __typeof( ((struct intel_dp *)0)->mst_mgr ) *__mptr = (mgr); (struct intel_dp *)( (char *)__mptr - __builtin_offsetof (struct intel_dp, mst_mgr) );}); |
772 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
773 | struct drm_device *dev = dig_port->base.base.dev; |
774 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev); |
775 | struct intel_connector *intel_connector; |
776 | struct drm_connector *connector; |
777 | enum pipe pipe; |
778 | int ret; |
779 | |
780 | intel_connector = intel_connector_alloc(); |
781 | if (!intel_connector) |
782 | return NULL((void *)0); |
783 | |
784 | intel_connector->get_hw_state = intel_dp_mst_get_hw_state; |
785 | intel_connector->mst_port = intel_dp; |
786 | intel_connector->port = port; |
787 | drm_dp_mst_get_port_malloc(port); |
788 | |
789 | connector = &intel_connector->base; |
790 | ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, |
791 | DRM_MODE_CONNECTOR_DisplayPort10); |
792 | if (ret) { |
793 | intel_connector_free(intel_connector); |
794 | return NULL((void *)0); |
795 | } |
796 | |
797 | drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs); |
798 | |
799 | for_each_pipe(dev_priv, pipe)for ((pipe) = 0; (pipe) < I915_MAX_PIPES; (pipe)++) if (!( (&(dev_priv)->__info)->pipe_mask & (1UL << (pipe)))) {} else { |
800 | struct drm_encoder *enc = |
801 | &intel_dp->mst_encoders[pipe]->base.base; |
802 | |
803 | ret = drm_connector_attach_encoder(&intel_connector->base, enc); |
804 | if (ret) |
805 | goto err; |
806 | } |
807 | |
808 | drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0); |
809 | drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0); |
810 | |
811 | ret = drm_connector_set_path_property(connector, pathprop); |
812 | if (ret) |
813 | goto err; |
814 | |
815 | intel_attach_force_audio_property(connector); |
816 | intel_attach_broadcast_rgb_property(connector); |
817 | |
818 | |
819 | /* TODO: Figure out how to make HDCP work on GEN12+ */ |
820 | if (INTEL_GEN(dev_priv)((&(dev_priv)->__info)->gen) < 12) { |
821 | ret = intel_dp_init_hdcp(dig_port, intel_connector); |
822 | if (ret) |
823 | DRM_DEBUG_KMS("HDCP init failed, skipping.\n")__drm_dbg(DRM_UT_KMS, "HDCP init failed, skipping.\n"); |
824 | } |
825 | |
826 | /* |
827 | * Reuse the prop from the SST connector because we're |
828 | * not allowed to create new props after device registration. |
829 | */ |
830 | connector->max_bpc_property = |
831 | intel_dp->attached_connector->base.max_bpc_property; |
832 | if (connector->max_bpc_property) |
833 | drm_connector_attach_max_bpc_property(connector, 6, 12); |
834 | |
835 | return connector; |
836 | |
837 | err: |
838 | drm_connector_cleanup(connector); |
839 | return NULL((void *)0); |
840 | } |
841 | |
842 | static void |
843 | intel_dp_mst_poll_hpd_irq(struct drm_dp_mst_topology_mgr *mgr) |
844 | { |
845 | struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr)({ const __typeof( ((struct intel_dp *)0)->mst_mgr ) *__mptr = (mgr); (struct intel_dp *)( (char *)__mptr - __builtin_offsetof (struct intel_dp, mst_mgr) );}); |
846 | |
847 | intel_hpd_trigger_irq(dp_to_dig_port(intel_dp)); |
848 | } |
849 | |
850 | static const struct drm_dp_mst_topology_cbs mst_cbs = { |
851 | .add_connector = intel_dp_add_mst_connector, |
852 | .poll_hpd_irq = intel_dp_mst_poll_hpd_irq, |
853 | }; |
854 | |
855 | static struct intel_dp_mst_encoder * |
856 | intel_dp_create_fake_mst_encoder(struct intel_digital_port *dig_port, enum pipe pipe) |
857 | { |
858 | struct intel_dp_mst_encoder *intel_mst; |
859 | struct intel_encoder *intel_encoder; |
860 | struct drm_device *dev = dig_port->base.base.dev; |
861 | |
862 | intel_mst = kzalloc(sizeof(*intel_mst), GFP_KERNEL(0x0001 | 0x0004)); |
863 | |
864 | if (!intel_mst) |
865 | return NULL((void *)0); |
866 | |
867 | intel_mst->pipe = pipe; |
868 | intel_encoder = &intel_mst->base; |
869 | intel_mst->primary = dig_port; |
870 | |
871 | drm_encoder_init(dev, &intel_encoder->base, &intel_dp_mst_enc_funcs, |
872 | DRM_MODE_ENCODER_DPMST7, "DP-MST %c", pipe_name(pipe)((pipe) + 'A')); |
873 | |
874 | intel_encoder->type = INTEL_OUTPUT_DP_MST; |
875 | intel_encoder->power_domain = dig_port->base.power_domain; |
876 | intel_encoder->port = dig_port->base.port; |
877 | intel_encoder->cloneable = 0; |
878 | /* |
879 | * This is wrong, but broken userspace uses the intersection |
880 | * of possible_crtcs of all the encoders of a given connector |
881 | * to figure out which crtcs can drive said connector. What |
882 | * should be used instead is the union of possible_crtcs. |
883 | * To keep such userspace functioning we must misconfigure |
884 | * this to make sure the intersection is not empty :( |
885 | */ |
886 | intel_encoder->pipe_mask = ~0; |
887 | |
888 | intel_encoder->compute_config = intel_dp_mst_compute_config; |
889 | intel_encoder->compute_config_late = intel_dp_mst_compute_config_late; |
890 | intel_encoder->disable = intel_mst_disable_dp; |
891 | intel_encoder->post_disable = intel_mst_post_disable_dp; |
892 | intel_encoder->update_pipe = intel_ddi_update_pipe; |
893 | intel_encoder->pre_pll_enable = intel_mst_pre_pll_enable_dp; |
894 | intel_encoder->pre_enable = intel_mst_pre_enable_dp; |
895 | intel_encoder->enable = intel_mst_enable_dp; |
896 | intel_encoder->get_hw_state = intel_dp_mst_enc_get_hw_state; |
897 | intel_encoder->get_config = intel_dp_mst_enc_get_config; |
898 | |
899 | return intel_mst; |
900 | |
901 | } |
902 | |
903 | static bool_Bool |
904 | intel_dp_create_fake_mst_encoders(struct intel_digital_port *dig_port) |
905 | { |
906 | struct intel_dp *intel_dp = &dig_port->dp; |
907 | struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dig_port->base.base.dev); |
908 | enum pipe pipe; |
909 | |
910 | for_each_pipe(dev_priv, pipe)for ((pipe) = 0; (pipe) < I915_MAX_PIPES; (pipe)++) if (!( (&(dev_priv)->__info)->pipe_mask & (1UL << (pipe)))) {} else |
911 | intel_dp->mst_encoders[pipe] = intel_dp_create_fake_mst_encoder(dig_port, pipe); |
912 | return true1; |
913 | } |
914 | |
915 | int |
916 | intel_dp_mst_encoder_active_links(struct intel_digital_port *dig_port) |
917 | { |
918 | return dig_port->dp.active_mst_links; |
919 | } |
920 | |
921 | int |
922 | intel_dp_mst_encoder_init(struct intel_digital_port *dig_port, int conn_base_id) |
923 | { |
924 | struct drm_i915_privateinteldrm_softc *i915 = to_i915(dig_port->base.base.dev); |
925 | struct intel_dp *intel_dp = &dig_port->dp; |
926 | enum port port = dig_port->base.port; |
927 | int ret; |
928 | |
929 | if (!HAS_DP_MST(i915)((&(i915)->__info)->display.has_dp_mst) || intel_dp_is_edp(intel_dp)) |
930 | return 0; |
931 | |
932 | if (INTEL_GEN(i915)((&(i915)->__info)->gen) < 12 && port == PORT_A) |
933 | return 0; |
934 | |
935 | if (INTEL_GEN(i915)((&(i915)->__info)->gen) < 11 && port == PORT_E) |
936 | return 0; |
937 | |
938 | intel_dp->mst_mgr.cbs = &mst_cbs; |
939 | |
940 | /* create encoders */ |
941 | intel_dp_create_fake_mst_encoders(dig_port); |
942 | ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, &i915->drm, |
943 | &intel_dp->aux, 16, 3, conn_base_id); |
944 | if (ret) |
945 | return ret; |
946 | |
947 | intel_dp->can_mst = true1; |
948 | |
949 | return 0; |
950 | } |
951 | |
952 | void |
953 | intel_dp_mst_encoder_cleanup(struct intel_digital_port *dig_port) |
954 | { |
955 | struct intel_dp *intel_dp = &dig_port->dp; |
956 | |
957 | if (!intel_dp->can_mst) |
958 | return; |
959 | |
960 | drm_dp_mst_topology_mgr_destroy(&intel_dp->mst_mgr); |
961 | /* encoders will get killed by normal cleanup */ |
962 | } |
963 | |
964 | bool_Bool intel_dp_mst_is_master_trans(const struct intel_crtc_state *crtc_state) |
965 | { |
966 | return crtc_state->mst_master_transcoder == crtc_state->cpu_transcoder; |
967 | } |
968 | |
969 | bool_Bool intel_dp_mst_is_slave_trans(const struct intel_crtc_state *crtc_state) |
970 | { |
971 | return crtc_state->mst_master_transcoder != INVALID_TRANSCODER && |
972 | crtc_state->mst_master_transcoder != crtc_state->cpu_transcoder; |
973 | } |