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

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
...@@ -8774,6 +8774,7 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
...@@ -359,6 +359,7 @@ struct intel_crtc { ...@@ -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 { ...@@ -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;
......
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