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: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com> [danvet: Add Ville's explanation why removing the encoder possible_clones is save.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
842f1c8b76
commit
bc079e8b16
|
@ -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)
|
||||||
|
|
||||||
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,
|
||||||
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) &&
|
||||||
struct intel_encoder *encoder;
|
b->cloneable & (1 << a->type));
|
||||||
|
}
|
||||||
|
|
||||||
list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list,
|
static bool check_single_encoder_cloning(struct intel_crtc *crtc,
|
||||||
base.head) {
|
struct intel_encoder *encoder)
|
||||||
if (&encoder->new_crtc->base != crtc)
|
{
|
||||||
|
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;
|
continue;
|
||||||
|
|
||||||
num_encoders++;
|
if (!encoders_cloneable(encoder, source_encoder))
|
||||||
if (!encoder->cloneable)
|
return false;
|
||||||
uncloneable_encoders = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return !(num_encoders > 1 && uncloneable_encoders);
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool check_encoder_cloning(struct intel_crtc *crtc)
|
||||||
|
{
|
||||||
|
struct drm_device *dev = crtc->base.dev;
|
||||||
|
struct intel_encoder *encoder;
|
||||||
|
|
||||||
|
list_for_each_entry(encoder,
|
||||||
|
&dev->mode_config.encoder_list, base.head) {
|
||||||
|
if (encoder->new_crtc != crtc)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!check_single_encoder_cloning(crtc, encoder))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct intel_crtc_config *
|
static struct intel_crtc_config *
|
||||||
|
@ -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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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 {
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
* 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)
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in New Issue