From ef9c3aee60442d1eaf81fbd7b63f256410cc0aa9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 29 Jun 2012 22:40:09 +0200 Subject: drm/i915: add direct encoder disable/enable infrastructure Just prep work, not yet put to some use. Note that because we're still using the crtc helper to switch modes (and their complicated way to do partial modesets), we need to call the encoder's disable function unconditionally. But once this is cleaned up we shouldn't call the encoder's disable function unconditionally any more, because then we know that we'll only call it if the encoder is actually enabled. Also note that we then need to be careful about which crtc we're filtering the encoder list on: We want to filter on the crtc of the _current_ mode, not the one we're about to set up. For the enabling side we need to do the same trick. And again, we should be able to simplify this quite a bit when things have settled into place. Also note that this simply does not take cloning into account, so dpms needs to be handled specially for the few outputs where we even bother with it. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 95f635b70b5b..9a5adcc35bde 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -141,6 +141,8 @@ struct intel_encoder { */ bool cloneable; void (*hot_plug)(struct intel_encoder *); + void (*enable)(struct intel_encoder *); + void (*disable)(struct intel_encoder *); int crtc_mask; }; -- cgit v1.2.1 From 5ab432ef4997ce32c9406721b37ef6e97e57dae1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sat, 30 Jun 2012 08:59:56 +0200 Subject: drm/i915/hdmi: convert to encoder->disable/enable I've picked hdmi as the first encoder to convert because it's rather simple: - no cloning possible - no differences between prepare/commit and dpms off/on switching. A few changes are required to do so: - Split up the dpms code into an enable/disable function and wire it up with the intel encoder. - Noop out the existing encoder prepare/commit functions used by the crtc helper - our crtc enable/disable code now calls back into the encoder enable/disable code at the right spot. - Create new helper functions to handle dpms changes. - Add intel_encoder->connectors_active to better track dpms state. Atm this is unused, but it will be useful to correctly disable the entire display pipe for cloned configurations. Also note that for now this is only useful in the dpms code - thanks to the crtc helper's dpms confusion across a modeset operation we can't (yet) rely on this having a sensible value in all circumstances. - Rip out the encoder helper dpms callback, if this is still getting called somewhere we have a bug. The slight issue with that is that the crtc helper abuses dpms off to disable unused functions. Hence we also need to implement a default encoder disable function to do just that with the new encoder->disable callback. - Note that we drop the cpt modeset verification in the commit callback, too. The right place to do this would be in the crtc's enable function, _after_ all the encoders are set up. But because not all encoders are converted yet, we can't do that. Hence disable this check temporarily as a minor concession to bisectability. v2: Squash the dpms mode to only the supported values - connector->dpms is for internal tracking only, we can hence avoid needless state-changes a bit whithout causing harm. v3: Apply bikeshed to disable|enable_ddi, suggested by Paulo Zanoni. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9a5adcc35bde..759dcbab0e5d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -140,6 +140,7 @@ struct intel_encoder { * simple flag is enough to compute the possible_clones mask. */ bool cloneable; + bool connectors_active; void (*hot_plug)(struct intel_encoder *); void (*enable)(struct intel_encoder *); void (*disable)(struct intel_encoder *); @@ -412,7 +413,11 @@ extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_encoder_prepare(struct drm_encoder *encoder); extern void intel_encoder_commit(struct drm_encoder *encoder); +extern void intel_encoder_noop(struct drm_encoder *encoder); +extern void intel_encoder_disable(struct drm_encoder *encoder); extern void intel_encoder_destroy(struct drm_encoder *encoder); +extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode); +extern void intel_connector_dpms(struct drm_connector *, int mode); static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector) { @@ -519,7 +524,8 @@ extern void intel_disable_gt_powersave(struct drm_device *dev); extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv); extern void ironlake_teardown_rc6(struct drm_device *dev); -extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode); +extern void intel_enable_ddi(struct intel_encoder *encoder); +extern void intel_disable_ddi(struct intel_encoder *encoder); extern void intel_ddi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); -- cgit v1.2.1 From b2cabb0e1d205708dab11bd9e1b97fd080537096 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 1 Jul 2012 22:42:24 +0200 Subject: drm/i915: convert dpms functions of dvo/sdvo/crt Yeah, big patch but I couldn't come up with a neat idea of how to split it up further, that wouldn't break dpms on cloned configs somehow. But the changes in dvo/sdvo/crt are all pretty much orthonogal, so it's not too bad a patch. These are the only encoders that support cloning, which requires a few special changes compared to the previous patches. - Compute the desired state of the display pipe by walking all connected encoders and checking whether any has active connectors. To make this clearer, drop the old mode parameter to the crtc dpms function and rename it to intel_crtc_update_dpms. - There's the curious case of intel_crtc->dpms_mode. With the previous patches to remove the overlay pipe A code and to rework the load detect pipe code, the big users are gone. We still keep it to avoid enabling the pipe twice, but we duplicate this logic with crtc->active, too. Still, leave this for now and just push a fake dpms mode into it that reflects the state of the display pipe. Changes in the encoder dpms functions: - We clamp the dpms state to the supported range right away. This is escpecially important for the VGA outputs, where only older hw supports the intermediate states. This (and the crt->adpa_reg patch) allows us to unify the crt dpms code again between all variants (gmch, vlv and pch). - We only enable/disable the output for dvo/sdvo and leave the encoder running. The encoder will be disabled/enabled when we switch the state of the entire output pipeline (which will happen right away for non-cloned setups). This way the duplication is reduced and strange interaction when disabling output ports at the wrong time avoided. The dpms code for all three types of connectors contains a bit of duplicated logic, but I think keeping these special cases separate is simpler: CRT is the only one that hanldes intermediate dpms state (which requires extra logic to enable/disable things in the right order), and introducing some abstraction just to share the code between dvo and sdvo smells like overkill. We can do that once someone bothers to implement cloning for the more modern outputs. But I doubt that this will ever happen. v2: s/crtc/crt/_set_dpms, noticed by Paulo Zanoni. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 759dcbab0e5d..245624587db1 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -411,6 +411,7 @@ extern void intel_panel_destroy_backlight(struct drm_device *dev); extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); extern void intel_crtc_load_lut(struct drm_crtc *crtc); +extern void intel_crtc_update_dpms(struct drm_crtc *crtc); extern void intel_encoder_prepare(struct drm_encoder *encoder); extern void intel_encoder_commit(struct drm_encoder *encoder); extern void intel_encoder_noop(struct drm_encoder *encoder); -- cgit v1.2.1 From 61b77ddda6cf6f1f6f543339cfeee4c623f82784 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 2 Jul 2012 00:16:19 +0200 Subject: drm/i915: clean up encoder_prepare/commit We no longer need them. And now that all encoders are converted, we can finally move the cpt modeset check to the right place - at the end of the crtc_enable function. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 245624587db1..e59cac34ec68 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -412,8 +412,6 @@ extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_crtc_update_dpms(struct drm_crtc *crtc); -extern void intel_encoder_prepare(struct drm_encoder *encoder); -extern void intel_encoder_commit(struct drm_encoder *encoder); extern void intel_encoder_noop(struct drm_encoder *encoder); extern void intel_encoder_disable(struct drm_encoder *encoder); extern void intel_encoder_destroy(struct drm_encoder *encoder); -- cgit v1.2.1 From a6778b3cfd7711951d8973286b783bc061281256 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 2 Jul 2012 09:56:42 +0200 Subject: drm/i915: copy&paste drm_crtc_helper_set_mode Together with the static helper functions drm_crtc_prepare_encoders and drm_encoder_disable (which will be simplified in the next patch, but for now are 1:1 copies). Again, no changes beside new names for these functions. Also call our new set_mode instead of the crtc helper one now in all the places we've done so far. v2: Call the function just intel_set_mode to better differentia it from intel_crtc_mode_set which really only does the ->mode_set step of the entire modeset sequence on one crtc. Whereas this function does the global change. Acked-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e59cac34ec68..c28fadae8758 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -410,6 +410,8 @@ extern void intel_panel_disable_backlight(struct drm_device *dev); extern void intel_panel_destroy_backlight(struct drm_device *dev); extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); +extern bool intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, + int x, int y, struct drm_framebuffer *old_fb); extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_crtc_update_dpms(struct drm_crtc *crtc); extern void intel_encoder_noop(struct drm_encoder *encoder); -- cgit v1.2.1 From c9deac9776b0a95b876bd845ea359d5975c3ba80 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 2 Jul 2012 10:21:35 +0200 Subject: drm/i915: rip out encoder->prepare/commit With the new infrastructure we're doing this when enabling/disabling the entire display pipe. Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c28fadae8758..673e8d484bfa 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -414,7 +414,6 @@ extern bool intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb); extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_crtc_update_dpms(struct drm_crtc *crtc); -extern void intel_encoder_noop(struct drm_encoder *encoder); extern void intel_encoder_disable(struct drm_encoder *encoder); extern void intel_encoder_destroy(struct drm_encoder *encoder); extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode); -- cgit v1.2.1 From 08a48469691a1b9ed6ee92e726b66d4e59ffc253 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 2 Jul 2012 11:43:47 +0200 Subject: drm/i915: WARN when trying to enabled an unused crtc This is the first tiny step towards cross-checking the entire modeset state machine with WARNs. A crtc can only be enabled when it's actually in use, i.e. crtc->active imlies crtc->enabled. Unfortunately we can't (yet) check this when disabling the crtc, because the crtc helpers are a bit slopy with updating state and unconditionally update crtc->enabled before changing the hw state. Fixing that requires quite some more work. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 673e8d484bfa..36991dee2d40 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -158,7 +158,15 @@ struct intel_crtc { enum plane plane; u8 lut_r[256], lut_g[256], lut_b[256]; int dpms_mode; - bool active; /* is the crtc on? independent of the dpms mode */ + /* + * Whether the crtc and the connected output pipeline is active. Implies + * that crtc->enabled is set, i.e. the current mode configuration has + * some outputs connected to this crtc. + * + * Atm crtc->enabled is unconditionally updated _before_ the hw state is + * changed, hence we can only check this when enabling the crtc. + */ + bool active; bool primary_disabled; /* is the crtc obscured by a plane? */ bool lowfreq_avail; struct intel_overlay *overlay; -- cgit v1.2.1 From f0947c376f6944ade7079df9f84bbc958a893e0f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 2 Jul 2012 13:10:34 +0200 Subject: drm/i915: Add interfaces to read out encoder/connector hw state It is all glorious if we try really hard to only enable/disable an entire display pipe to ensure that everyting happens in the right order. But if we don't know the output configuration when the driver takes over, this will all be for vain because we'll make the hw angry right on the first modeset - we don't know what outputs/ports are enabled and hence have to disable everything in a rather ad-hoc way. Hence we need to be able to read out the current hw state, so that we can properly tear down the current hw state on the first modeset. Obviously this is also a nice preparation for the fastboot work, where we try to avoid the modeset on driver load if it matches what the hw is currently using. Furthermore we'll be using these functions to cross-check the actual hw state with what we think it should be, to ensure that the modeset state machine actually works as advertised. This patch only contains the interface definitions and a little helper for the simple case where we have a 1:1 encoder to connector mapping. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 36991dee2d40..c39c70554891 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -144,12 +144,19 @@ struct intel_encoder { void (*hot_plug)(struct intel_encoder *); void (*enable)(struct intel_encoder *); void (*disable)(struct intel_encoder *); + /* Read out the current hw state of this connector, returning true if + * the encoder is active. If the encoder is enabled it also set the pipe + * it is connected to in the pipe parameter. */ + bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe); int crtc_mask; }; struct intel_connector { struct drm_connector base; struct intel_encoder *encoder; + /* Reads out the current hw, returning true if the connector is enabled + * and active (i.e. dpms ON state). */ + bool (*get_hw_state)(struct intel_connector *); }; struct intel_crtc { @@ -426,6 +433,7 @@ extern void intel_encoder_disable(struct drm_encoder *encoder); extern void intel_encoder_destroy(struct drm_encoder *encoder); extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode); extern void intel_connector_dpms(struct drm_connector *, int mode); +extern bool intel_connector_get_hw_state(struct intel_connector *connector); static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector) { -- cgit v1.2.1 From 85234cdc28f622dc94d8bb0089635113e2aa5609 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 2 Jul 2012 13:27:29 +0200 Subject: drm/i915/hdmi: implement get_hw_state Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c39c70554891..4daa7e65b04a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -542,6 +542,8 @@ extern void ironlake_teardown_rc6(struct drm_device *dev); extern void intel_enable_ddi(struct intel_encoder *encoder); extern void intel_disable_ddi(struct intel_encoder *encoder); +extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder, + enum pipe *pipe); extern void intel_ddi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); -- cgit v1.2.1 From 0a91ca29215a41760cca03999498959d0e05d9b3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 2 Jul 2012 21:54:27 +0200 Subject: drm/i915: check connector hw/sw state Atm we can only check the connector state after a dpms call - while doing modeset with the copy&pasted crtc helper code things are too ill-defined for proper checking. But the idea is very much to call this check from the modeset code, too. v2: Fix dpms check and don't presume that if the hw isn't on that it must not be linked up with an encoder (it could simply be switched off with the dpms state). Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4daa7e65b04a..e2116d96bd6f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -434,6 +434,7 @@ extern void intel_encoder_destroy(struct drm_encoder *encoder); extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode); extern void intel_connector_dpms(struct drm_connector *, int mode); extern bool intel_connector_get_hw_state(struct intel_connector *connector); +extern void intel_connector_check_state(struct intel_connector *); static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector) { -- cgit v1.2.1 From 84bb65bded92028a6c803fef332586fedbe092b2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 3 Jul 2012 13:19:00 +0200 Subject: drm/i915: rip out intel_crtc->dpms_mode Afaict this has been used for two things: - To prevent the crtc enable code from being run twice. We have now intel_crtc->active to track this in a more precise way. - To ensure the code copes correctly with the unknown hw state after boot and resume. Thanks to the hw state readout and sanitize code we have now a better way to handle this. The only thing it still does is complicate our modeset state space. Having outlived its usefullness, let it just die. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e2116d96bd6f..a7d79dee2be3 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -164,7 +164,6 @@ struct intel_crtc { enum pipe pipe; enum plane plane; u8 lut_r[256], lut_g[256], lut_b[256]; - int dpms_mode; /* * Whether the crtc and the connected output pipeline is active. Implies * that crtc->enabled is set, i.e. the current mode configuration has -- cgit v1.2.1 From 24e804ba9731bf4b05bc17a6702d802e76b3bbc4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 26 Jul 2012 19:25:46 +0200 Subject: drm/i915: rip out intel_dp->dpms_mode We now track the connector state in encoder->connectors_active, and because the DP output can't be cloned, that is sufficient to track the link state. Hence use this instead of adding yet another modeset state variable with dubious semantics at driver load and resume time. Also, connectors_active should only ever be set when the encoder is linked to a crtc, hence convert that crtc test into a WARN. v2: Rebase on top of struct intel_dp moving. v3: The rebase accidentally killed the newly-introduced intel_dp->port Noticed by Paulo Zanoni. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a7d79dee2be3..c080c829cbff 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -324,7 +324,6 @@ struct intel_dp { enum hdmi_force_audio force_audio; enum port port; uint32_t color_range; - int dpms_mode; uint8_t link_bw; uint8_t lane_count; uint8_t dpcd[DP_RECEIVER_CAP_SIZE]; -- cgit v1.2.1 From d9e55608cdcd875c4c1f319c1a5a438c7cc55f57 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 4 Jul 2012 22:16:09 +0200 Subject: drm/i915: introduce struct intel_set_config intel_crtc_set_config is an unwidly beast and is in serious need of some function extraction. To facilitate that, introduce a struct to keep track of all the state involved. Atm it doesn't do much more than keep track of all the allocated memory. v2: Apply some bikeshed to intel_set_config_free, as suggested by Jesse Barnes. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c080c829cbff..1cb64dd9c7f0 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -423,6 +423,12 @@ extern void intel_panel_disable_backlight(struct drm_device *dev); extern void intel_panel_destroy_backlight(struct drm_device *dev); extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); +struct intel_set_config { + struct drm_connector *save_connectors; + struct drm_encoder *save_encoders; + struct drm_crtc *save_crtcs; +}; + extern bool intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb); extern void intel_crtc_load_lut(struct drm_crtc *crtc); -- cgit v1.2.1 From 5e2b584ed1563c4c5199510710df6eaa1a36f3b1 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 4 Jul 2012 22:41:29 +0200 Subject: drm/i915: extract intel_set_config_compute_mode_changes This computes what exactly changed in the modeset configuration, i.e. whether a full modeset is required or only an update of the framebuffer base address or no change at all. In the future we might add more checks for e.g. when only the output mode changed, so that we could do a minimal modeset for outputs that support this. Like the lvds/eDP panels where we only need to update the panel fitter. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1cb64dd9c7f0..fad11c83ba40 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -427,6 +427,9 @@ struct intel_set_config { struct drm_connector *save_connectors; struct drm_encoder *save_encoders; struct drm_crtc *save_crtcs; + + bool fb_changed; + bool mode_changed; }; extern bool intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, -- cgit v1.2.1 From 1aa4b628ee63f55db96c7e820257b6e4948abb74 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 5 Jul 2012 16:20:48 +0200 Subject: drm/i915: don't save all the encoder/crtc state in set_config We actually only touch the connector -> encoder and encoder -> crtc linking. So it's enough to just save/restore that. While at it, also switch to kcalloc to allocate these arrays (omission in the commit message spotted by Jesse Barnes). Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index fad11c83ba40..4946282bd324 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -424,8 +424,8 @@ extern void intel_panel_destroy_backlight(struct drm_device *dev); extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); struct intel_set_config { - struct drm_connector *save_connectors; - struct drm_encoder *save_encoders; + struct drm_encoder **save_connector_encoders; + struct drm_crtc **save_encoder_crtcs; struct drm_crtc *save_crtcs; bool fb_changed; -- cgit v1.2.1 From 9a935856992d68b9194f825ce6e115df7ecc5bca Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 5 Jul 2012 22:34:27 +0200 Subject: drm/i915: stage modeset output changes This is the core of the new modeset logic. The current code which is based upon the crtc helper code first updates all the link of the new display pipeline and then calls the lower-level set_mode function to execute the required callbacks to get there. The issue with this approach is that for disabling we need to know the _current_ display pipe state, not the new one. Hence we need to stage the new state of the display pipe and only update it once we have disabled the current configuration and before we start to update the hw registers with the new configuration. This patch here just prepares the ground by switching the new output state computation to these staging pointers. To make it clearer, rename the old update_output_state function to stage_output_state. A few peculiarities: - We're also calling the set_mode function at various places to update properties. Hence after a successfule modeset we need to stage the current configuration (for otherwise we might fall back again). This happens automatically because as part of the (successful) modeset we need to copy the staged state to the real one. But for the hw readout code we need to make sure that this happens, too. - Teach the new staged output state computation code the required smarts to handle the disabling of outputs. The current code handles this in a special case, but to better handle global modeset changes covering more than one crtc, we want to do this all in the same low-level modeset code. - The actual modeset code is still a bit ugly and wants to know the new crtc->enabled state a bit early. Follow-on patches will clean that up, for now we have to apply the staged output configuration early, outside of the set_mode functions. - Improve/add comments in stage_output_state. Essentially all that is left to do now is move the disabling code into set_mode and then move the staged state update code also into set_mode, at the right place between disabling things and calling the mode_set callbacks for the new configuration. v2: Disabling a crtc works by passing in a NULL mode or fb, userspace doesn't hand in the list of connectors. We therefore need to detect this case manually and tear down all the output links. v3: Properly update the output staging pointers after having read out the hw state. v4: Simplify the code, add more DRM_DEBUG_KMS output and check a few assumptions with WARN_ON. Essentially all things that I've noticed while debugging issues in other places of the code. v4: Correctly disable the old set of connectors when enabling an already enabled crtc on a new set of crtc. Reported by Paulo Zanoni. Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4946282bd324..ae807afc5fbf 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -133,6 +133,12 @@ struct intel_fbdev { struct intel_encoder { struct drm_encoder base; + /* + * The new crtc this encoder will be driven from. Only differs from + * base->crtc while a modeset is in progress. + */ + struct intel_crtc *new_crtc; + int type; bool needs_tv_clock; /* @@ -153,7 +159,17 @@ struct intel_encoder { struct intel_connector { struct drm_connector base; + /* + * The fixed encoder this connector is connected to. + */ struct intel_encoder *encoder; + + /* + * The new encoder this connector will be driven. Only differs from + * encoder while a modeset is in progress. + */ + struct intel_encoder *new_encoder; + /* Reads out the current hw, returning true if the connector is enabled * and active (i.e. dpms ON state). */ bool (*get_hw_state)(struct intel_connector *); -- cgit v1.2.1 From 94352cf9a5328bb1a44288e6c2c1276695f8a356 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 5 Jul 2012 22:51:56 +0200 Subject: drm/i915: push crtc->fb update into pipe_set_base Passing in the old fb, having overwritten the current fb, leads to some neatly convoluted code. It's much simpler if we defer the crtc->fb update to the place that updates the hw, in pipe_set_base. This way we also don't need to restore anything in case something fails - we only update crtc->fb once things have succeeded. The real reason for this change is that now we keep the old fb assigned to crtc->fb, which allows us to finally move the crtc disable case into the common low-level set_mode function in the next patch. Also don't clobber crtc->x and crtc->y, we neatly pass these down the callchain already. Unfortunately we can't do the same with crtc->mode, because that one is being used in the mode_set callbacks. v2: Don't restore the drm_crtc object any more on failed modesets, since we've lose an fb reference otherwise. Also (and this is the reason this has been found), this totally confused the modeset state tracking, since it clobbers crtc->enabled. Issue reported by Paulo Zanoni. v3: Rip out the entire crtc saving into struct intel_set_config, not just the restoring part. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ae807afc5fbf..1aa0b9c0a4d5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -442,7 +442,6 @@ extern enum drm_connector_status intel_panel_detect(struct drm_device *dev); struct intel_set_config { struct drm_encoder **save_connector_encoders; struct drm_crtc **save_encoder_crtcs; - struct drm_crtc *save_crtcs; bool fb_changed; bool mode_changed; -- cgit v1.2.1 From 6ed0f796c22cd638fac60f29ff72b3a7a03485e6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Sun, 8 Jul 2012 19:41:43 +0200 Subject: drm/i915: use staged outuput config in tv->mode_fixup The "is this encoder cloned" check will be reused by the lvds encoder, hence exract it. v2: Be a bit more careful about that we need to check the new, staged ouput configuration in the check_non_cloned helper ... v3: Kill the double negation with s/!non_cloned/is_cloned/, suggested by Jesse Barnes. Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1aa0b9c0a4d5..8686f47f6829 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -454,6 +454,7 @@ extern void intel_crtc_update_dpms(struct drm_crtc *crtc); extern void intel_encoder_disable(struct drm_encoder *encoder); extern void intel_encoder_destroy(struct drm_encoder *encoder); extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode); +extern bool intel_encoder_check_is_cloned(struct intel_encoder *encoder); extern void intel_connector_dpms(struct drm_connector *, int mode); extern bool intel_connector_get_hw_state(struct intel_connector *connector); extern void intel_connector_check_state(struct intel_connector *); -- cgit v1.2.1 From 1f70385510991992f3aef339982ca790faa52b06 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 11 Jul 2012 16:51:39 +0200 Subject: drm/i915: s/intel_encoder_disable/intel_encoder_noop Because that's what it is. Unfortunately we can't rip this out because the fb helper has an incetious relationship with the crtc helper - it likes to call disable_unused_functions, among other things. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8686f47f6829..5137f9bef13e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -451,7 +451,7 @@ extern bool intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb); extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_crtc_update_dpms(struct drm_crtc *crtc); -extern void intel_encoder_disable(struct drm_encoder *encoder); +extern void intel_encoder_noop(struct drm_encoder *encoder); extern void intel_encoder_destroy(struct drm_encoder *encoder); extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode); extern bool intel_encoder_check_is_cloned(struct intel_encoder *encoder); -- cgit v1.2.1 From ea9d758d6ddb9f4bb9639619100743e8f5fa85a0 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 10 Jul 2012 10:42:52 +0200 Subject: drm/i915: push commit_output_state past the crtc/encoder preparing With this change we can (finally!) rip out a few of the temporary hacks and clean up a few other things: - Kill intel_crtc_prepare_encoders, now unused. - Kill the hacks in the crtc_disable/enable functions to always call the encoder callbacks, we now always call the crtc functions with the right encoder -> crtc links. - Also push down the crtc->enable, encoder and connector dpms state updates. Unfortunately we can't add a WARN in the crtc_disable callbacks to ensure that the crtc is always still enabled when disabling an output pipe - the crtc sanitizer of the hw readout path can hit this when it needs to disable an active pipe without any enabled outputs. - Only call crtc->disable if the pipe is already enabled - again avoids running afoul of the new WARN. v2: Copy&paste our own version of crtc_in_use, too. v3: We need to update the dpms an encoder->connectors_active states, too. v4: I've forgotten to kill the unconditional encoder->disable calls in the crtc_disable functions. v5: Rip out leftover debug printk. v6: Properly clear intel_encoder->connectors_active. This wasn't properly cleared when disabling an encoder because it was no longer on the new connector list, but the crtc was still enabled (i.e. switching the encoder of an active crtc). Reported by Jani Nikula. v7: Don't clobber the encoder->connectors_active state of untouched encoders. Since X likes to first disable all outputs with dpms off before setting a new framebuffer, this hit a few warnings. Reported by Paulo Zanoni. v8: Kill the now stale comment warning that intel_crtc->active is not always updated at the right times. Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5137f9bef13e..d03e77752157 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -184,9 +184,6 @@ struct intel_crtc { * Whether the crtc and the connected output pipeline is active. Implies * that crtc->enabled is set, i.e. the current mode configuration has * some outputs connected to this crtc. - * - * Atm crtc->enabled is unconditionally updated _before_ the hw state is - * changed, hence we can only check this when enabling the crtc. */ bool active; bool primary_disabled; /* is the crtc obscured by a plane? */ -- cgit v1.2.1 From a261b246ebd552fd5d5a8ed84cc931bb821c427f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 26 Jul 2012 19:21:47 +0200 Subject: drm/i915: disable all crtcs at suspend time We need this to avoid confusing the hw state readout code with the cpt pch plls at resume time: We'd read the new pipe state (which is disabled), but still believe that we have a life pll connected to that pipe (from before the suspend). Hence properly disable pipes to clear out all the residual state. This has the neat side-effect that we don't enable ports prematurely by restoring bogus state from the saved register values. Reviewed-by: Jesse Barnes Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d03e77752157..2061399d92c1 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -446,6 +446,7 @@ struct intel_set_config { extern bool intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, int x, int y, struct drm_framebuffer *old_fb); +extern void intel_modeset_disable(struct drm_device *dev); extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_crtc_update_dpms(struct drm_crtc *crtc); extern void intel_encoder_noop(struct drm_encoder *encoder); -- cgit v1.2.1 From b980514c9adf403e3f43ead08196f5ce0e61fd05 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 31 Aug 2012 17:37:33 +0200 Subject: drm/i915: improve modeset state checking after dpms calls Now that we have solid modeset state tracking and checking code in place, we can do the Full Monty also after dpms calls. Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2061399d92c1..19e69285ba31 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -455,7 +455,8 @@ extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode); extern bool intel_encoder_check_is_cloned(struct intel_encoder *encoder); extern void intel_connector_dpms(struct drm_connector *, int mode); extern bool intel_connector_get_hw_state(struct intel_connector *connector); -extern void intel_connector_check_state(struct intel_connector *); +extern void intel_modeset_check_state(struct drm_device *dev); + static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector) { -- cgit v1.2.1