File Index
Files and directories
Sign in
FILE

intel_pipe_crc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/i915/display/intel_pipe_crc.c C
  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/ctype.h>
 28#include <linux/debugfs.h>
 29#include <linux/seq_file.h>
 30
 31#include <drm/drm_print.h>
 32
 33#include "i915_drv.h"
 34#include "i915_irq.h"
 35#include "intel_atomic.h"
 36#include "intel_de.h"
 37#include "intel_display_irq.h"
 38#include "intel_display_regs.h"
 39#include "intel_display_types.h"
 40#include "intel_pipe_crc.h"
 41#include "intel_pipe_crc_regs.h"
 42
 43static const char * const pipe_crc_sources[] = {
 44	[INTEL_PIPE_CRC_SOURCE_NONE] = "none",
 45	[INTEL_PIPE_CRC_SOURCE_PLANE1] = "plane1",
 46	[INTEL_PIPE_CRC_SOURCE_PLANE2] = "plane2",
 47	[INTEL_PIPE_CRC_SOURCE_PLANE3] = "plane3",
 48	[INTEL_PIPE_CRC_SOURCE_PLANE4] = "plane4",
 49	[INTEL_PIPE_CRC_SOURCE_PLANE5] = "plane5",
 50	[INTEL_PIPE_CRC_SOURCE_PLANE6] = "plane6",
 51	[INTEL_PIPE_CRC_SOURCE_PLANE7] = "plane7",
 52	[INTEL_PIPE_CRC_SOURCE_PIPE] = "pipe",
 53	[INTEL_PIPE_CRC_SOURCE_TV] = "TV",
 54	[INTEL_PIPE_CRC_SOURCE_DP_B] = "DP-B",
 55	[INTEL_PIPE_CRC_SOURCE_DP_C] = "DP-C",
 56	[INTEL_PIPE_CRC_SOURCE_DP_D] = "DP-D",
 57	[INTEL_PIPE_CRC_SOURCE_AUTO] = "auto",
 58};
 59
 60static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
 61				 u32 *val)
 62{
 63	if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
 64		*source = INTEL_PIPE_CRC_SOURCE_PIPE;
 65
 66	switch (*source) {
 67	case INTEL_PIPE_CRC_SOURCE_PIPE:
 68		*val = PIPE_CRC_ENABLE | PIPE_CRC_INCLUDE_BORDER_I8XX;
 69		break;
 70	case INTEL_PIPE_CRC_SOURCE_NONE:
 71		*val = 0;
 72		break;
 73	default:
 74		return -EINVAL;
 75	}
 76
 77	return 0;
 78}
 79
 80static void i9xx_pipe_crc_auto_source(struct intel_display *display,
 81				      enum pipe pipe,
 82				      enum intel_pipe_crc_source *source)
 83{
 84	struct intel_encoder *encoder;
 85	struct intel_crtc *crtc;
 86	struct intel_digital_port *dig_port;
 87
 88	*source = INTEL_PIPE_CRC_SOURCE_PIPE;
 89
 90	drm_modeset_lock_all(display->drm);
 91	for_each_intel_encoder(display->drm, 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				drm_WARN(display->drm, 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(display->drm);
128}
129
130static int vlv_pipe_crc_ctl_reg(struct intel_display *display,
131				enum pipe pipe,
132				enum intel_pipe_crc_source *source,
133				u32 *val)
134{
135	bool need_stable_symbols = false;
136
137	if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
138		i9xx_pipe_crc_auto_source(display, pipe, source);
139
140	switch (*source) {
141	case INTEL_PIPE_CRC_SOURCE_PIPE:
142		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_VLV;
143		break;
144	case INTEL_PIPE_CRC_SOURCE_DP_B:
145		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_VLV;
146		need_stable_symbols = true;
147		break;
148	case INTEL_PIPE_CRC_SOURCE_DP_C:
149		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_VLV;
150		need_stable_symbols = true;
151		break;
152	case INTEL_PIPE_CRC_SOURCE_DP_D:
153		if (!display->platform.cherryview)
154			return -EINVAL;
155		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_VLV;
156		need_stable_symbols = true;
157		break;
158	case INTEL_PIPE_CRC_SOURCE_NONE:
159		*val = 0;
160		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	if (need_stable_symbols) {
175		u32 tmp = intel_de_read(display, PORT_DFT2_G4X(display));
176
177		tmp |= DC_BALANCE_RESET_VLV;
178		switch (pipe) {
179		case PIPE_A:
180			tmp |= PIPE_A_SCRAMBLE_RESET;
181			break;
182		case PIPE_B:
183			tmp |= PIPE_B_SCRAMBLE_RESET;
184			break;
185		case PIPE_C:
186			tmp |= PIPE_C_SCRAMBLE_RESET;
187			break;
188		default:
189			return -EINVAL;
190		}
191		intel_de_write(display, PORT_DFT2_G4X(display), tmp);
192	}
193
194	return 0;
195}
196
197static int i9xx_pipe_crc_ctl_reg(struct intel_display *display,
198				 enum pipe pipe,
199				 enum intel_pipe_crc_source *source,
200				 u32 *val)
201{
202	if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
203		i9xx_pipe_crc_auto_source(display, pipe, source);
204
205	switch (*source) {
206	case INTEL_PIPE_CRC_SOURCE_PIPE:
207		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_I9XX;
208		break;
209	case INTEL_PIPE_CRC_SOURCE_TV:
210		if (!SUPPORTS_TV(display))
211			return -EINVAL;
212		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_TV_PRE;
213		break;
214	case INTEL_PIPE_CRC_SOURCE_NONE:
215		*val = 0;
216		break;
217	default:
218		/*
219		 * The DP CRC source doesn't work on g4x.
220		 * It can be made to work to some degree by selecting
221		 * the correct CRC source before the port is enabled,
222		 * and not touching the CRC source bits again until
223		 * the port is disabled. But even then the bits
224		 * eventually get stuck and a reboot is needed to get
225		 * working CRCs on the pipe again. Let's simply
226		 * refuse to use DP CRCs on g4x.
227		 */
228		return -EINVAL;
229	}
230
231	return 0;
232}
233
234static void vlv_undo_pipe_scramble_reset(struct intel_display *display,
235					 enum pipe pipe)
236{
237	u32 tmp = intel_de_read(display, PORT_DFT2_G4X(display));
238
239	switch (pipe) {
240	case PIPE_A:
241		tmp &= ~PIPE_A_SCRAMBLE_RESET;
242		break;
243	case PIPE_B:
244		tmp &= ~PIPE_B_SCRAMBLE_RESET;
245		break;
246	case PIPE_C:
247		tmp &= ~PIPE_C_SCRAMBLE_RESET;
248		break;
249	default:
250		return;
251	}
252	if (!(tmp & PIPE_SCRAMBLE_RESET_MASK))
253		tmp &= ~DC_BALANCE_RESET_VLV;
254	intel_de_write(display, PORT_DFT2_G4X(display), tmp);
255}
256
257static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
258				u32 *val)
259{
260	if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
261		*source = INTEL_PIPE_CRC_SOURCE_PIPE;
262
263	switch (*source) {
264	case INTEL_PIPE_CRC_SOURCE_PLANE1:
265		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_ILK;
266		break;
267	case INTEL_PIPE_CRC_SOURCE_PLANE2:
268		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_ILK;
269		break;
270	case INTEL_PIPE_CRC_SOURCE_PIPE:
271		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_ILK;
272		break;
273	case INTEL_PIPE_CRC_SOURCE_NONE:
274		*val = 0;
275		break;
276	default:
277		return -EINVAL;
278	}
279
280	return 0;
281}
282
283static void
284intel_crtc_crc_setup_workarounds(struct intel_crtc *crtc, bool enable)
285{
286	struct intel_display *display = to_intel_display(crtc);
287	struct intel_crtc_state *pipe_config;
288	struct drm_atomic_state *state;
289	struct drm_modeset_acquire_ctx ctx;
290	int ret;
291
292	if (display->platform.i945gm || display->platform.i915gm)
293		i915gm_irq_cstate_wa(display, enable);
294
295	drm_modeset_acquire_init(&ctx, 0);
296
297	state = drm_atomic_state_alloc(display->drm);
298	if (!state) {
299		ret = -ENOMEM;
300		goto unlock;
301	}
302
303	state->acquire_ctx = &ctx;
304	to_intel_atomic_state(state)->internal = true;
305
306retry:
307	pipe_config = intel_atomic_get_crtc_state(state, crtc);
308	if (IS_ERR(pipe_config)) {
309		ret = PTR_ERR(pipe_config);
310		goto put_state;
311	}
312
313	pipe_config->uapi.mode_changed = pipe_config->has_psr;
314	pipe_config->crc_enabled = enable;
315
316	if (display->platform.haswell &&
317	    pipe_config->hw.active && crtc->pipe == PIPE_A &&
318	    pipe_config->cpu_transcoder == TRANSCODER_EDP)
319		pipe_config->uapi.mode_changed = true;
320
321	ret = drm_atomic_commit(state);
322
323put_state:
324	if (ret == -EDEADLK) {
325		drm_atomic_state_clear(state);
326		drm_modeset_backoff(&ctx);
327		goto retry;
328	}
329
330	drm_atomic_state_put(state);
331unlock:
332	drm_WARN(display->drm, ret,
333		 "Toggling workaround to %i returns %i\n", enable, ret);
334	drm_modeset_drop_locks(&ctx);
335	drm_modeset_acquire_fini(&ctx);
336}
337
338static int ivb_pipe_crc_ctl_reg(struct intel_display *display,
339				enum pipe pipe,
340				enum intel_pipe_crc_source *source,
341				u32 *val)
342{
343	if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
344		*source = INTEL_PIPE_CRC_SOURCE_PIPE;
345
346	switch (*source) {
347	case INTEL_PIPE_CRC_SOURCE_PLANE1:
348		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_IVB;
349		break;
350	case INTEL_PIPE_CRC_SOURCE_PLANE2:
351		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB;
352		break;
353	case INTEL_PIPE_CRC_SOURCE_PIPE:
354		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB;
355		break;
356	case INTEL_PIPE_CRC_SOURCE_NONE:
357		*val = 0;
358		break;
359	default:
360		return -EINVAL;
361	}
362
363	return 0;
364}
365
366static int skl_pipe_crc_ctl_reg(struct intel_display *display,
367				enum pipe pipe,
368				enum intel_pipe_crc_source *source,
369				u32 *val)
370{
371	if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
372		*source = INTEL_PIPE_CRC_SOURCE_PIPE;
373
374	switch (*source) {
375	case INTEL_PIPE_CRC_SOURCE_PLANE1:
376		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_1_SKL;
377		break;
378	case INTEL_PIPE_CRC_SOURCE_PLANE2:
379		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_2_SKL;
380		break;
381	case INTEL_PIPE_CRC_SOURCE_PLANE3:
382		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_3_SKL;
383		break;
384	case INTEL_PIPE_CRC_SOURCE_PLANE4:
385		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_4_SKL;
386		break;
387	case INTEL_PIPE_CRC_SOURCE_PLANE5:
388		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_5_SKL;
389		break;
390	case INTEL_PIPE_CRC_SOURCE_PLANE6:
391		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_6_SKL;
392		break;
393	case INTEL_PIPE_CRC_SOURCE_PLANE7:
394		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_7_SKL;
395		break;
396	case INTEL_PIPE_CRC_SOURCE_PIPE:
397		*val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DMUX_SKL;
398		break;
399	case INTEL_PIPE_CRC_SOURCE_NONE:
400		*val = 0;
401		break;
402	default:
403		return -EINVAL;
404	}
405
406	return 0;
407}
408
409static int get_new_crc_ctl_reg(struct intel_display *display,
410			       enum pipe pipe,
411			       enum intel_pipe_crc_source *source, u32 *val)
412{
413	if (DISPLAY_VER(display) == 2)
414		return i8xx_pipe_crc_ctl_reg(source, val);
415	else if (DISPLAY_VER(display) < 5)
416		return i9xx_pipe_crc_ctl_reg(display, pipe, source, val);
417	else if (display->platform.valleyview || display->platform.cherryview)
418		return vlv_pipe_crc_ctl_reg(display, pipe, source, val);
419	else if (display->platform.ironlake || display->platform.sandybridge)
420		return ilk_pipe_crc_ctl_reg(source, val);
421	else if (DISPLAY_VER(display) < 9)
422		return ivb_pipe_crc_ctl_reg(display, pipe, source, val);
423	else
424		return skl_pipe_crc_ctl_reg(display, pipe, source, val);
425}
426
427static int
428display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s)
429{
430	int i;
431
432	if (!buf) {
433		*s = INTEL_PIPE_CRC_SOURCE_NONE;
434		return 0;
435	}
436
437	i = match_string(pipe_crc_sources, ARRAY_SIZE(pipe_crc_sources), buf);
438	if (i < 0)
439		return i;
440
441	*s = i;
442	return 0;
443}
444
445void intel_crtc_crc_init(struct intel_crtc *crtc)
446{
447	struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
448
449	spin_lock_init(&pipe_crc->lock);
450}
451
452static int i8xx_crc_source_valid(struct intel_display *display,
453				 const enum intel_pipe_crc_source source)
454{
455	switch (source) {
456	case INTEL_PIPE_CRC_SOURCE_PIPE:
457	case INTEL_PIPE_CRC_SOURCE_NONE:
458		return 0;
459	default:
460		return -EINVAL;
461	}
462}
463
464static int i9xx_crc_source_valid(struct intel_display *display,
465				 const enum intel_pipe_crc_source source)
466{
467	switch (source) {
468	case INTEL_PIPE_CRC_SOURCE_PIPE:
469	case INTEL_PIPE_CRC_SOURCE_TV:
470	case INTEL_PIPE_CRC_SOURCE_NONE:
471		return 0;
472	default:
473		return -EINVAL;
474	}
475}
476
477static int vlv_crc_source_valid(struct intel_display *display,
478				const enum intel_pipe_crc_source source)
479{
480	switch (source) {
481	case INTEL_PIPE_CRC_SOURCE_PIPE:
482	case INTEL_PIPE_CRC_SOURCE_DP_B:
483	case INTEL_PIPE_CRC_SOURCE_DP_C:
484	case INTEL_PIPE_CRC_SOURCE_DP_D:
485	case INTEL_PIPE_CRC_SOURCE_NONE:
486		return 0;
487	default:
488		return -EINVAL;
489	}
490}
491
492static int ilk_crc_source_valid(struct intel_display *display,
493				const enum intel_pipe_crc_source source)
494{
495	switch (source) {
496	case INTEL_PIPE_CRC_SOURCE_PIPE:
497	case INTEL_PIPE_CRC_SOURCE_PLANE1:
498	case INTEL_PIPE_CRC_SOURCE_PLANE2:
499	case INTEL_PIPE_CRC_SOURCE_NONE:
500		return 0;
501	default:
502		return -EINVAL;
503	}
504}
505
506static int ivb_crc_source_valid(struct intel_display *display,
507				const enum intel_pipe_crc_source source)
508{
509	switch (source) {
510	case INTEL_PIPE_CRC_SOURCE_PIPE:
511	case INTEL_PIPE_CRC_SOURCE_PLANE1:
512	case INTEL_PIPE_CRC_SOURCE_PLANE2:
513	case INTEL_PIPE_CRC_SOURCE_NONE:
514		return 0;
515	default:
516		return -EINVAL;
517	}
518}
519
520static int skl_crc_source_valid(struct intel_display *display,
521				const enum intel_pipe_crc_source source)
522{
523	switch (source) {
524	case INTEL_PIPE_CRC_SOURCE_PIPE:
525	case INTEL_PIPE_CRC_SOURCE_PLANE1:
526	case INTEL_PIPE_CRC_SOURCE_PLANE2:
527	case INTEL_PIPE_CRC_SOURCE_PLANE3:
528	case INTEL_PIPE_CRC_SOURCE_PLANE4:
529	case INTEL_PIPE_CRC_SOURCE_PLANE5:
530	case INTEL_PIPE_CRC_SOURCE_PLANE6:
531	case INTEL_PIPE_CRC_SOURCE_PLANE7:
532	case INTEL_PIPE_CRC_SOURCE_NONE:
533		return 0;
534	default:
535		return -EINVAL;
536	}
537}
538
539static int
540intel_is_valid_crc_source(struct intel_display *display,
541			  const enum intel_pipe_crc_source source)
542{
543	if (DISPLAY_VER(display) == 2)
544		return i8xx_crc_source_valid(display, source);
545	else if (DISPLAY_VER(display) < 5)
546		return i9xx_crc_source_valid(display, source);
547	else if (display->platform.valleyview || display->platform.cherryview)
548		return vlv_crc_source_valid(display, source);
549	else if (display->platform.ironlake || display->platform.sandybridge)
550		return ilk_crc_source_valid(display, source);
551	else if (DISPLAY_VER(display) < 9)
552		return ivb_crc_source_valid(display, source);
553	else
554		return skl_crc_source_valid(display, source);
555}
556
557const char *const *intel_crtc_get_crc_sources(struct drm_crtc *crtc,
558					      size_t *count)
559{
560	*count = ARRAY_SIZE(pipe_crc_sources);
561	return pipe_crc_sources;
562}
563
564int intel_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
565				 size_t *values_cnt)
566{
567	struct intel_display *display = to_intel_display(crtc->dev);
568	enum intel_pipe_crc_source source;
569
570	if (display_crc_ctl_parse_source(source_name, &source) < 0) {
571		drm_dbg_kms(display->drm, "unknown source %s\n", source_name);
572		return -EINVAL;
573	}
574
575	if (source == INTEL_PIPE_CRC_SOURCE_AUTO ||
576	    intel_is_valid_crc_source(display, source) == 0) {
577		*values_cnt = 5;
578		return 0;
579	}
580
581	return -EINVAL;
582}
583
584int intel_crtc_set_crc_source(struct drm_crtc *_crtc, const char *source_name)
585{
586	struct intel_crtc *crtc = to_intel_crtc(_crtc);
587	struct intel_display *display = to_intel_display(crtc);
588	struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
589	enum intel_display_power_domain power_domain;
590	enum intel_pipe_crc_source source;
591	enum pipe pipe = crtc->pipe;
592	intel_wakeref_t wakeref;
593	u32 val = 0; /* shut up gcc */
594	int ret = 0;
595	bool enable;
596
597	if (display_crc_ctl_parse_source(source_name, &source) < 0) {
598		drm_dbg_kms(display->drm, "unknown source %s\n", source_name);
599		return -EINVAL;
600	}
601
602	power_domain = POWER_DOMAIN_PIPE(pipe);
603	wakeref = intel_display_power_get_if_enabled(display, power_domain);
604	if (!wakeref) {
605		drm_dbg_kms(display->drm,
606			    "Trying to capture CRC while pipe is off\n");
607		return -EIO;
608	}
609
610	enable = source != INTEL_PIPE_CRC_SOURCE_NONE;
611	if (enable)
612		intel_crtc_crc_setup_workarounds(crtc, true);
613
614	ret = get_new_crc_ctl_reg(display, pipe, &source, &val);
615	if (ret != 0)
616		goto out;
617
618	pipe_crc->source = source;
619	intel_de_write(display, PIPE_CRC_CTL(display, pipe), val);
620	intel_de_posting_read(display, PIPE_CRC_CTL(display, pipe));
621
622	if (!source) {
623		if (display->platform.valleyview || display->platform.cherryview)
624			vlv_undo_pipe_scramble_reset(display, pipe);
625	}
626
627	pipe_crc->skipped = 0;
628
629out:
630	if (!enable)
631		intel_crtc_crc_setup_workarounds(crtc, false);
632
633	intel_display_power_put(display, power_domain, wakeref);
634
635	return ret;
636}
637
638void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc)
639{
640	struct intel_display *display = to_intel_display(crtc);
641	struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
642	enum pipe pipe = crtc->pipe;
643	u32 val = 0;
644
645	if (!crtc->base.crc.opened)
646		return;
647
648	if (get_new_crc_ctl_reg(display, pipe, &pipe_crc->source, &val) < 0)
649		return;
650
651	/* Don't need pipe_crc->lock here, IRQs are not generated. */
652	pipe_crc->skipped = 0;
653
654	intel_de_write(display, PIPE_CRC_CTL(display, pipe), val);
655	intel_de_posting_read(display, PIPE_CRC_CTL(display, pipe));
656}
657
658void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc)
659{
660	struct intel_display *display = to_intel_display(crtc);
661	struct drm_i915_private *dev_priv = to_i915(display->drm);
662	struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
663	enum pipe pipe = crtc->pipe;
664
665	/* Swallow crc's until we stop generating them. */
666	spin_lock_irq(&pipe_crc->lock);
667	pipe_crc->skipped = INT_MIN;
668	spin_unlock_irq(&pipe_crc->lock);
669
670	intel_de_write(display, PIPE_CRC_CTL(display, pipe), 0);
671	intel_de_posting_read(display, PIPE_CRC_CTL(display, pipe));
672	intel_synchronize_irq(dev_priv);
673}
~/ Read-only file preview.