Commit | Line | Data |
---|---|---|
5b0c5945 MN |
1 | // SPDX-License-Identifier: MIT |
2 | /* | |
3 | * Copyright © 2020 Intel Corporation | |
4 | * | |
5 | */ | |
6 | ||
7 | #include "i915_drv.h" | |
801543b2 | 8 | #include "i915_reg.h" |
7785ae0b | 9 | #include "intel_de.h" |
5b0c5945 MN |
10 | #include "intel_display_types.h" |
11 | #include "intel_vrr.h" | |
12 | ||
51ab3b85 | 13 | bool intel_vrr_is_capable(struct intel_connector *connector) |
5b0c5945 | 14 | { |
51ab3b85 VS |
15 | const struct drm_display_info *info = &connector->base.display_info; |
16 | struct drm_i915_private *i915 = to_i915(connector->base.dev); | |
5b0c5945 | 17 | struct intel_dp *intel_dp; |
5b0c5945 | 18 | |
5b0c5945 | 19 | /* |
3dafe8a8 | 20 | * DP Sink is capable of VRR video timings if |
5b0c5945 MN |
21 | * Ignore MSA bit is set in DPCD. |
22 | * EDID monitor range also should be atleast 10 for reasonable | |
3dafe8a8 | 23 | * Adaptive Sync or Variable Refresh Rate end user experience. |
5b0c5945 | 24 | */ |
fba99b1a VS |
25 | switch (connector->base.connector_type) { |
26 | case DRM_MODE_CONNECTOR_eDP: | |
27 | if (!connector->panel.vbt.vrr) | |
28 | return false; | |
29 | fallthrough; | |
30 | case DRM_MODE_CONNECTOR_DisplayPort: | |
31 | intel_dp = intel_attached_dp(connector); | |
32 | ||
33 | if (!drm_dp_sink_can_do_video_without_timing_msa(intel_dp->dpcd)) | |
34 | return false; | |
35 | ||
36 | break; | |
37 | default: | |
38 | return false; | |
39 | } | |
40 | ||
5b0c5945 | 41 | return HAS_VRR(i915) && |
5b0c5945 MN |
42 | info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10; |
43 | } | |
117cd09b | 44 | |
f0f7ec74 VS |
45 | bool intel_vrr_is_in_range(struct intel_connector *connector, int vrefresh) |
46 | { | |
47 | const struct drm_display_info *info = &connector->base.display_info; | |
48 | ||
49 | return intel_vrr_is_capable(connector) && | |
50 | vrefresh >= info->monitor_range.min_vfreq && | |
51 | vrefresh <= info->monitor_range.max_vfreq; | |
52 | } | |
53 | ||
117cd09b MN |
54 | void |
55 | intel_vrr_check_modeset(struct intel_atomic_state *state) | |
56 | { | |
57 | int i; | |
58 | struct intel_crtc_state *old_crtc_state, *new_crtc_state; | |
59 | struct intel_crtc *crtc; | |
60 | ||
61 | for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, | |
62 | new_crtc_state, i) { | |
63 | if (new_crtc_state->uapi.vrr_enabled != | |
64 | old_crtc_state->uapi.vrr_enabled) | |
65 | new_crtc_state->uapi.mode_changed = true; | |
66 | } | |
67 | } | |
68 | ||
4ef619a7 VS |
69 | /* |
70 | * Without VRR registers get latched at: | |
71 | * vblank_start | |
72 | * | |
73 | * With VRR the earliest registers can get latched is: | |
74 | * intel_vrr_vmin_vblank_start(), which if we want to maintain | |
75 | * the correct min vtotal is >=vblank_start+1 | |
76 | * | |
77 | * The latest point registers can get latched is the vmax decision boundary: | |
78 | * intel_vrr_vmax_vblank_start() | |
79 | * | |
80 | * Between those two points the vblank exit starts (and hence registers get | |
81 | * latched) ASAP after a push is sent. | |
82 | * | |
9cca74b5 | 83 | * framestart_delay is programmable 1-4. |
4ef619a7 VS |
84 | */ |
85 | static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_state) | |
86 | { | |
87 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); | |
88 | struct drm_i915_private *i915 = to_i915(crtc->base.dev); | |
89 | ||
bb265dbd | 90 | if (DISPLAY_VER(i915) >= 13) |
944bda74 | 91 | return crtc_state->vrr.guardband; |
bb265dbd | 92 | else |
944bda74 | 93 | /* The hw imposes the extra scanline before frame start */ |
50c335f9 | 94 | return crtc_state->vrr.pipeline_full + crtc_state->framestart_delay + 1; |
4ef619a7 VS |
95 | } |
96 | ||
97 | int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state) | |
98 | { | |
99 | /* Min vblank actually determined by flipline that is always >=vmin+1 */ | |
100 | return crtc_state->vrr.vmin + 1 - intel_vrr_vblank_exit_length(crtc_state); | |
101 | } | |
102 | ||
103 | int intel_vrr_vmax_vblank_start(const struct intel_crtc_state *crtc_state) | |
104 | { | |
105 | return crtc_state->vrr.vmax - intel_vrr_vblank_exit_length(crtc_state); | |
106 | } | |
107 | ||
117cd09b MN |
108 | void |
109 | intel_vrr_compute_config(struct intel_crtc_state *crtc_state, | |
110 | struct drm_connector_state *conn_state) | |
111 | { | |
bb265dbd MN |
112 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); |
113 | struct drm_i915_private *i915 = to_i915(crtc->base.dev); | |
117cd09b MN |
114 | struct intel_connector *connector = |
115 | to_intel_connector(conn_state->connector); | |
116 | struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; | |
117 | const struct drm_display_info *info = &connector->base.display_info; | |
118 | int vmin, vmax; | |
119 | ||
dcd8992e VS |
120 | /* |
121 | * FIXME all joined pipes share the same transcoder. | |
122 | * Need to account for that during VRR toggle/push/etc. | |
123 | */ | |
124 | if (crtc_state->bigjoiner_pipes) | |
125 | return; | |
126 | ||
6a38b36c | 127 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) |
117cd09b MN |
128 | return; |
129 | ||
16a93594 VS |
130 | crtc_state->vrr.in_range = |
131 | intel_vrr_is_in_range(connector, drm_mode_vrefresh(adjusted_mode)); | |
132 | if (!crtc_state->vrr.in_range) | |
117cd09b MN |
133 | return; |
134 | ||
16a93594 VS |
135 | if (HAS_LRR(i915)) |
136 | crtc_state->update_lrr = true; | |
137 | ||
117cd09b MN |
138 | vmin = DIV_ROUND_UP(adjusted_mode->crtc_clock * 1000, |
139 | adjusted_mode->crtc_htotal * info->monitor_range.max_vfreq); | |
140 | vmax = adjusted_mode->crtc_clock * 1000 / | |
141 | (adjusted_mode->crtc_htotal * info->monitor_range.min_vfreq); | |
142 | ||
143 | vmin = max_t(int, vmin, adjusted_mode->crtc_vtotal); | |
144 | vmax = max_t(int, vmax, adjusted_mode->crtc_vtotal); | |
145 | ||
146 | if (vmin >= vmax) | |
147 | return; | |
148 | ||
149 | /* | |
150 | * flipline determines the min vblank length the hardware will | |
151 | * generate, and flipline>=vmin+1, hence we reduce vmin by one | |
152 | * to make sure we can get the actual min vblank length. | |
153 | */ | |
154 | crtc_state->vrr.vmin = vmin - 1; | |
155 | crtc_state->vrr.vmax = vmax; | |
117cd09b MN |
156 | |
157 | crtc_state->vrr.flipline = crtc_state->vrr.vmin + 1; | |
158 | ||
159 | /* | |
bb265dbd MN |
160 | * For XE_LPD+, we use guardband and pipeline override |
161 | * is deprecated. | |
117cd09b | 162 | */ |
44eba1b8 | 163 | if (DISPLAY_VER(i915) >= 13) { |
bb265dbd | 164 | crtc_state->vrr.guardband = |
d34b4288 | 165 | crtc_state->vrr.vmin + 1 - adjusted_mode->crtc_vblank_start; |
44eba1b8 | 166 | } else { |
bb265dbd | 167 | crtc_state->vrr.pipeline_full = |
d34b4288 | 168 | min(255, crtc_state->vrr.vmin - adjusted_mode->crtc_vblank_start - |
98f974aa | 169 | crtc_state->framestart_delay - 1); |
44eba1b8 | 170 | } |
7a2ec4a0 | 171 | |
99cfbed1 VS |
172 | if (crtc_state->uapi.vrr_enabled) { |
173 | crtc_state->vrr.enable = true; | |
174 | crtc_state->mode_flags |= I915_MODE_FLAG_VRR; | |
175 | } | |
117cd09b | 176 | } |
aa52b39d | 177 | |
2ac5438c VS |
178 | static u32 trans_vrr_ctl(const struct intel_crtc_state *crtc_state) |
179 | { | |
180 | struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); | |
181 | ||
182 | if (DISPLAY_VER(i915) >= 13) | |
183 | return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN | | |
184 | XELPD_VRR_CTL_VRR_GUARDBAND(crtc_state->vrr.guardband); | |
185 | else | |
186 | return VRR_CTL_IGN_MAX_SHIFT | VRR_CTL_FLIP_LINE_EN | | |
187 | VRR_CTL_PIPELINE_FULL(crtc_state->vrr.pipeline_full) | | |
188 | VRR_CTL_PIPELINE_FULL_OVERRIDE; | |
189 | } | |
190 | ||
99cfbed1 | 191 | void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state) |
aa52b39d | 192 | { |
b25e0741 | 193 | struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); |
aa52b39d | 194 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
aa52b39d | 195 | |
fa9e4fce | 196 | /* |
f7d3b927 VS |
197 | * This bit seems to have two meanings depending on the platform: |
198 | * TGL: generate VRR "safe window" for DSB vblank waits | |
199 | * ADL/DG2: make TRANS_SET_CONTEXT_LATENCY effective with VRR | |
fa9e4fce | 200 | */ |
f7d3b927 | 201 | if (IS_DISPLAY_VER(dev_priv, 12, 13)) |
fa9e4fce VS |
202 | intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder), |
203 | 0, PIPE_VBLANK_WITH_DELAY); | |
204 | ||
99cfbed1 VS |
205 | if (!crtc_state->vrr.flipline) { |
206 | intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), 0); | |
aa52b39d | 207 | return; |
99cfbed1 | 208 | } |
aa52b39d | 209 | |
aa52b39d MN |
210 | intel_de_write(dev_priv, TRANS_VRR_VMIN(cpu_transcoder), crtc_state->vrr.vmin - 1); |
211 | intel_de_write(dev_priv, TRANS_VRR_VMAX(cpu_transcoder), crtc_state->vrr.vmax - 1); | |
2ac5438c | 212 | intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), trans_vrr_ctl(crtc_state)); |
aa52b39d | 213 | intel_de_write(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder), crtc_state->vrr.flipline - 1); |
aa52b39d | 214 | } |
13c6d51f MN |
215 | |
216 | void intel_vrr_send_push(const struct intel_crtc_state *crtc_state) | |
217 | { | |
218 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); | |
219 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); | |
220 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; | |
221 | ||
222 | if (!crtc_state->vrr.enable) | |
223 | return; | |
224 | ||
225 | intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), | |
226 | TRANS_PUSH_EN | TRANS_PUSH_SEND); | |
227 | } | |
f0651232 | 228 | |
0088d39b VS |
229 | bool intel_vrr_is_push_sent(const struct intel_crtc_state *crtc_state) |
230 | { | |
231 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); | |
232 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); | |
233 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; | |
234 | ||
235 | if (!crtc_state->vrr.enable) | |
236 | return false; | |
237 | ||
238 | return intel_de_read(dev_priv, TRANS_PUSH(cpu_transcoder)) & TRANS_PUSH_SEND; | |
239 | } | |
240 | ||
99cfbed1 VS |
241 | void intel_vrr_enable(const struct intel_crtc_state *crtc_state) |
242 | { | |
243 | struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); | |
244 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; | |
245 | ||
246 | if (!crtc_state->vrr.enable) | |
247 | return; | |
248 | ||
249 | intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), TRANS_PUSH_EN); | |
250 | intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), | |
251 | VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state)); | |
252 | } | |
253 | ||
f0651232 MN |
254 | void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state) |
255 | { | |
256 | struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); | |
257 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); | |
258 | enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; | |
259 | ||
260 | if (!old_crtc_state->vrr.enable) | |
261 | return; | |
262 | ||
2ac5438c VS |
263 | intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), |
264 | trans_vrr_ctl(old_crtc_state)); | |
265 | intel_de_wait_for_clear(dev_priv, TRANS_VRR_STATUS(cpu_transcoder), | |
266 | VRR_STATUS_VRR_EN_LIVE, 1000); | |
f0651232 MN |
267 | intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), 0); |
268 | } | |
c7f0f437 | 269 | |
b25e0741 | 270 | void intel_vrr_get_config(struct intel_crtc_state *crtc_state) |
c7f0f437 | 271 | { |
b25e0741 | 272 | struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); |
c7f0f437 MN |
273 | enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; |
274 | u32 trans_vrr_ctl; | |
275 | ||
276 | trans_vrr_ctl = intel_de_read(dev_priv, TRANS_VRR_CTL(cpu_transcoder)); | |
99cfbed1 | 277 | |
c7f0f437 | 278 | crtc_state->vrr.enable = trans_vrr_ctl & VRR_CTL_VRR_ENABLE; |
c7f0f437 | 279 | |
bb265dbd MN |
280 | if (DISPLAY_VER(dev_priv) >= 13) |
281 | crtc_state->vrr.guardband = | |
282 | REG_FIELD_GET(XELPD_VRR_CTL_VRR_GUARDBAND_MASK, trans_vrr_ctl); | |
283 | else | |
284 | if (trans_vrr_ctl & VRR_CTL_PIPELINE_FULL_OVERRIDE) | |
285 | crtc_state->vrr.pipeline_full = | |
286 | REG_FIELD_GET(VRR_CTL_PIPELINE_FULL_MASK, trans_vrr_ctl); | |
99cfbed1 VS |
287 | |
288 | if (trans_vrr_ctl & VRR_CTL_FLIP_LINE_EN) { | |
c7f0f437 | 289 | crtc_state->vrr.flipline = intel_de_read(dev_priv, TRANS_VRR_FLIPLINE(cpu_transcoder)) + 1; |
99cfbed1 VS |
290 | crtc_state->vrr.vmax = intel_de_read(dev_priv, TRANS_VRR_VMAX(cpu_transcoder)) + 1; |
291 | crtc_state->vrr.vmin = intel_de_read(dev_priv, TRANS_VRR_VMIN(cpu_transcoder)) + 1; | |
292 | } | |
7a2ec4a0 | 293 | |
99cfbed1 VS |
294 | if (crtc_state->vrr.enable) |
295 | crtc_state->mode_flags |= I915_MODE_FLAG_VRR; | |
c7f0f437 | 296 | } |