diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2014-01-10 04:28:06 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-01-24 11:22:40 -0500 |
commit | 7668851fec5c207d1d62c4c9311e083edf940bcc (patch) | |
tree | 89001547195a1875f64efd2940ee3eb2559bbe65 /drivers/gpu | |
parent | 85ba7b7d399dd2c4c65bd84b9ae4dfbd707e79e7 (diff) |
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>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 78 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 2 |
2 files changed, 64 insertions, 16 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 40a9338ad54f..204c09c9b63f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -8774,6 +8774,7 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder, | |||
8774 | */ | 8774 | */ |
8775 | static void intel_modeset_update_staged_output_state(struct drm_device *dev) | 8775 | static void intel_modeset_update_staged_output_state(struct drm_device *dev) |
8776 | { | 8776 | { |
8777 | struct intel_crtc *crtc; | ||
8777 | struct intel_encoder *encoder; | 8778 | struct intel_encoder *encoder; |
8778 | struct intel_connector *connector; | 8779 | struct intel_connector *connector; |
8779 | 8780 | ||
@@ -8788,6 +8789,11 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev) | |||
8788 | encoder->new_crtc = | 8789 | encoder->new_crtc = |
8789 | to_intel_crtc(encoder->base.crtc); | 8790 | to_intel_crtc(encoder->base.crtc); |
8790 | } | 8791 | } |
8792 | |||
8793 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, | ||
8794 | base.head) { | ||
8795 | crtc->new_enabled = crtc->base.enabled; | ||
8796 | } | ||
8791 | } | 8797 | } |
8792 | 8798 | ||
8793 | /** | 8799 | /** |
@@ -8797,6 +8803,7 @@ static void intel_modeset_update_staged_output_state(struct drm_device *dev) | |||
8797 | */ | 8803 | */ |
8798 | static void intel_modeset_commit_output_state(struct drm_device *dev) | 8804 | static void intel_modeset_commit_output_state(struct drm_device *dev) |
8799 | { | 8805 | { |
8806 | struct intel_crtc *crtc; | ||
8800 | struct intel_encoder *encoder; | 8807 | struct intel_encoder *encoder; |
8801 | struct intel_connector *connector; | 8808 | struct intel_connector *connector; |
8802 | 8809 | ||
@@ -8809,6 +8816,11 @@ static void intel_modeset_commit_output_state(struct drm_device *dev) | |||
8809 | base.head) { | 8816 | base.head) { |
8810 | encoder->base.crtc = &encoder->new_crtc->base; | 8817 | encoder->base.crtc = &encoder->new_crtc->base; |
8811 | } | 8818 | } |
8819 | |||
8820 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, | ||
8821 | base.head) { | ||
8822 | crtc->base.enabled = crtc->new_enabled; | ||
8823 | } | ||
8812 | } | 8824 | } |
8813 | 8825 | ||
8814 | static void | 8826 | static void |
@@ -9135,29 +9147,22 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes, | |||
9135 | *prepare_pipes |= 1 << encoder->new_crtc->pipe; | 9147 | *prepare_pipes |= 1 << encoder->new_crtc->pipe; |
9136 | } | 9148 | } |
9137 | 9149 | ||
9138 | /* Check for any pipes that will be fully disabled ... */ | 9150 | /* Check for pipes that will be enabled/disabled ... */ |
9139 | list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, | 9151 | list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, |
9140 | base.head) { | 9152 | base.head) { |
9141 | bool used = false; | 9153 | if (intel_crtc->base.enabled == intel_crtc->new_enabled) |
9142 | |||
9143 | /* Don't try to disable disabled crtcs. */ | ||
9144 | if (!intel_crtc->base.enabled) | ||
9145 | continue; | 9154 | continue; |
9146 | 9155 | ||
9147 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, | 9156 | if (!intel_crtc->new_enabled) |
9148 | base.head) { | ||
9149 | if (encoder->new_crtc == intel_crtc) | ||
9150 | used = true; | ||
9151 | } | ||
9152 | |||
9153 | if (!used) | ||
9154 | *disable_pipes |= 1 << intel_crtc->pipe; | 9157 | *disable_pipes |= 1 << intel_crtc->pipe; |
9158 | else | ||
9159 | *prepare_pipes |= 1 << intel_crtc->pipe; | ||
9155 | } | 9160 | } |
9156 | 9161 | ||
9157 | 9162 | ||
9158 | /* set_mode is also used to update properties on life display pipes. */ | 9163 | /* set_mode is also used to update properties on life display pipes. */ |
9159 | intel_crtc = to_intel_crtc(crtc); | 9164 | intel_crtc = to_intel_crtc(crtc); |
9160 | if (crtc->enabled) | 9165 | if (intel_crtc->new_enabled) |
9161 | *prepare_pipes |= 1 << intel_crtc->pipe; | 9166 | *prepare_pipes |= 1 << intel_crtc->pipe; |
9162 | 9167 | ||
9163 | /* | 9168 | /* |
@@ -9216,10 +9221,10 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes) | |||
9216 | 9221 | ||
9217 | intel_modeset_commit_output_state(dev); | 9222 | intel_modeset_commit_output_state(dev); |
9218 | 9223 | ||
9219 | /* Update computed state. */ | 9224 | /* Double check state. */ |
9220 | list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, | 9225 | list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, |
9221 | base.head) { | 9226 | base.head) { |
9222 | intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base); | 9227 | WARN_ON(intel_crtc->base.enabled != intel_crtc_in_use(&intel_crtc->base)); |
9223 | } | 9228 | } |
9224 | 9229 | ||
9225 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 9230 | 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 | 9759 | ||
9755 | kfree(config->save_connector_encoders); | 9760 | kfree(config->save_connector_encoders); |
9756 | kfree(config->save_encoder_crtcs); | 9761 | kfree(config->save_encoder_crtcs); |
9762 | kfree(config->save_crtc_enabled); | ||
9757 | kfree(config); | 9763 | kfree(config); |
9758 | } | 9764 | } |
9759 | 9765 | ||
9760 | static int intel_set_config_save_state(struct drm_device *dev, | 9766 | static int intel_set_config_save_state(struct drm_device *dev, |
9761 | struct intel_set_config *config) | 9767 | struct intel_set_config *config) |
9762 | { | 9768 | { |
9769 | struct drm_crtc *crtc; | ||
9763 | struct drm_encoder *encoder; | 9770 | struct drm_encoder *encoder; |
9764 | struct drm_connector *connector; | 9771 | struct drm_connector *connector; |
9765 | int count; | 9772 | int count; |
9766 | 9773 | ||
9774 | config->save_crtc_enabled = | ||
9775 | kcalloc(dev->mode_config.num_crtc, | ||
9776 | sizeof(bool), GFP_KERNEL); | ||
9777 | if (!config->save_crtc_enabled) | ||
9778 | return -ENOMEM; | ||
9779 | |||
9767 | config->save_encoder_crtcs = | 9780 | config->save_encoder_crtcs = |
9768 | kcalloc(dev->mode_config.num_encoder, | 9781 | kcalloc(dev->mode_config.num_encoder, |
9769 | sizeof(struct drm_crtc *), GFP_KERNEL); | 9782 | sizeof(struct drm_crtc *), GFP_KERNEL); |
@@ -9781,6 +9794,11 @@ static int intel_set_config_save_state(struct drm_device *dev, | |||
9781 | * restored, not the drivers personal bookkeeping. | 9794 | * restored, not the drivers personal bookkeeping. |
9782 | */ | 9795 | */ |
9783 | count = 0; | 9796 | count = 0; |
9797 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
9798 | config->save_crtc_enabled[count++] = crtc->enabled; | ||
9799 | } | ||
9800 | |||
9801 | count = 0; | ||
9784 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 9802 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
9785 | config->save_encoder_crtcs[count++] = encoder->crtc; | 9803 | config->save_encoder_crtcs[count++] = encoder->crtc; |
9786 | } | 9804 | } |
@@ -9796,11 +9814,17 @@ static int intel_set_config_save_state(struct drm_device *dev, | |||
9796 | static void intel_set_config_restore_state(struct drm_device *dev, | 9814 | static void intel_set_config_restore_state(struct drm_device *dev, |
9797 | struct intel_set_config *config) | 9815 | struct intel_set_config *config) |
9798 | { | 9816 | { |
9817 | struct intel_crtc *crtc; | ||
9799 | struct intel_encoder *encoder; | 9818 | struct intel_encoder *encoder; |
9800 | struct intel_connector *connector; | 9819 | struct intel_connector *connector; |
9801 | int count; | 9820 | int count; |
9802 | 9821 | ||
9803 | count = 0; | 9822 | count = 0; |
9823 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { | ||
9824 | crtc->new_enabled = config->save_crtc_enabled[count++]; | ||
9825 | } | ||
9826 | |||
9827 | count = 0; | ||
9804 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { | 9828 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) { |
9805 | encoder->new_crtc = | 9829 | encoder->new_crtc = |
9806 | to_intel_crtc(config->save_encoder_crtcs[count++]); | 9830 | to_intel_crtc(config->save_encoder_crtcs[count++]); |
@@ -9884,9 +9908,9 @@ intel_modeset_stage_output_state(struct drm_device *dev, | |||
9884 | struct drm_mode_set *set, | 9908 | struct drm_mode_set *set, |
9885 | struct intel_set_config *config) | 9909 | struct intel_set_config *config) |
9886 | { | 9910 | { |
9887 | struct drm_crtc *new_crtc; | ||
9888 | struct intel_connector *connector; | 9911 | struct intel_connector *connector; |
9889 | struct intel_encoder *encoder; | 9912 | struct intel_encoder *encoder; |
9913 | struct intel_crtc *crtc; | ||
9890 | int ro; | 9914 | int ro; |
9891 | 9915 | ||
9892 | /* The upper layers ensure that we either disable a crtc or have a list | 9916 | /* 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 | /* Update crtc of enabled connectors. */ | 9953 | /* Update crtc of enabled connectors. */ |
9930 | list_for_each_entry(connector, &dev->mode_config.connector_list, | 9954 | list_for_each_entry(connector, &dev->mode_config.connector_list, |
9931 | base.head) { | 9955 | base.head) { |
9956 | struct drm_crtc *new_crtc; | ||
9957 | |||
9932 | if (!connector->new_encoder) | 9958 | if (!connector->new_encoder) |
9933 | continue; | 9959 | continue; |
9934 | 9960 | ||
@@ -9979,6 +10005,26 @@ intel_modeset_stage_output_state(struct drm_device *dev, | |||
9979 | } | 10005 | } |
9980 | /* Now we've also updated encoder->new_crtc for all encoders. */ | 10006 | /* Now we've also updated encoder->new_crtc for all encoders. */ |
9981 | 10007 | ||
10008 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, | ||
10009 | base.head) { | ||
10010 | crtc->new_enabled = false; | ||
10011 | |||
10012 | list_for_each_entry(encoder, | ||
10013 | &dev->mode_config.encoder_list, | ||
10014 | base.head) { | ||
10015 | if (encoder->new_crtc == crtc) { | ||
10016 | crtc->new_enabled = true; | ||
10017 | break; | ||
10018 | } | ||
10019 | } | ||
10020 | |||
10021 | if (crtc->new_enabled != crtc->base.enabled) { | ||
10022 | DRM_DEBUG_KMS("crtc %sabled, full mode switch\n", | ||
10023 | crtc->new_enabled ? "en" : "dis"); | ||
10024 | config->mode_changed = true; | ||
10025 | } | ||
10026 | } | ||
10027 | |||
9982 | return 0; | 10028 | return 0; |
9983 | } | 10029 | } |
9984 | 10030 | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index fbfaaba5cc3b..718befff98e8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -359,6 +359,7 @@ struct intel_crtc { | |||
359 | bool cursor_visible; | 359 | bool cursor_visible; |
360 | 360 | ||
361 | struct intel_crtc_config config; | 361 | struct intel_crtc_config config; |
362 | bool new_enabled; | ||
362 | 363 | ||
363 | uint32_t ddi_pll_sel; | 364 | uint32_t ddi_pll_sel; |
364 | 365 | ||
@@ -540,6 +541,7 @@ struct intel_unpin_work { | |||
540 | struct intel_set_config { | 541 | struct intel_set_config { |
541 | struct drm_encoder **save_connector_encoders; | 542 | struct drm_encoder **save_connector_encoders; |
542 | struct drm_crtc **save_encoder_crtcs; | 543 | struct drm_crtc **save_encoder_crtcs; |
544 | bool *save_crtc_enabled; | ||
543 | 545 | ||
544 | bool fb_changed; | 546 | bool fb_changed; |
545 | bool mode_changed; | 547 | bool mode_changed; |