@@ -653,7 +653,8 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
intel_encoder = dev_priv->dig_port_map[port];
/* intel_encoder might be NULL for DP MST */
if (!intel_encoder || !intel_encoder->base.crtc ||
- intel_encoder->type != INTEL_OUTPUT_HDMI) {
+ !intel_crtc_has_type(to_intel_crtc(intel_encoder->base.crtc)->config,
+ INTEL_OUTPUT_HDMI)) {
DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
err = -ENODEV;
goto unlock;
@@ -301,8 +301,8 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = {
{ 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */
};
-static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv,
- u32 level, enum port port, int type);
+static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder,
+ u32 level);
static void ddi_get_encoder_port(struct intel_encoder *intel_encoder,
struct intel_digital_port **dig_port,
@@ -318,10 +318,8 @@ static void ddi_get_encoder_port(struct intel_encoder *intel_encoder,
default:
WARN(1, "Invalid DDI encoder type %d\n", intel_encoder->type);
/* fallthrough and treat as unknown */
- case INTEL_OUTPUT_DP:
+ case INTEL_OUTPUT_DDI:
case INTEL_OUTPUT_EDP:
- case INTEL_OUTPUT_HDMI:
- case INTEL_OUTPUT_UNKNOWN:
*dig_port = enc_to_dig_port(encoder);
*port = (*dig_port)->port;
break;
@@ -398,6 +396,7 @@ skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries)
void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
u32 iboost_bit = 0;
int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry,
size;
@@ -413,12 +412,9 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
if (IS_BROXTON(dev_priv)) {
- if (encoder->type != INTEL_OUTPUT_HDMI)
- return;
-
/* Vswing programming for HDMI */
- bxt_ddi_vswing_sequence(dev_priv, hdmi_level, port,
- INTEL_OUTPUT_HDMI);
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
+ bxt_ddi_vswing_sequence(encoder, hdmi_level);
return;
}
@@ -436,7 +432,7 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
dev_priv->vbt.ddi_port_info[port].dp_boost_level)
iboost_bit = 1<<31;
- if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP &&
+ if (WARN_ON(intel_crtc_has_type(crtc->config, INTEL_OUTPUT_EDP) &&
port != PORT_A && port != PORT_E &&
n_edp_entries > 9))
n_edp_entries = 9;
@@ -477,22 +473,20 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
hdmi_default_entry = 7;
}
- switch (encoder->type) {
- case INTEL_OUTPUT_EDP:
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_EDP)) {
ddi_translations = ddi_translations_edp;
size = n_edp_entries;
- break;
- case INTEL_OUTPUT_DP:
- case INTEL_OUTPUT_HDMI:
+ } else if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP) ||
+ intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
ddi_translations = ddi_translations_dp;
size = n_dp_entries;
- break;
- case INTEL_OUTPUT_ANALOG:
+ } else if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_ANALOG)) {
ddi_translations = ddi_translations_fdi;
size = n_dp_entries;
- break;
- default:
- BUG();
+ } else {
+ WARN(1, "Invalid encoder type 0x%x for pipe %c\n",
+ crtc->config->output_types, pipe_name(crtc->pipe));
+ return;
}
for (i = 0; i < size; i++) {
@@ -502,7 +496,7 @@ void intel_prepare_ddi_buffer(struct intel_encoder *encoder)
ddi_translations[i].trans2);
}
- if (encoder->type != INTEL_OUTPUT_HDMI)
+ if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
return;
/* Choose a good default if VBT is badly populated */
@@ -549,7 +543,7 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
u32 temp, i, rx_ctl_val;
for_each_encoder_on_crtc(dev, crtc, encoder) {
- WARN_ON(encoder->type != INTEL_OUTPUT_ANALOG);
+ WARN_ON(!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_ANALOG));
intel_prepare_ddi_buffer(encoder);
}
@@ -1063,12 +1057,10 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc)
{
struct drm_i915_private *dev_priv = crtc->dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
- int type = intel_encoder->type;
uint32_t temp;
- if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP_MST) {
+ if (intel_crtc_has_dp_encoder(intel_crtc->config)) {
WARN_ON(transcoder_is_dsi(cpu_transcoder));
temp = TRANS_MSA_SYNC_CLK;
@@ -1117,7 +1109,6 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
enum pipe pipe = intel_crtc->pipe;
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
enum port port = intel_ddi_get_encoder_port(intel_encoder);
- int type = intel_encoder->type;
uint32_t temp;
/* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */
@@ -1172,18 +1163,16 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
}
}
- if (type == INTEL_OUTPUT_HDMI) {
+ if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_HDMI)) {
if (intel_crtc->config->has_hdmi_sink)
temp |= TRANS_DDI_MODE_SELECT_HDMI;
else
temp |= TRANS_DDI_MODE_SELECT_DVI;
-
- } else if (type == INTEL_OUTPUT_ANALOG) {
+ } else if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_ANALOG)) {
temp |= TRANS_DDI_MODE_SELECT_FDI;
temp |= (intel_crtc->config->fdi_lanes - 1) << 1;
-
- } else if (type == INTEL_OUTPUT_DP ||
- type == INTEL_OUTPUT_EDP) {
+ } else if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP) ||
+ intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_EDP)) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
if (intel_dp->is_mst) {
@@ -1192,7 +1181,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
temp |= TRANS_DDI_MODE_SELECT_DP_SST;
temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
- } else if (type == INTEL_OUTPUT_DP_MST) {
+ } else if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST)) {
struct intel_dp *intel_dp = &enc_to_mst(encoder)->primary->dp;
if (intel_dp->is_mst) {
@@ -1202,8 +1191,8 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc)
temp |= DDI_PORT_WIDTH(intel_crtc->config->lane_count);
} else {
- WARN(1, "Invalid encoder type %d for pipe %c\n",
- intel_encoder->type, pipe_name(pipe));
+ WARN(1, "Invalid encoder type 0x%x for pipe %c\n",
+ intel_crtc->config->output_types, pipe_name(pipe));
}
I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), temp);
@@ -1371,9 +1360,13 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
TRANS_CLK_SEL_DISABLED);
}
-static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
- u32 level, enum port port, int type)
+static void skl_ddi_set_iboost(struct intel_encoder *encoder,
+ u32 level)
+
{
+ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum port port = enc_to_dig_port(&encoder->base)->port;
const struct ddi_buf_trans *ddi_translations;
uint8_t iboost;
uint8_t dp_iboost, hdmi_iboost;
@@ -1384,14 +1377,14 @@ static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
dp_iboost = dev_priv->vbt.ddi_port_info[port].dp_boost_level;
hdmi_iboost = dev_priv->vbt.ddi_port_info[port].hdmi_boost_level;
- if (type == INTEL_OUTPUT_DP) {
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
if (dp_iboost) {
iboost = dp_iboost;
} else {
ddi_translations = skl_get_buf_trans_dp(dev_priv, &n_entries);
iboost = ddi_translations[level].i_boost;
}
- } else if (type == INTEL_OUTPUT_EDP) {
+ } else if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_EDP)) {
if (dp_iboost) {
iboost = dp_iboost;
} else {
@@ -1403,7 +1396,7 @@ static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
iboost = ddi_translations[level].i_boost;
}
- } else if (type == INTEL_OUTPUT_HDMI) {
+ } else if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
if (hdmi_iboost) {
iboost = hdmi_iboost;
} else {
@@ -1432,32 +1425,38 @@ static void skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
I915_WRITE(DISPIO_CR_TX_BMU_CR0, reg);
}
-static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv,
- u32 level, enum port port, int type)
+static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder,
+ u32 level)
{
+ struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ enum port port = enc_to_dig_port(&encoder->base)->port;
+
const struct bxt_ddi_buf_trans *ddi_translations;
u32 n_entries, i;
uint32_t val;
- if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_EDP) &&
+ dev_priv->vbt.edp.low_vswing) {
n_entries = ARRAY_SIZE(bxt_ddi_translations_edp);
ddi_translations = bxt_ddi_translations_edp;
- } else if (type == INTEL_OUTPUT_DP
- || type == INTEL_OUTPUT_EDP) {
+ } else if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP) ||
+ intel_crtc_has_type(crtc->config, INTEL_OUTPUT_EDP)) {
n_entries = ARRAY_SIZE(bxt_ddi_translations_dp);
ddi_translations = bxt_ddi_translations_dp;
- } else if (type == INTEL_OUTPUT_HDMI) {
+ } else if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
n_entries = ARRAY_SIZE(bxt_ddi_translations_hdmi);
ddi_translations = bxt_ddi_translations_hdmi;
} else {
- DRM_DEBUG_KMS("Vswing programming not done for encoder %d\n",
- type);
+ DRM_DEBUG_KMS("Vswing programming not done for encoder 0x%x\n",
+ crtc->config->output_types);
return;
}
/* Check if default value has to be used */
if (level >= n_entries ||
- (type == INTEL_OUTPUT_HDMI && level == HDMI_LEVEL_SHIFT_UNKNOWN)) {
+ (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI) &&
+ level == HDMI_LEVEL_SHIFT_UNKNOWN)) {
for (i = 0; i < n_entries; i++) {
if (ddi_translations[i].default_index) {
level = i;
@@ -1548,21 +1547,19 @@ static uint32_t translate_signal_level(int signal_levels)
uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
{
- struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
- struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
- struct intel_encoder *encoder = &dport->base;
+ struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
uint8_t train_set = intel_dp->train_set[0];
int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
DP_TRAIN_PRE_EMPHASIS_MASK);
- enum port port = dport->port;
uint32_t level;
level = translate_signal_level(signal_levels);
if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
- skl_ddi_set_iboost(dev_priv, level, port, encoder->type);
+ skl_ddi_set_iboost(encoder, level);
else if (IS_BROXTON(dev_priv))
- bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type);
+ bxt_ddi_vswing_sequence(encoder, level);
return DDI_BUF_TRANS_SELECT(level);
}
@@ -1599,9 +1596,8 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
struct drm_i915_private *dev_priv = to_i915(encoder->dev);
struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
enum port port = intel_ddi_get_encoder_port(intel_encoder);
- int type = intel_encoder->type;
- if (type == INTEL_OUTPUT_HDMI) {
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
@@ -1609,14 +1605,15 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
intel_prepare_ddi_buffer(intel_encoder);
- if (type == INTEL_OUTPUT_EDP) {
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_EDP)) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_edp_panel_on(intel_dp);
}
intel_ddi_clk_select(intel_encoder, crtc->config);
- if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP) ||
+ intel_crtc_has_type(crtc->config, INTEL_OUTPUT_EDP)) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_dp_set_link_params(intel_dp, crtc->config);
@@ -1627,7 +1624,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
intel_dp_start_link_train(intel_dp);
if (port != PORT_A || INTEL_INFO(dev_priv)->gen >= 9)
intel_dp_stop_link_train(intel_dp);
- } else if (type == INTEL_OUTPUT_HDMI) {
+ } else if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
intel_hdmi->set_infoframes(encoder,
@@ -1639,10 +1636,10 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
{
struct drm_encoder *encoder = &intel_encoder->base;
+ struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = intel_ddi_get_encoder_port(intel_encoder);
- int type = intel_encoder->type;
uint32_t val;
bool wait = false;
@@ -1661,7 +1658,8 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
if (wait)
intel_wait_ddi_buf_idle(dev_priv, port);
- if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP) ||
+ intel_crtc_has_type(crtc->config, INTEL_OUTPUT_EDP)) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
intel_edp_panel_vdd_on(intel_dp);
@@ -1674,7 +1672,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder)
else if (INTEL_INFO(dev)->gen < 9)
I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
- if (type == INTEL_OUTPUT_HDMI) {
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
@@ -1689,9 +1687,8 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = intel_ddi_get_encoder_port(intel_encoder);
- int type = intel_encoder->type;
- if (type == INTEL_OUTPUT_HDMI) {
+ if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_HDMI)) {
struct intel_digital_port *intel_dig_port =
enc_to_dig_port(encoder);
@@ -1702,7 +1699,7 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder)
I915_WRITE(DDI_BUF_CTL(port),
intel_dig_port->saved_port_bits |
DDI_BUF_CTL_ENABLE);
- } else if (type == INTEL_OUTPUT_EDP) {
+ } else if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_EDP)) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
if (port == PORT_A && INTEL_INFO(dev)->gen < 9)
@@ -1724,7 +1721,6 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
struct drm_encoder *encoder = &intel_encoder->base;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int type = intel_encoder->type;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1733,7 +1729,7 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder)
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
}
- if (type == INTEL_OUTPUT_EDP) {
+ if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_EDP)) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
intel_edp_drrs_disable(intel_dp);
@@ -2157,6 +2153,26 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
return;
temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+
+ switch (temp & TRANS_DDI_MODE_SELECT_MASK) {
+ case TRANS_DDI_MODE_SELECT_HDMI:
+ case TRANS_DDI_MODE_SELECT_DVI:
+ pipe_config->output_types |= 1 << INTEL_OUTPUT_HDMI;
+ break;
+ case TRANS_DDI_MODE_SELECT_DP_SST:
+ if (encoder->type == INTEL_OUTPUT_EDP)
+ pipe_config->output_types |= 1 << INTEL_OUTPUT_EDP;
+ else
+ pipe_config->output_types |= 1 << INTEL_OUTPUT_DP;
+ break;
+ case TRANS_DDI_MODE_SELECT_FDI:
+ WARN_ON(pipe_config->output_types != 1 << INTEL_OUTPUT_ANALOG);
+ break;
+ default:
+ MISSING_CASE(pipe_config->output_types);
+ break;
+ }
+
if (temp & TRANS_DDI_PHSYNC)
flags |= DRM_MODE_FLAG_PHSYNC;
else
@@ -2214,7 +2230,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
pipe_config->has_audio = true;
}
- if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.bpp &&
+ if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_EDP) &&
+ dev_priv->vbt.edp.bpp &&
pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) {
/*
* This is a big fat ugly hack.
@@ -2237,18 +2254,54 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
intel_ddi_clock_get(encoder, pipe_config);
}
+static enum intel_output_type
+intel_ddi_compute_output_type(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state)
+{
+ struct drm_atomic_state *state = crtc_state->base.state;
+ struct drm_crtc *crtc = crtc_state->base.crtc;
+ struct drm_connector *connector;
+ struct drm_connector_state *connector_state;
+ int i;
+
+ for_each_connector_in_state(state, connector, connector_state, i) {
+ if (connector_state->crtc != crtc)
+ continue;
+
+ if (connector_state->best_encoder != &encoder->base)
+ continue;
+
+ switch (connector->connector_type) {
+ case DRM_MODE_CONNECTOR_HDMIA:
+ return INTEL_OUTPUT_HDMI;
+ case DRM_MODE_CONNECTOR_eDP:
+ return INTEL_OUTPUT_EDP;
+ case DRM_MODE_CONNECTOR_DisplayPort:
+ return INTEL_OUTPUT_DP;
+ default:
+ MISSING_CASE(connector->connector_type);
+ break;
+ }
+ }
+
+ return INTEL_OUTPUT_UNUSED;
+}
+
static bool intel_ddi_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
- int type = encoder->type;
- int port = intel_ddi_get_encoder_port(encoder);
+ enum port port = intel_ddi_get_encoder_port(encoder);
- WARN(type == INTEL_OUTPUT_UNKNOWN, "compute_config() on unknown output!\n");
+ WARN(pipe_config->output_types == 0 ||
+ pipe_config->output_types & ~(1 << INTEL_OUTPUT_EDP |
+ 1 << INTEL_OUTPUT_DP |
+ 1 << INTEL_OUTPUT_HDMI),
+ "Bad output_types = 0x%x\n", pipe_config->output_types);
if (port == PORT_A)
pipe_config->cpu_transcoder = TRANSCODER_EDP;
- if (type == INTEL_OUTPUT_HDMI)
+ if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI))
return intel_hdmi_compute_config(encoder, pipe_config);
else
return intel_dp_compute_config(encoder, pipe_config);
@@ -2348,6 +2401,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
drm_encoder_init(dev, encoder, &intel_ddi_funcs,
DRM_MODE_ENCODER_TMDS, "DDI %c", port_name(port));
+ intel_encoder->compute_output_type = intel_ddi_compute_output_type;
intel_encoder->compute_config = intel_ddi_compute_config;
intel_encoder->enable = intel_enable_ddi;
intel_encoder->pre_enable = intel_ddi_pre_enable;
@@ -2379,7 +2433,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
intel_dig_port->max_lanes = max_lanes;
- intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
+ intel_encoder->type = INTEL_OUTPUT_DDI;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
intel_encoder->cloneable = 0;
@@ -5113,7 +5113,7 @@ intel_display_port_power_domain(struct intel_encoder *intel_encoder)
struct intel_digital_port *intel_dig_port;
switch (intel_encoder->type) {
- case INTEL_OUTPUT_UNKNOWN:
+ case INTEL_OUTPUT_DDI:
/* Only DDI platforms should ever use this output type */
WARN_ON_ONCE(!HAS_DDI(dev));
case INTEL_OUTPUT_DP:
@@ -5140,15 +5140,8 @@ intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder)
struct intel_digital_port *intel_dig_port;
switch (intel_encoder->type) {
- case INTEL_OUTPUT_UNKNOWN:
- case INTEL_OUTPUT_HDMI:
- /*
- * Only DDI platforms should ever use these output types.
- * We can get here after the HDMI detect code has already set
- * the type of the shared encoder. Since we can't be sure
- * what's the status of the given connectors, play safe and
- * run the DP detection too.
- */
+ case INTEL_OUTPUT_DDI:
+ /* Only DDI platforms should ever use this output type */
WARN_ON_ONCE(!HAS_DDI(dev));
case INTEL_OUTPUT_DP:
case INTEL_OUTPUT_EDP:
@@ -12341,7 +12334,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
switch (encoder->type) {
unsigned int port_mask;
- case INTEL_OUTPUT_UNKNOWN:
+ case INTEL_OUTPUT_DDI:
if (WARN_ON(!HAS_DDI(dev)))
break;
case INTEL_OUTPUT_DP:
@@ -12447,6 +12440,8 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
encoder = to_intel_encoder(connector_state->best_encoder);
+ DRM_DEBUG_KMS("Using encoder %s\n", encoder->base.name);
+
if (!check_single_encoder_cloning(state, to_intel_crtc(crtc), encoder)) {
DRM_DEBUG_KMS("rejecting invalid cloning configuration\n");
goto fail;
@@ -12456,7 +12451,11 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
* Determine output_types before calling the .compute_config()
* hooks so that the hooks can use this information safely.
*/
- pipe_config->output_types |= 1 << encoder->type;
+ if (encoder->compute_output_type)
+ pipe_config->output_types |=
+ 1 << encoder->compute_output_type(encoder, pipe_config);
+ else
+ pipe_config->output_types |= 1 << encoder->type;
}
encoder_retry:
@@ -13023,7 +13022,12 @@ verify_crtc_state(struct drm_crtc *crtc,
pipe_name(pipe));
if (active) {
- pipe_config->output_types |= 1 << encoder->type;
+ /*
+ * .get_config() is responsible for this if the
+ * encoder has multiple personalities
+ */
+ if (!encoder->compute_output_type)
+ pipe_config->output_types |= 1 << encoder->type;
encoder->get_config(encoder, pipe_config);
}
}
@@ -15916,7 +15920,12 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
if (encoder->get_hw_state(encoder, &pipe)) {
crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
encoder->base.crtc = &crtc->base;
- crtc->config->output_types |= 1 << encoder->type;
+ /*
+ * .get_config() is responsible for this if the
+ * encoder has multiple personalities
+ */
+ if (!encoder->compute_output_type)
+ crtc->config->output_types |= 1 << encoder->type;
encoder->get_config(encoder, crtc->config);
} else {
encoder->base.crtc = NULL;
@@ -4200,9 +4200,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
goto out;
}
- if (intel_encoder->type != INTEL_OUTPUT_EDP)
- intel_encoder->type = INTEL_OUTPUT_DP;
-
intel_dp_probe_oui(intel_dp);
ret = intel_dp_probe_mst(intel_dp);
@@ -4266,8 +4263,6 @@ static enum drm_connector_status
intel_dp_detect(struct drm_connector *connector, bool force)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
- struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- struct intel_encoder *intel_encoder = &intel_dig_port->base;
struct intel_connector *intel_connector = to_intel_connector(connector);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
@@ -4276,8 +4271,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)
if (intel_dp->is_mst) {
/* MST devices are disconnected from a monitor POV */
intel_dp_unset_edid(intel_dp);
- if (intel_encoder->type != INTEL_OUTPUT_EDP)
- intel_encoder->type = INTEL_OUTPUT_DP;
return connector_status_disconnected;
}
@@ -4314,9 +4307,6 @@ intel_dp_force(struct drm_connector *connector)
intel_dp_set_edid(intel_dp);
intel_display_power_put(dev_priv, power_domain);
-
- if (intel_encoder->type != INTEL_OUTPUT_EDP)
- intel_encoder->type = INTEL_OUTPUT_DP;
}
static int intel_dp_get_modes(struct drm_connector *connector)
@@ -4595,10 +4585,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
enum intel_display_power_domain power_domain;
enum irqreturn ret = IRQ_NONE;
- if (intel_dig_port->base.type != INTEL_OUTPUT_EDP &&
- intel_dig_port->base.type != INTEL_OUTPUT_HDMI)
- intel_dig_port->base.type = INTEL_OUTPUT_DP;
-
if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) {
/*
* vdd off can generate a long pulse on eDP which
@@ -5455,7 +5441,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
/*
* For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but
* for DP the encoder type can be set by the caller to
- * INTEL_OUTPUT_UNKNOWN for DDI, so don't rewrite it.
+ * INTEL_OUTPUT_DDI, so don't rewrite it.
*/
if (type == DRM_MODE_CONNECTOR_eDP)
intel_encoder->type = INTEL_OUTPUT_EDP;
@@ -698,7 +698,7 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
memset(&crtc_state->dpll_hw_state, 0,
sizeof(crtc_state->dpll_hw_state));
- if (encoder->type == INTEL_OUTPUT_HDMI) {
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
uint32_t val;
unsigned p, n2, r2;
@@ -713,9 +713,7 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
pll = intel_find_shared_dpll(crtc, crtc_state,
DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
- } else if (encoder->type == INTEL_OUTPUT_DP ||
- encoder->type == INTEL_OUTPUT_DP_MST ||
- encoder->type == INTEL_OUTPUT_EDP) {
+ } else if (intel_crtc_has_dp_encoder(crtc_state)) {
enum intel_dpll_id pll_id;
switch (clock / 2) {
@@ -735,7 +733,7 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
- } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
+ } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
if (WARN_ON(crtc_state->port_clock / 2 != 135000))
return NULL;
@@ -1205,7 +1203,7 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
ctrl1 = DPLL_CTRL1_OVERRIDE(0);
- if (encoder->type == INTEL_OUTPUT_HDMI) {
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
struct skl_wrpll_params wrpll_params = { 0, };
ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
@@ -1222,9 +1220,7 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
wrpll_params.central_freq;
- } else if (encoder->type == INTEL_OUTPUT_DP ||
- encoder->type == INTEL_OUTPUT_DP_MST ||
- encoder->type == INTEL_OUTPUT_EDP) {
+ } else if (intel_crtc_has_dp_encoder(crtc_state)) {
switch (crtc_state->port_clock / 2) {
case 81000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
@@ -1259,7 +1255,7 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
- if (encoder->type == INTEL_OUTPUT_EDP)
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
pll = intel_find_shared_dpll(crtc, crtc_state,
DPLL_ID_SKL_DPLL0,
DPLL_ID_SKL_DPLL0);
@@ -1507,7 +1503,7 @@ bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
uint32_t lanestagger;
int clock = crtc_state->port_clock;
- if (encoder->type == INTEL_OUTPUT_HDMI) {
+ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
struct dpll best_clock;
/* Calculate HDMI div */
@@ -1530,8 +1526,7 @@ bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
clk_div.m2_frac_en = clk_div.m2_frac != 0;
vco = best_clock.vco;
- } else if (encoder->type == INTEL_OUTPUT_DP ||
- encoder->type == INTEL_OUTPUT_EDP) {
+ } else if (intel_crtc_has_dp_encoder(crtc_state)) {
int i;
clk_div = bxt_dp_clk_val[0];
@@ -138,7 +138,7 @@ enum intel_output_type {
INTEL_OUTPUT_DP = 7,
INTEL_OUTPUT_EDP = 8,
INTEL_OUTPUT_DSI = 9,
- INTEL_OUTPUT_UNKNOWN = 10,
+ INTEL_OUTPUT_DDI = 10,
INTEL_OUTPUT_DP_MST = 11,
};
@@ -168,6 +168,8 @@ struct intel_encoder {
enum intel_output_type type;
unsigned int cloneable;
void (*hot_plug)(struct intel_encoder *);
+ enum intel_output_type (*compute_output_type)(struct intel_encoder *,
+ struct intel_crtc_state *);
bool (*compute_config)(struct intel_encoder *,
struct intel_crtc_state *);
void (*pre_pll_enable)(struct intel_encoder *);
@@ -1495,12 +1495,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
intel_hdmi_unset_edid(connector);
- if (intel_hdmi_set_edid(connector, live_status)) {
- struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-
- hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
+ if (intel_hdmi_set_edid(connector, live_status))
status = connector_status_connected;
- } else
+ else
status = connector_status_disconnected;
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
@@ -1511,8 +1508,6 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
static void
intel_hdmi_force(struct drm_connector *connector)
{
- struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
-
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
@@ -1522,7 +1517,6 @@ intel_hdmi_force(struct drm_connector *connector)
return;
intel_hdmi_set_edid(connector, true);
- hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;
}
static int intel_hdmi_get_modes(struct drm_connector *connector)
@@ -365,7 +365,7 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
case INTEL_OUTPUT_ANALOG:
type = DISPLAY_TYPE_CRT;
break;
- case INTEL_OUTPUT_UNKNOWN:
+ case INTEL_OUTPUT_DDI:
case INTEL_OUTPUT_DP:
case INTEL_OUTPUT_HDMI:
case INTEL_OUTPUT_DP_MST: