1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * Copyright © 2022 Intel Corporation |
4 | * |
5 | * High level crtc/connector/encoder modeset state verification. |
6 | */ |
7 | |
8 | #include <drm/drm_atomic_state_helper.h> |
9 | |
10 | #include "i915_drv.h" |
11 | #include "intel_atomic.h" |
12 | #include "intel_crtc.h" |
13 | #include "intel_crtc_state_dump.h" |
14 | #include "intel_cx0_phy.h" |
15 | #include "intel_display.h" |
16 | #include "intel_display_types.h" |
17 | #include "intel_fdi.h" |
18 | #include "intel_modeset_verify.h" |
19 | #include "intel_snps_phy.h" |
20 | #include "skl_watermark.h" |
21 | |
22 | /* |
23 | * Cross check the actual hw state with our own modeset state tracking (and its |
24 | * internal consistency). |
25 | */ |
26 | static void intel_connector_verify_state(const struct intel_crtc_state *crtc_state, |
27 | const struct drm_connector_state *conn_state) |
28 | { |
29 | struct intel_connector *connector = to_intel_connector(conn_state->connector); |
30 | struct drm_i915_private *i915 = to_i915(dev: connector->base.dev); |
31 | |
32 | drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s]\n" , |
33 | connector->base.base.id, connector->base.name); |
34 | |
35 | if (connector->get_hw_state(connector)) { |
36 | struct intel_encoder *encoder = intel_attached_encoder(connector); |
37 | |
38 | I915_STATE_WARN(i915, !crtc_state, |
39 | "connector enabled without attached crtc\n" ); |
40 | |
41 | if (!crtc_state) |
42 | return; |
43 | |
44 | I915_STATE_WARN(i915, !crtc_state->hw.active, |
45 | "connector is active, but attached crtc isn't\n" ); |
46 | |
47 | if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST) |
48 | return; |
49 | |
50 | I915_STATE_WARN(i915, |
51 | conn_state->best_encoder != &encoder->base, |
52 | "atomic encoder doesn't match attached encoder\n" ); |
53 | |
54 | I915_STATE_WARN(i915, conn_state->crtc != encoder->base.crtc, |
55 | "attached encoder crtc differs from connector crtc\n" ); |
56 | } else { |
57 | I915_STATE_WARN(i915, crtc_state && crtc_state->hw.active, |
58 | "attached crtc is active, but connector isn't\n" ); |
59 | I915_STATE_WARN(i915, !crtc_state && conn_state->best_encoder, |
60 | "best encoder set without crtc!\n" ); |
61 | } |
62 | } |
63 | |
64 | static void |
65 | verify_connector_state(struct intel_atomic_state *state, |
66 | struct intel_crtc *crtc) |
67 | { |
68 | struct drm_connector *connector; |
69 | const struct drm_connector_state *new_conn_state; |
70 | int i; |
71 | |
72 | for_each_new_connector_in_state(&state->base, connector, new_conn_state, i) { |
73 | struct drm_encoder *encoder = connector->encoder; |
74 | const struct intel_crtc_state *crtc_state = NULL; |
75 | |
76 | if (new_conn_state->crtc != &crtc->base) |
77 | continue; |
78 | |
79 | if (crtc) |
80 | crtc_state = intel_atomic_get_new_crtc_state(state, crtc); |
81 | |
82 | intel_connector_verify_state(crtc_state, conn_state: new_conn_state); |
83 | |
84 | I915_STATE_WARN(to_i915(connector->dev), new_conn_state->best_encoder != encoder, |
85 | "connector's atomic encoder doesn't match legacy encoder\n" ); |
86 | } |
87 | } |
88 | |
89 | static void intel_pipe_config_sanity_check(const struct intel_crtc_state *crtc_state) |
90 | { |
91 | struct drm_i915_private *i915 = to_i915(dev: crtc_state->uapi.crtc->dev); |
92 | |
93 | if (crtc_state->has_pch_encoder) { |
94 | int fdi_dotclock = intel_dotclock_calculate(link_freq: intel_fdi_link_freq(i915, pipe_config: crtc_state), |
95 | m_n: &crtc_state->fdi_m_n); |
96 | int dotclock = crtc_state->hw.adjusted_mode.crtc_clock; |
97 | |
98 | /* |
99 | * FDI already provided one idea for the dotclock. |
100 | * Yell if the encoder disagrees. Allow for slight |
101 | * rounding differences. |
102 | */ |
103 | drm_WARN(&i915->drm, abs(fdi_dotclock - dotclock) > 1, |
104 | "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n" , |
105 | fdi_dotclock, dotclock); |
106 | } |
107 | } |
108 | |
109 | static void |
110 | verify_encoder_state(struct intel_atomic_state *state) |
111 | { |
112 | struct drm_i915_private *i915 = to_i915(dev: state->base.dev); |
113 | struct intel_encoder *encoder; |
114 | struct drm_connector *connector; |
115 | const struct drm_connector_state *old_conn_state, *new_conn_state; |
116 | int i; |
117 | |
118 | for_each_intel_encoder(&i915->drm, encoder) { |
119 | bool enabled = false, found = false; |
120 | enum pipe pipe; |
121 | |
122 | drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s]\n" , |
123 | encoder->base.base.id, |
124 | encoder->base.name); |
125 | |
126 | for_each_oldnew_connector_in_state(&state->base, connector, old_conn_state, |
127 | new_conn_state, i) { |
128 | if (old_conn_state->best_encoder == &encoder->base) |
129 | found = true; |
130 | |
131 | if (new_conn_state->best_encoder != &encoder->base) |
132 | continue; |
133 | |
134 | found = true; |
135 | enabled = true; |
136 | |
137 | I915_STATE_WARN(i915, |
138 | new_conn_state->crtc != encoder->base.crtc, |
139 | "connector's crtc doesn't match encoder crtc\n" ); |
140 | } |
141 | |
142 | if (!found) |
143 | continue; |
144 | |
145 | I915_STATE_WARN(i915, !!encoder->base.crtc != enabled, |
146 | "encoder's enabled state mismatch (expected %i, found %i)\n" , |
147 | !!encoder->base.crtc, enabled); |
148 | |
149 | if (!encoder->base.crtc) { |
150 | bool active; |
151 | |
152 | active = encoder->get_hw_state(encoder, &pipe); |
153 | I915_STATE_WARN(i915, active, |
154 | "encoder detached but still enabled on pipe %c.\n" , |
155 | pipe_name(pipe)); |
156 | } |
157 | } |
158 | } |
159 | |
160 | static void |
161 | verify_crtc_state(struct intel_atomic_state *state, |
162 | struct intel_crtc *crtc) |
163 | { |
164 | struct drm_device *dev = crtc->base.dev; |
165 | struct drm_i915_private *i915 = to_i915(dev); |
166 | const struct intel_crtc_state *sw_crtc_state = |
167 | intel_atomic_get_new_crtc_state(state, crtc); |
168 | struct intel_crtc_state *hw_crtc_state; |
169 | struct intel_crtc *master_crtc; |
170 | struct intel_encoder *encoder; |
171 | |
172 | hw_crtc_state = intel_crtc_state_alloc(crtc); |
173 | if (!hw_crtc_state) |
174 | return; |
175 | |
176 | drm_dbg_kms(&i915->drm, "[CRTC:%d:%s]\n" , crtc->base.base.id, |
177 | crtc->base.name); |
178 | |
179 | hw_crtc_state->hw.enable = sw_crtc_state->hw.enable; |
180 | |
181 | intel_crtc_get_pipe_config(crtc_state: hw_crtc_state); |
182 | |
183 | /* we keep both pipes enabled on 830 */ |
184 | if (IS_I830(i915) && hw_crtc_state->hw.active) |
185 | hw_crtc_state->hw.active = sw_crtc_state->hw.active; |
186 | |
187 | I915_STATE_WARN(i915, |
188 | sw_crtc_state->hw.active != hw_crtc_state->hw.active, |
189 | "crtc active state doesn't match with hw state (expected %i, found %i)\n" , |
190 | sw_crtc_state->hw.active, hw_crtc_state->hw.active); |
191 | |
192 | I915_STATE_WARN(i915, crtc->active != sw_crtc_state->hw.active, |
193 | "transitional active state does not match atomic hw state (expected %i, found %i)\n" , |
194 | sw_crtc_state->hw.active, crtc->active); |
195 | |
196 | master_crtc = intel_master_crtc(crtc_state: sw_crtc_state); |
197 | |
198 | for_each_encoder_on_crtc(dev, &master_crtc->base, encoder) { |
199 | enum pipe pipe; |
200 | bool active; |
201 | |
202 | active = encoder->get_hw_state(encoder, &pipe); |
203 | I915_STATE_WARN(i915, active != sw_crtc_state->hw.active, |
204 | "[ENCODER:%i] active %i with crtc active %i\n" , |
205 | encoder->base.base.id, active, |
206 | sw_crtc_state->hw.active); |
207 | |
208 | I915_STATE_WARN(i915, active && master_crtc->pipe != pipe, |
209 | "Encoder connected to wrong pipe %c\n" , |
210 | pipe_name(pipe)); |
211 | |
212 | if (active) |
213 | intel_encoder_get_config(encoder, crtc_state: hw_crtc_state); |
214 | } |
215 | |
216 | if (!sw_crtc_state->hw.active) |
217 | goto destroy_state; |
218 | |
219 | intel_pipe_config_sanity_check(crtc_state: hw_crtc_state); |
220 | |
221 | if (!intel_pipe_config_compare(current_config: sw_crtc_state, |
222 | pipe_config: hw_crtc_state, fastset: false)) { |
223 | I915_STATE_WARN(i915, 1, "pipe state doesn't match!\n" ); |
224 | intel_crtc_state_dump(crtc_state: hw_crtc_state, NULL, context: "hw state" ); |
225 | intel_crtc_state_dump(crtc_state: sw_crtc_state, NULL, context: "sw state" ); |
226 | } |
227 | |
228 | destroy_state: |
229 | intel_crtc_destroy_state(crtc: &crtc->base, state: &hw_crtc_state->uapi); |
230 | } |
231 | |
232 | void intel_modeset_verify_crtc(struct intel_atomic_state *state, |
233 | struct intel_crtc *crtc) |
234 | { |
235 | const struct intel_crtc_state *new_crtc_state = |
236 | intel_atomic_get_new_crtc_state(state, crtc); |
237 | |
238 | if (!intel_crtc_needs_modeset(crtc_state: new_crtc_state) && |
239 | !intel_crtc_needs_fastset(crtc_state: new_crtc_state)) |
240 | return; |
241 | |
242 | intel_wm_state_verify(state, crtc); |
243 | verify_connector_state(state, crtc); |
244 | verify_crtc_state(state, crtc); |
245 | intel_shared_dpll_state_verify(state, crtc); |
246 | intel_mpllb_state_verify(state, crtc); |
247 | intel_cx0pll_state_verify(state, crtc); |
248 | } |
249 | |
250 | void intel_modeset_verify_disabled(struct intel_atomic_state *state) |
251 | { |
252 | verify_encoder_state(state); |
253 | verify_connector_state(state, NULL); |
254 | intel_shared_dpll_verify_disabled(state); |
255 | } |
256 | |