Branch data Line data Source code
1 : : /*
2 : : * Copyright © 2013 Intel Corporation
3 : : *
4 : : * Permission is hereby granted, free of charge, to any person obtaining a
5 : : * copy of this software and associated documentation files (the "Software"),
6 : : * to deal in the Software without restriction, including without limitation
7 : : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 : : * and/or sell copies of the Software, and to permit persons to whom the
9 : : * Software is furnished to do so, subject to the following conditions:
10 : : *
11 : : * The above copyright notice and this permission notice (including the next
12 : : * paragraph) shall be included in all copies or substantial portions of the
13 : : * Software.
14 : : *
15 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 : : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 : : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 : : * IN THE SOFTWARE.
22 : : *
23 : : * Author: Damien Lespiau <damien.lespiau@intel.com>
24 : : *
25 : : */
26 : :
27 : : #include <linux/circ_buf.h>
28 : : #include <linux/ctype.h>
29 : : #include <linux/debugfs.h>
30 : : #include <linux/seq_file.h>
31 : :
32 : : #include "intel_atomic.h"
33 : : #include "intel_display_types.h"
34 : : #include "intel_pipe_crc.h"
35 : :
36 : : static const char * const pipe_crc_sources[] = {
37 : : [INTEL_PIPE_CRC_SOURCE_NONE] = "none",
38 : : [INTEL_PIPE_CRC_SOURCE_PLANE1] = "plane1",
39 : : [INTEL_PIPE_CRC_SOURCE_PLANE2] = "plane2",
40 : : [INTEL_PIPE_CRC_SOURCE_PLANE3] = "plane3",
41 : : [INTEL_PIPE_CRC_SOURCE_PLANE4] = "plane4",
42 : : [INTEL_PIPE_CRC_SOURCE_PLANE5] = "plane5",
43 : : [INTEL_PIPE_CRC_SOURCE_PLANE6] = "plane6",
44 : : [INTEL_PIPE_CRC_SOURCE_PLANE7] = "plane7",
45 : : [INTEL_PIPE_CRC_SOURCE_PIPE] = "pipe",
46 : : [INTEL_PIPE_CRC_SOURCE_TV] = "TV",
47 : : [INTEL_PIPE_CRC_SOURCE_DP_B] = "DP-B",
48 : : [INTEL_PIPE_CRC_SOURCE_DP_C] = "DP-C",
49 : : [INTEL_PIPE_CRC_SOURCE_DP_D] = "DP-D",
50 : : [INTEL_PIPE_CRC_SOURCE_AUTO] = "auto",
51 : : };
52 : :
53 : 0 : static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
54 : : u32 *val)
55 : : {
56 : 0 : if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
57 : 0 : *source = INTEL_PIPE_CRC_SOURCE_PIPE;
58 : :
59 [ # # # ]: 0 : switch (*source) {
60 : 0 : case INTEL_PIPE_CRC_SOURCE_PIPE:
61 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_INCLUDE_BORDER_I8XX;
62 : 0 : break;
63 : 0 : case INTEL_PIPE_CRC_SOURCE_NONE:
64 : 0 : *val = 0;
65 : 0 : break;
66 : : default:
67 : : return -EINVAL;
68 : : }
69 : :
70 : : return 0;
71 : : }
72 : :
73 : 0 : static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv,
74 : : enum pipe pipe,
75 : : enum intel_pipe_crc_source *source)
76 : : {
77 : 0 : struct drm_device *dev = &dev_priv->drm;
78 : 0 : struct intel_encoder *encoder;
79 : 0 : struct intel_crtc *crtc;
80 : 0 : struct intel_digital_port *dig_port;
81 : 0 : int ret = 0;
82 : :
83 : 0 : *source = INTEL_PIPE_CRC_SOURCE_PIPE;
84 : :
85 : 0 : drm_modeset_lock_all(dev);
86 [ # # ]: 0 : for_each_intel_encoder(dev, encoder) {
87 [ # # ]: 0 : if (!encoder->base.crtc)
88 : 0 : continue;
89 : :
90 : 0 : crtc = to_intel_crtc(encoder->base.crtc);
91 : :
92 [ # # ]: 0 : if (crtc->pipe != pipe)
93 : 0 : continue;
94 : :
95 [ # # # ]: 0 : switch (encoder->type) {
96 : 0 : case INTEL_OUTPUT_TVOUT:
97 : 0 : *source = INTEL_PIPE_CRC_SOURCE_TV;
98 : 0 : break;
99 : : case INTEL_OUTPUT_DP:
100 : : case INTEL_OUTPUT_EDP:
101 [ # # ]: 0 : dig_port = enc_to_dig_port(encoder);
102 [ # # # # ]: 0 : switch (dig_port->base.port) {
103 : 0 : case PORT_B:
104 : 0 : *source = INTEL_PIPE_CRC_SOURCE_DP_B;
105 : 0 : break;
106 : 0 : case PORT_C:
107 : 0 : *source = INTEL_PIPE_CRC_SOURCE_DP_C;
108 : 0 : break;
109 : 0 : case PORT_D:
110 : 0 : *source = INTEL_PIPE_CRC_SOURCE_DP_D;
111 : 0 : break;
112 : : default:
113 : 0 : WARN(1, "nonexisting DP port %c\n",
114 : : port_name(dig_port->base.port));
115 : 0 : break;
116 : : }
117 : : break;
118 : : default:
119 : : break;
120 : : }
121 : : }
122 : 0 : drm_modeset_unlock_all(dev);
123 : :
124 : 0 : return ret;
125 : : }
126 : :
127 : 0 : static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
128 : : enum pipe pipe,
129 : : enum intel_pipe_crc_source *source,
130 : : u32 *val)
131 : : {
132 : 0 : bool need_stable_symbols = false;
133 : :
134 [ # # ]: 0 : if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) {
135 : 0 : int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source);
136 [ # # ]: 0 : if (ret)
137 : : return ret;
138 : : }
139 : :
140 [ # # # # : 0 : switch (*source) {
# # ]
141 : 0 : case INTEL_PIPE_CRC_SOURCE_PIPE:
142 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_VLV;
143 : 0 : break;
144 : 0 : case INTEL_PIPE_CRC_SOURCE_DP_B:
145 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_VLV;
146 : 0 : need_stable_symbols = true;
147 : 0 : break;
148 : 0 : case INTEL_PIPE_CRC_SOURCE_DP_C:
149 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_VLV;
150 : 0 : need_stable_symbols = true;
151 : 0 : break;
152 : : case INTEL_PIPE_CRC_SOURCE_DP_D:
153 [ # # ]: 0 : if (!IS_CHERRYVIEW(dev_priv))
154 : : return -EINVAL;
155 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_VLV;
156 : 0 : need_stable_symbols = true;
157 : 0 : break;
158 : 0 : case INTEL_PIPE_CRC_SOURCE_NONE:
159 : 0 : *val = 0;
160 : 0 : break;
161 : : default:
162 : : return -EINVAL;
163 : : }
164 : :
165 : : /*
166 : : * When the pipe CRC tap point is after the transcoders we need
167 : : * to tweak symbol-level features to produce a deterministic series of
168 : : * symbols for a given frame. We need to reset those features only once
169 : : * a frame (instead of every nth symbol):
170 : : * - DC-balance: used to ensure a better clock recovery from the data
171 : : * link (SDVO)
172 : : * - DisplayPort scrambling: used for EMI reduction
173 : : */
174 : 0 : if (need_stable_symbols) {
175 : 0 : u32 tmp = I915_READ(PORT_DFT2_G4X);
176 : :
177 : 0 : tmp |= DC_BALANCE_RESET_VLV;
178 [ # # # # ]: 0 : switch (pipe) {
179 : 0 : case PIPE_A:
180 : 0 : tmp |= PIPE_A_SCRAMBLE_RESET;
181 : 0 : break;
182 : 0 : case PIPE_B:
183 : 0 : tmp |= PIPE_B_SCRAMBLE_RESET;
184 : 0 : break;
185 : 0 : case PIPE_C:
186 : 0 : tmp |= PIPE_C_SCRAMBLE_RESET;
187 : 0 : break;
188 : : default:
189 : : return -EINVAL;
190 : : }
191 : 0 : I915_WRITE(PORT_DFT2_G4X, tmp);
192 : : }
193 : :
194 : : return 0;
195 : : }
196 : :
197 : 0 : static int i9xx_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
198 : : enum pipe pipe,
199 : : enum intel_pipe_crc_source *source,
200 : : u32 *val)
201 : : {
202 [ # # ]: 0 : if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) {
203 : 0 : int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source);
204 [ # # ]: 0 : if (ret)
205 : : return ret;
206 : : }
207 : :
208 [ # # # # ]: 0 : switch (*source) {
209 : 0 : case INTEL_PIPE_CRC_SOURCE_PIPE:
210 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_I9XX;
211 : 0 : break;
212 : 0 : case INTEL_PIPE_CRC_SOURCE_TV:
213 [ # # ]: 0 : if (!SUPPORTS_TV(dev_priv))
214 : : return -EINVAL;
215 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_TV_PRE;
216 : 0 : break;
217 : 0 : case INTEL_PIPE_CRC_SOURCE_NONE:
218 : 0 : *val = 0;
219 : 0 : break;
220 : : default:
221 : : /*
222 : : * The DP CRC source doesn't work on g4x.
223 : : * It can be made to work to some degree by selecting
224 : : * the correct CRC source before the port is enabled,
225 : : * and not touching the CRC source bits again until
226 : : * the port is disabled. But even then the bits
227 : : * eventually get stuck and a reboot is needed to get
228 : : * working CRCs on the pipe again. Let's simply
229 : : * refuse to use DP CRCs on g4x.
230 : : */
231 : : return -EINVAL;
232 : : }
233 : :
234 : : return 0;
235 : : }
236 : :
237 : 0 : static void vlv_undo_pipe_scramble_reset(struct drm_i915_private *dev_priv,
238 : : enum pipe pipe)
239 : : {
240 : 0 : u32 tmp = I915_READ(PORT_DFT2_G4X);
241 : :
242 [ # # # # ]: 0 : switch (pipe) {
243 : 0 : case PIPE_A:
244 : 0 : tmp &= ~PIPE_A_SCRAMBLE_RESET;
245 : 0 : break;
246 : 0 : case PIPE_B:
247 : 0 : tmp &= ~PIPE_B_SCRAMBLE_RESET;
248 : 0 : break;
249 : 0 : case PIPE_C:
250 : 0 : tmp &= ~PIPE_C_SCRAMBLE_RESET;
251 : 0 : break;
252 : : default:
253 : : return;
254 : : }
255 [ # # ]: 0 : if (!(tmp & PIPE_SCRAMBLE_RESET_MASK))
256 : 0 : tmp &= ~DC_BALANCE_RESET_VLV;
257 : 0 : I915_WRITE(PORT_DFT2_G4X, tmp);
258 : : }
259 : :
260 : 0 : static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
261 : : u32 *val)
262 : : {
263 : 0 : if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
264 : 0 : *source = INTEL_PIPE_CRC_SOURCE_PIPE;
265 : :
266 [ # # # # : 0 : switch (*source) {
# ]
267 : 0 : case INTEL_PIPE_CRC_SOURCE_PLANE1:
268 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_ILK;
269 : 0 : break;
270 : 0 : case INTEL_PIPE_CRC_SOURCE_PLANE2:
271 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_ILK;
272 : 0 : break;
273 : 0 : case INTEL_PIPE_CRC_SOURCE_PIPE:
274 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_ILK;
275 : 0 : break;
276 : 0 : case INTEL_PIPE_CRC_SOURCE_NONE:
277 : 0 : *val = 0;
278 : 0 : break;
279 : : default:
280 : : return -EINVAL;
281 : : }
282 : :
283 : : return 0;
284 : : }
285 : :
286 : : static void
287 : 0 : intel_crtc_crc_setup_workarounds(struct intel_crtc *crtc, bool enable)
288 : : {
289 : 0 : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
290 : 0 : struct intel_crtc_state *pipe_config;
291 : 0 : struct drm_atomic_state *state;
292 : 0 : struct drm_modeset_acquire_ctx ctx;
293 : 0 : int ret;
294 : :
295 : 0 : drm_modeset_acquire_init(&ctx, 0);
296 : :
297 : 0 : state = drm_atomic_state_alloc(&dev_priv->drm);
298 [ # # ]: 0 : if (!state) {
299 : 0 : ret = -ENOMEM;
300 : 0 : goto unlock;
301 : : }
302 : :
303 : 0 : state->acquire_ctx = &ctx;
304 : :
305 : 0 : retry:
306 : 0 : pipe_config = intel_atomic_get_crtc_state(state, crtc);
307 [ # # ]: 0 : if (IS_ERR(pipe_config)) {
308 : 0 : ret = PTR_ERR(pipe_config);
309 : 0 : goto put_state;
310 : : }
311 : :
312 : 0 : pipe_config->uapi.mode_changed = pipe_config->has_psr;
313 : 0 : pipe_config->crc_enabled = enable;
314 : :
315 [ # # ]: 0 : if (IS_HASWELL(dev_priv) &&
316 [ # # # # ]: 0 : pipe_config->hw.active && crtc->pipe == PIPE_A &&
317 [ # # ]: 0 : pipe_config->cpu_transcoder == TRANSCODER_EDP)
318 : 0 : pipe_config->uapi.mode_changed = true;
319 : :
320 : 0 : ret = drm_atomic_commit(state);
321 : :
322 : 0 : put_state:
323 [ # # ]: 0 : if (ret == -EDEADLK) {
324 : 0 : drm_atomic_state_clear(state);
325 : 0 : drm_modeset_backoff(&ctx);
326 : 0 : goto retry;
327 : : }
328 : :
329 : 0 : drm_atomic_state_put(state);
330 : 0 : unlock:
331 [ # # ]: 0 : WARN(ret, "Toggling workaround to %i returns %i\n", enable, ret);
332 : 0 : drm_modeset_drop_locks(&ctx);
333 : 0 : drm_modeset_acquire_fini(&ctx);
334 : 0 : }
335 : :
336 : 0 : static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
337 : : enum pipe pipe,
338 : : enum intel_pipe_crc_source *source,
339 : : u32 *val)
340 : : {
341 : 0 : if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
342 : 0 : *source = INTEL_PIPE_CRC_SOURCE_PIPE;
343 : :
344 [ # # # # : 0 : switch (*source) {
# ]
345 : 0 : case INTEL_PIPE_CRC_SOURCE_PLANE1:
346 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_IVB;
347 : 0 : break;
348 : 0 : case INTEL_PIPE_CRC_SOURCE_PLANE2:
349 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB;
350 : 0 : break;
351 : 0 : case INTEL_PIPE_CRC_SOURCE_PIPE:
352 : 0 : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB;
353 : 0 : break;
354 : 0 : case INTEL_PIPE_CRC_SOURCE_NONE:
355 : 0 : *val = 0;
356 : 0 : break;
357 : : default:
358 : : return -EINVAL;
359 : : }
360 : :
361 : : return 0;
362 : : }
363 : :
364 : : static int skl_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
365 : : enum pipe pipe,
366 : : enum intel_pipe_crc_source *source,
367 : : u32 *val)
368 : : {
369 : : if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
370 : : *source = INTEL_PIPE_CRC_SOURCE_PIPE;
371 : :
372 : : switch (*source) {
373 : : case INTEL_PIPE_CRC_SOURCE_PLANE1:
374 : : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_1_SKL;
375 : : break;
376 : : case INTEL_PIPE_CRC_SOURCE_PLANE2:
377 : : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_2_SKL;
378 : : break;
379 : : case INTEL_PIPE_CRC_SOURCE_PLANE3:
380 : : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_3_SKL;
381 : : break;
382 : : case INTEL_PIPE_CRC_SOURCE_PLANE4:
383 : : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_4_SKL;
384 : : break;
385 : : case INTEL_PIPE_CRC_SOURCE_PLANE5:
386 : : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_5_SKL;
387 : : break;
388 : : case INTEL_PIPE_CRC_SOURCE_PLANE6:
389 : : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_6_SKL;
390 : : break;
391 : : case INTEL_PIPE_CRC_SOURCE_PLANE7:
392 : : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_7_SKL;
393 : : break;
394 : : case INTEL_PIPE_CRC_SOURCE_PIPE:
395 : : *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DMUX_SKL;
396 : : break;
397 : : case INTEL_PIPE_CRC_SOURCE_NONE:
398 : : *val = 0;
399 : : break;
400 : : default:
401 : : return -EINVAL;
402 : : }
403 : :
404 : : return 0;
405 : : }
406 : :
407 : 0 : static int get_new_crc_ctl_reg(struct drm_i915_private *dev_priv,
408 : : enum pipe pipe,
409 : : enum intel_pipe_crc_source *source, u32 *val)
410 : : {
411 [ # # ]: 0 : if (IS_GEN(dev_priv, 2))
412 [ # # ]: 0 : return i8xx_pipe_crc_ctl_reg(source, val);
413 [ # # ]: 0 : else if (INTEL_GEN(dev_priv) < 5)
414 : 0 : return i9xx_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
415 [ # # # # ]: 0 : else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
416 : 0 : return vlv_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
417 [ # # ]: 0 : else if (IS_GEN_RANGE(dev_priv, 5, 6))
418 [ # # ]: 0 : return ilk_pipe_crc_ctl_reg(source, val);
419 [ # # ]: 0 : else if (INTEL_GEN(dev_priv) < 9)
420 [ # # ]: 0 : return ivb_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
421 : : else
422 : 0 : return skl_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
423 : : }
424 : :
425 : : static int
426 : 0 : display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s)
427 : : {
428 : 0 : int i;
429 : :
430 : 0 : if (!buf) {
431 : 0 : *s = INTEL_PIPE_CRC_SOURCE_NONE;
432 : 0 : return 0;
433 : : }
434 : :
435 : 0 : i = match_string(pipe_crc_sources, ARRAY_SIZE(pipe_crc_sources), buf);
436 [ # # # # ]: 0 : if (i < 0)
437 : : return i;
438 : :
439 : 0 : *s = i;
440 : 0 : return 0;
441 : : }
442 : :
443 : 0 : void intel_display_crc_init(struct drm_i915_private *dev_priv)
444 : : {
445 : 0 : enum pipe pipe;
446 : :
447 [ # # # # ]: 0 : for_each_pipe(dev_priv, pipe) {
448 : 0 : struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
449 : :
450 : 0 : spin_lock_init(&pipe_crc->lock);
451 : : }
452 : 0 : }
453 : :
454 : 0 : static int i8xx_crc_source_valid(struct drm_i915_private *dev_priv,
455 : : const enum intel_pipe_crc_source source)
456 : : {
457 : 0 : switch (source) {
458 : : case INTEL_PIPE_CRC_SOURCE_PIPE:
459 : : case INTEL_PIPE_CRC_SOURCE_NONE:
460 : : return 0;
461 : 0 : default:
462 : 0 : return -EINVAL;
463 : : }
464 : : }
465 : :
466 : 0 : static int i9xx_crc_source_valid(struct drm_i915_private *dev_priv,
467 : : const enum intel_pipe_crc_source source)
468 : : {
469 : 0 : switch (source) {
470 : : case INTEL_PIPE_CRC_SOURCE_PIPE:
471 : : case INTEL_PIPE_CRC_SOURCE_TV:
472 : : case INTEL_PIPE_CRC_SOURCE_NONE:
473 : : return 0;
474 : 0 : default:
475 : 0 : return -EINVAL;
476 : : }
477 : : }
478 : :
479 : 0 : static int vlv_crc_source_valid(struct drm_i915_private *dev_priv,
480 : : const enum intel_pipe_crc_source source)
481 : : {
482 : 0 : switch (source) {
483 : : case INTEL_PIPE_CRC_SOURCE_PIPE:
484 : : case INTEL_PIPE_CRC_SOURCE_DP_B:
485 : : case INTEL_PIPE_CRC_SOURCE_DP_C:
486 : : case INTEL_PIPE_CRC_SOURCE_DP_D:
487 : : case INTEL_PIPE_CRC_SOURCE_NONE:
488 : : return 0;
489 : 0 : default:
490 : 0 : return -EINVAL;
491 : : }
492 : : }
493 : :
494 : 0 : static int ilk_crc_source_valid(struct drm_i915_private *dev_priv,
495 : : const enum intel_pipe_crc_source source)
496 : : {
497 : 0 : switch (source) {
498 : : case INTEL_PIPE_CRC_SOURCE_PIPE:
499 : : case INTEL_PIPE_CRC_SOURCE_PLANE1:
500 : : case INTEL_PIPE_CRC_SOURCE_PLANE2:
501 : : case INTEL_PIPE_CRC_SOURCE_NONE:
502 : : return 0;
503 : 0 : default:
504 : 0 : return -EINVAL;
505 : : }
506 : : }
507 : :
508 : 0 : static int ivb_crc_source_valid(struct drm_i915_private *dev_priv,
509 : : const enum intel_pipe_crc_source source)
510 : : {
511 : 0 : switch (source) {
512 : : case INTEL_PIPE_CRC_SOURCE_PIPE:
513 : : case INTEL_PIPE_CRC_SOURCE_PLANE1:
514 : : case INTEL_PIPE_CRC_SOURCE_PLANE2:
515 : : case INTEL_PIPE_CRC_SOURCE_NONE:
516 : : return 0;
517 : 0 : default:
518 : 0 : return -EINVAL;
519 : : }
520 : : }
521 : :
522 : 0 : static int skl_crc_source_valid(struct drm_i915_private *dev_priv,
523 : : const enum intel_pipe_crc_source source)
524 : : {
525 : 0 : switch (source) {
526 : : case INTEL_PIPE_CRC_SOURCE_PIPE:
527 : : case INTEL_PIPE_CRC_SOURCE_PLANE1:
528 : : case INTEL_PIPE_CRC_SOURCE_PLANE2:
529 : : case INTEL_PIPE_CRC_SOURCE_PLANE3:
530 : : case INTEL_PIPE_CRC_SOURCE_PLANE4:
531 : : case INTEL_PIPE_CRC_SOURCE_PLANE5:
532 : : case INTEL_PIPE_CRC_SOURCE_PLANE6:
533 : : case INTEL_PIPE_CRC_SOURCE_PLANE7:
534 : : case INTEL_PIPE_CRC_SOURCE_NONE:
535 : : return 0;
536 : 0 : default:
537 : 0 : return -EINVAL;
538 : : }
539 : : }
540 : :
541 : : static int
542 : 0 : intel_is_valid_crc_source(struct drm_i915_private *dev_priv,
543 : : const enum intel_pipe_crc_source source)
544 : : {
545 [ # # ]: 0 : if (IS_GEN(dev_priv, 2))
546 [ # # ]: 0 : return i8xx_crc_source_valid(dev_priv, source);
547 [ # # ]: 0 : else if (INTEL_GEN(dev_priv) < 5)
548 [ # # ]: 0 : return i9xx_crc_source_valid(dev_priv, source);
549 [ # # # # ]: 0 : else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
550 [ # # ]: 0 : return vlv_crc_source_valid(dev_priv, source);
551 [ # # ]: 0 : else if (IS_GEN_RANGE(dev_priv, 5, 6))
552 [ # # ]: 0 : return ilk_crc_source_valid(dev_priv, source);
553 [ # # ]: 0 : else if (INTEL_GEN(dev_priv) < 9)
554 [ # # ]: 0 : return ivb_crc_source_valid(dev_priv, source);
555 : : else
556 [ # # ]: 0 : return skl_crc_source_valid(dev_priv, source);
557 : : }
558 : :
559 : 0 : const char *const *intel_crtc_get_crc_sources(struct drm_crtc *crtc,
560 : : size_t *count)
561 : : {
562 : 0 : *count = ARRAY_SIZE(pipe_crc_sources);
563 : 0 : return pipe_crc_sources;
564 : : }
565 : :
566 : 0 : int intel_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
567 : : size_t *values_cnt)
568 : : {
569 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(crtc->dev);
570 : 0 : enum intel_pipe_crc_source source;
571 : :
572 [ # # ]: 0 : if (display_crc_ctl_parse_source(source_name, &source) < 0) {
573 : 0 : DRM_DEBUG_DRIVER("unknown source %s\n", source_name);
574 : 0 : return -EINVAL;
575 : : }
576 : :
577 [ # # ]: 0 : if (source == INTEL_PIPE_CRC_SOURCE_AUTO ||
578 [ # # ]: 0 : intel_is_valid_crc_source(dev_priv, source) == 0) {
579 : 0 : *values_cnt = 5;
580 : 0 : return 0;
581 : : }
582 : :
583 : : return -EINVAL;
584 : : }
585 : :
586 : 0 : int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name)
587 : : {
588 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(crtc->dev);
589 : 0 : struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
590 : 0 : enum intel_display_power_domain power_domain;
591 : 0 : enum intel_pipe_crc_source source;
592 : 0 : intel_wakeref_t wakeref;
593 : 0 : u32 val = 0; /* shut up gcc */
594 : 0 : int ret = 0;
595 : 0 : bool enable;
596 : :
597 [ # # ]: 0 : if (display_crc_ctl_parse_source(source_name, &source) < 0) {
598 : 0 : DRM_DEBUG_DRIVER("unknown source %s\n", source_name);
599 : 0 : return -EINVAL;
600 : : }
601 : :
602 : 0 : power_domain = POWER_DOMAIN_PIPE(crtc->index);
603 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
604 [ # # ]: 0 : if (!wakeref) {
605 : 0 : DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
606 : 0 : return -EIO;
607 : : }
608 : :
609 : 0 : enable = source != INTEL_PIPE_CRC_SOURCE_NONE;
610 [ # # ]: 0 : if (enable)
611 : 0 : intel_crtc_crc_setup_workarounds(to_intel_crtc(crtc), true);
612 : :
613 : 0 : ret = get_new_crc_ctl_reg(dev_priv, crtc->index, &source, &val);
614 [ # # ]: 0 : if (ret != 0)
615 : 0 : goto out;
616 : :
617 : 0 : pipe_crc->source = source;
618 : 0 : I915_WRITE(PIPE_CRC_CTL(crtc->index), val);
619 : 0 : POSTING_READ(PIPE_CRC_CTL(crtc->index));
620 : :
621 [ # # ]: 0 : if (!source) {
622 [ # # # # ]: 0 : if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
623 : 0 : vlv_undo_pipe_scramble_reset(dev_priv, crtc->index);
624 : : }
625 : :
626 : 0 : pipe_crc->skipped = 0;
627 : :
628 : 0 : out:
629 [ # # ]: 0 : if (!enable)
630 : 0 : intel_crtc_crc_setup_workarounds(to_intel_crtc(crtc), false);
631 : :
632 : 0 : intel_display_power_put(dev_priv, power_domain, wakeref);
633 : :
634 : 0 : return ret;
635 : : }
636 : :
637 : 0 : void intel_crtc_enable_pipe_crc(struct intel_crtc *intel_crtc)
638 : : {
639 : 0 : struct drm_crtc *crtc = &intel_crtc->base;
640 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(crtc->dev);
641 : 0 : struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
642 : 0 : u32 val = 0;
643 : :
644 [ # # ]: 0 : if (!crtc->crc.opened)
645 : 0 : return;
646 : :
647 [ # # ]: 0 : if (get_new_crc_ctl_reg(dev_priv, crtc->index, &pipe_crc->source, &val) < 0)
648 : : return;
649 : :
650 : : /* Don't need pipe_crc->lock here, IRQs are not generated. */
651 : 0 : pipe_crc->skipped = 0;
652 : :
653 : 0 : I915_WRITE(PIPE_CRC_CTL(crtc->index), val);
654 : 0 : POSTING_READ(PIPE_CRC_CTL(crtc->index));
655 : : }
656 : :
657 : 0 : void intel_crtc_disable_pipe_crc(struct intel_crtc *intel_crtc)
658 : : {
659 : 0 : struct drm_crtc *crtc = &intel_crtc->base;
660 : 0 : struct drm_i915_private *dev_priv = to_i915(crtc->dev);
661 : 0 : struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[crtc->index];
662 : :
663 : : /* Swallow crc's until we stop generating them. */
664 : 0 : spin_lock_irq(&pipe_crc->lock);
665 : 0 : pipe_crc->skipped = INT_MIN;
666 : 0 : spin_unlock_irq(&pipe_crc->lock);
667 : :
668 : 0 : I915_WRITE(PIPE_CRC_CTL(crtc->index), 0);
669 : 0 : POSTING_READ(PIPE_CRC_CTL(crtc->index));
670 : 0 : intel_synchronize_irq(dev_priv);
671 : 0 : }
|