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

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

drm/i915: Pre-compute pipe enabled state



Add 'new_enabled' to intel_crtc and precompute it alongside new_encoder
and new_crtc. This will allow making decisions about shared resources
that are affected by the set of active pipes, before we've clobbered
anything for real.

Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarImre Deak <imre.deak@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 85ba7b7d
Loading
Loading
Loading
Loading
+62 −16
Original line number Original line Diff line number Diff line
@@ -8774,6 +8774,7 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
 */
 */
static void intel_modeset_update_staged_output_state(struct drm_device *dev)
static void intel_modeset_update_staged_output_state(struct drm_device *dev)
{
{
	struct intel_crtc *crtc;
	struct intel_encoder *encoder;
	struct intel_encoder *encoder;
	struct intel_connector *connector;
	struct intel_connector *connector;


@@ -8788,6 +8789,11 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev)
		encoder->new_crtc =
		encoder->new_crtc =
			to_intel_crtc(encoder->base.crtc);
			to_intel_crtc(encoder->base.crtc);
	}
	}

	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
			    base.head) {
		crtc->new_enabled = crtc->base.enabled;
	}
}
}


/**
/**
@@ -8797,6 +8803,7 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev)
 */
 */
static void intel_modeset_commit_output_state(struct drm_device *dev)
static void intel_modeset_commit_output_state(struct drm_device *dev)
{
{
	struct intel_crtc *crtc;
	struct intel_encoder *encoder;
	struct intel_encoder *encoder;
	struct intel_connector *connector;
	struct intel_connector *connector;


@@ -8809,6 +8816,11 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
			    base.head) {
			    base.head) {
		encoder->base.crtc = &encoder->new_crtc->base;
		encoder->base.crtc = &encoder->new_crtc->base;
	}
	}

	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
			    base.head) {
		crtc->base.enabled = crtc->new_enabled;
	}
}
}


static void
static void
@@ -9135,29 +9147,22 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
			*prepare_pipes |= 1 << encoder->new_crtc->pipe;
			*prepare_pipes |= 1 << encoder->new_crtc->pipe;
	}
	}


	/* Check for any pipes that will be fully disabled ... */
	/* Check for pipes that will be enabled/disabled ... */
	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
			    base.head) {
			    base.head) {
		bool used = false;
		if (intel_crtc->base.enabled == intel_crtc->new_enabled)

		/* Don't try to disable disabled crtcs. */
		if (!intel_crtc->base.enabled)
			continue;
			continue;


		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
		if (!intel_crtc->new_enabled)
				    base.head) {
			if (encoder->new_crtc == intel_crtc)
				used = true;
		}

		if (!used)
			*disable_pipes |= 1 << intel_crtc->pipe;
			*disable_pipes |= 1 << intel_crtc->pipe;
		else
			*prepare_pipes |= 1 << intel_crtc->pipe;
	}
	}




	/* set_mode is also used to update properties on life display pipes. */
	/* set_mode is also used to update properties on life display pipes. */
	intel_crtc = to_intel_crtc(crtc);
	intel_crtc = to_intel_crtc(crtc);
	if (crtc->enabled)
	if (intel_crtc->new_enabled)
		*prepare_pipes |= 1 << intel_crtc->pipe;
		*prepare_pipes |= 1 << intel_crtc->pipe;


	/*
	/*
@@ -9216,10 +9221,10 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)


	intel_modeset_commit_output_state(dev);
	intel_modeset_commit_output_state(dev);


	/* Update computed state. */
	/* Double check state. */
	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
			    base.head) {
			    base.head) {
		intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base);
		WARN_ON(intel_crtc->base.enabled != intel_crtc_in_use(&intel_crtc->base));
	}
	}


	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -9754,16 +9759,24 @@ static void intel_set_config_free(struct intel_set_config *config)


	kfree(config->save_connector_encoders);
	kfree(config->save_connector_encoders);
	kfree(config->save_encoder_crtcs);
	kfree(config->save_encoder_crtcs);
	kfree(config->save_crtc_enabled);
	kfree(config);
	kfree(config);
}
}


