| /* |
| * Copyright © 2014-2016 Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| * DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #include "intel_drv.h" |
| |
| void chv_set_phy_signal_level(struct intel_encoder *encoder, |
| u32 deemph_reg_value, u32 margin_reg_value, |
| bool uniq_trans_scale) |
| { |
| struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
| struct intel_crtc *intel_crtc = to_intel_crtc(dport->base.base.crtc); |
| enum dpio_channel ch = vlv_dport_to_channel(dport); |
| enum pipe pipe = intel_crtc->pipe; |
| u32 val; |
| int i; |
| |
| mutex_lock(&dev_priv->sb_lock); |
| |
| /* Clear calc init */ |
| val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); |
| val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); |
| val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); |
| val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; |
| vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val); |
| |
| if (intel_crtc->config->lane_count > 2) { |
| val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); |
| val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); |
| val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); |
| val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; |
| vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); |
| } |
| |
| val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW9(ch)); |
| val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); |
| val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; |
| vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW9(ch), val); |
| |
| if (intel_crtc->config->lane_count > 2) { |
| val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch)); |
| val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); |
| val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; |
| vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val); |
| } |
| |
| /* Program swing deemph */ |
| for (i = 0; i < intel_crtc->config->lane_count; i++) { |
| val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW4(ch, i)); |
| val &= ~DPIO_SWING_DEEMPH9P5_MASK; |
| val |= deemph_reg_value << DPIO_SWING_DEEMPH9P5_SHIFT; |
| vlv_dpio_write(dev_priv, pipe, CHV_TX_DW4(ch, i), val); |
| } |
| |
| /* Program swing margin */ |
| for (i = 0; i < intel_crtc->config->lane_count; i++) { |
| val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); |
| |
| val &= ~DPIO_SWING_MARGIN000_MASK; |
| val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT; |
| |
| /* |
| * Supposedly this value shouldn't matter when unique transition |
| * scale is disabled, but in fact it does matter. Let's just |
| * always program the same value and hope it's OK. |
| */ |
| val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT); |
| val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT; |
| |
| vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); |
| } |
| |
| /* |
| * The document said it needs to set bit 27 for ch0 and bit 26 |
| * for ch1. Might be a typo in the doc. |
| * For now, for this unique transition scale selection, set bit |
| * 27 for ch0 and ch1. |
| */ |
| for (i = 0; i < intel_crtc->config->lane_count; i++) { |
| val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i)); |
| if (uniq_trans_scale) |
| val |= DPIO_TX_UNIQ_TRANS_SCALE_EN; |
| else |
| val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN; |
| vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val); |
| } |
| |
| /* Start swing calculation */ |
| val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); |
| val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; |
| vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val); |
| |
| if (intel_crtc->config->lane_count > 2) { |
| val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); |
| val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; |
| vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); |
| } |
| |
| mutex_unlock(&dev_priv->sb_lock); |
| |
| } |
| |
| void chv_data_lane_soft_reset(struct intel_encoder *encoder, |
| bool reset) |
| { |
| struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base)); |
| struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
| enum pipe pipe = crtc->pipe; |
| uint32_t val; |
| |
| val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); |
| if (reset) |
| val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); |
| else |
| val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; |
| vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); |
| |
| if (crtc->config->lane_count > 2) { |
| val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); |
| if (reset) |
| val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); |
| else |
| val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; |
| vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); |
| } |
| |
| val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); |
| val |= CHV_PCS_REQ_SOFTRESET_EN; |
| if (reset) |
| val &= ~DPIO_PCS_CLK_SOFT_RESET; |
| else |
| val |= DPIO_PCS_CLK_SOFT_RESET; |
| vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); |
| |
| if (crtc->config->lane_count > 2) { |
| val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); |
| val |= CHV_PCS_REQ_SOFTRESET_EN; |
| if (reset) |
| val &= ~DPIO_PCS_CLK_SOFT_RESET; |
| else |
| val |= DPIO_PCS_CLK_SOFT_RESET; |
| vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); |
| } |
| } |