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)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user