static int intel_set_config_save_state(struct drm_device *dev,
static int intel_set_config_save_state(struct drm_device *dev,
				       struct intel_set_config *config)
				       struct intel_set_config *config)
{
{
	struct drm_crtc *crtc;
	struct drm_encoder *encoder;
	struct drm_encoder *encoder;
	struct drm_connector *connector;
	struct drm_connector *connector;
	int count;
	int count;


	config->save_crtc_enabled =
		kcalloc(dev->mode_config.num_crtc,
			sizeof(bool), GFP_KERNEL);
	if (!config->save_crtc_enabled)
		return -ENOMEM;

	config->save_encoder_crtcs =
	config->save_encoder_crtcs =
		kcalloc(dev->mode_config.num_encoder,
		kcalloc(dev->mode_config.num_encoder,
			sizeof(struct drm_crtc *), GFP_KERNEL);
			sizeof(struct drm_crtc *), GFP_KERNEL);
@@ -9780,6 +9793,11 @@ static int intel_set_config_save_state(struct drm_device *dev,
	 * Should anything bad happen only the expected state is
	 * Should anything bad happen only the expected state is
	 * restored, not the drivers personal bookkeeping.
	 * restored, not the drivers personal bookkeeping.
	 */
	 */
	count = 0;
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
		config->save_crtc_enabled[count++] = crtc->enabled;
	}

	count = 0;
	count = 0;
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		config->save_encoder_crtcs[count++] = encoder->crtc;
		config->save_encoder_crtcs[count++] = encoder->crtc;
@@ -9796,10 +9814,16 @@ static int intel_set_config_save_state(struct drm_device *dev,
static void intel_set_config_restore_state(struct drm_device *dev,
static void intel_set_config_restore_state(struct drm_device *dev,
					   struct intel_set_config *config)
					   struct intel_set_config *config)
{
{
	struct intel_crtc *crtc;
	struct intel_encoder *encoder;
	struct intel_encoder *encoder;
	struct intel_connector *connector;
	struct intel_connector *connector;
	int count;
	int count;


	count = 0;
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
		crtc->new_enabled = config->save_crtc_enabled[count++];
	}

	count = 0;
	count = 0;
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
		encoder->new_crtc =
		encoder->new_crtc =
@@ -9884,9 +9908,9 @@ intel_modeset_stage_output_state(struct drm_device *dev,
				 struct drm_mode_set *set,
				 struct drm_mode_set *set,
				 struct intel_set_config *config)
				 struct intel_set_config *config)
{
{
	struct drm_crtc *new_crtc;
	struct intel_connector *connector;
	struct intel_connector *connector;
	struct intel_encoder *encoder;
	struct intel_encoder *encoder;
	struct intel_crtc *crtc;
	int ro;
	int ro;


	/* The upper layers ensure that we either disable a crtc or have a list
	/* The upper layers ensure that we either disable a crtc or have a list
@@ -9929,6 +9953,8 @@ intel_modeset_stage_output_state(struct drm_device *dev,
	/* Update crtc of enabled connectors. */
	/* Update crtc of enabled connectors. */
	list_for_each_entry(connector, &dev->mode_config.connector_list,
	list_for_each_entry(connector, &dev->mode_config.connector_list,
			    base.head) {
			    base.head) {
		struct drm_crtc *new_crtc;

		if (!connector->new_encoder)
		if (!connector->new_encoder)
			continue;
			continue;


@@ -9979,6 +10005,26 @@ intel_modeset_stage_output_state(struct drm_device *dev,
	}
	}
	/* Now we've also updated encoder->new_crtc for all encoders. */
	/* Now we've also updated encoder->new_crtc for all encoders. */


	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
			    base.head) {
		crtc->new_enabled = false;

		list_for_each_entry(encoder,
				    &dev->mode_config.encoder_list,
				    base.head) {
			if (encoder->new_crtc == crtc) {
				crtc->new_enabled = true;
				break;
			}
		}

		if (crtc->new_enabled != crtc->base.enabled) {
			DRM_DEBUG_KMS("crtc %sabled, full mode switch\n",
				      crtc->new_enabled ? "en" : "dis");
			config->mode_changed = true;
		}
	}

	return 0;
	return 0;
}
}


+2 −0
Original line number Original line Diff line number Diff line
@@ -359,6 +359,7 @@ struct intel_crtc {
	bool cursor_visible;
	bool cursor_visible;


	struct intel_crtc_config config;
	struct intel_crtc_config config;
	bool new_enabled;


	uint32_t ddi_pll_sel;
	uint32_t ddi_pll_sel;


@@ -540,6 +541,7 @@ struct intel_unpin_work {
struct intel_set_config {
struct intel_set_config {
	struct drm_encoder **save_connector_encoders;
	struct drm_encoder **save_connector_encoders;
	struct drm_crtc **save_encoder_crtcs;
	struct drm_crtc **save_encoder_crtcs;
	bool *save_crtc_enabled;


	bool fb_changed;
	bool fb_changed;
	bool mode_changed;
	bool mode_changed;