0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 #include <linux/circ_buf.h>
0028 #include <linux/ctype.h>
0029 #include <linux/debugfs.h>
0030 #include <linux/seq_file.h>
0031
0032 #include "intel_atomic.h"
0033 #include "intel_de.h"
0034 #include "intel_display_types.h"
0035 #include "intel_pipe_crc.h"
0036
0037 static const char * const pipe_crc_sources[] = {
0038 [INTEL_PIPE_CRC_SOURCE_NONE] = "none",
0039 [INTEL_PIPE_CRC_SOURCE_PLANE1] = "plane1",
0040 [INTEL_PIPE_CRC_SOURCE_PLANE2] = "plane2",
0041 [INTEL_PIPE_CRC_SOURCE_PLANE3] = "plane3",
0042 [INTEL_PIPE_CRC_SOURCE_PLANE4] = "plane4",
0043 [INTEL_PIPE_CRC_SOURCE_PLANE5] = "plane5",
0044 [INTEL_PIPE_CRC_SOURCE_PLANE6] = "plane6",
0045 [INTEL_PIPE_CRC_SOURCE_PLANE7] = "plane7",
0046 [INTEL_PIPE_CRC_SOURCE_PIPE] = "pipe",
0047 [INTEL_PIPE_CRC_SOURCE_TV] = "TV",
0048 [INTEL_PIPE_CRC_SOURCE_DP_B] = "DP-B",
0049 [INTEL_PIPE_CRC_SOURCE_DP_C] = "DP-C",
0050 [INTEL_PIPE_CRC_SOURCE_DP_D] = "DP-D",
0051 [INTEL_PIPE_CRC_SOURCE_AUTO] = "auto",
0052 };
0053
0054 static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
0055 u32 *val)
0056 {
0057 if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
0058 *source = INTEL_PIPE_CRC_SOURCE_PIPE;
0059
0060 switch (*source) {
0061 case INTEL_PIPE_CRC_SOURCE_PIPE:
0062 *val = PIPE_CRC_ENABLE | PIPE_CRC_INCLUDE_BORDER_I8XX;
0063 break;
0064 case INTEL_PIPE_CRC_SOURCE_NONE:
0065 *val = 0;
0066 break;
0067 default:
0068 return -EINVAL;
0069 }
0070
0071 return 0;
0072 }
0073
0074 static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv,
0075 enum pipe pipe,
0076 enum intel_pipe_crc_source *source)
0077 {
0078 struct drm_device *dev = &dev_priv->drm;
0079 struct intel_encoder *encoder;
0080 struct intel_crtc *crtc;
0081 struct intel_digital_port *dig_port;
0082 int ret = 0;
0083
0084 *source = INTEL_PIPE_CRC_SOURCE_PIPE;
0085
0086 drm_modeset_lock_all(dev);
0087 for_each_intel_encoder(dev, encoder) {
0088 if (!encoder->base.crtc)
0089 continue;
0090
0091 crtc = to_intel_crtc(encoder->base.crtc);
0092
0093 if (crtc->pipe != pipe)
0094 continue;
0095
0096 switch (encoder->type) {
0097 case INTEL_OUTPUT_TVOUT:
0098 *source = INTEL_PIPE_CRC_SOURCE_TV;
0099 break;
0100 case INTEL_OUTPUT_DP:
0101 case INTEL_OUTPUT_EDP:
0102 dig_port = enc_to_dig_port(encoder);
0103 switch (dig_port->base.port) {
0104 case PORT_B:
0105 *source = INTEL_PIPE_CRC_SOURCE_DP_B;
0106 break;
0107 case PORT_C:
0108 *source = INTEL_PIPE_CRC_SOURCE_DP_C;
0109 break;
0110 case PORT_D:
0111 *source = INTEL_PIPE_CRC_SOURCE_DP_D;
0112 break;
0113 default:
0114 drm_WARN(dev, 1, "nonexisting DP port %c\n",
0115 port_name(dig_port->base.port));
0116 break;
0117 }
0118 break;
0119 default:
0120 break;
0121 }
0122 }
0123 drm_modeset_unlock_all(dev);
0124
0125 return ret;
0126 }
0127
0128 static int vlv_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
0129 enum pipe pipe,
0130 enum intel_pipe_crc_source *source,
0131 u32 *val)
0132 {
0133 bool need_stable_symbols = false;
0134
0135 if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) {
0136 int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source);
0137 if (ret)
0138 return ret;
0139 }
0140
0141 switch (*source) {
0142 case INTEL_PIPE_CRC_SOURCE_PIPE:
0143 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_VLV;
0144 break;
0145 case INTEL_PIPE_CRC_SOURCE_DP_B:
0146 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_VLV;
0147 need_stable_symbols = true;
0148 break;
0149 case INTEL_PIPE_CRC_SOURCE_DP_C:
0150 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_VLV;
0151 need_stable_symbols = true;
0152 break;
0153 case INTEL_PIPE_CRC_SOURCE_DP_D:
0154 if (!IS_CHERRYVIEW(dev_priv))
0155 return -EINVAL;
0156 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_VLV;
0157 need_stable_symbols = true;
0158 break;
0159 case INTEL_PIPE_CRC_SOURCE_NONE:
0160 *val = 0;
0161 break;
0162 default:
0163 return -EINVAL;
0164 }
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 if (need_stable_symbols) {
0176 u32 tmp = intel_de_read(dev_priv, PORT_DFT2_G4X);
0177
0178 tmp |= DC_BALANCE_RESET_VLV;
0179 switch (pipe) {
0180 case PIPE_A:
0181 tmp |= PIPE_A_SCRAMBLE_RESET;
0182 break;
0183 case PIPE_B:
0184 tmp |= PIPE_B_SCRAMBLE_RESET;
0185 break;
0186 case PIPE_C:
0187 tmp |= PIPE_C_SCRAMBLE_RESET;
0188 break;
0189 default:
0190 return -EINVAL;
0191 }
0192 intel_de_write(dev_priv, PORT_DFT2_G4X, tmp);
0193 }
0194
0195 return 0;
0196 }
0197
0198 static int i9xx_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
0199 enum pipe pipe,
0200 enum intel_pipe_crc_source *source,
0201 u32 *val)
0202 {
0203 if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) {
0204 int ret = i9xx_pipe_crc_auto_source(dev_priv, pipe, source);
0205 if (ret)
0206 return ret;
0207 }
0208
0209 switch (*source) {
0210 case INTEL_PIPE_CRC_SOURCE_PIPE:
0211 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_I9XX;
0212 break;
0213 case INTEL_PIPE_CRC_SOURCE_TV:
0214 if (!SUPPORTS_TV(dev_priv))
0215 return -EINVAL;
0216 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_TV_PRE;
0217 break;
0218 case INTEL_PIPE_CRC_SOURCE_NONE:
0219 *val = 0;
0220 break;
0221 default:
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 return -EINVAL;
0233 }
0234
0235 return 0;
0236 }
0237
0238 static void vlv_undo_pipe_scramble_reset(struct drm_i915_private *dev_priv,
0239 enum pipe pipe)
0240 {
0241 u32 tmp = intel_de_read(dev_priv, PORT_DFT2_G4X);
0242
0243 switch (pipe) {
0244 case PIPE_A:
0245 tmp &= ~PIPE_A_SCRAMBLE_RESET;
0246 break;
0247 case PIPE_B:
0248 tmp &= ~PIPE_B_SCRAMBLE_RESET;
0249 break;
0250 case PIPE_C:
0251 tmp &= ~PIPE_C_SCRAMBLE_RESET;
0252 break;
0253 default:
0254 return;
0255 }
0256 if (!(tmp & PIPE_SCRAMBLE_RESET_MASK))
0257 tmp &= ~DC_BALANCE_RESET_VLV;
0258 intel_de_write(dev_priv, PORT_DFT2_G4X, tmp);
0259 }
0260
0261 static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source,
0262 u32 *val)
0263 {
0264 if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
0265 *source = INTEL_PIPE_CRC_SOURCE_PIPE;
0266
0267 switch (*source) {
0268 case INTEL_PIPE_CRC_SOURCE_PLANE1:
0269 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_ILK;
0270 break;
0271 case INTEL_PIPE_CRC_SOURCE_PLANE2:
0272 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_ILK;
0273 break;
0274 case INTEL_PIPE_CRC_SOURCE_PIPE:
0275 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_ILK;
0276 break;
0277 case INTEL_PIPE_CRC_SOURCE_NONE:
0278 *val = 0;
0279 break;
0280 default:
0281 return -EINVAL;
0282 }
0283
0284 return 0;
0285 }
0286
0287 static void
0288 intel_crtc_crc_setup_workarounds(struct intel_crtc *crtc, bool enable)
0289 {
0290 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
0291 struct intel_crtc_state *pipe_config;
0292 struct drm_atomic_state *state;
0293 struct drm_modeset_acquire_ctx ctx;
0294 int ret;
0295
0296 drm_modeset_acquire_init(&ctx, 0);
0297
0298 state = drm_atomic_state_alloc(&dev_priv->drm);
0299 if (!state) {
0300 ret = -ENOMEM;
0301 goto unlock;
0302 }
0303
0304 state->acquire_ctx = &ctx;
0305
0306 retry:
0307 pipe_config = intel_atomic_get_crtc_state(state, crtc);
0308 if (IS_ERR(pipe_config)) {
0309 ret = PTR_ERR(pipe_config);
0310 goto put_state;
0311 }
0312
0313 pipe_config->uapi.mode_changed = pipe_config->has_psr;
0314 pipe_config->crc_enabled = enable;
0315
0316 if (IS_HASWELL(dev_priv) &&
0317 pipe_config->hw.active && crtc->pipe == PIPE_A &&
0318 pipe_config->cpu_transcoder == TRANSCODER_EDP)
0319 pipe_config->uapi.mode_changed = true;
0320
0321 ret = drm_atomic_commit(state);
0322
0323 put_state:
0324 if (ret == -EDEADLK) {
0325 drm_atomic_state_clear(state);
0326 drm_modeset_backoff(&ctx);
0327 goto retry;
0328 }
0329
0330 drm_atomic_state_put(state);
0331 unlock:
0332 drm_WARN(&dev_priv->drm, ret,
0333 "Toggling workaround to %i returns %i\n", enable, ret);
0334 drm_modeset_drop_locks(&ctx);
0335 drm_modeset_acquire_fini(&ctx);
0336 }
0337
0338 static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
0339 enum pipe pipe,
0340 enum intel_pipe_crc_source *source,
0341 u32 *val)
0342 {
0343 if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
0344 *source = INTEL_PIPE_CRC_SOURCE_PIPE;
0345
0346 switch (*source) {
0347 case INTEL_PIPE_CRC_SOURCE_PLANE1:
0348 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_IVB;
0349 break;
0350 case INTEL_PIPE_CRC_SOURCE_PLANE2:
0351 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB;
0352 break;
0353 case INTEL_PIPE_CRC_SOURCE_PIPE:
0354 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB;
0355 break;
0356 case INTEL_PIPE_CRC_SOURCE_NONE:
0357 *val = 0;
0358 break;
0359 default:
0360 return -EINVAL;
0361 }
0362
0363 return 0;
0364 }
0365
0366 static int skl_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
0367 enum pipe pipe,
0368 enum intel_pipe_crc_source *source,
0369 u32 *val)
0370 {
0371 if (*source == INTEL_PIPE_CRC_SOURCE_AUTO)
0372 *source = INTEL_PIPE_CRC_SOURCE_PIPE;
0373
0374 switch (*source) {
0375 case INTEL_PIPE_CRC_SOURCE_PLANE1:
0376 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_1_SKL;
0377 break;
0378 case INTEL_PIPE_CRC_SOURCE_PLANE2:
0379 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_2_SKL;
0380 break;
0381 case INTEL_PIPE_CRC_SOURCE_PLANE3:
0382 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_3_SKL;
0383 break;
0384 case INTEL_PIPE_CRC_SOURCE_PLANE4:
0385 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_4_SKL;
0386 break;
0387 case INTEL_PIPE_CRC_SOURCE_PLANE5:
0388 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_5_SKL;
0389 break;
0390 case INTEL_PIPE_CRC_SOURCE_PLANE6:
0391 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_6_SKL;
0392 break;
0393 case INTEL_PIPE_CRC_SOURCE_PLANE7:
0394 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PLANE_7_SKL;
0395 break;
0396 case INTEL_PIPE_CRC_SOURCE_PIPE:
0397 *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DMUX_SKL;
0398 break;
0399 case INTEL_PIPE_CRC_SOURCE_NONE:
0400 *val = 0;
0401 break;
0402 default:
0403 return -EINVAL;
0404 }
0405
0406 return 0;
0407 }
0408
0409 static int get_new_crc_ctl_reg(struct drm_i915_private *dev_priv,
0410 enum pipe pipe,
0411 enum intel_pipe_crc_source *source, u32 *val)
0412 {
0413 if (DISPLAY_VER(dev_priv) == 2)
0414 return i8xx_pipe_crc_ctl_reg(source, val);
0415 else if (DISPLAY_VER(dev_priv) < 5)
0416 return i9xx_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
0417 else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
0418 return vlv_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
0419 else if (IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv))
0420 return ilk_pipe_crc_ctl_reg(source, val);
0421 else if (DISPLAY_VER(dev_priv) < 9)
0422 return ivb_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
0423 else
0424 return skl_pipe_crc_ctl_reg(dev_priv, pipe, source, val);
0425 }
0426
0427 static int
0428 display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s)
0429 {
0430 int i;
0431
0432 if (!buf) {
0433 *s = INTEL_PIPE_CRC_SOURCE_NONE;
0434 return 0;
0435 }
0436
0437 i = match_string(pipe_crc_sources, ARRAY_SIZE(pipe_crc_sources), buf);
0438 if (i < 0)
0439 return i;
0440
0441 *s = i;
0442 return 0;
0443 }
0444
0445 void intel_crtc_crc_init(struct intel_crtc *crtc)
0446 {
0447 struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
0448
0449 spin_lock_init(&pipe_crc->lock);
0450 }
0451
0452 static int i8xx_crc_source_valid(struct drm_i915_private *dev_priv,
0453 const enum intel_pipe_crc_source source)
0454 {
0455 switch (source) {
0456 case INTEL_PIPE_CRC_SOURCE_PIPE:
0457 case INTEL_PIPE_CRC_SOURCE_NONE:
0458 return 0;
0459 default:
0460 return -EINVAL;
0461 }
0462 }
0463
0464 static int i9xx_crc_source_valid(struct drm_i915_private *dev_priv,
0465 const enum intel_pipe_crc_source source)
0466 {
0467 switch (source) {
0468 case INTEL_PIPE_CRC_SOURCE_PIPE:
0469 case INTEL_PIPE_CRC_SOURCE_TV:
0470 case INTEL_PIPE_CRC_SOURCE_NONE:
0471 return 0;
0472 default:
0473 return -EINVAL;
0474 }
0475 }
0476
0477 static int vlv_crc_source_valid(struct drm_i915_private *dev_priv,
0478 const enum intel_pipe_crc_source source)
0479 {
0480 switch (source) {
0481 case INTEL_PIPE_CRC_SOURCE_PIPE:
0482 case INTEL_PIPE_CRC_SOURCE_DP_B:
0483 case INTEL_PIPE_CRC_SOURCE_DP_C:
0484 case INTEL_PIPE_CRC_SOURCE_DP_D:
0485 case INTEL_PIPE_CRC_SOURCE_NONE:
0486 return 0;
0487 default:
0488 return -EINVAL;
0489 }
0490 }
0491
0492 static int ilk_crc_source_valid(struct drm_i915_private *dev_priv,
0493 const enum intel_pipe_crc_source source)
0494 {
0495 switch (source) {
0496 case INTEL_PIPE_CRC_SOURCE_PIPE:
0497 case INTEL_PIPE_CRC_SOURCE_PLANE1:
0498 case INTEL_PIPE_CRC_SOURCE_PLANE2:
0499 case INTEL_PIPE_CRC_SOURCE_NONE:
0500 return 0;
0501 default:
0502 return -EINVAL;
0503 }
0504 }
0505
0506 static int ivb_crc_source_valid(struct drm_i915_private *dev_priv,
0507 const enum intel_pipe_crc_source source)
0508 {
0509 switch (source) {
0510 case INTEL_PIPE_CRC_SOURCE_PIPE:
0511 case INTEL_PIPE_CRC_SOURCE_PLANE1:
0512 case INTEL_PIPE_CRC_SOURCE_PLANE2:
0513 case INTEL_PIPE_CRC_SOURCE_NONE:
0514 return 0;
0515 default:
0516 return -EINVAL;
0517 }
0518 }
0519
0520 static int skl_crc_source_valid(struct drm_i915_private *dev_priv,
0521 const enum intel_pipe_crc_source source)
0522 {
0523 switch (source) {
0524 case INTEL_PIPE_CRC_SOURCE_PIPE:
0525 case INTEL_PIPE_CRC_SOURCE_PLANE1:
0526 case INTEL_PIPE_CRC_SOURCE_PLANE2:
0527 case INTEL_PIPE_CRC_SOURCE_PLANE3:
0528 case INTEL_PIPE_CRC_SOURCE_PLANE4:
0529 case INTEL_PIPE_CRC_SOURCE_PLANE5:
0530 case INTEL_PIPE_CRC_SOURCE_PLANE6:
0531 case INTEL_PIPE_CRC_SOURCE_PLANE7:
0532 case INTEL_PIPE_CRC_SOURCE_NONE:
0533 return 0;
0534 default:
0535 return -EINVAL;
0536 }
0537 }
0538
0539 static int
0540 intel_is_valid_crc_source(struct drm_i915_private *dev_priv,
0541 const enum intel_pipe_crc_source source)
0542 {
0543 if (DISPLAY_VER(dev_priv) == 2)
0544 return i8xx_crc_source_valid(dev_priv, source);
0545 else if (DISPLAY_VER(dev_priv) < 5)
0546 return i9xx_crc_source_valid(dev_priv, source);
0547 else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
0548 return vlv_crc_source_valid(dev_priv, source);
0549 else if (IS_IRONLAKE(dev_priv) || IS_SANDYBRIDGE(dev_priv))
0550 return ilk_crc_source_valid(dev_priv, source);
0551 else if (DISPLAY_VER(dev_priv) < 9)
0552 return ivb_crc_source_valid(dev_priv, source);
0553 else
0554 return skl_crc_source_valid(dev_priv, source);
0555 }
0556
0557 const char *const *intel_crtc_get_crc_sources(struct drm_crtc *crtc,
0558 size_t *count)
0559 {
0560 *count = ARRAY_SIZE(pipe_crc_sources);
0561 return pipe_crc_sources;
0562 }
0563
0564 int intel_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
0565 size_t *values_cnt)
0566 {
0567 struct drm_i915_private *dev_priv = to_i915(crtc->dev);
0568 enum intel_pipe_crc_source source;
0569
0570 if (display_crc_ctl_parse_source(source_name, &source) < 0) {
0571 drm_dbg(&dev_priv->drm, "unknown source %s\n", source_name);
0572 return -EINVAL;
0573 }
0574
0575 if (source == INTEL_PIPE_CRC_SOURCE_AUTO ||
0576 intel_is_valid_crc_source(dev_priv, source) == 0) {
0577 *values_cnt = 5;
0578 return 0;
0579 }
0580
0581 return -EINVAL;
0582 }
0583
0584 int intel_crtc_set_crc_source(struct drm_crtc *_crtc, const char *source_name)
0585 {
0586 struct intel_crtc *crtc = to_intel_crtc(_crtc);
0587 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
0588 struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
0589 enum intel_display_power_domain power_domain;
0590 enum intel_pipe_crc_source source;
0591 enum pipe pipe = crtc->pipe;
0592 intel_wakeref_t wakeref;
0593 u32 val = 0;
0594 int ret = 0;
0595 bool enable;
0596
0597 if (display_crc_ctl_parse_source(source_name, &source) < 0) {
0598 drm_dbg(&dev_priv->drm, "unknown source %s\n", source_name);
0599 return -EINVAL;
0600 }
0601
0602 power_domain = POWER_DOMAIN_PIPE(pipe);
0603 wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
0604 if (!wakeref) {
0605 drm_dbg_kms(&dev_priv->drm,
0606 "Trying to capture CRC while pipe is off\n");
0607 return -EIO;
0608 }
0609
0610 enable = source != INTEL_PIPE_CRC_SOURCE_NONE;
0611 if (enable)
0612 intel_crtc_crc_setup_workarounds(crtc, true);
0613
0614 ret = get_new_crc_ctl_reg(dev_priv, pipe, &source, &val);
0615 if (ret != 0)
0616 goto out;
0617
0618 pipe_crc->source = source;
0619 intel_de_write(dev_priv, PIPE_CRC_CTL(pipe), val);
0620 intel_de_posting_read(dev_priv, PIPE_CRC_CTL(pipe));
0621
0622 if (!source) {
0623 if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
0624 vlv_undo_pipe_scramble_reset(dev_priv, pipe);
0625 }
0626
0627 pipe_crc->skipped = 0;
0628
0629 out:
0630 if (!enable)
0631 intel_crtc_crc_setup_workarounds(crtc, false);
0632
0633 intel_display_power_put(dev_priv, power_domain, wakeref);
0634
0635 return ret;
0636 }
0637
0638 void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc)
0639 {
0640 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
0641 struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
0642 enum pipe pipe = crtc->pipe;
0643 u32 val = 0;
0644
0645 if (!crtc->base.crc.opened)
0646 return;
0647
0648 if (get_new_crc_ctl_reg(dev_priv, pipe, &pipe_crc->source, &val) < 0)
0649 return;
0650
0651
0652 pipe_crc->skipped = 0;
0653
0654 intel_de_write(dev_priv, PIPE_CRC_CTL(pipe), val);
0655 intel_de_posting_read(dev_priv, PIPE_CRC_CTL(pipe));
0656 }
0657
0658 void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc)
0659 {
0660 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
0661 struct intel_pipe_crc *pipe_crc = &crtc->pipe_crc;
0662 enum pipe pipe = crtc->pipe;
0663
0664
0665 spin_lock_irq(&pipe_crc->lock);
0666 pipe_crc->skipped = INT_MIN;
0667 spin_unlock_irq(&pipe_crc->lock);
0668
0669 intel_de_write(dev_priv, PIPE_CRC_CTL(pipe), 0);
0670 intel_de_posting_read(dev_priv, PIPE_CRC_CTL(pipe));
0671 intel_synchronize_irq(dev_priv);
0672 }