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