xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/i915/display/intel_pipe_crc.c (revision 2a8c33eaff5adddac3ef2c5cb48ee67ef6d5d6dc)
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