Commit bc079e8b authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Daniel Vetter

drm/i915: Make encoder cloning more flexible

Currently we allow encoders to indicate whether they can be part of a
cloned set with just one flag. That's not flexible enough to describe
the actual hardware capabilities. Instead make it a bitmask of encoder
types with which the current encoder can be cloned.

For now we set the bitmask to allow DVO+DVO and DVO+VGA, which should
match what the old boolean flag allowed. We will add some more cloning
options in the future.

Note that this patch also removes the encoder.possible_clones setting
from encoder setup code - we compute this dynamically.
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@gmail.com>
[danvet: Add Ville's explanation why removing the encoder
possible_clones is save.]
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 842f1c8b
...@@ -839,7 +839,7 @@ void intel_crt_init(struct drm_device *dev) ...@@ -839,7 +839,7 @@ void intel_crt_init(struct drm_device *dev)
intel_connector_attach_encoder(intel_connector, &crt->base); intel_connector_attach_encoder(intel_connector, &crt->base);
crt->base.type = INTEL_OUTPUT_ANALOG; crt->base.type = INTEL_OUTPUT_ANALOG;
crt->base.cloneable = true; crt->base.cloneable = 1 << INTEL_OUTPUT_DVO;
if (IS_I830(dev)) if (IS_I830(dev))
crt->base.crtc_mask = (1 << 0); crt->base.crtc_mask = (1 << 0);
else else
......
...@@ -1717,7 +1717,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) ...@@ -1717,7 +1717,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
intel_encoder->type = INTEL_OUTPUT_UNKNOWN; intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
intel_encoder->cloneable = false; intel_encoder->cloneable = 0;
intel_encoder->hot_plug = intel_ddi_hot_plug; intel_encoder->hot_plug = intel_ddi_hot_plug;
if (init_dp) if (init_dp)
......
...@@ -9221,23 +9221,47 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, ...@@ -9221,23 +9221,47 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide); DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide);
} }
static bool check_encoder_cloning(struct drm_crtc *crtc) static bool encoders_cloneable(const struct intel_encoder *a,
const struct intel_encoder *b)
{ {
int num_encoders = 0; /* masks could be asymmetric, so check both ways */
bool uncloneable_encoders = false; return a == b || (a->cloneable & (1 << b->type) &&
b->cloneable & (1 << a->type));
}
static bool check_single_encoder_cloning(struct intel_crtc *crtc,
struct intel_encoder *encoder)
{
struct drm_device *dev = crtc->base.dev;
struct intel_encoder *source_encoder;
list_for_each_entry(source_encoder,
&dev->mode_config.encoder_list, base.head) {
if (source_encoder->new_crtc != crtc)
continue;
if (!encoders_cloneable(encoder, source_encoder))
return false;
}
return true;
}
static bool check_encoder_cloning(struct intel_crtc *crtc)
{
struct drm_device *dev = crtc->base.dev;
struct intel_encoder *encoder; struct intel_encoder *encoder;
list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list, list_for_each_entry(encoder,
base.head) { &dev->mode_config.encoder_list, base.head) {
if (&encoder->new_crtc->base != crtc) if (encoder->new_crtc != crtc)
continue; continue;
num_encoders++; if (!check_single_encoder_cloning(crtc, encoder))
if (!encoder->cloneable) return false;
uncloneable_encoders = true;
} }
return !(num_encoders > 1 && uncloneable_encoders); return true;
} }
static struct intel_crtc_config * static struct intel_crtc_config *
...@@ -9251,7 +9275,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, ...@@ -9251,7 +9275,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
int plane_bpp, ret = -EINVAL; int plane_bpp, ret = -EINVAL;
bool retry = true; bool retry = true;
if (!check_encoder_cloning(crtc)) { if (!check_encoder_cloning(to_intel_crtc(crtc))) {
DRM_DEBUG_KMS("rejecting invalid cloning configuration\n"); DRM_DEBUG_KMS("rejecting invalid cloning configuration\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
...@@ -10614,12 +10638,7 @@ static int intel_encoder_clones(struct intel_encoder *encoder) ...@@ -10614,12 +10638,7 @@ static int intel_encoder_clones(struct intel_encoder *encoder)
list_for_each_entry(source_encoder, list_for_each_entry(source_encoder,
&dev->mode_config.encoder_list, base.head) { &dev->mode_config.encoder_list, base.head) {
if (encoders_cloneable(encoder, source_encoder))
if (encoder == source_encoder)
index_mask |= (1 << entry);
/* Intel hw has only one MUX where enocoders could be cloned. */
if (encoder->cloneable && source_encoder->cloneable)
index_mask |= (1 << entry); index_mask |= (1 << entry);
entry++; entry++;
......
...@@ -3980,7 +3980,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) ...@@ -3980,7 +3980,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
intel_encoder->cloneable = false; intel_encoder->cloneable = 0;
intel_encoder->hot_plug = intel_dp_hot_plug; intel_encoder->hot_plug = intel_dp_hot_plug;
if (!intel_dp_init_connector(intel_dig_port, intel_connector)) { if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
......
...@@ -125,11 +125,7 @@ struct intel_encoder { ...@@ -125,11 +125,7 @@ struct intel_encoder {
struct intel_crtc *new_crtc; struct intel_crtc *new_crtc;
int type; int type;
/* unsigned int cloneable;
* Intel hw has only one MUX where encoders could be clone, hence a
* simple flag is enough to compute the possible_clones mask.
*/
bool cloneable;
bool connectors_active; bool connectors_active;
void (*hot_plug)(struct intel_encoder *); void (*hot_plug)(struct intel_encoder *);
bool (*compute_config)(struct intel_encoder *, bool (*compute_config)(struct intel_encoder *,
......
...@@ -620,7 +620,7 @@ bool intel_dsi_init(struct drm_device *dev) ...@@ -620,7 +620,7 @@ bool intel_dsi_init(struct drm_device *dev)
intel_encoder->type = INTEL_OUTPUT_DSI; intel_encoder->type = INTEL_OUTPUT_DSI;
intel_encoder->crtc_mask = (1 << 0); /* XXX */ intel_encoder->crtc_mask = (1 << 0); /* XXX */
intel_encoder->cloneable = false; intel_encoder->cloneable = 0;
drm_connector_init(dev, connector, &intel_dsi_connector_funcs, drm_connector_init(dev, connector, &intel_dsi_connector_funcs,
DRM_MODE_CONNECTOR_DSI); DRM_MODE_CONNECTOR_DSI);
......
...@@ -522,14 +522,15 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -522,14 +522,15 @@ void intel_dvo_init(struct drm_device *dev)
intel_encoder->crtc_mask = (1 << 0) | (1 << 1); intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
switch (dvo->type) { switch (dvo->type) {
case INTEL_DVO_CHIP_TMDS: case INTEL_DVO_CHIP_TMDS:
intel_encoder->cloneable = true; intel_encoder->cloneable = (1 << INTEL_OUTPUT_ANALOG) |
(1 << INTEL_OUTPUT_DVO);
drm_connector_init(dev, connector, drm_connector_init(dev, connector,
&intel_dvo_connector_funcs, &intel_dvo_connector_funcs,
DRM_MODE_CONNECTOR_DVII); DRM_MODE_CONNECTOR_DVII);
encoder_type = DRM_MODE_ENCODER_TMDS; encoder_type = DRM_MODE_ENCODER_TMDS;
break; break;
case INTEL_DVO_CHIP_LVDS: case INTEL_DVO_CHIP_LVDS:
intel_encoder->cloneable = false; intel_encoder->cloneable = 0;
drm_connector_init(dev, connector, drm_connector_init(dev, connector,
&intel_dvo_connector_funcs, &intel_dvo_connector_funcs,
DRM_MODE_CONNECTOR_LVDS); DRM_MODE_CONNECTOR_LVDS);
......
...@@ -1318,7 +1318,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) ...@@ -1318,7 +1318,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
intel_encoder->type = INTEL_OUTPUT_HDMI; intel_encoder->type = INTEL_OUTPUT_HDMI;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
intel_encoder->cloneable = false; intel_encoder->cloneable = 0;
intel_dig_port->port = port; intel_dig_port->port = port;
intel_dig_port->hdmi.hdmi_reg = hdmi_reg; intel_dig_port->hdmi.hdmi_reg = hdmi_reg;
......
...@@ -963,7 +963,7 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -963,7 +963,7 @@ void intel_lvds_init(struct drm_device *dev)
intel_connector_attach_encoder(intel_connector, intel_encoder); intel_connector_attach_encoder(intel_connector, intel_encoder);
intel_encoder->type = INTEL_OUTPUT_LVDS; intel_encoder->type = INTEL_OUTPUT_LVDS;
intel_encoder->cloneable = false; intel_encoder->cloneable = 0;
if (HAS_PCH_SPLIT(dev)) if (HAS_PCH_SPLIT(dev))
intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
else if (IS_GEN4(dev)) else if (IS_GEN4(dev))
......
...@@ -3032,7 +3032,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) ...@@ -3032,7 +3032,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
* simplistic anyway to express such constraints, so just give up on * simplistic anyway to express such constraints, so just give up on
* cloning for SDVO encoders. * cloning for SDVO encoders.
*/ */
intel_sdvo->base.cloneable = false; intel_sdvo->base.cloneable = 0;
intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);
......
...@@ -1639,9 +1639,8 @@ intel_tv_init(struct drm_device *dev) ...@@ -1639,9 +1639,8 @@ intel_tv_init(struct drm_device *dev)
intel_connector_attach_encoder(intel_connector, intel_encoder); intel_connector_attach_encoder(intel_connector, intel_encoder);
intel_encoder->type = INTEL_OUTPUT_TVOUT; intel_encoder->type = INTEL_OUTPUT_TVOUT;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1); intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
intel_encoder->cloneable = false; intel_encoder->cloneable = 0;
intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1)); intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
intel_tv->type = DRM_MODE_CONNECTOR_Unknown; intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
/* BIOS margin values */ /* BIOS margin values */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment