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