@@ -3135,17 +3135,22 @@ static void intel_ddi_enable_fec(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum port port = encoder->port;
+ i915_reg_t ctl, status;
u32 val;
if (!crtc_state->fec_enable)
return;
- val = I915_READ(DP_TP_CTL(port));
+ ctl = intel_dp_tp_ctl_reg(dev_priv, cpu_transcoder, port);
+ status = intel_dp_tp_status_reg(dev_priv, cpu_transcoder, port);
+
+ val = I915_READ(ctl);
val |= DP_TP_CTL_FEC_ENABLE;
- I915_WRITE(DP_TP_CTL(port), val);
+ I915_WRITE(ctl, val);
- if (intel_wait_for_register(&dev_priv->uncore, DP_TP_STATUS(port),
+ if (intel_wait_for_register(&dev_priv->uncore, status,
DP_TP_STATUS_FEC_ENABLE_LIVE,
DP_TP_STATUS_FEC_ENABLE_LIVE,
1))
@@ -3156,16 +3161,19 @@ static void intel_ddi_disable_fec_state(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum port port = encoder->port;
+ i915_reg_t ctl;
u32 val;
if (!crtc_state->fec_enable)
return;
- val = I915_READ(DP_TP_CTL(port));
+ ctl = intel_dp_tp_ctl_reg(dev_priv, cpu_transcoder, port);
+ val = I915_READ(ctl);
val &= ~DP_TP_CTL_FEC_ENABLE;
- I915_WRITE(DP_TP_CTL(port), val);
- POSTING_READ(DP_TP_CTL(port));
+ I915_WRITE(ctl, val);
+ POSTING_READ(ctl);
}
static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
@@ -3327,7 +3335,9 @@ static void intel_disable_ddi_buf(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum port port = encoder->port;
+ i915_reg_t ctl;
bool wait = false;
u32 val;
@@ -3338,10 +3348,11 @@ static void intel_disable_ddi_buf(struct intel_encoder *encoder,
wait = true;
}
- val = I915_READ(DP_TP_CTL(port));
+ ctl = intel_dp_tp_ctl_reg(dev_priv, cpu_transcoder, port);
+ val = I915_READ(ctl);
val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
val |= DP_TP_CTL_LINK_TRAIN_PAT1;
- I915_WRITE(DP_TP_CTL(port), val);
+ I915_WRITE(ctl, val);
/* Disable FEC in DP Sink */
intel_ddi_disable_fec_state(encoder, crtc_state);
@@ -3766,10 +3777,13 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv =
to_i915(intel_dig_port->base.base.dev);
enum port port = intel_dig_port->base.port;
+ i915_reg_t ctl;
u32 val;
bool wait = false;
+ enum transcoder cpu_transcoder = intel_dp_get_transcoder(intel_dp);
- if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) {
+ ctl = intel_dp_tp_ctl_reg(dev_priv, cpu_transcoder, port);
+ if (I915_READ(ctl) & DP_TP_CTL_ENABLE) {
val = I915_READ(DDI_BUF_CTL(port));
if (val & DDI_BUF_CTL_ENABLE) {
val &= ~DDI_BUF_CTL_ENABLE;
@@ -3777,11 +3791,11 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
wait = true;
}
- val = I915_READ(DP_TP_CTL(port));
+ val = I915_READ(ctl);
val &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
val |= DP_TP_CTL_LINK_TRAIN_PAT1;
- I915_WRITE(DP_TP_CTL(port), val);
- POSTING_READ(DP_TP_CTL(port));
+ I915_WRITE(ctl, val);
+ POSTING_READ(ctl);
if (wait)
intel_wait_ddi_buf_idle(dev_priv, port);
@@ -3796,8 +3810,8 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
val |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
}
- I915_WRITE(DP_TP_CTL(port), val);
- POSTING_READ(DP_TP_CTL(port));
+ I915_WRITE(ctl, val);
+ POSTING_READ(ctl);
intel_dp->DP |= DDI_BUF_CTL_ENABLE;
I915_WRITE(DDI_BUF_CTL(port), intel_dp->DP);
@@ -1213,6 +1213,7 @@ struct intel_dp {
bool can_mst; /* this port supports mst */
bool is_mst;
int active_mst_links;
+ enum transcoder mst_master_trans; /* Only valid on TGL+ */
/* connector directly attached - won't be use for modeset in mst world */
struct intel_connector *attached_connector;
@@ -3206,6 +3206,51 @@ static void chv_post_disable_dp(struct intel_encoder *encoder,
vlv_dpio_put(dev_priv);
}
+i915_reg_t intel_dp_tp_ctl_reg(const struct drm_i915_private *dev_priv,
+ enum transcoder cpu_transcoder,
+ enum port port)
+{
+ if (INTEL_GEN(dev_priv) >= 12) {
+ WARN_ON(cpu_transcoder == TRANSCODER_INVALID);
+ return TGL_DP_TP_CTL(cpu_transcoder);
+ } else {
+ return DP_TP_CTL(port);
+ }
+}
+
+i915_reg_t intel_dp_tp_status_reg(const struct drm_i915_private *dev_priv,
+ enum transcoder cpu_transcoder,
+ enum port port)
+{
+ if (INTEL_GEN(dev_priv) >= 12) {
+ WARN_ON(cpu_transcoder == TRANSCODER_INVALID);
+ return TGL_DP_TP_STATUS(cpu_transcoder);
+ } else {
+ return DP_TP_STATUS(port);
+ }
+}
+
+/*
+ * Return the transcoder that this intel_dp port is driven.
+ * When in MST mode it will return the master transcoder of the MST so do not
+ * use it when reading or writing registers in the slave transcoders.
+ */
+enum transcoder intel_dp_get_transcoder(struct intel_dp *intel_dp)
+{
+ struct intel_connector *connector;
+ struct drm_connector_state *conn_state;
+ struct intel_crtc_state *crtc_state;
+
+ if (intel_dp->is_mst)
+ return intel_dp->mst_master_trans;
+
+ connector = intel_dp->attached_connector;
+ conn_state = connector->base.state;
+ crtc_state = to_intel_crtc_state(conn_state->crtc->state);
+
+ return crtc_state->cpu_transcoder;
+}
+
static void
_intel_dp_set_link_train(struct intel_dp *intel_dp,
u32 *DP,
@@ -3221,8 +3266,13 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,
dp_train_pat & train_pat_mask);
if (HAS_DDI(dev_priv)) {
- u32 temp = I915_READ(DP_TP_CTL(port));
+ enum transcoder cpu_transcoder;
+ i915_reg_t ctl;
+ u32 temp;
+ cpu_transcoder = intel_dp_get_transcoder(intel_dp);
+ ctl = intel_dp_tp_ctl_reg(dev_priv, cpu_transcoder, port);
+ temp = I915_READ(ctl);
if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
else
@@ -3247,7 +3297,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp,
temp |= DP_TP_CTL_LINK_TRAIN_PAT4;
break;
}
- I915_WRITE(DP_TP_CTL(port), temp);
+ I915_WRITE(ctl, temp);
} else if ((IS_IVYBRIDGE(dev_priv) && port == PORT_A) ||
(HAS_PCH_CPT(dev_priv) && port != PORT_A)) {
@@ -3940,15 +3990,21 @@ void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
enum port port = intel_dig_port->base.port;
+ enum transcoder cpu_transcoder;
+ i915_reg_t ctl, status;
u32 val;
if (!HAS_DDI(dev_priv))
return;
- val = I915_READ(DP_TP_CTL(port));
+ cpu_transcoder = intel_dp_get_transcoder(intel_dp);
+ ctl = intel_dp_tp_ctl_reg(dev_priv, cpu_transcoder, port);
+ status = intel_dp_tp_status_reg(dev_priv, cpu_transcoder, port);
+
+ val = I915_READ(ctl);
val &= ~DP_TP_CTL_LINK_TRAIN_MASK;
val |= DP_TP_CTL_LINK_TRAIN_IDLE;
- I915_WRITE(DP_TP_CTL(port), val);
+ I915_WRITE(ctl, val);
/*
* On PORT_A we can have only eDP in SST mode. There the only reason
@@ -3960,7 +4016,7 @@ void intel_dp_set_idle_link_train(struct intel_dp *intel_dp)
if (port == PORT_A)
return;
- if (intel_wait_for_register(&dev_priv->uncore, DP_TP_STATUS(port),
+ if (intel_wait_for_register(&dev_priv->uncore, status,
DP_TP_STATUS_IDLE_DONE,
DP_TP_STATUS_IDLE_DONE,
1))
@@ -11,6 +11,7 @@
#include <drm/i915_drm.h>
#include "i915_reg.h"
+#include "intel_display.h"
enum pipe;
struct drm_connector_state;
@@ -113,6 +114,14 @@ int intel_dp_link_required(int pixel_clock, int bpp);
int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
bool intel_digital_port_connected(struct intel_encoder *encoder);
+i915_reg_t intel_dp_tp_ctl_reg(const struct drm_i915_private *dev_priv,
+ enum transcoder cpu_transcoder,
+ enum port port);
+i915_reg_t intel_dp_tp_status_reg(const struct drm_i915_private *dev_priv,
+ enum transcoder cpu_transcoder,
+ enum port port);
+enum transcoder intel_dp_get_transcoder(struct intel_dp *intel_dp);
+
static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
{
return ~((1 << lane_count) - 1) & 0xf;
@@ -354,9 +354,11 @@ static void intel_mst_pre_pll_enable_dp(struct intel_encoder *encoder,
struct intel_digital_port *intel_dig_port = intel_mst->primary;
struct intel_dp *intel_dp = &intel_dig_port->dp;
- if (intel_dp->active_mst_links == 0)
+ if (intel_dp->active_mst_links == 0) {
+ intel_dp->mst_master_trans = pipe_config->mst_master_trans;
intel_dig_port->base.pre_pll_enable(&intel_dig_port->base,
pipe_config, NULL);
+ }
}
static void intel_mst_post_pll_disable_dp(struct intel_encoder *encoder,
@@ -384,6 +386,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder,
enum port port = intel_dig_port->base.port;
struct intel_connector *connector =
to_intel_connector(conn_state->connector);
+ i915_reg_t status;
int ret;
u32 temp;
@@ -412,8 +415,12 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder,
DRM_ERROR("failed to allocate vcpi\n");
intel_dp->active_mst_links++;
- temp = I915_READ(DP_TP_STATUS(port));
- I915_WRITE(DP_TP_STATUS(port), temp);
+
+ status = intel_dp_tp_status_reg(dev_priv,
+ pipe_config->mst_master_trans,
+ port);
+ temp = I915_READ(status);
+ I915_WRITE(status, temp);
ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr);
@@ -429,11 +436,16 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder,
struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
enum port port = intel_dig_port->base.port;
+ i915_reg_t status;
DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links);
+ status = intel_dp_tp_status_reg(dev_priv,
+ pipe_config->mst_master_trans,
+ port);
+
if (intel_wait_for_register(&dev_priv->uncore,
- DP_TP_STATUS(port),
+ status,
DP_TP_STATUS_ACT_SENT,
DP_TP_STATUS_ACT_SENT,
1))
@@ -9517,7 +9517,9 @@ enum skl_power_gate {
/* DisplayPort Transport Control */
#define _DP_TP_CTL_A 0x64040
#define _DP_TP_CTL_B 0x64140
+#define _TGL_DP_TP_CTL_A 0x60540
#define DP_TP_CTL(port) _MMIO_PORT(port, _DP_TP_CTL_A, _DP_TP_CTL_B)
+#define TGL_DP_TP_CTL(tran) _MMIO_TRANS2((tran), _TGL_DP_TP_CTL_A)
#define DP_TP_CTL_ENABLE (1 << 31)
#define DP_TP_CTL_FEC_ENABLE (1 << 30)
#define DP_TP_CTL_MODE_SST (0 << 27)
@@ -9537,7 +9539,9 @@ enum skl_power_gate {
/* DisplayPort Transport Status */
#define _DP_TP_STATUS_A 0x64044
#define _DP_TP_STATUS_B 0x64144
+#define _TGL_DP_TP_STATUS_A 0x60544
#define DP_TP_STATUS(port) _MMIO_PORT(port, _DP_TP_STATUS_A, _DP_TP_STATUS_B)
+#define TGL_DP_TP_STATUS(tran) _MMIO_TRANS2((tran), _TGL_DP_TP_STATUS_A)
#define DP_TP_STATUS_FEC_ENABLE_LIVE (1 << 28)
#define DP_TP_STATUS_IDLE_DONE (1 << 25)
#define DP_TP_STATUS_ACT_SENT (1 << 24)
Gen 12 onwards moves the DP_TP_* registers to be transcoder-based rather than port-based. This add the new register address and changes the functions that are used with DDI on gen 12 to use the new registers. On MST the master transcoder is the one to be used. Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com> --- drivers/gpu/drm/i915/display/intel_ddi.c | 42 ++++++++---- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_dp.c | 66 +++++++++++++++++-- drivers/gpu/drm/i915/display/intel_dp.h | 9 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 20 ++++-- drivers/gpu/drm/i915/i915_reg.h | 4 ++ 6 files changed, 119 insertions(+), 23 deletions(-)