Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -839,7 +839,7 @@ void intel_crt_init(struct drm_device *dev)
	intel_connector_attach_encoder(intel_connector, &crt->base);

	crt->base.type = INTEL_OUTPUT_ANALOG;
	crt->base.cloneable = true;
	crt->base.cloneable = 1 << INTEL_OUTPUT_DVO;
	if (IS_I830(dev))
		crt->base.crtc_mask = (1 << 0);
	else
+1 −1
Original line number Diff line number Diff line
@@ -1717,7 +1717,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)

	intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
	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;

	if (init_dp)
+36 −17
Original line number Diff line number Diff line
@@ -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);
}

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;
	bool uncloneable_encoders = false;
	/* masks could be asymmetric, so check both ways */
	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;

	list_for_each_entry(encoder, &crtc->dev->mode_config.encoder_list,
			    base.head) {
		if (&encoder->new_crtc->base != crtc)
	list_for_each_entry(encoder,
			    &dev->mode_config.encoder_list, base.head) {
		if (encoder->new_crtc != crtc)
			continue;

		num_encoders++;
		if (!encoder->cloneable)
			uncloneable_encoders = true;
		if (!check_single_encoder_cloning(crtc, encoder))
			return false;
	}

	return !(num_encoders > 1 && uncloneable_encoders);
	return true;
}

static struct intel_crtc_config *
@@ -9251,7 +9275,7 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
	int plane_bpp, ret = -EINVAL;
	bool retry = true;

	if (!check_encoder_cloning(crtc)) {
	if (!check_encoder_cloning(to_intel_crtc(crtc))) {
		DRM_DEBUG_KMS("rejecting invalid cloning configuration\n");
		return ERR_PTR(-EINVAL);
	}
@@ -10614,12 +10638,7 @@ static int intel_encoder_clones(struct intel_encoder *encoder)

	list_for_each_entry(source_encoder,
			    &dev->mode_config.encoder_list, base.head) {

		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)
		if (encoders_cloneable(encoder, source_encoder))
			index_mask |= (1 << entry);

		entry++;
+1 −1
Original line number Diff line number Diff line
@@ -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->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
	intel_encoder->cloneable = false;
	intel_encoder->cloneable = 0;
	intel_encoder->hot_plug = intel_dp_hot_plug;

	if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
+1 −5
Original line number Diff line number Diff line
@@ -125,11 +125,7 @@ struct intel_encoder {
	struct intel_crtc *new_crtc;

	int type;
	/*
	 * 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;
	unsigned int cloneable;
	bool connectors_active;
	void (*hot_plug)(struct intel_encoder *);
	bool (*compute_config)(struct intel_encoder *,
Loading