forked from Minki/linux
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: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
85ba7b7d39
commit
7668851fec
@ -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)
|
||||
{
|
||||
struct intel_crtc *crtc;
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_connector *connector;
|
||||
|
||||
@ -8788,6 +8789,11 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev)
|
||||
encoder->new_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)
|
||||
{
|
||||
struct intel_crtc *crtc;
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_connector *connector;
|
||||
|
||||
@ -8809,6 +8816,11 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
|
||||
base.head) {
|
||||
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
|
||||
@ -9135,29 +9147,22 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
|
||||
*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,
|
||||
base.head) {
|
||||
bool used = false;
|
||||
|
||||
/* Don't try to disable disabled crtcs. */
|
||||
if (!intel_crtc->base.enabled)
|
||||
if (intel_crtc->base.enabled == intel_crtc->new_enabled)
|
||||
continue;
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
|
||||
base.head) {
|
||||
if (encoder->new_crtc == intel_crtc)
|
||||
used = true;
|
||||
}
|
||||
|
||||
if (!used)
|
||||
if (!intel_crtc->new_enabled)
|
||||
*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. */
|
||||
intel_crtc = to_intel_crtc(crtc);
|
||||
if (crtc->enabled)
|
||||
if (intel_crtc->new_enabled)
|
||||
*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);
|
||||
|
||||
/* Update computed state. */
|
||||
/* Double check state. */
|
||||
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
|
||||
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) {
|
||||
@ -9754,16 +9759,24 @@ static void intel_set_config_free(struct intel_set_config *config)
|
||||
|
||||
kfree(config->save_connector_encoders);
|
||||
kfree(config->save_encoder_crtcs);
|
||||
kfree(config->save_crtc_enabled);
|
||||
kfree(config);
|
||||
}
|
||||
|
||||
static int intel_set_config_save_state(struct drm_device *dev,
|
||||
struct intel_set_config *config)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_connector *connector;
|
||||
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 =
|
||||
kcalloc(dev->mode_config.num_encoder,
|
||||
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
|
||||
* 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;
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
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,
|
||||
struct intel_set_config *config)
|
||||
{
|
||||
struct intel_crtc *crtc;
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_connector *connector;
|
||||
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;
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
|
||||
encoder->new_crtc =
|
||||
@ -9884,9 +9908,9 @@ intel_modeset_stage_output_state(struct drm_device *dev,
|
||||
struct drm_mode_set *set,
|
||||
struct intel_set_config *config)
|
||||
{
|
||||
struct drm_crtc *new_crtc;
|
||||
struct intel_connector *connector;
|
||||
struct intel_encoder *encoder;
|
||||
struct intel_crtc *crtc;
|
||||
int ro;
|
||||
|
||||
/* 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. */
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list,
|
||||
base.head) {
|
||||
struct drm_crtc *new_crtc;
|
||||
|
||||
if (!connector->new_encoder)
|
||||
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. */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -359,6 +359,7 @@ struct intel_crtc {
|
||||
bool cursor_visible;
|
||||
|
||||
struct intel_crtc_config config;
|
||||
bool new_enabled;
|
||||
|
||||
uint32_t ddi_pll_sel;
|
||||
|
||||
@ -540,6 +541,7 @@ struct intel_unpin_work {
|
||||
struct intel_set_config {
|
||||
struct drm_encoder **save_connector_encoders;
|
||||
struct drm_crtc **save_encoder_crtcs;
|
||||
bool *save_crtc_enabled;
|
||||
|
||||
bool fb_changed;
|
||||
bool mode_changed;
|
||||
|
Loading…
Reference in New Issue
Block a user