2016-04-27 20:44:17 +08:00
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-04-27 20:44:18 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|