|
@@ -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;
|
|
|
}
|
|
|
|