1153 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2020 Intel Corporation4 */5 6#include <linux/string_helpers.h>7 8#include <drm/drm_fixed.h>9 10#include "i915_reg.h"11#include "intel_atomic.h"12#include "intel_crtc.h"13#include "intel_ddi.h"14#include "intel_de.h"15#include "intel_dp.h"16#include "intel_display_types.h"17#include "intel_fdi.h"18#include "intel_fdi_regs.h"19#include "intel_link_bw.h"20 21struct intel_fdi_funcs {22 void (*fdi_link_train)(struct intel_crtc *crtc,23 const struct intel_crtc_state *crtc_state);24};25 26static void assert_fdi_tx(struct drm_i915_private *dev_priv,27 enum pipe pipe, bool state)28{29 bool cur_state;30 31 if (HAS_DDI(dev_priv)) {32 /*33 * DDI does not have a specific FDI_TX register.34 *35 * FDI is never fed from EDP transcoder36 * so pipe->transcoder cast is fine here.37 */38 enum transcoder cpu_transcoder = (enum transcoder)pipe;39 cur_state = intel_de_read(dev_priv,40 TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)) & TRANS_DDI_FUNC_ENABLE;41 } else {42 cur_state = intel_de_read(dev_priv, FDI_TX_CTL(pipe)) & FDI_TX_ENABLE;43 }44 I915_STATE_WARN(dev_priv, cur_state != state,45 "FDI TX state assertion failure (expected %s, current %s)\n",46 str_on_off(state), str_on_off(cur_state));47}48 49void assert_fdi_tx_enabled(struct drm_i915_private *i915, enum pipe pipe)50{51 assert_fdi_tx(i915, pipe, true);52}53 54void assert_fdi_tx_disabled(struct drm_i915_private *i915, enum pipe pipe)55{56 assert_fdi_tx(i915, pipe, false);57}58 59static void assert_fdi_rx(struct drm_i915_private *dev_priv,60 enum pipe pipe, bool state)61{62 bool cur_state;63 64 cur_state = intel_de_read(dev_priv, FDI_RX_CTL(pipe)) & FDI_RX_ENABLE;65 I915_STATE_WARN(dev_priv, cur_state != state,66 "FDI RX state assertion failure (expected %s, current %s)\n",67 str_on_off(state), str_on_off(cur_state));68}69 70void assert_fdi_rx_enabled(struct drm_i915_private *i915, enum pipe pipe)71{72 assert_fdi_rx(i915, pipe, true);73}74 75void assert_fdi_rx_disabled(struct drm_i915_private *i915, enum pipe pipe)76{77 assert_fdi_rx(i915, pipe, false);78}79 80void assert_fdi_tx_pll_enabled(struct drm_i915_private *i915,81 enum pipe pipe)82{83 bool cur_state;84 85 /* ILK FDI PLL is always enabled */86 if (IS_IRONLAKE(i915))87 return;88 89 /* On Haswell, DDI ports are responsible for the FDI PLL setup */90 if (HAS_DDI(i915))91 return;92 93 cur_state = intel_de_read(i915, FDI_TX_CTL(pipe)) & FDI_TX_PLL_ENABLE;94 I915_STATE_WARN(i915, !cur_state,95 "FDI TX PLL assertion failure, should be active but is disabled\n");96}97 98static void assert_fdi_rx_pll(struct drm_i915_private *i915,99 enum pipe pipe, bool state)100{101 bool cur_state;102 103 cur_state = intel_de_read(i915, FDI_RX_CTL(pipe)) & FDI_RX_PLL_ENABLE;104 I915_STATE_WARN(i915, cur_state != state,105 "FDI RX PLL assertion failure (expected %s, current %s)\n",106 str_on_off(state), str_on_off(cur_state));107}108 109void assert_fdi_rx_pll_enabled(struct drm_i915_private *i915, enum pipe pipe)110{111 assert_fdi_rx_pll(i915, pipe, true);112}113 114void assert_fdi_rx_pll_disabled(struct drm_i915_private *i915, enum pipe pipe)115{116 assert_fdi_rx_pll(i915, pipe, false);117}118 119void intel_fdi_link_train(struct intel_crtc *crtc,120 const struct intel_crtc_state *crtc_state)121{122 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);123 124 dev_priv->display.funcs.fdi->fdi_link_train(crtc, crtc_state);125}126 127/**128 * intel_fdi_add_affected_crtcs - add CRTCs on FDI affected by other modeset CRTCs129 * @state: intel atomic state130 *131 * Add a CRTC using FDI to @state if changing another CRTC's FDI BW usage is132 * known to affect the available FDI BW for the former CRTC. In practice this133 * means adding CRTC B on IVYBRIDGE if its use of FDI lanes is limited (by134 * CRTC C) and CRTC C is getting disabled.135 *136 * Returns 0 in case of success, or a negative error code otherwise.137 */138int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)139{140 struct drm_i915_private *i915 = to_i915(state->base.dev);141 const struct intel_crtc_state *old_crtc_state;142 const struct intel_crtc_state *new_crtc_state;143 struct intel_crtc *crtc;144 145 if (!IS_IVYBRIDGE(i915) || INTEL_NUM_PIPES(i915) != 3)146 return 0;147 148 crtc = intel_crtc_for_pipe(i915, PIPE_C);149 new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);150 if (!new_crtc_state)151 return 0;152 153 if (!intel_crtc_needs_modeset(new_crtc_state))154 return 0;155 156 old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);157 if (!old_crtc_state->fdi_lanes)158 return 0;159 160 crtc = intel_crtc_for_pipe(i915, PIPE_B);161 new_crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);162 if (IS_ERR(new_crtc_state))163 return PTR_ERR(new_crtc_state);164 165 old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);166 if (!old_crtc_state->fdi_lanes)167 return 0;168 169 return intel_modeset_pipes_in_mask_early(state,170 "FDI link BW decrease on pipe C",171 BIT(PIPE_B));172}173 174/* units of 100MHz */175static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)176{177 if (crtc_state->hw.enable && crtc_state->has_pch_encoder)178 return crtc_state->fdi_lanes;179 180 return 0;181}182 183static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,184 struct intel_crtc_state *pipe_config,185 enum pipe *pipe_to_reduce)186{187 struct drm_i915_private *dev_priv = to_i915(dev);188 struct drm_atomic_state *state = pipe_config->uapi.state;189 struct intel_crtc *other_crtc;190 struct intel_crtc_state *other_crtc_state;191 192 *pipe_to_reduce = pipe;193 194 drm_dbg_kms(&dev_priv->drm,195 "checking fdi config on pipe %c, lanes %i\n",196 pipe_name(pipe), pipe_config->fdi_lanes);197 if (pipe_config->fdi_lanes > 4) {198 drm_dbg_kms(&dev_priv->drm,199 "invalid fdi lane config on pipe %c: %i lanes\n",200 pipe_name(pipe), pipe_config->fdi_lanes);201 return -EINVAL;202 }203 204 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {205 if (pipe_config->fdi_lanes > 2) {206 drm_dbg_kms(&dev_priv->drm,207 "only 2 lanes on haswell, required: %i lanes\n",208 pipe_config->fdi_lanes);209 return -EINVAL;210 } else {211 return 0;212 }213 }214 215 if (INTEL_NUM_PIPES(dev_priv) == 2)216 return 0;217 218 /* Ivybridge 3 pipe is really complicated */219 switch (pipe) {220 case PIPE_A:221 return 0;222 case PIPE_B:223 if (pipe_config->fdi_lanes <= 2)224 return 0;225 226 other_crtc = intel_crtc_for_pipe(dev_priv, PIPE_C);227 other_crtc_state =228 intel_atomic_get_crtc_state(state, other_crtc);229 if (IS_ERR(other_crtc_state))230 return PTR_ERR(other_crtc_state);231 232 if (pipe_required_fdi_lanes(other_crtc_state) > 0) {233 drm_dbg_kms(&dev_priv->drm,234 "invalid shared fdi lane config on pipe %c: %i lanes\n",235 pipe_name(pipe), pipe_config->fdi_lanes);236 return -EINVAL;237 }238 return 0;239 case PIPE_C:240 if (pipe_config->fdi_lanes > 2) {241 drm_dbg_kms(&dev_priv->drm,242 "only 2 lanes on pipe %c: required %i lanes\n",243 pipe_name(pipe), pipe_config->fdi_lanes);244 return -EINVAL;245 }246 247 other_crtc = intel_crtc_for_pipe(dev_priv, PIPE_B);248 other_crtc_state =249 intel_atomic_get_crtc_state(state, other_crtc);250 if (IS_ERR(other_crtc_state))251 return PTR_ERR(other_crtc_state);252 253 if (pipe_required_fdi_lanes(other_crtc_state) > 2) {254 drm_dbg_kms(&dev_priv->drm,255 "fdi link B uses too many lanes to enable link C\n");256 257 *pipe_to_reduce = PIPE_B;258 259 return -EINVAL;260 }261 return 0;262 default:263 MISSING_CASE(pipe);264 return 0;265 }266}267 268void intel_fdi_pll_freq_update(struct drm_i915_private *i915)269{270 if (IS_IRONLAKE(i915)) {271 u32 fdi_pll_clk =272 intel_de_read(i915, FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK;273 274 i915->display.fdi.pll_freq = (fdi_pll_clk + 2) * 10000;275 } else if (IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) {276 i915->display.fdi.pll_freq = 270000;277 } else {278 return;279 }280 281 drm_dbg(&i915->drm, "FDI PLL freq=%d\n", i915->display.fdi.pll_freq);282}283 284int intel_fdi_link_freq(struct drm_i915_private *i915,285 const struct intel_crtc_state *pipe_config)286{287 if (HAS_DDI(i915))288 return pipe_config->port_clock; /* SPLL */289 else290 return i915->display.fdi.pll_freq;291}292 293/**294 * intel_fdi_compute_pipe_bpp - compute pipe bpp limited by max link bpp295 * @crtc_state: the crtc state296 *297 * Compute the pipe bpp limited by the CRTC's maximum link bpp. Encoders can298 * call this function during state computation in the simple case where the299 * link bpp will always match the pipe bpp. This is the case for all non-DP300 * encoders, while DP encoders will use a link bpp lower than pipe bpp in case301 * of DSC compression.302 *303 * Returns %true in case of success, %false if pipe bpp would need to be304 * reduced below its valid range.305 */306bool intel_fdi_compute_pipe_bpp(struct intel_crtc_state *crtc_state)307{308 int pipe_bpp = min(crtc_state->pipe_bpp,309 fxp_q4_to_int(crtc_state->max_link_bpp_x16));310 311 pipe_bpp = rounddown(pipe_bpp, 2 * 3);312 313 if (pipe_bpp < 6 * 3)314 return false;315 316 crtc_state->pipe_bpp = pipe_bpp;317 318 return true;319}320 321int ilk_fdi_compute_config(struct intel_crtc *crtc,322 struct intel_crtc_state *pipe_config)323{324 struct drm_device *dev = crtc->base.dev;325 struct drm_i915_private *i915 = to_i915(dev);326 const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;327 int lane, link_bw, fdi_dotclock;328 329 /* FDI is a binary signal running at ~2.7GHz, encoding330 * each output octet as 10 bits. The actual frequency331 * is stored as a divider into a 100MHz clock, and the332 * mode pixel clock is stored in units of 1KHz.333 * Hence the bw of each lane in terms of the mode signal334 * is:335 */336 link_bw = intel_fdi_link_freq(i915, pipe_config);337 338 fdi_dotclock = adjusted_mode->crtc_clock;339 340 lane = ilk_get_lanes_required(fdi_dotclock, link_bw,341 pipe_config->pipe_bpp);342 343 pipe_config->fdi_lanes = lane;344 345 intel_link_compute_m_n(fxp_q4_from_int(pipe_config->pipe_bpp),346 lane, fdi_dotclock,347 link_bw,348 intel_dp_bw_fec_overhead(false),349 &pipe_config->fdi_m_n);350 351 return 0;352}353 354static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,355 struct intel_crtc *crtc,356 struct intel_crtc_state *pipe_config,357 struct intel_link_bw_limits *limits)358{359 struct drm_i915_private *i915 = to_i915(crtc->base.dev);360 enum pipe pipe_to_reduce;361 int ret;362 363 ret = ilk_check_fdi_lanes(&i915->drm, crtc->pipe, pipe_config,364 &pipe_to_reduce);365 if (ret != -EINVAL)366 return ret;367 368 ret = intel_link_bw_reduce_bpp(state, limits,369 BIT(pipe_to_reduce),370 "FDI link BW");371 372 return ret ? : -EAGAIN;373}374 375/**376 * intel_fdi_atomic_check_link - check all modeset FDI link configuration377 * @state: intel atomic state378 * @limits: link BW limits379 *380 * Check the link configuration for all modeset FDI outputs. If the381 * configuration is invalid @limits will be updated if possible to382 * reduce the total BW, after which the configuration for all CRTCs in383 * @state must be recomputed with the updated @limits.384 *385 * Returns:386 * - 0 if the confugration is valid387 * - %-EAGAIN, if the configuration is invalid and @limits got updated388 * with fallback values with which the configuration of all CRTCs389 * in @state must be recomputed390 * - Other negative error, if the configuration is invalid without a391 * fallback possibility, or the check failed for another reason392 */393int intel_fdi_atomic_check_link(struct intel_atomic_state *state,394 struct intel_link_bw_limits *limits)395{396 struct intel_crtc *crtc;397 struct intel_crtc_state *crtc_state;398 int i;399 400 for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {401 int ret;402 403 if (!crtc_state->has_pch_encoder ||404 !intel_crtc_needs_modeset(crtc_state) ||405 !crtc_state->hw.enable)406 continue;407 408 ret = intel_fdi_atomic_check_bw(state, crtc, crtc_state, limits);409 if (ret)410 return ret;411 }412 413 return 0;414}415 416static void cpt_set_fdi_bc_bifurcation(struct drm_i915_private *dev_priv, bool enable)417{418 u32 temp;419 420 temp = intel_de_read(dev_priv, SOUTH_CHICKEN1);421 if (!!(temp & FDI_BC_BIFURCATION_SELECT) == enable)422 return;423 424 drm_WARN_ON(&dev_priv->drm,425 intel_de_read(dev_priv, FDI_RX_CTL(PIPE_B)) &426 FDI_RX_ENABLE);427 drm_WARN_ON(&dev_priv->drm,428 intel_de_read(dev_priv, FDI_RX_CTL(PIPE_C)) &429 FDI_RX_ENABLE);430 431 temp &= ~FDI_BC_BIFURCATION_SELECT;432 if (enable)433 temp |= FDI_BC_BIFURCATION_SELECT;434 435 drm_dbg_kms(&dev_priv->drm, "%sabling fdi C rx\n",436 enable ? "en" : "dis");437 intel_de_write(dev_priv, SOUTH_CHICKEN1, temp);438 intel_de_posting_read(dev_priv, SOUTH_CHICKEN1);439}440 441static void ivb_update_fdi_bc_bifurcation(const struct intel_crtc_state *crtc_state)442{443 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);444 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);445 446 switch (crtc->pipe) {447 case PIPE_A:448 break;449 case PIPE_B:450 if (crtc_state->fdi_lanes > 2)451 cpt_set_fdi_bc_bifurcation(dev_priv, false);452 else453 cpt_set_fdi_bc_bifurcation(dev_priv, true);454 455 break;456 case PIPE_C:457 cpt_set_fdi_bc_bifurcation(dev_priv, true);458 459 break;460 default:461 MISSING_CASE(crtc->pipe);462 }463}464 465void intel_fdi_normal_train(struct intel_crtc *crtc)466{467 struct drm_device *dev = crtc->base.dev;468 struct drm_i915_private *dev_priv = to_i915(dev);469 enum pipe pipe = crtc->pipe;470 i915_reg_t reg;471 u32 temp;472 473 /* enable normal train */474 reg = FDI_TX_CTL(pipe);475 temp = intel_de_read(dev_priv, reg);476 if (IS_IVYBRIDGE(dev_priv)) {477 temp &= ~FDI_LINK_TRAIN_NONE_IVB;478 temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE;479 } else {480 temp &= ~FDI_LINK_TRAIN_NONE;481 temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;482 }483 intel_de_write(dev_priv, reg, temp);484 485 reg = FDI_RX_CTL(pipe);486 temp = intel_de_read(dev_priv, reg);487 if (HAS_PCH_CPT(dev_priv)) {488 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;489 temp |= FDI_LINK_TRAIN_NORMAL_CPT;490 } else {491 temp &= ~FDI_LINK_TRAIN_NONE;492 temp |= FDI_LINK_TRAIN_NONE;493 }494 intel_de_write(dev_priv, reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE);495 496 /* wait one idle pattern time */497 intel_de_posting_read(dev_priv, reg);498 udelay(1000);499 500 /* IVB wants error correction enabled */501 if (IS_IVYBRIDGE(dev_priv))502 intel_de_rmw(dev_priv, reg, 0, FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE);503}504 505/* The FDI link training functions for ILK/Ibexpeak. */506static void ilk_fdi_link_train(struct intel_crtc *crtc,507 const struct intel_crtc_state *crtc_state)508{509 struct drm_device *dev = crtc->base.dev;510 struct drm_i915_private *dev_priv = to_i915(dev);511 enum pipe pipe = crtc->pipe;512 i915_reg_t reg;513 u32 temp, tries;514 515 /*516 * Write the TU size bits before fdi link training, so that error517 * detection works.518 */519 intel_de_write(dev_priv, FDI_RX_TUSIZE1(pipe),520 intel_de_read(dev_priv, PIPE_DATA_M1(dev_priv, pipe)) & TU_SIZE_MASK);521 522 /* FDI needs bits from pipe first */523 assert_transcoder_enabled(dev_priv, crtc_state->cpu_transcoder);524 525 /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit526 for train result */527 reg = FDI_RX_IMR(pipe);528 temp = intel_de_read(dev_priv, reg);529 temp &= ~FDI_RX_SYMBOL_LOCK;530 temp &= ~FDI_RX_BIT_LOCK;531 intel_de_write(dev_priv, reg, temp);532 intel_de_read(dev_priv, reg);533 udelay(150);534 535 /* enable CPU FDI TX and PCH FDI RX */536 reg = FDI_TX_CTL(pipe);537 temp = intel_de_read(dev_priv, reg);538 temp &= ~FDI_DP_PORT_WIDTH_MASK;539 temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);540 temp &= ~FDI_LINK_TRAIN_NONE;541 temp |= FDI_LINK_TRAIN_PATTERN_1;542 intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE);543 544 reg = FDI_RX_CTL(pipe);545 temp = intel_de_read(dev_priv, reg);546 temp &= ~FDI_LINK_TRAIN_NONE;547 temp |= FDI_LINK_TRAIN_PATTERN_1;548 intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE);549 550 intel_de_posting_read(dev_priv, reg);551 udelay(150);552 553 /* Ironlake workaround, enable clock pointer after FDI enable*/554 intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe),555 FDI_RX_PHASE_SYNC_POINTER_OVR);556 intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe),557 FDI_RX_PHASE_SYNC_POINTER_OVR | FDI_RX_PHASE_SYNC_POINTER_EN);558 559 reg = FDI_RX_IIR(pipe);560 for (tries = 0; tries < 5; tries++) {561 temp = intel_de_read(dev_priv, reg);562 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);563 564 if ((temp & FDI_RX_BIT_LOCK)) {565 drm_dbg_kms(&dev_priv->drm, "FDI train 1 done.\n");566 intel_de_write(dev_priv, reg, temp | FDI_RX_BIT_LOCK);567 break;568 }569 }570 if (tries == 5)571 drm_err(&dev_priv->drm, "FDI train 1 fail!\n");572 573 /* Train 2 */574 intel_de_rmw(dev_priv, FDI_TX_CTL(pipe),575 FDI_LINK_TRAIN_NONE, FDI_LINK_TRAIN_PATTERN_2);576 intel_de_rmw(dev_priv, FDI_RX_CTL(pipe),577 FDI_LINK_TRAIN_NONE, FDI_LINK_TRAIN_PATTERN_2);578 intel_de_posting_read(dev_priv, FDI_RX_CTL(pipe));579 udelay(150);580 581 reg = FDI_RX_IIR(pipe);582 for (tries = 0; tries < 5; tries++) {583 temp = intel_de_read(dev_priv, reg);584 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);585 586 if (temp & FDI_RX_SYMBOL_LOCK) {587 intel_de_write(dev_priv, reg,588 temp | FDI_RX_SYMBOL_LOCK);589 drm_dbg_kms(&dev_priv->drm, "FDI train 2 done.\n");590 break;591 }592 }593 if (tries == 5)594 drm_err(&dev_priv->drm, "FDI train 2 fail!\n");595 596 drm_dbg_kms(&dev_priv->drm, "FDI train done\n");597 598}599 600static const int snb_b_fdi_train_param[] = {601 FDI_LINK_TRAIN_400MV_0DB_SNB_B,602 FDI_LINK_TRAIN_400MV_6DB_SNB_B,603 FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,604 FDI_LINK_TRAIN_800MV_0DB_SNB_B,605};606 607/* The FDI link training functions for SNB/Cougarpoint. */608static void gen6_fdi_link_train(struct intel_crtc *crtc,609 const struct intel_crtc_state *crtc_state)610{611 struct drm_device *dev = crtc->base.dev;612 struct drm_i915_private *dev_priv = to_i915(dev);613 enum pipe pipe = crtc->pipe;614 i915_reg_t reg;615 u32 temp, i, retry;616 617 /*618 * Write the TU size bits before fdi link training, so that error619 * detection works.620 */621 intel_de_write(dev_priv, FDI_RX_TUSIZE1(pipe),622 intel_de_read(dev_priv, PIPE_DATA_M1(dev_priv, pipe)) & TU_SIZE_MASK);623 624 /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit625 for train result */626 reg = FDI_RX_IMR(pipe);627 temp = intel_de_read(dev_priv, reg);628 temp &= ~FDI_RX_SYMBOL_LOCK;629 temp &= ~FDI_RX_BIT_LOCK;630 intel_de_write(dev_priv, reg, temp);631 632 intel_de_posting_read(dev_priv, reg);633 udelay(150);634 635 /* enable CPU FDI TX and PCH FDI RX */636 reg = FDI_TX_CTL(pipe);637 temp = intel_de_read(dev_priv, reg);638 temp &= ~FDI_DP_PORT_WIDTH_MASK;639 temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);640 temp &= ~FDI_LINK_TRAIN_NONE;641 temp |= FDI_LINK_TRAIN_PATTERN_1;642 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;643 /* SNB-B */644 temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;645 intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE);646 647 intel_de_write(dev_priv, FDI_RX_MISC(pipe),648 FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);649 650 reg = FDI_RX_CTL(pipe);651 temp = intel_de_read(dev_priv, reg);652 if (HAS_PCH_CPT(dev_priv)) {653 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;654 temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;655 } else {656 temp &= ~FDI_LINK_TRAIN_NONE;657 temp |= FDI_LINK_TRAIN_PATTERN_1;658 }659 intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE);660 661 intel_de_posting_read(dev_priv, reg);662 udelay(150);663 664 for (i = 0; i < 4; i++) {665 intel_de_rmw(dev_priv, FDI_TX_CTL(pipe),666 FDI_LINK_TRAIN_VOL_EMP_MASK, snb_b_fdi_train_param[i]);667 intel_de_posting_read(dev_priv, FDI_TX_CTL(pipe));668 udelay(500);669 670 for (retry = 0; retry < 5; retry++) {671 reg = FDI_RX_IIR(pipe);672 temp = intel_de_read(dev_priv, reg);673 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);674 if (temp & FDI_RX_BIT_LOCK) {675 intel_de_write(dev_priv, reg,676 temp | FDI_RX_BIT_LOCK);677 drm_dbg_kms(&dev_priv->drm,678 "FDI train 1 done.\n");679 break;680 }681 udelay(50);682 }683 if (retry < 5)684 break;685 }686 if (i == 4)687 drm_err(&dev_priv->drm, "FDI train 1 fail!\n");688 689 /* Train 2 */690 reg = FDI_TX_CTL(pipe);691 temp = intel_de_read(dev_priv, reg);692 temp &= ~FDI_LINK_TRAIN_NONE;693 temp |= FDI_LINK_TRAIN_PATTERN_2;694 if (IS_SANDYBRIDGE(dev_priv)) {695 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;696 /* SNB-B */697 temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;698 }699 intel_de_write(dev_priv, reg, temp);700 701 reg = FDI_RX_CTL(pipe);702 temp = intel_de_read(dev_priv, reg);703 if (HAS_PCH_CPT(dev_priv)) {704 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;705 temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;706 } else {707 temp &= ~FDI_LINK_TRAIN_NONE;708 temp |= FDI_LINK_TRAIN_PATTERN_2;709 }710 intel_de_write(dev_priv, reg, temp);711 712 intel_de_posting_read(dev_priv, reg);713 udelay(150);714 715 for (i = 0; i < 4; i++) {716 intel_de_rmw(dev_priv, FDI_TX_CTL(pipe),717 FDI_LINK_TRAIN_VOL_EMP_MASK, snb_b_fdi_train_param[i]);718 intel_de_posting_read(dev_priv, FDI_TX_CTL(pipe));719 udelay(500);720 721 for (retry = 0; retry < 5; retry++) {722 reg = FDI_RX_IIR(pipe);723 temp = intel_de_read(dev_priv, reg);724 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);725 if (temp & FDI_RX_SYMBOL_LOCK) {726 intel_de_write(dev_priv, reg,727 temp | FDI_RX_SYMBOL_LOCK);728 drm_dbg_kms(&dev_priv->drm,729 "FDI train 2 done.\n");730 break;731 }732 udelay(50);733 }734 if (retry < 5)735 break;736 }737 if (i == 4)738 drm_err(&dev_priv->drm, "FDI train 2 fail!\n");739 740 drm_dbg_kms(&dev_priv->drm, "FDI train done.\n");741}742 743/* Manual link training for Ivy Bridge A0 parts */744static void ivb_manual_fdi_link_train(struct intel_crtc *crtc,745 const struct intel_crtc_state *crtc_state)746{747 struct drm_device *dev = crtc->base.dev;748 struct drm_i915_private *dev_priv = to_i915(dev);749 enum pipe pipe = crtc->pipe;750 i915_reg_t reg;751 u32 temp, i, j;752 753 ivb_update_fdi_bc_bifurcation(crtc_state);754 755 /*756 * Write the TU size bits before fdi link training, so that error757 * detection works.758 */759 intel_de_write(dev_priv, FDI_RX_TUSIZE1(pipe),760 intel_de_read(dev_priv, PIPE_DATA_M1(dev_priv, pipe)) & TU_SIZE_MASK);761 762 /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit763 for train result */764 reg = FDI_RX_IMR(pipe);765 temp = intel_de_read(dev_priv, reg);766 temp &= ~FDI_RX_SYMBOL_LOCK;767 temp &= ~FDI_RX_BIT_LOCK;768 intel_de_write(dev_priv, reg, temp);769 770 intel_de_posting_read(dev_priv, reg);771 udelay(150);772 773 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR before link train 0x%x\n",774 intel_de_read(dev_priv, FDI_RX_IIR(pipe)));775 776 /* Try each vswing and preemphasis setting twice before moving on */777 for (j = 0; j < ARRAY_SIZE(snb_b_fdi_train_param) * 2; j++) {778 /* disable first in case we need to retry */779 reg = FDI_TX_CTL(pipe);780 temp = intel_de_read(dev_priv, reg);781 temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB);782 temp &= ~FDI_TX_ENABLE;783 intel_de_write(dev_priv, reg, temp);784 785 reg = FDI_RX_CTL(pipe);786 temp = intel_de_read(dev_priv, reg);787 temp &= ~FDI_LINK_TRAIN_AUTO;788 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;789 temp &= ~FDI_RX_ENABLE;790 intel_de_write(dev_priv, reg, temp);791 792 /* enable CPU FDI TX and PCH FDI RX */793 reg = FDI_TX_CTL(pipe);794 temp = intel_de_read(dev_priv, reg);795 temp &= ~FDI_DP_PORT_WIDTH_MASK;796 temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);797 temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;798 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;799 temp |= snb_b_fdi_train_param[j/2];800 temp |= FDI_COMPOSITE_SYNC;801 intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE);802 803 intel_de_write(dev_priv, FDI_RX_MISC(pipe),804 FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90);805 806 reg = FDI_RX_CTL(pipe);807 temp = intel_de_read(dev_priv, reg);808 temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;809 temp |= FDI_COMPOSITE_SYNC;810 intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE);811 812 intel_de_posting_read(dev_priv, reg);813 udelay(1); /* should be 0.5us */814 815 for (i = 0; i < 4; i++) {816 reg = FDI_RX_IIR(pipe);817 temp = intel_de_read(dev_priv, reg);818 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);819 820 if (temp & FDI_RX_BIT_LOCK ||821 (intel_de_read(dev_priv, reg) & FDI_RX_BIT_LOCK)) {822 intel_de_write(dev_priv, reg,823 temp | FDI_RX_BIT_LOCK);824 drm_dbg_kms(&dev_priv->drm,825 "FDI train 1 done, level %i.\n",826 i);827 break;828 }829 udelay(1); /* should be 0.5us */830 }831 if (i == 4) {832 drm_dbg_kms(&dev_priv->drm,833 "FDI train 1 fail on vswing %d\n", j / 2);834 continue;835 }836 837 /* Train 2 */838 intel_de_rmw(dev_priv, FDI_TX_CTL(pipe),839 FDI_LINK_TRAIN_NONE_IVB,840 FDI_LINK_TRAIN_PATTERN_2_IVB);841 intel_de_rmw(dev_priv, FDI_RX_CTL(pipe),842 FDI_LINK_TRAIN_PATTERN_MASK_CPT,843 FDI_LINK_TRAIN_PATTERN_2_CPT);844 intel_de_posting_read(dev_priv, FDI_RX_CTL(pipe));845 udelay(2); /* should be 1.5us */846 847 for (i = 0; i < 4; i++) {848 reg = FDI_RX_IIR(pipe);849 temp = intel_de_read(dev_priv, reg);850 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp);851 852 if (temp & FDI_RX_SYMBOL_LOCK ||853 (intel_de_read(dev_priv, reg) & FDI_RX_SYMBOL_LOCK)) {854 intel_de_write(dev_priv, reg,855 temp | FDI_RX_SYMBOL_LOCK);856 drm_dbg_kms(&dev_priv->drm,857 "FDI train 2 done, level %i.\n",858 i);859 goto train_done;860 }861 udelay(2); /* should be 1.5us */862 }863 if (i == 4)864 drm_dbg_kms(&dev_priv->drm,865 "FDI train 2 fail on vswing %d\n", j / 2);866 }867 868train_done:869 drm_dbg_kms(&dev_priv->drm, "FDI train done.\n");870}871 872/* Starting with Haswell, different DDI ports can work in FDI mode for873 * connection to the PCH-located connectors. For this, it is necessary to train874 * both the DDI port and PCH receiver for the desired DDI buffer settings.875 *876 * The recommended port to work in FDI mode is DDI E, which we use here. Also,877 * please note that when FDI mode is active on DDI E, it shares 2 lines with878 * DDI A (which is used for eDP)879 */880void hsw_fdi_link_train(struct intel_encoder *encoder,881 const struct intel_crtc_state *crtc_state)882{883 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);884 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);885 u32 temp, i, rx_ctl_val;886 int n_entries;887 888 encoder->get_buf_trans(encoder, crtc_state, &n_entries);889 890 hsw_prepare_dp_ddi_buffers(encoder, crtc_state);891 892 /* Set the FDI_RX_MISC pwrdn lanes and the 2 workarounds listed at the893 * mode set "sequence for CRT port" document:894 * - TP1 to TP2 time with the default value895 * - FDI delay to 90h896 *897 * WaFDIAutoLinkSetTimingOverrride:hsw898 */899 intel_de_write(dev_priv, FDI_RX_MISC(PIPE_A),900 FDI_RX_PWRDN_LANE1_VAL(2) |901 FDI_RX_PWRDN_LANE0_VAL(2) |902 FDI_RX_TP1_TO_TP2_48 |903 FDI_RX_FDI_DELAY_90);904 905 /* Enable the PCH Receiver FDI PLL */906 rx_ctl_val = dev_priv->display.fdi.rx_config | FDI_RX_ENHANCE_FRAME_ENABLE |907 FDI_RX_PLL_ENABLE |908 FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);909 intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);910 intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));911 udelay(220);912 913 /* Switch from Rawclk to PCDclk */914 rx_ctl_val |= FDI_PCDCLK;915 intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);916 917 /* Configure Port Clock Select */918 drm_WARN_ON(&dev_priv->drm, crtc_state->shared_dpll->info->id != DPLL_ID_SPLL);919 intel_ddi_enable_clock(encoder, crtc_state);920 921 /* Start the training iterating through available voltages and emphasis,922 * testing each value twice. */923 for (i = 0; i < n_entries * 2; i++) {924 /* Configure DP_TP_CTL with auto-training */925 intel_de_write(dev_priv, DP_TP_CTL(PORT_E),926 DP_TP_CTL_FDI_AUTOTRAIN |927 DP_TP_CTL_ENHANCED_FRAME_ENABLE |928 DP_TP_CTL_LINK_TRAIN_PAT1 |929 DP_TP_CTL_ENABLE);930 931 /* Configure and enable DDI_BUF_CTL for DDI E with next voltage.932 * DDI E does not support port reversal, the functionality is933 * achieved on the PCH side in FDI_RX_CTL, so no need to set the934 * port reversal bit */935 intel_de_write(dev_priv, DDI_BUF_CTL(PORT_E),936 DDI_BUF_CTL_ENABLE |937 ((crtc_state->fdi_lanes - 1) << 1) |938 DDI_BUF_TRANS_SELECT(i / 2));939 intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));940 941 udelay(600);942 943 /* Program PCH FDI Receiver TU */944 intel_de_write(dev_priv, FDI_RX_TUSIZE1(PIPE_A), TU_SIZE(64));945 946 /* Enable PCH FDI Receiver with auto-training */947 rx_ctl_val |= FDI_RX_ENABLE | FDI_LINK_TRAIN_AUTO;948 intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);949 intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));950 951 /* Wait for FDI receiver lane calibration */952 udelay(30);953 954 /* Unset FDI_RX_MISC pwrdn lanes */955 intel_de_rmw(dev_priv, FDI_RX_MISC(PIPE_A),956 FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK, 0);957 intel_de_posting_read(dev_priv, FDI_RX_MISC(PIPE_A));958 959 /* Wait for FDI auto training time */960 udelay(5);961 962 temp = intel_de_read(dev_priv, DP_TP_STATUS(PORT_E));963 if (temp & DP_TP_STATUS_AUTOTRAIN_DONE) {964 drm_dbg_kms(&dev_priv->drm,965 "FDI link training done on step %d\n", i);966 break;967 }968 969 /*970 * Leave things enabled even if we failed to train FDI.971 * Results in less fireworks from the state checker.972 */973 if (i == n_entries * 2 - 1) {974 drm_err(&dev_priv->drm, "FDI link training failed!\n");975 break;976 }977 978 rx_ctl_val &= ~FDI_RX_ENABLE;979 intel_de_write(dev_priv, FDI_RX_CTL(PIPE_A), rx_ctl_val);980 intel_de_posting_read(dev_priv, FDI_RX_CTL(PIPE_A));981 982 intel_de_rmw(dev_priv, DDI_BUF_CTL(PORT_E), DDI_BUF_CTL_ENABLE, 0);983 intel_de_posting_read(dev_priv, DDI_BUF_CTL(PORT_E));984 985 /* Disable DP_TP_CTL and FDI_RX_CTL and retry */986 intel_de_rmw(dev_priv, DP_TP_CTL(PORT_E), DP_TP_CTL_ENABLE, 0);987 intel_de_posting_read(dev_priv, DP_TP_CTL(PORT_E));988 989 intel_wait_ddi_buf_idle(dev_priv, PORT_E);990 991 /* Reset FDI_RX_MISC pwrdn lanes */992 intel_de_rmw(dev_priv, FDI_RX_MISC(PIPE_A),993 FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK,994 FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2));995 intel_de_posting_read(dev_priv, FDI_RX_MISC(PIPE_A));996 }997 998 /* Enable normal pixel sending for FDI */999 intel_de_write(dev_priv, DP_TP_CTL(PORT_E),1000 DP_TP_CTL_FDI_AUTOTRAIN |1001 DP_TP_CTL_LINK_TRAIN_NORMAL |1002 DP_TP_CTL_ENHANCED_FRAME_ENABLE |1003 DP_TP_CTL_ENABLE);1004}1005 1006void hsw_fdi_disable(struct intel_encoder *encoder)1007{1008 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);1009 1010 /*1011 * Bspec lists this as both step 13 (before DDI_BUF_CTL disable)1012 * and step 18 (after clearing PORT_CLK_SEL). Based on a BUN,1013 * step 13 is the correct place for it. Step 18 is where it was1014 * originally before the BUN.1015 */1016 intel_de_rmw(dev_priv, FDI_RX_CTL(PIPE_A), FDI_RX_ENABLE, 0);1017 intel_de_rmw(dev_priv, DDI_BUF_CTL(PORT_E), DDI_BUF_CTL_ENABLE, 0);1018 intel_wait_ddi_buf_idle(dev_priv, PORT_E);1019 intel_ddi_disable_clock(encoder);1020 intel_de_rmw(dev_priv, FDI_RX_MISC(PIPE_A),1021 FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK,1022 FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2));1023 intel_de_rmw(dev_priv, FDI_RX_CTL(PIPE_A), FDI_PCDCLK, 0);1024 intel_de_rmw(dev_priv, FDI_RX_CTL(PIPE_A), FDI_RX_PLL_ENABLE, 0);1025}1026 1027void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state)1028{1029 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);1030 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);1031 enum pipe pipe = crtc->pipe;1032 i915_reg_t reg;1033 u32 temp;1034 1035 /* enable PCH FDI RX PLL, wait warmup plus DMI latency */1036 reg = FDI_RX_CTL(pipe);1037 temp = intel_de_read(dev_priv, reg);1038 temp &= ~(FDI_DP_PORT_WIDTH_MASK | (0x7 << 16));1039 temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes);1040 temp |= (intel_de_read(dev_priv, TRANSCONF(dev_priv, pipe)) & TRANSCONF_BPC_MASK) << 11;1041 intel_de_write(dev_priv, reg, temp | FDI_RX_PLL_ENABLE);1042 1043 intel_de_posting_read(dev_priv, reg);1044 udelay(200);1045 1046 /* Switch from Rawclk to PCDclk */1047 intel_de_rmw(dev_priv, reg, 0, FDI_PCDCLK);1048 intel_de_posting_read(dev_priv, reg);1049 udelay(200);1050 1051 /* Enable CPU FDI TX PLL, always on for Ironlake */1052 reg = FDI_TX_CTL(pipe);1053 temp = intel_de_read(dev_priv, reg);1054 if ((temp & FDI_TX_PLL_ENABLE) == 0) {1055 intel_de_write(dev_priv, reg, temp | FDI_TX_PLL_ENABLE);1056 1057 intel_de_posting_read(dev_priv, reg);1058 udelay(100);1059 }1060}1061 1062void ilk_fdi_pll_disable(struct intel_crtc *crtc)1063{1064 struct drm_device *dev = crtc->base.dev;1065 struct drm_i915_private *dev_priv = to_i915(dev);1066 enum pipe pipe = crtc->pipe;1067 1068 /* Switch from PCDclk to Rawclk */1069 intel_de_rmw(dev_priv, FDI_RX_CTL(pipe), FDI_PCDCLK, 0);1070 1071 /* Disable CPU FDI TX PLL */1072 intel_de_rmw(dev_priv, FDI_TX_CTL(pipe), FDI_TX_PLL_ENABLE, 0);1073 intel_de_posting_read(dev_priv, FDI_TX_CTL(pipe));1074 udelay(100);1075 1076 /* Wait for the clocks to turn off. */1077 intel_de_rmw(dev_priv, FDI_RX_CTL(pipe), FDI_RX_PLL_ENABLE, 0);1078 intel_de_posting_read(dev_priv, FDI_RX_CTL(pipe));1079 udelay(100);1080}1081 1082void ilk_fdi_disable(struct intel_crtc *crtc)1083{1084 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);1085 enum pipe pipe = crtc->pipe;1086 i915_reg_t reg;1087 u32 temp;1088 1089 /* disable CPU FDI tx and PCH FDI rx */1090 intel_de_rmw(dev_priv, FDI_TX_CTL(pipe), FDI_TX_ENABLE, 0);1091 intel_de_posting_read(dev_priv, FDI_TX_CTL(pipe));1092 1093 reg = FDI_RX_CTL(pipe);1094 temp = intel_de_read(dev_priv, reg);1095 temp &= ~(0x7 << 16);1096 temp |= (intel_de_read(dev_priv, TRANSCONF(dev_priv, pipe)) & TRANSCONF_BPC_MASK) << 11;1097 intel_de_write(dev_priv, reg, temp & ~FDI_RX_ENABLE);1098 1099 intel_de_posting_read(dev_priv, reg);1100 udelay(100);1101 1102 /* Ironlake workaround, disable clock pointer after downing FDI */1103 if (HAS_PCH_IBX(dev_priv))1104 intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe),1105 FDI_RX_PHASE_SYNC_POINTER_OVR);1106 1107 /* still set train pattern 1 */1108 intel_de_rmw(dev_priv, FDI_TX_CTL(pipe),1109 FDI_LINK_TRAIN_NONE, FDI_LINK_TRAIN_PATTERN_1);1110 1111 reg = FDI_RX_CTL(pipe);1112 temp = intel_de_read(dev_priv, reg);1113 if (HAS_PCH_CPT(dev_priv)) {1114 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;1115 temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;1116 } else {1117 temp &= ~FDI_LINK_TRAIN_NONE;1118 temp |= FDI_LINK_TRAIN_PATTERN_1;1119 }1120 /* BPC in FDI rx is consistent with that in TRANSCONF */1121 temp &= ~(0x07 << 16);1122 temp |= (intel_de_read(dev_priv, TRANSCONF(dev_priv, pipe)) & TRANSCONF_BPC_MASK) << 11;1123 intel_de_write(dev_priv, reg, temp);1124 1125 intel_de_posting_read(dev_priv, reg);1126 udelay(100);1127}1128 1129static const struct intel_fdi_funcs ilk_funcs = {1130 .fdi_link_train = ilk_fdi_link_train,1131};1132 1133static const struct intel_fdi_funcs gen6_funcs = {1134 .fdi_link_train = gen6_fdi_link_train,1135};1136 1137static const struct intel_fdi_funcs ivb_funcs = {1138 .fdi_link_train = ivb_manual_fdi_link_train,1139};1140 1141void1142intel_fdi_init_hook(struct drm_i915_private *dev_priv)1143{1144 if (IS_IRONLAKE(dev_priv)) {1145 dev_priv->display.funcs.fdi = &ilk_funcs;1146 } else if (IS_SANDYBRIDGE(dev_priv)) {1147 dev_priv->display.funcs.fdi = &gen6_funcs;1148 } else if (IS_IVYBRIDGE(dev_priv)) {1149 /* FIXME: detect B0+ stepping and use auto training */1150 dev_priv->display.funcs.fdi = &ivb_funcs;1151 }1152}1153