All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/58] modeset-rework, the basic conversion
@ 2012-08-19 19:12 Daniel Vetter
  2012-08-19 19:12 ` [PATCH 01/58] drm/i915: add crtc->enable/disable vfuncs insted of dpms Daniel Vetter
                   ` (65 more replies)
  0 siblings, 66 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Hi all,

Changes since last time around:
- The prep patches are all merged now.
- I've left out the actual DP fixes/cleanups, I think we should merge those in a
  separte step.
- A few bugfixes (thanks to Paulo, Jani and Chris).
- I've also applied a few bikesheds for naming that Paulo suggested (but I'm not
  sure whether I've sent those out already in a previous patchbomb).

Essentially this is just the core rework, which addes the new get_hw_state code,
refactors all the encoders to use the new functions and finally reworks the
modeset logic to disable/enable entire pipes, always (and with a deterministic
order).

For merging to -next, I plan to pull in everything with a real merge commit. For
that reason I've put up a modeset-rework-base branch onto my private fdo repo[1].
That way I can put a short documentation for the new modeset design into the
merge commit (stichted together from the previous patchbomb cover letters),
documenting my folly assumptions for eternity.

I'll also plan to put tags for the entire series in the merge commit, so if you
have tested this on a few machines, read through and agree with the new designs,
please reply with your tested-by/acked-by/reviewed-by tags.

Flames, comments and test reports highly welcome.

Cheers, Daniel

[1] http://cgit.freedesktop.org/~danvet/drm/log/?h=modeset-rework-base

Daniel Vetter (58):
  drm/i915: add crtc->enable/disable vfuncs insted of dpms
  drm/i915: rip out crtc prepare/commit indirection
  drm/i915: add direct encoder disable/enable infrastructure
  drm/i915/hdmi: convert to encoder->disable/enable
  drm/i915/tv: convert to encoder enable/disable
  drm/i915/lvds: convert to encoder disable/enable
  drm/i915/dp: convert to encoder disable/enable
  drm/i915/crt: convert to encoder disable/enable
  drm/i915/sdvo: convert to encoder disable/enable
  drm/i915/dvo: convert to encoder disable/enable
  drm/i915: convert dpms functions of dvo/sdvo/crt
  drm/i915: rip out encoder->disable/enable checks
  drm/i915: clean up encoder_prepare/commit
  drm/i915: copy&paste drm_crtc_helper_set_config
  drm/i915: call set_base directly
  drm/i915: inline intel_best_encoder
  drm/i915: copy&paste drm_crtc_helper_set_mode
  drm/i915: simplify intel_crtc_prepare_encoders
  drm/i915: rip out encoder->prepare/commit
  drm/i915: call crtc functions directly
  drm/i915: WARN when trying to enabled an unused crtc
  drm/i915: Add interfaces to read out encoder/connector hw state
  drm/i915/dp: implement get_hw_state
  drm/i915/hdmi: implement get_hw_state
  drm/i915/tv: implement get_hw_state
  drm/i915/lvds: implement get_hw_state
  drm/i915/crt: implement get_hw_state
  drm/i915/sdvo: implement get_hw_state
  drm/i915/dvo: implement get_hw_state
  drm/i915: read out the modeset hw state at load and resume time
  drm/i915: check connector hw/sw state
  drm/i915: rip out intel_crtc->dpms_mode
  drm/i915: rip out intel_dp->dpms_mode
  drm/i915: ensure the force pipe A quirk is actually followed
  drm/i915: introduce struct intel_set_config
  drm/i915: extract modeset config save/restore code
  drm/i915: extract intel_set_config_compute_mode_changes
  drm/i915: extract intel_set_config_update_output_state
  drm/i915: implement crtc helper semantics relied upon by the fb
    helper
  drm/i915: don't update the fb base if there is no fb
  drm/i915: convert pointless error checks in set_config to BUGs
  drm/i915: don't save all the encoder/crtc state in set_config
  drm/i915: stage modeset output changes
  drm/i915: push crtc->fb update into pipe_set_base
  drm/i915: remove crtc disabling special case
  drm/i915: move output commit and crtc disabling into set_mode
  drm/i915: extract adjusted mode computation
  drm/i915: use staged outuput config in tv->mode_fixup
  drm/i915: use staged outuput config in lvds->mode_fixup
  drm/i915: compute masks of crtcs affected in set_mode
  drm/i915: implement new set_mode code flow
  drm/i915: push commit_output_state past crtc disabling
  drm/i915: s/intel_encoder_disable/intel_encoder_noop
  drm/i915: WARN if the pipe won't turn off
  drm/i915: switch the load detect code to the staged modeset config
  drm/i915: push commit_output_state past the crtc/encoder preparing
  drm/i915: disable all crtcs at suspend time
  drm/i915: add tons of modeset state checks

 drivers/gpu/drm/i915/dvo.h           |    6 +
 drivers/gpu/drm/i915/dvo_ch7017.c    |   13 +
 drivers/gpu/drm/i915/dvo_ch7xxx.c    |   13 +
 drivers/gpu/drm/i915/dvo_ivch.c      |   15 +
 drivers/gpu/drm/i915/dvo_ns2501.c    |   15 +
 drivers/gpu/drm/i915/dvo_sil164.c    |   16 +
 drivers/gpu/drm/i915/dvo_tfp410.c    |   14 +
 drivers/gpu/drm/i915/i915_drv.c      |    4 +
 drivers/gpu/drm/i915/i915_drv.h      |    4 +-
 drivers/gpu/drm/i915/i915_reg.h      |    2 +
 drivers/gpu/drm/i915/intel_crt.c     |  136 ++-
 drivers/gpu/drm/i915/intel_ddi.c     |   59 +-
 drivers/gpu/drm/i915/intel_display.c | 1499 ++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_dp.c      |  144 ++--
 drivers/gpu/drm/i915/intel_drv.h     |   64 +-
 drivers/gpu/drm/i915/intel_dvo.c     |   94 ++-
 drivers/gpu/drm/i915/intel_hdmi.c    |  151 +++-
 drivers/gpu/drm/i915/intel_lvds.c    |   95 +--
 drivers/gpu/drm/i915/intel_sdvo.c    |  164 +++-
 drivers/gpu/drm/i915/intel_tv.c      |   61 +-
 20 files changed, 2044 insertions(+), 525 deletions(-)

-- 
1.7.11.2

^ permalink raw reply	[flat|nested] 173+ messages in thread

* [PATCH 01/58] drm/i915: add crtc->enable/disable vfuncs insted of dpms
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-08-29 17:51   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 02/58] drm/i915: rip out crtc prepare/commit indirection Daniel Vetter
                   ` (64 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Because that's what we're essentially calling. This is the first step
in untangling the crtc_helper induced dpms handling mess we have - at
the crtc level we only have 2 states and the magic is just in
selecting which one (and atm there isn't even much magic, but on
recent platforms where not even the crt output has more than 2 states
we could do better).

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.h      |  3 +-
 drivers/gpu/drm/i915/intel_display.c | 62 +++++++++++-------------------------
 2 files changed, 20 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ed3ba70..fb46c6f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -240,7 +240,6 @@ struct drm_i915_error_state {
 };
 
 struct drm_i915_display_funcs {
-	void (*dpms)(struct drm_crtc *crtc, int mode);
 	bool (*fbc_enabled)(struct drm_device *dev);
 	void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
 	void (*disable_fbc)(struct drm_device *dev);
@@ -256,6 +255,8 @@ struct drm_i915_display_funcs {
 			     struct drm_display_mode *adjusted_mode,
 			     int x, int y,
 			     struct drm_framebuffer *old_fb);
+	void (*crtc_enable)(struct drm_crtc *crtc);
+	void (*crtc_disable)(struct drm_crtc *crtc);
 	void (*off)(struct drm_crtc *crtc);
 	void (*write_eld)(struct drm_connector *connector,
 			  struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 42c5758..adc9868 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3342,30 +3342,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	mutex_unlock(&dev->struct_mutex);
 }
 
-static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
-
-	/* XXX: When our outputs are all unaware of DPMS modes other than off
-	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
-	 */
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-		DRM_DEBUG_KMS("crtc %d/%d dpms on\n", pipe, plane);
-		ironlake_crtc_enable(crtc);
-		break;
-
-	case DRM_MODE_DPMS_OFF:
-		DRM_DEBUG_KMS("crtc %d/%d dpms off\n", pipe, plane);
-		ironlake_crtc_disable(crtc);
-		break;
-	}
-}
-
 static void ironlake_crtc_off(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -3445,23 +3421,6 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	intel_update_watermarks(dev);
 }
 
-static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-	/* XXX: When our outputs are all unaware of DPMS modes other than off
-	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
-	 */
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-		i9xx_crtc_enable(crtc);
-		break;
-	case DRM_MODE_DPMS_OFF:
-		i9xx_crtc_disable(crtc);
-		break;
-	}
-}
-
 static void i9xx_crtc_off(struct drm_crtc *crtc)
 {
 }
@@ -3483,7 +3442,20 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 
 	intel_crtc->dpms_mode = mode;
 
-	dev_priv->display.dpms(crtc, mode);
+	/* XXX: When our outputs are all unaware of DPMS modes other than off
+	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+	 */
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+		dev_priv->display.crtc_enable(crtc);
+		break;
+
+	case DRM_MODE_DPMS_OFF:
+		dev_priv->display.crtc_disable(crtc);
+		break;
+	}
 
 	if (!dev->primary->master)
 		return;
@@ -6971,13 +6943,15 @@ static void intel_init_display(struct drm_device *dev)
 
 	/* We always want a DPMS function */
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->display.dpms = ironlake_crtc_dpms;
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
+		dev_priv->display.crtc_enable = ironlake_crtc_enable;
+		dev_priv->display.crtc_disable = ironlake_crtc_disable;
 		dev_priv->display.off = ironlake_crtc_off;
 		dev_priv->display.update_plane = ironlake_update_plane;
 	} else {
-		dev_priv->display.dpms = i9xx_crtc_dpms;
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
+		dev_priv->display.crtc_enable = i9xx_crtc_enable;
+		dev_priv->display.crtc_disable = i9xx_crtc_disable;
 		dev_priv->display.off = i9xx_crtc_off;
 		dev_priv->display.update_plane = i9xx_update_plane;
 	}
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 02/58] drm/i915: rip out crtc prepare/commit indirection
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
  2012-08-19 19:12 ` [PATCH 01/58] drm/i915: add crtc->enable/disable vfuncs insted of dpms Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-08-29 17:52   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 03/58] drm/i915: add direct encoder disable/enable infrastructure Daniel Vetter
                   ` (63 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Just impendance matching with the the crtc helper stuff.

... and somehow the design of this all ended up in this commit here,
too ;-)

The big plan is that this new set of crtc display_funcs take full
responsibility of modeset operations for the entire display output
pipeline (by calling down into object-specific callbacks and
functions). The platform-specific callbacks simply know best what the
proper order is.

This has the drawback that we can't do minimal change-overs any more
if a modeset just disables one encoder in a cloned configuration
(because we will only expose a disable/enable action that takes
down/sets up the entire crtc including all encoders). Imo that's the
only sane way to do it though:
- The use-case for this is pretty minimal, even when presenting (at
  least sane people) should use a dual-screen output so that you can
  see your notes on your panel. Clone mode is imo BS.
- With all the clone mode constrains, shared resources, and special
  ordering requirements (which differ even on the same platform
  sometimes for different outputs) there's no way we'd get this right
  for all cases. Especially since this is a under-used feature.
- And to top it off: On haswell even dp link re-training requires us
  to take down the entire display pipe - otherwise the chip dies.

So the only sane way is to do a full modeset on every crtc where the
output config changes in any way.

To support global modeset (i.e. set the configuration for all crtcs at
once) we'd then add one more function to allocate global and shared
objects in the best ways (e.g. fdi links, pch plls, ...). The crtc
functions would then simply use the pre-allocated stuff (and shouldn't
be able to fail, ever). We could even do all the object pinning in
there (and maybe try to defragment the global gtt if we fail)!

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 37 ++----------------------------------
 1 file changed, 2 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index adc9868..04bec4b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3500,34 +3500,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
 	}
 }
 
-/* Prepare for a mode set.
- *
- * Note we could be a lot smarter here.  We need to figure out which outputs
- * will be enabled, which disabled (in short, how the config will changes)
- * and perform the minimum necessary steps to accomplish that, e.g. updating
- * watermarks, FBC configuration, making sure PLLs are programmed correctly,
- * panel fitting is in the proper state, etc.
- */
-static void i9xx_crtc_prepare(struct drm_crtc *crtc)
-{
-	i9xx_crtc_disable(crtc);
-}
-
-static void i9xx_crtc_commit(struct drm_crtc *crtc)
-{
-	i9xx_crtc_enable(crtc);
-}
-
-static void ironlake_crtc_prepare(struct drm_crtc *crtc)
-{
-	ironlake_crtc_disable(crtc);
-}
-
-static void ironlake_crtc_commit(struct drm_crtc *crtc)
-{
-	ironlake_crtc_enable(crtc);
-}
-
 void intel_encoder_prepare(struct drm_encoder *encoder)
 {
 	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
@@ -6626,13 +6598,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	intel_crtc->active = true; /* force the pipe off on setup_init_config */
 	intel_crtc->bpp = 24; /* default for pre-Ironlake */
 
-	if (HAS_PCH_SPLIT(dev)) {
-		intel_helper_funcs.prepare = ironlake_crtc_prepare;
-		intel_helper_funcs.commit = ironlake_crtc_commit;
-	} else {
-		intel_helper_funcs.prepare = i9xx_crtc_prepare;
-		intel_helper_funcs.commit = i9xx_crtc_commit;
-	}
+	intel_helper_funcs.prepare = dev_priv->display.crtc_disable;
+	intel_helper_funcs.commit = dev_priv->display.crtc_enable;
 
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 }
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 03/58] drm/i915: add direct encoder disable/enable infrastructure
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
  2012-08-19 19:12 ` [PATCH 01/58] drm/i915: add crtc->enable/disable vfuncs insted of dpms Daniel Vetter
  2012-08-19 19:12 ` [PATCH 02/58] drm/i915: rip out crtc prepare/commit indirection Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-08-29 18:01   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 04/58] drm/i915/hdmi: convert to encoder->disable/enable Daniel Vetter
                   ` (62 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 38 ++++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_drv.h     |  2 ++
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 04bec4b..82aaded 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3209,13 +3209,16 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	u32 temp;
 	bool is_pch_port;
 
+	/* XXX: For compatability with the crtc helper code, call the encoder's
+	 * enable function unconditionally for now. */
 	if (intel_crtc->active)
-		return;
+		goto encoders;
 
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
@@ -3262,6 +3265,12 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	mutex_unlock(&dev->struct_mutex);
 
 	intel_crtc_update_cursor(crtc, true);
+
+encoders:
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		if (encoder->enable)
+			encoder->enable(encoder);
+	}
 }
 
 static void ironlake_crtc_disable(struct drm_crtc *crtc)
@@ -3269,10 +3278,18 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	u32 reg, temp;
 
+	/* XXX: For compatability with the crtc helper code, call the encoder's
+	 * disable function unconditionally for now. */
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		if (encoder->disable)
+			encoder->disable(encoder);
+	}
+
 	if (!intel_crtc->active)
 		return;
 
@@ -3371,11 +3388,14 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
+	/* XXX: For compatability with the crtc helper code, call the encoder's
+	 * enable function unconditionally for now. */
 	if (intel_crtc->active)
-		return;
+		goto encoders;
 
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
@@ -3390,6 +3410,12 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	/* Give the overlay scaler a chance to enable if it's on this pipe */
 	intel_crtc_dpms_overlay(intel_crtc, true);
 	intel_crtc_update_cursor(crtc, true);
+
+encoders:
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		if (encoder->enable)
+			encoder->enable(encoder);
+	}
 }
 
 static void i9xx_crtc_disable(struct drm_crtc *crtc)
@@ -3397,9 +3423,17 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
+	/* XXX: For compatability with the crtc helper code, call the encoder's
+	 * disable function unconditionally for now. */
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		if (encoder->disable)
+			encoder->disable(encoder);
+	}
+
 	if (!intel_crtc->active)
 		return;
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 95f635b..9a5adcc 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;
 };
 
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 04/58] drm/i915/hdmi: convert to encoder->disable/enable
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (2 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 03/58] drm/i915: add direct encoder disable/enable infrastructure Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 19:24   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 05/58] drm/i915/tv: convert to encoder enable/disable Daniel Vetter
                   ` (61 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_ddi.c     |  30 ++++++---
 drivers/gpu/drm/i915/intel_display.c |  49 ++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |   8 ++-
 drivers/gpu/drm/i915/intel_hdmi.c    | 126 +++++++++++++++++++++++------------
 4 files changed, 160 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 170e386..38a7006 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -757,26 +757,34 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
-void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
+void intel_enable_ddi(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	int port = intel_hdmi->ddi_port;
 	u32 temp;
 
 	temp = I915_READ(DDI_BUF_CTL(port));
-
-	if (mode != DRM_MODE_DPMS_ON) {
-		temp &= ~DDI_BUF_CTL_ENABLE;
-	} else {
-		temp |= DDI_BUF_CTL_ENABLE;
-	}
+	temp |= DDI_BUF_CTL_ENABLE;
 
 	/* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width,
 	 * and swing/emphasis values are ignored so nothing special needs
 	 * to be done besides enabling the port.
 	 */
-	I915_WRITE(DDI_BUF_CTL(port),
-			temp);
+	I915_WRITE(DDI_BUF_CTL(port), temp);
+}
+
+void intel_disable_ddi(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	int port = intel_hdmi->ddi_port;
+	u32 temp;
+
+	temp = I915_READ(DDI_BUF_CTL(port));
+	temp &= ~DDI_BUF_CTL_ENABLE;
+
+	I915_WRITE(DDI_BUF_CTL(port), temp);
 }
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 82aaded..cbd356f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3554,6 +3554,17 @@ void intel_encoder_commit(struct drm_encoder *encoder)
 		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
+void intel_encoder_noop(struct drm_encoder *encoder)
+{
+}
+
+void intel_encoder_disable(struct drm_encoder *encoder)
+{
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+
+	intel_encoder->disable(intel_encoder);
+}
+
 void intel_encoder_destroy(struct drm_encoder *encoder)
 {
 	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
@@ -3562,6 +3573,44 @@ void intel_encoder_destroy(struct drm_encoder *encoder)
 	kfree(intel_encoder);
 }
 
+/* Simple dpms helper for encodres with just one connector, no cloning and only
+ * one kind of off state. It clamps all !ON modes to fully OFF and changes the
+ * state of the entire output pipe. */
+void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
+{
+	if (mode == DRM_MODE_DPMS_ON) {
+		encoder->connectors_active = true;
+
+		intel_crtc_dpms(encoder->base.crtc, DRM_MODE_DPMS_ON);
+	} else {
+		encoder->connectors_active = false;
+
+		intel_crtc_dpms(encoder->base.crtc, DRM_MODE_DPMS_OFF);
+	}
+}
+
+/* Even simpler default implementation, if there's really no special case to
+ * consider. */
+void intel_connector_dpms(struct drm_connector *connector, int mode)
+{
+	struct intel_encoder *encoder = intel_attached_encoder(connector);
+
+	/* All the simple cases only support two dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == connector->dpms)
+		return;
+
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	if (encoder->base.crtc)
+		intel_encoder_dpms(encoder, mode);
+	else
+		encoder->connectors_active = false;
+}
+
 static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
 				  const struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9a5adcc..759dcba 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);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index e4c37bb..acddaaa 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -601,11 +601,11 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 	intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
-static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
+static void intel_enable_hdmi(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	u32 temp;
 	u32 enable_bits = SDVO_ENABLE;
 
@@ -617,31 +617,12 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
 	/* HW workaround for IBX, we need to move the port to transcoder A
 	 * before disabling it. */
 	if (HAS_PCH_IBX(dev)) {
-		struct drm_crtc *crtc = encoder->crtc;
+		struct drm_crtc *crtc = encoder->base.crtc;
 		int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
 
-		if (mode != DRM_MODE_DPMS_ON) {
-			if (temp & SDVO_PIPE_B_SELECT) {
-				temp &= ~SDVO_PIPE_B_SELECT;
-				I915_WRITE(intel_hdmi->sdvox_reg, temp);
-				POSTING_READ(intel_hdmi->sdvox_reg);
-
-				/* Again we need to write this twice. */
-				I915_WRITE(intel_hdmi->sdvox_reg, temp);
-				POSTING_READ(intel_hdmi->sdvox_reg);
-
-				/* Transcoder selection bits only update
-				 * effectively on vblank. */
-				if (crtc)
-					intel_wait_for_vblank(dev, pipe);
-				else
-					msleep(50);
-			}
-		} else {
-			/* Restore the transcoder select bit. */
-			if (pipe == PIPE_B)
-				enable_bits |= SDVO_PIPE_B_SELECT;
-		}
+		/* Restore the transcoder select bit. */
+		if (pipe == PIPE_B)
+			enable_bits |= SDVO_PIPE_B_SELECT;
 	}
 
 	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
@@ -652,12 +633,67 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
 		POSTING_READ(intel_hdmi->sdvox_reg);
 	}
 
-	if (mode != DRM_MODE_DPMS_ON) {
-		temp &= ~enable_bits;
-	} else {
-		temp |= enable_bits;
+	temp |= enable_bits;
+
+	I915_WRITE(intel_hdmi->sdvox_reg, temp);
+	POSTING_READ(intel_hdmi->sdvox_reg);
+
+	/* HW workaround, need to write this twice for issue that may result
+	 * in first write getting masked.
+	 */
+	if (HAS_PCH_SPLIT(dev)) {
+		I915_WRITE(intel_hdmi->sdvox_reg, temp);
+		POSTING_READ(intel_hdmi->sdvox_reg);
+	}
+}
+
+static void intel_disable_hdmi(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	u32 temp;
+	u32 enable_bits = SDVO_ENABLE;
+
+	if (intel_hdmi->has_audio)
+		enable_bits |= SDVO_AUDIO_ENABLE;
+
+	temp = I915_READ(intel_hdmi->sdvox_reg);
+
+	/* HW workaround for IBX, we need to move the port to transcoder A
+	 * before disabling it. */
+	if (HAS_PCH_IBX(dev)) {
+		struct drm_crtc *crtc = encoder->base.crtc;
+		int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
+
+		if (temp & SDVO_PIPE_B_SELECT) {
+			temp &= ~SDVO_PIPE_B_SELECT;
+			I915_WRITE(intel_hdmi->sdvox_reg, temp);
+			POSTING_READ(intel_hdmi->sdvox_reg);
+
+			/* Again we need to write this twice. */
+			I915_WRITE(intel_hdmi->sdvox_reg, temp);
+			POSTING_READ(intel_hdmi->sdvox_reg);
+
+			/* Transcoder selection bits only update
+			 * effectively on vblank. */
+			if (crtc)
+				intel_wait_for_vblank(dev, pipe);
+			else
+				msleep(50);
+		}
 	}
 
+	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
+	 * we do this anyway which shows more stable in testing.
+	 */
+	if (HAS_PCH_SPLIT(dev)) {
+		I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE);
+		POSTING_READ(intel_hdmi->sdvox_reg);
+	}
+
+	temp &= ~enable_bits;
+
 	I915_WRITE(intel_hdmi->sdvox_reg, temp);
 	POSTING_READ(intel_hdmi->sdvox_reg);
 
@@ -849,23 +885,23 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
 }
 
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
-	.dpms = intel_ddi_dpms,
 	.mode_fixup = intel_hdmi_mode_fixup,
-	.prepare = intel_encoder_prepare,
+	.prepare = intel_encoder_noop,
 	.mode_set = intel_ddi_mode_set,
-	.commit = intel_encoder_commit,
+	.commit = intel_encoder_noop,
+	.disable = intel_encoder_disable,
 };
 
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
-	.dpms = intel_hdmi_dpms,
 	.mode_fixup = intel_hdmi_mode_fixup,
-	.prepare = intel_encoder_prepare,
+	.prepare = intel_encoder_noop,
 	.mode_set = intel_hdmi_mode_set,
-	.commit = intel_encoder_commit,
+	.commit = intel_encoder_noop,
+	.disable = intel_encoder_disable,
 };
 
 static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_connector_dpms,
 	.detect = intel_hdmi_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_hdmi_set_property,
@@ -964,10 +1000,18 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 		intel_hdmi->set_infoframes = cpt_set_infoframes;
 	}
 
-	if (IS_HASWELL(dev))
-		drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs_hsw);
-	else
-		drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
+	if (IS_HASWELL(dev)) {
+		intel_encoder->enable = intel_enable_ddi;
+		intel_encoder->disable = intel_disable_ddi;
+		drm_encoder_helper_add(&intel_encoder->base,
+				       &intel_hdmi_helper_funcs_hsw);
+	} else {
+		intel_encoder->enable = intel_enable_hdmi;
+		intel_encoder->disable = intel_disable_hdmi;
+		drm_encoder_helper_add(&intel_encoder->base,
+				       &intel_hdmi_helper_funcs);
+	}
+
 
 	intel_hdmi_add_properties(intel_hdmi, connector);
 
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 05/58] drm/i915/tv: convert to encoder enable/disable
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (3 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 04/58] drm/i915/hdmi: convert to encoder->disable/enable Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 19:25   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 06/58] drm/i915/lvds: convert to encoder disable/enable Daniel Vetter
                   ` (60 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Like hdmi tv outputs are simple: They only have 2 states and can't be
cloned. Hence give it the same treatment.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_tv.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 95653a5..281e0cf 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -837,21 +837,21 @@ static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
 }
 
 static void
-intel_tv_dpms(struct drm_encoder *encoder, int mode)
+intel_enable_tv(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-	case DRM_MODE_DPMS_OFF:
-		I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE);
-		break;
-	}
+	I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
+}
+
+static void
+intel_disable_tv(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE);
 }
 
 static const struct tv_mode *
@@ -1478,15 +1478,15 @@ out:
 }
 
 static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
-	.dpms = intel_tv_dpms,
 	.mode_fixup = intel_tv_mode_fixup,
-	.prepare = intel_encoder_prepare,
+	.prepare = intel_encoder_noop,
 	.mode_set = intel_tv_mode_set,
-	.commit = intel_encoder_commit,
+	.commit = intel_encoder_noop,
+	.disable = intel_encoder_disable,
 };
 
 static const struct drm_connector_funcs intel_tv_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_connector_dpms,
 	.detect = intel_tv_detect,
 	.destroy = intel_tv_destroy,
 	.set_property = intel_tv_set_property,
@@ -1616,6 +1616,9 @@ intel_tv_init(struct drm_device *dev)
 	drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
 			 DRM_MODE_ENCODER_TVDAC);
 
+	intel_encoder->enable = intel_enable_tv;
+	intel_encoder->disable = intel_disable_tv;
+
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_TVOUT;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 06/58] drm/i915/lvds: convert to encoder disable/enable
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (4 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 05/58] drm/i915/tv: convert to encoder enable/disable Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 19:26   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 07/58] drm/i915/dp: " Daniel Vetter
                   ` (59 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

With the previous patch LVDS is also a simple case. Treat it
accordingly.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_lvds.c | 52 +++++++++++----------------------------
 1 file changed, 14 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index d789fda..3baa224 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -68,10 +68,11 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
 /**
  * Sets the power state for the panel.
  */
-static void intel_lvds_enable(struct intel_lvds *intel_lvds)
+static void intel_enable_lvds(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = intel_lvds->base.base.dev;
-	struct intel_crtc *intel_crtc = to_intel_crtc(intel_lvds->base.base.crtc);
+	struct drm_device *dev = encoder->base.dev;
+	struct intel_lvds *intel_lvds = to_intel_lvds(&encoder->base);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 ctl_reg, lvds_reg, stat_reg;
 
@@ -111,9 +112,10 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds)
 	intel_panel_enable_backlight(dev, intel_crtc->pipe);
 }
 
-static void intel_lvds_disable(struct intel_lvds *intel_lvds)
+static void intel_disable_lvds(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = intel_lvds->base.base.dev;
+	struct drm_device *dev = encoder->base.dev;
+	struct intel_lvds *intel_lvds = to_intel_lvds(&encoder->base);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 ctl_reg, lvds_reg, stat_reg;
 
@@ -142,18 +144,6 @@ static void intel_lvds_disable(struct intel_lvds *intel_lvds)
 	POSTING_READ(lvds_reg);
 }
 
-static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
-{
-	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-
-	if (mode == DRM_MODE_DPMS_ON)
-		intel_lvds_enable(intel_lvds);
-	else
-		intel_lvds_disable(intel_lvds);
-
-	/* XXX: We never power down the LVDS pairs. */
-}
-
 static int intel_lvds_mode_valid(struct drm_connector *connector,
 				 struct drm_display_mode *mode)
 {
@@ -405,23 +395,6 @@ out:
 	return true;
 }
 
-static void intel_lvds_prepare(struct drm_encoder *encoder)
-{
-	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-
-	intel_lvds_disable(intel_lvds);
-}
-
-static void intel_lvds_commit(struct drm_encoder *encoder)
-{
-	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-
-	/* Always do a full power on as we do not know what state
-	 * we were left in.
-	 */
-	intel_lvds_enable(intel_lvds);
-}
-
 static void intel_lvds_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
@@ -596,11 +569,11 @@ static int intel_lvds_set_property(struct drm_connector *connector,
 }
 
 static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
-	.dpms = intel_lvds_dpms,
 	.mode_fixup = intel_lvds_mode_fixup,
-	.prepare = intel_lvds_prepare,
+	.prepare = intel_encoder_noop,
 	.mode_set = intel_lvds_mode_set,
-	.commit = intel_lvds_commit,
+	.commit = intel_encoder_noop,
+	.disable = intel_encoder_disable,
 };
 
 static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
@@ -610,7 +583,7 @@ static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs
 };
 
 static const struct drm_connector_funcs intel_lvds_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_connector_dpms,
 	.detect = intel_lvds_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_lvds_set_property,
@@ -964,6 +937,9 @@ bool intel_lvds_init(struct drm_device *dev)
 	drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
 			 DRM_MODE_ENCODER_LVDS);
 
+	intel_encoder->enable = intel_enable_lvds;
+	intel_encoder->disable = intel_disable_lvds;
+
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_LVDS;
 
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 07/58] drm/i915/dp: convert to encoder disable/enable
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (5 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 06/58] drm/i915/lvds: convert to encoder disable/enable Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 19:33   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 08/58] drm/i915/crt: " Daniel Vetter
                   ` (58 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

DP is the first encoder which isn't simple. As

commit d240f20f545fa4ed78ce48d1eb62ab529f2b1467
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
Date:   Fri Aug 13 15:43:26 2010 -0700

    drm/i915: make sure eDP PLL is enabled at the right time

discovered, we need to enable the eDP PLL for the cpu port _before_ we
enable the pipes and planes. After a few more commits the current
solution is to enable the PLL in the dp mode_set function (because
this is the only encoder callback the crtc helper code calls before it
calls the crtc's commit function).

Now I suspect that we actually should enable/disable the entire cpu
eDP port before/after planes, but thanks to how the crtc helper code
assumes that you can disable an encoder without disabling it's crtc
right away, this won't work.

The result is that the current prepare/commit hooks don't touch the
eDP PLL, but instead it get's frobbed in dp_mode_set and in the dp
dpms function. Hence we need to keep things (at least for now)
bug-for-bug compatible by using our own special dp dpms function and
keep everything else more-or-less as-is (just using our own
infrastrucutre now).

This mess can only be cleaned up once we control the entire modeset
sequence and can move things around freely.

v2: Squash unsupported dpms modes to OFF at the beginning of the DP
dpms function.

v3: Need to set the dpms state to off in dp_disable, otherwise this
breaks the newly added WARNs ...

v4: Rebased against edp panel off sequence changes in 3.6-rc2

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_dp.c | 88 +++++++++++++++++++++--------------------
 1 file changed, 46 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 977d9d2..7ee954c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1250,10 +1250,9 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
 	}
 }
 
-static void intel_dp_prepare(struct drm_encoder *encoder)
+static void intel_disable_dp(struct intel_encoder *encoder)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
 	/* Make sure the panel is off before trying to change the mode. But also
 	 * ensure that we have vdd while we switch off the panel. */
@@ -1262,62 +1261,64 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	ironlake_edp_panel_off(intel_dp);
 	intel_dp_link_down(intel_dp);
+
+	intel_dp->dpms_mode = DRM_MODE_DPMS_OFF;
 }
 
-static void intel_dp_commit(struct drm_encoder *encoder)
+static void intel_enable_dp(struct intel_encoder *encoder)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 
 	ironlake_edp_panel_vdd_on(intel_dp);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
-	intel_dp_start_link_train(intel_dp);
-	ironlake_edp_panel_on(intel_dp);
-	ironlake_edp_panel_vdd_off(intel_dp, true);
-	intel_dp_complete_link_train(intel_dp);
+	if (!(dp_reg & DP_PORT_EN)) {
+		intel_dp_start_link_train(intel_dp);
+		ironlake_edp_panel_on(intel_dp);
+		ironlake_edp_panel_vdd_off(intel_dp, true);
+		intel_dp_complete_link_train(intel_dp);
+	} else
+		ironlake_edp_panel_vdd_off(intel_dp, false);
 	ironlake_edp_backlight_on(intel_dp);
 
 	intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
-
-	if (HAS_PCH_CPT(dev))
-		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
 static void
-intel_dp_dpms(struct drm_encoder *encoder, int mode)
+intel_dp_dpms(struct drm_connector *connector, int mode)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+
+	/* DP supports only 2 dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == connector->dpms)
+		return;
+
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	if (!intel_dp->base.base.crtc) {
+		intel_dp->base.connectors_active = false;
+		return;
+	}
 
 	if (mode != DRM_MODE_DPMS_ON) {
-		/* Switching the panel off requires vdd. */
-		ironlake_edp_panel_vdd_on(intel_dp);
-		ironlake_edp_backlight_off(intel_dp);
-		intel_dp_sink_dpms(intel_dp, mode);
-		ironlake_edp_panel_off(intel_dp);
-		intel_dp_link_down(intel_dp);
+		intel_encoder_dpms(&intel_dp->base, mode);
+		WARN_ON(intel_dp->dpms_mode != DRM_MODE_DPMS_OFF);
 
 		if (is_cpu_edp(intel_dp))
-			ironlake_edp_pll_off(encoder);
+			ironlake_edp_pll_off(&intel_dp->base.base);
 	} else {
 		if (is_cpu_edp(intel_dp))
-			ironlake_edp_pll_on(encoder);
+			ironlake_edp_pll_on(&intel_dp->base.base);
 
-		ironlake_edp_panel_vdd_on(intel_dp);
-		intel_dp_sink_dpms(intel_dp, mode);
-		if (!(dp_reg & DP_PORT_EN)) {
-			intel_dp_start_link_train(intel_dp);
-			ironlake_edp_panel_on(intel_dp);
-			ironlake_edp_panel_vdd_off(intel_dp, true);
-			intel_dp_complete_link_train(intel_dp);
-		} else
-			ironlake_edp_panel_vdd_off(intel_dp, false);
-		ironlake_edp_backlight_on(intel_dp);
+		intel_encoder_dpms(&intel_dp->base, mode);
+		WARN_ON(intel_dp->dpms_mode != DRM_MODE_DPMS_ON);
 	}
-	intel_dp->dpms_mode = mode;
 }
 
 /*
@@ -2347,15 +2348,15 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 }
 
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
-	.dpms = intel_dp_dpms,
 	.mode_fixup = intel_dp_mode_fixup,
-	.prepare = intel_dp_prepare,
+	.prepare = intel_encoder_noop,
 	.mode_set = intel_dp_mode_set,
-	.commit = intel_dp_commit,
+	.commit = intel_encoder_noop,
+	.disable = intel_encoder_disable,
 };
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_dp_dpms,
 	.detect = intel_dp_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_dp_set_property,
@@ -2486,6 +2487,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	drm_sysfs_connector_add(connector);
 
+	intel_encoder->enable = intel_enable_dp;
+	intel_encoder->disable = intel_disable_dp;
+
 	/* Set up the DDC bus. */
 	switch (port) {
 	case PORT_A:
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 08/58] drm/i915/crt: convert to encoder disable/enable
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (6 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 07/58] drm/i915/dp: " Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 19:50   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 09/58] drm/i915/sdvo: " Daniel Vetter
                   ` (57 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

CRT is the first output which can be cloned, hence we cannot (yet)
move the dpms handling over to disable/enable. This requires some more
smarts in intel_crtc_dpms first to set the display pipe status
depening upon encoder->connectors_active of all connected encoders.

Because that will happen in a separate step, don't touch the dpms
functions, yet.

v2: Be careful about clearing the _DISABLE flags for intermediate dpms
modes - otherwise we might clobber the crt state when another (cloned)
connector gets enabled.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_crt.c | 36 ++++++++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 1d05b2d..543ea40 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -61,6 +61,29 @@ static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
 	return container_of(encoder, struct intel_crt, base);
 }
 
+static void intel_disable_crt(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+	u32 temp;
+
+	temp = I915_READ(crt->adpa_reg);
+	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
+	temp &= ~ADPA_DAC_ENABLE;
+	I915_WRITE(crt->adpa_reg, temp);
+}
+
+static void intel_enable_crt(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+	u32 temp;
+
+	temp = I915_READ(crt->adpa_reg);
+	temp |= ADPA_DAC_ENABLE;
+	I915_WRITE(crt->adpa_reg, temp);
+}
+
 static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
@@ -575,18 +598,20 @@ static void intel_crt_reset(struct drm_connector *connector)
 
 static const struct drm_encoder_helper_funcs pch_encoder_funcs = {
 	.mode_fixup = intel_crt_mode_fixup,
-	.prepare = intel_encoder_prepare,
-	.commit = intel_encoder_commit,
+	.prepare = intel_encoder_noop,
+	.commit = intel_encoder_noop,
 	.mode_set = intel_crt_mode_set,
 	.dpms = pch_crt_dpms,
+	.disable = intel_encoder_disable,
 };
 
 static const struct drm_encoder_helper_funcs gmch_encoder_funcs = {
 	.mode_fixup = intel_crt_mode_fixup,
-	.prepare = intel_encoder_prepare,
-	.commit = intel_encoder_commit,
+	.prepare = intel_encoder_noop,
+	.commit = intel_encoder_noop,
 	.mode_set = intel_crt_mode_set,
 	.dpms = gmch_crt_dpms,
+	.disable = intel_encoder_disable,
 };
 
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
@@ -682,6 +707,9 @@ void intel_crt_init(struct drm_device *dev)
 	else
 		crt->adpa_reg = ADPA;
 
+	crt->base.disable = intel_disable_crt;
+	crt->base.enable = intel_enable_crt;
+
 	drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs);
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 09/58] drm/i915/sdvo: convert to encoder disable/enable
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (7 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 08/58] drm/i915/crt: " Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 19:52   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 10/58] drm/i915/dvo: " Daniel Vetter
                   ` (56 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Similar to crt, this doesn't convert the dpms functions.
Also similar to crt, we don't switch of the display pipe
for the intermediate modes, only DPMS_OFF is truely off.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_sdvo.c | 58 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 56 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index f3762f8..20feaa3 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1142,6 +1142,56 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 	intel_sdvo_write_sdvox(intel_sdvo, sdvox);
 }
 
+static void intel_disable_sdvo(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	u32 temp;
+
+	intel_sdvo_set_active_outputs(intel_sdvo, 0);
+	if (0)
+		intel_sdvo_set_encoder_power_state(intel_sdvo,
+						   DRM_MODE_DPMS_OFF);
+
+	temp = I915_READ(intel_sdvo->sdvo_reg);
+	if ((temp & SDVO_ENABLE) != 0) {
+		intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE);
+	}
+}
+
+static void intel_enable_sdvo(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	u32 temp;
+	bool input1, input2;
+	int i;
+	u8 status;
+
+	temp = I915_READ(intel_sdvo->sdvo_reg);
+	if ((temp & SDVO_ENABLE) == 0)
+		intel_sdvo_write_sdvox(intel_sdvo, temp | SDVO_ENABLE);
+	for (i = 0; i < 2; i++)
+		intel_wait_for_vblank(dev, intel_crtc->pipe);
+
+	status = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2);
+	/* Warn if the device reported failure to sync.
+	 * A lot of SDVO devices fail to notify of sync, but it's
+	 * a given it the status is a success, we succeeded.
+	 */
+	if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
+		DRM_DEBUG_KMS("First %s output reported failure to "
+				"sync\n", SDVO_NAME(intel_sdvo));
+	}
+
+	if (0)
+		intel_sdvo_set_encoder_power_state(intel_sdvo,
+						   DRM_MODE_DPMS_ON);
+	intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
+}
+
 static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
@@ -1847,9 +1897,10 @@ done:
 static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
 	.dpms = intel_sdvo_dpms,
 	.mode_fixup = intel_sdvo_mode_fixup,
-	.prepare = intel_encoder_prepare,
+	.prepare = intel_encoder_noop,
 	.mode_set = intel_sdvo_mode_set,
-	.commit = intel_encoder_commit,
+	.commit = intel_encoder_noop,
+	.disable = intel_encoder_disable
 };
 
 static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
@@ -2576,6 +2627,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 
 	drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
 
+	intel_encoder->disable = intel_disable_sdvo;
+	intel_encoder->enable = intel_enable_sdvo;
+
 	/* In default case sdvo lvds is false */
 	if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
 		goto err;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 10/58] drm/i915/dvo: convert to encoder disable/enable
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (8 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 09/58] drm/i915/sdvo: " Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 19:53   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 11/58] drm/i915: convert dpms functions of dvo/sdvo/crt Daniel Vetter
                   ` (55 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Similar to the sdvo conversion.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_dvo.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 227551f..4ad988f 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -105,6 +105,30 @@ static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector)
 			    struct intel_dvo, base);
 }
 
+static void intel_disable_dvo(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	u32 dvo_reg = intel_dvo->dev.dvo_reg;
+	u32 temp = I915_READ(dvo_reg);
+
+	intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
+	I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
+	I915_READ(dvo_reg);
+}
+
+static void intel_enable_dvo(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	u32 dvo_reg = intel_dvo->dev.dvo_reg;
+	u32 temp = I915_READ(dvo_reg);
+
+	I915_WRITE(dvo_reg, temp | DVO_ENABLE);
+	I915_READ(dvo_reg);
+	intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
+}
+
 static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
@@ -277,9 +301,10 @@ static void intel_dvo_destroy(struct drm_connector *connector)
 static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
 	.dpms = intel_dvo_dpms,
 	.mode_fixup = intel_dvo_mode_fixup,
-	.prepare = intel_encoder_prepare,
+	.prepare = intel_encoder_noop,
 	.mode_set = intel_dvo_mode_set,
-	.commit = intel_encoder_commit,
+	.commit = intel_encoder_noop,
+	.disable = intel_encoder_disable,
 };
 
 static const struct drm_connector_funcs intel_dvo_connector_funcs = {
@@ -372,6 +397,9 @@ void intel_dvo_init(struct drm_device *dev)
 	drm_encoder_init(dev, &intel_encoder->base,
 			 &intel_dvo_enc_funcs, encoder_type);
 
+	intel_encoder->disable = intel_disable_dvo;
+	intel_encoder->enable = intel_enable_dvo;
+
 	/* Now, try to find a controller */
 	for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
 		struct drm_connector *connector = &intel_connector->base;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 11/58] drm/i915: convert dpms functions of dvo/sdvo/crt
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (9 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 10/58] drm/i915/dvo: " Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-08-29  7:12   ` [PATCH] " Daniel Vetter
  2012-08-19 19:12 ` [PATCH 12/58] drm/i915: rip out encoder->disable/enable checks Daniel Vetter
                   ` (54 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_crt.c     | 97 +++++++++++++++++++-----------------
 drivers/gpu/drm/i915/intel_display.c | 37 +++++++-------
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 drivers/gpu/drm/i915/intel_dvo.c     | 39 +++++++++++----
 drivers/gpu/drm/i915/intel_sdvo.c    | 60 ++++++++++------------
 5 files changed, 122 insertions(+), 112 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 543ea40..15c1ff8 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -84,13 +84,17 @@ static void intel_enable_crt(struct intel_encoder *encoder)
 	I915_WRITE(crt->adpa_reg, temp);
 }
 
-static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
+/* Note: The caller is required to filter out dpms modes not supported by the
+ * platform. */
+static void intel_crtc_set_dpms(struct intel_encoder *encoder, int mode)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
 	u32 temp;
 
-	temp = I915_READ(PCH_ADPA);
+	temp = I915_READ(crt->adpa_reg);
+	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
 	temp &= ~ADPA_DAC_ENABLE;
 
 	switch (mode) {
@@ -98,44 +102,59 @@ static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
 		temp |= ADPA_DAC_ENABLE;
 		break;
 	case DRM_MODE_DPMS_STANDBY:
+		temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
+		break;
 	case DRM_MODE_DPMS_SUSPEND:
+		temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
+		break;
 	case DRM_MODE_DPMS_OFF:
-		/* Just leave port enable cleared */
+		temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
 		break;
 	}
 
-	I915_WRITE(PCH_ADPA, temp);
+	I915_WRITE(crt->adpa_reg, temp);
 }
 
-static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
+static void intel_crt_dpms(struct drm_connector *connector, int mode)
 {
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 temp;
-
-	temp = I915_READ(ADPA);
-	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
-	temp &= ~ADPA_DAC_ENABLE;
+	struct drm_device *dev = connector->dev;
+	struct intel_encoder *encoder = intel_attached_encoder(connector);
+	struct drm_crtc *crtc;
+	int old_dpms;
 
-	if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON)
+	/* PCH platforms and VLV only support on/off. */
+	if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
 		mode = DRM_MODE_DPMS_OFF;
 
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		temp |= ADPA_DAC_ENABLE;
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-		temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
-		break;
-	case DRM_MODE_DPMS_SUSPEND:
-		temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
-		break;
-	case DRM_MODE_DPMS_OFF:
-		temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
-		break;
+	if (mode == connector->dpms)
+		return;
+
+	old_dpms = connector->dpms;
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	crtc = encoder->base.crtc;
+	if (!crtc) {
+		encoder->connectors_active = false;
+		return;
 	}
 
-	I915_WRITE(ADPA, temp);
+	/* We need the pipe to run for anything but OFF. */
+	if (mode == DRM_MODE_DPMS_OFF)
+		encoder->connectors_active = false;
+	else
+		encoder->connectors_active = true;
+
+	if (mode < old_dpms) {
+		/* From off to on, enable the pipe first. */
+		intel_crtc_update_dpms(crtc);
+
+		intel_crtc_set_dpms(encoder, mode);
+	} else {
+		intel_crtc_set_dpms(encoder, mode);
+
+		intel_crtc_update_dpms(crtc);
+	}
 }
 
 static int intel_crt_mode_valid(struct drm_connector *connector,
@@ -596,27 +615,17 @@ static void intel_crt_reset(struct drm_connector *connector)
  * Routines for controlling stuff on the analog port
  */
 
-static const struct drm_encoder_helper_funcs pch_encoder_funcs = {
-	.mode_fixup = intel_crt_mode_fixup,
-	.prepare = intel_encoder_noop,
-	.commit = intel_encoder_noop,
-	.mode_set = intel_crt_mode_set,
-	.dpms = pch_crt_dpms,
-	.disable = intel_encoder_disable,
-};
-
-static const struct drm_encoder_helper_funcs gmch_encoder_funcs = {
+static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
 	.mode_fixup = intel_crt_mode_fixup,
 	.prepare = intel_encoder_noop,
 	.commit = intel_encoder_noop,
 	.mode_set = intel_crt_mode_set,
-	.dpms = gmch_crt_dpms,
 	.disable = intel_encoder_disable,
 };
 
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
 	.reset = intel_crt_reset,
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_crt_dpms,
 	.detect = intel_crt_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = intel_crt_destroy,
@@ -657,7 +666,6 @@ void intel_crt_init(struct drm_device *dev)
 	struct intel_crt *crt;
 	struct intel_connector *intel_connector;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	const struct drm_encoder_helper_funcs *encoder_helper_funcs;
 
 	/* Skip machines without VGA that falsely report hotplug events */
 	if (dmi_check_system(intel_no_crt))
@@ -696,11 +704,6 @@ void intel_crt_init(struct drm_device *dev)
 	connector->doublescan_allowed = 0;
 
 	if (HAS_PCH_SPLIT(dev))
-		encoder_helper_funcs = &pch_encoder_funcs;
-	else
-		encoder_helper_funcs = &gmch_encoder_funcs;
-
-	if (HAS_PCH_SPLIT(dev))
 		crt->adpa_reg = PCH_ADPA;
 	else if (IS_VALLEYVIEW(dev))
 		crt->adpa_reg = VLV_ADPA;
@@ -710,7 +713,7 @@ void intel_crt_init(struct drm_device *dev)
 	crt->base.disable = intel_disable_crt;
 	crt->base.enable = intel_enable_crt;
 
-	drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs);
+	drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs);
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
 	drm_sysfs_connector_add(connector);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cbd356f..0d48ebe 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3462,34 +3462,31 @@ static void i9xx_crtc_off(struct drm_crtc *crtc)
 /**
  * Sets the power management mode of the pipe and plane.
  */
-static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
+void intel_crtc_update_dpms(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder;
 	int pipe = intel_crtc->pipe;
-	bool enabled;
+	bool enabled, enable = false;
+	int mode;
+
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
+		enable |= intel_encoder->connectors_active;
+
+	mode = enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF;
 
 	if (intel_crtc->dpms_mode == mode)
 		return;
 
 	intel_crtc->dpms_mode = mode;
 
-	/* XXX: When our outputs are all unaware of DPMS modes other than off
-	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
-	 */
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
+	if (enable)
 		dev_priv->display.crtc_enable(crtc);
-		break;
-
-	case DRM_MODE_DPMS_OFF:
+	else
 		dev_priv->display.crtc_disable(crtc);
-		break;
-	}
 
 	if (!dev->primary->master)
 		return;
@@ -3498,7 +3495,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 	if (!master_priv->sarea_priv)
 		return;
 
-	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
+	enabled = crtc->enabled && enable;
 
 	switch (pipe) {
 	case 0:
@@ -3517,11 +3514,12 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 
 static void intel_crtc_disable(struct drm_crtc *crtc)
 {
-	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+	/* crtc->disable is only called when we have no encoders, hence this
+	 * will disable the pipe. */
+	intel_crtc_update_dpms(crtc);
 	dev_priv->display.off(crtc);
 
 	assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
@@ -3581,11 +3579,11 @@ void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
 	if (mode == DRM_MODE_DPMS_ON) {
 		encoder->connectors_active = true;
 
-		intel_crtc_dpms(encoder->base.crtc, DRM_MODE_DPMS_ON);
+		intel_crtc_update_dpms(encoder->base.crtc);
 	} else {
 		encoder->connectors_active = false;
 
-		intel_crtc_dpms(encoder->base.crtc, DRM_MODE_DPMS_OFF);
+		intel_crtc_update_dpms(encoder->base.crtc);
 	}
 }
 
@@ -6609,7 +6607,6 @@ static void intel_crtc_reset(struct drm_crtc *crtc)
 }
 
 static struct drm_crtc_helper_funcs intel_helper_funcs = {
-	.dpms = intel_crtc_dpms,
 	.mode_fixup = intel_crtc_mode_fixup,
 	.mode_set = intel_crtc_mode_set,
 	.mode_set_base = intel_pipe_set_base,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 759dcba..2456245 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);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 4ad988f..c55a13e 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -129,21 +129,39 @@ static void intel_enable_dvo(struct intel_encoder *encoder)
 	intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
 }
 
-static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
+static void intel_dvo_dpms(struct drm_connector *connector, int mode)
 {
-	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
-	struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
-	u32 dvo_reg = intel_dvo->dev.dvo_reg;
-	u32 temp = I915_READ(dvo_reg);
+	struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
+	struct drm_crtc *crtc;
+
+	/* dvo supports only 2 dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == connector->dpms)
+		return;
+
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	crtc = intel_dvo->base.base.crtc;
+	if (!crtc) {
+		intel_dvo->base.connectors_active = false;
+		return;
+	}
 
 	if (mode == DRM_MODE_DPMS_ON) {
-		I915_WRITE(dvo_reg, temp | DVO_ENABLE);
-		I915_READ(dvo_reg);
+		intel_dvo->base.connectors_active = true;
+
+		intel_crtc_update_dpms(crtc);
+
 		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
 	} else {
 		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
-		I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
-		I915_READ(dvo_reg);
+
+		intel_dvo->base.connectors_active = false;
+
+		intel_crtc_update_dpms(crtc);
 	}
 }
 
@@ -299,7 +317,6 @@ static void intel_dvo_destroy(struct drm_connector *connector)
 }
 
 static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
-	.dpms = intel_dvo_dpms,
 	.mode_fixup = intel_dvo_mode_fixup,
 	.prepare = intel_encoder_noop,
 	.mode_set = intel_dvo_mode_set,
@@ -308,7 +325,7 @@ static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
 };
 
 static const struct drm_connector_funcs intel_dvo_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_dvo_dpms,
 	.detect = intel_dvo_detect,
 	.destroy = intel_dvo_destroy,
 	.fill_modes = drm_helper_probe_single_connector_modes,
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 20feaa3..a01c470 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1192,51 +1192,44 @@ static void intel_enable_sdvo(struct intel_encoder *encoder)
 	intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
 }
 
-static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
+static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
 {
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-	u32 temp;
+	struct drm_crtc *crtc;
+	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
+
+	/* dvo supports only 2 dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == connector->dpms)
+		return;
+
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	crtc = intel_sdvo->base.base.crtc;
+	if (!crtc) {
+		intel_sdvo->base.connectors_active = false;
+		return;
+	}
 
 	if (mode != DRM_MODE_DPMS_ON) {
 		intel_sdvo_set_active_outputs(intel_sdvo, 0);
 		if (0)
 			intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
 
-		if (mode == DRM_MODE_DPMS_OFF) {
-			temp = I915_READ(intel_sdvo->sdvo_reg);
-			if ((temp & SDVO_ENABLE) != 0) {
-				intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE);
-			}
-		}
+		intel_sdvo->base.connectors_active = false;
+
+		intel_crtc_update_dpms(crtc);
 	} else {
-		bool input1, input2;
-		int i;
-		u8 status;
-
-		temp = I915_READ(intel_sdvo->sdvo_reg);
-		if ((temp & SDVO_ENABLE) == 0)
-			intel_sdvo_write_sdvox(intel_sdvo, temp | SDVO_ENABLE);
-		for (i = 0; i < 2; i++)
-			intel_wait_for_vblank(dev, intel_crtc->pipe);
-
-		status = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2);
-		/* Warn if the device reported failure to sync.
-		 * A lot of SDVO devices fail to notify of sync, but it's
-		 * a given it the status is a success, we succeeded.
-		 */
-		if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
-			DRM_DEBUG_KMS("First %s output reported failure to "
-					"sync\n", SDVO_NAME(intel_sdvo));
-		}
+		intel_sdvo->base.connectors_active = true;
+
+		intel_crtc_update_dpms(crtc);
 
 		if (0)
 			intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
 		intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
 	}
-	return;
 }
 
 static int intel_sdvo_mode_valid(struct drm_connector *connector,
@@ -1895,7 +1888,6 @@ done:
 }
 
 static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
-	.dpms = intel_sdvo_dpms,
 	.mode_fixup = intel_sdvo_mode_fixup,
 	.prepare = intel_encoder_noop,
 	.mode_set = intel_sdvo_mode_set,
@@ -1904,7 +1896,7 @@ static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
 };
 
 static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_sdvo_dpms,
 	.detect = intel_sdvo_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_sdvo_set_property,
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 12/58] drm/i915: rip out encoder->disable/enable checks
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (10 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 11/58] drm/i915: convert dpms functions of dvo/sdvo/crt Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:11   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 13/58] drm/i915: clean up encoder_prepare/commit Daniel Vetter
                   ` (53 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

All encoders are now converted so there's no need for these checks any
more.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0d48ebe..4805385 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3267,10 +3267,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_update_cursor(crtc, true);
 
 encoders:
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
-		if (encoder->enable)
-			encoder->enable(encoder);
-	}
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->enable(encoder);
 }
 
 static void ironlake_crtc_disable(struct drm_crtc *crtc)
@@ -3285,10 +3283,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
 	/* XXX: For compatability with the crtc helper code, call the encoder's
 	 * disable function unconditionally for now. */
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
-		if (encoder->disable)
-			encoder->disable(encoder);
-	}
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
 
 	if (!intel_crtc->active)
 		return;
@@ -3412,10 +3408,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_update_cursor(crtc, true);
 
 encoders:
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
-		if (encoder->enable)
-			encoder->enable(encoder);
-	}
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->enable(encoder);
 }
 
 static void i9xx_crtc_disable(struct drm_crtc *crtc)
@@ -3429,10 +3423,8 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 
 	/* XXX: For compatability with the crtc helper code, call the encoder's
 	 * disable function unconditionally for now. */
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
-		if (encoder->disable)
-			encoder->disable(encoder);
-	}
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
 
 	if (!intel_crtc->active)
 		return;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 13/58] drm/i915: clean up encoder_prepare/commit
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (11 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 12/58] drm/i915: rip out encoder->disable/enable checks Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:12   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 14/58] drm/i915: copy&paste drm_crtc_helper_set_config Daniel Vetter
                   ` (52 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 23 +++--------------------
 drivers/gpu/drm/i915/intel_drv.h     |  2 --
 2 files changed, 3 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4805385..07077b1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3269,6 +3269,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 encoders:
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
+
+	if (HAS_PCH_CPT(dev))
+		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
 static void ironlake_crtc_disable(struct drm_crtc *crtc)
@@ -3524,26 +3527,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
 	}
 }
 
-void intel_encoder_prepare(struct drm_encoder *encoder)
-{
-	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
-	/* lvds has its own version of prepare see intel_lvds_prepare */
-	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
-}
-
-void intel_encoder_commit(struct drm_encoder *encoder)
-{
-	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
-	struct drm_device *dev = encoder->dev;
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-
-	/* lvds has its own version of commit see intel_lvds_commit */
-	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
-
-	if (HAS_PCH_CPT(dev))
-		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
-}
-
 void intel_encoder_noop(struct drm_encoder *encoder)
 {
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 2456245..e59cac3 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);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 14/58] drm/i915: copy&paste drm_crtc_helper_set_config
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (12 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 13/58] drm/i915: clean up encoder_prepare/commit Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:13   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 15/58] drm/i915: call set_base directly Daniel Vetter
                   ` (51 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

And the following static functions required by it:
drm_encoder_crtc_ok, drm_crtc_helper_disable

No changes safe for the s/drm/intel prefix change.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 314 ++++++++++++++++++++++++++++++++++-
 1 file changed, 313 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 07077b1..33a5191 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6590,12 +6590,324 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = {
 	.disable = intel_crtc_disable,
 };
 
+static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
+				  struct drm_crtc *crtc)
+{
+	struct drm_device *dev;
+	struct drm_crtc *tmp;
+	int crtc_mask = 1;
+
+	WARN(!crtc, "checking null crtc?\n");
+
+	dev = crtc->dev;
+
+	list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
+		if (tmp == crtc)
+			break;
+		crtc_mask <<= 1;
+	}
+
+	if (encoder->possible_crtcs & crtc_mask)
+		return true;
+	return false;
+}
+
+static int
+intel_crtc_helper_disable(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+
+	/* Decouple all encoders and their attached connectors from this crtc */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->crtc != crtc)
+			continue;
+
+		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+			if (connector->encoder != encoder)
+				continue;
+
+			connector->encoder = NULL;
+		}
+	}
+
+	drm_helper_disable_unused_functions(dev);
+	return 0;
+}
+
+static int intel_crtc_set_config(struct drm_mode_set *set)
+{
+	struct drm_device *dev;
+	struct drm_crtc *save_crtcs, *new_crtc, *crtc;
+	struct drm_encoder *save_encoders, *new_encoder, *encoder;
+	struct drm_framebuffer *old_fb = NULL;
+	bool mode_changed = false; /* if true do a full mode set */
+	bool fb_changed = false; /* if true and !mode_changed just do a flip */
+	struct drm_connector *save_connectors, *connector;
+	int count = 0, ro, fail = 0;
+	struct drm_crtc_helper_funcs *crtc_funcs;
+	struct drm_mode_set save_set;
+	int ret;
+	int i;
+
+	DRM_DEBUG_KMS("\n");
+
+	if (!set)
+		return -EINVAL;
+
+	if (!set->crtc)
+		return -EINVAL;
+
+	if (!set->crtc->helper_private)
+		return -EINVAL;
+
+	crtc_funcs = set->crtc->helper_private;
+
+	if (!set->mode)
+		set->fb = NULL;
+
+	if (set->fb) {
+		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
+				set->crtc->base.id, set->fb->base.id,
+				(int)set->num_connectors, set->x, set->y);
+	} else {
+		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
+		return intel_crtc_helper_disable(set->crtc);
+	}
+
+	dev = set->crtc->dev;
+
+	/* Allocate space for the backup of all (non-pointer) crtc, encoder and
+	 * connector data. */
+	save_crtcs = kzalloc(dev->mode_config.num_crtc *
+			     sizeof(struct drm_crtc), GFP_KERNEL);
+	if (!save_crtcs)
+		return -ENOMEM;
+
+	save_encoders = kzalloc(dev->mode_config.num_encoder *
+				sizeof(struct drm_encoder), GFP_KERNEL);
+	if (!save_encoders) {
+		kfree(save_crtcs);
+		return -ENOMEM;
+	}
+
+	save_connectors = kzalloc(dev->mode_config.num_connector *
+				sizeof(struct drm_connector), GFP_KERNEL);
+	if (!save_connectors) {
+		kfree(save_crtcs);
+		kfree(save_encoders);
+		return -ENOMEM;
+	}
+
+	/* Copy data. Note that driver private data is not affected.
+	 * 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) {
+		save_crtcs[count++] = *crtc;
+	}
+
+	count = 0;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		save_encoders[count++] = *encoder;
+	}
+
+	count = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		save_connectors[count++] = *connector;
+	}
+
+	save_set.crtc = set->crtc;
+	save_set.mode = &set->crtc->mode;
+	save_set.x = set->crtc->x;
+	save_set.y = set->crtc->y;
+	save_set.fb = set->crtc->fb;
+
+	/* We should be able to check here if the fb has the same properties
+	 * and then just flip_or_move it */
+	if (set->crtc->fb != set->fb) {
+		/* If we have no fb then treat it as a full mode set */
+		if (set->crtc->fb == NULL) {
+			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
+			mode_changed = true;
+		} else if (set->fb == NULL) {
+			mode_changed = true;
+		} else if (set->fb->depth != set->crtc->fb->depth) {
+			mode_changed = true;
+		} else if (set->fb->bits_per_pixel !=
+			   set->crtc->fb->bits_per_pixel) {
+			mode_changed = true;
+		} else
+			fb_changed = true;
+	}
+
+	if (set->x != set->crtc->x || set->y != set->crtc->y)
+		fb_changed = true;
+
+	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
+		DRM_DEBUG_KMS("modes are different, full mode set\n");
+		drm_mode_debug_printmodeline(&set->crtc->mode);
+		drm_mode_debug_printmodeline(set->mode);
+		mode_changed = true;
+	}
+
+	/* a) traverse passed in connector list and get encoders for them */
+	count = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		struct drm_connector_helper_funcs *connector_funcs =
+			connector->helper_private;
+		new_encoder = connector->encoder;
+		for (ro = 0; ro < set->num_connectors; ro++) {
+			if (set->connectors[ro] == connector) {
+				new_encoder = connector_funcs->best_encoder(connector);
+				/* if we can't get an encoder for a connector
+				   we are setting now - then fail */
+				if (new_encoder == NULL)
+					/* don't break so fail path works correct */
+					fail = 1;
+				break;
+			}
+		}
+
+		if (new_encoder != connector->encoder) {
+			DRM_DEBUG_KMS("encoder changed, full mode switch\n");
+			mode_changed = true;
+			/* If the encoder is reused for another connector, then
+			 * the appropriate crtc will be set later.
+			 */
+			if (connector->encoder)
+				connector->encoder->crtc = NULL;
+			connector->encoder = new_encoder;
+		}
+	}
+
+	if (fail) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	count = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (!connector->encoder)
+			continue;
+
+		if (connector->encoder->crtc == set->crtc)
+			new_crtc = NULL;
+		else
+			new_crtc = connector->encoder->crtc;
+
+		for (ro = 0; ro < set->num_connectors; ro++) {
+			if (set->connectors[ro] == connector)
+				new_crtc = set->crtc;
+		}
+
+		/* Make sure the new CRTC will work with the encoder */
+		if (new_crtc &&
+		    !intel_encoder_crtc_ok(connector->encoder, new_crtc)) {
+			ret = -EINVAL;
+			goto fail;
+		}
+		if (new_crtc != connector->encoder->crtc) {
+			DRM_DEBUG_KMS("crtc changed, full mode switch\n");
+			mode_changed = true;
+			connector->encoder->crtc = new_crtc;
+		}
+		if (new_crtc) {
+			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
+				connector->base.id, drm_get_connector_name(connector),
+				new_crtc->base.id);
+		} else {
+			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
+				connector->base.id, drm_get_connector_name(connector));
+		}
+	}
+
+	/* mode_set_base is not a required function */
+	if (fb_changed && !crtc_funcs->mode_set_base)
+		mode_changed = true;
+
+	if (mode_changed) {
+		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
+		if (set->crtc->enabled) {
+			DRM_DEBUG_KMS("attempting to set mode from"
+					" userspace\n");
+			drm_mode_debug_printmodeline(set->mode);
+			old_fb = set->crtc->fb;
+			set->crtc->fb = set->fb;
+			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
+						      set->x, set->y,
+						      old_fb)) {
+				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
+					  set->crtc->base.id);
+				set->crtc->fb = old_fb;
+				ret = -EINVAL;
+				goto fail;
+			}
+			DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
+			for (i = 0; i < set->num_connectors; i++) {
+				DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
+					      drm_get_connector_name(set->connectors[i]));
+				set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
+			}
+		}
+		drm_helper_disable_unused_functions(dev);
+	} else if (fb_changed) {
+		set->crtc->x = set->x;
+		set->crtc->y = set->y;
+
+		old_fb = set->crtc->fb;
+		if (set->crtc->fb != set->fb)
+			set->crtc->fb = set->fb;
+		ret = crtc_funcs->mode_set_base(set->crtc,
+						set->x, set->y, old_fb);
+		if (ret != 0) {
+			set->crtc->fb = old_fb;
+			goto fail;
+		}
+	}
+
+	kfree(save_connectors);
+	kfree(save_encoders);
+	kfree(save_crtcs);
+	return 0;
+
+fail:
+	/* Restore all previous data. */
+	count = 0;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		*crtc = save_crtcs[count++];
+	}
+
+	count = 0;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		*encoder = save_encoders[count++];
+	}
+
+	count = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		*connector = save_connectors[count++];
+	}
+
+	/* Try to restore the config */
+	if (mode_changed &&
+	    !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
+				      save_set.y, save_set.fb))
+		DRM_ERROR("failed to restore config after modeset failure\n");
+
+	kfree(save_connectors);
+	kfree(save_encoders);
+	kfree(save_crtcs);
+	return ret;
+}
+
 static const struct drm_crtc_funcs intel_crtc_funcs = {
 	.reset = intel_crtc_reset,
 	.cursor_set = intel_crtc_cursor_set,
 	.cursor_move = intel_crtc_cursor_move,
 	.gamma_set = intel_crtc_gamma_set,
-	.set_config = drm_crtc_helper_set_config,
+	.set_config = intel_crtc_set_config,
 	.destroy = intel_crtc_destroy,
 	.page_flip = intel_crtc_page_flip,
 };
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 15/58] drm/i915: call set_base directly
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (13 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 14/58] drm/i915: copy&paste drm_crtc_helper_set_config Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:15   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 16/58] drm/i915: inline intel_best_encoder Daniel Vetter
                   ` (50 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

And drop the check, we always have it.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 33a5191..5dbe03a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6584,7 +6584,6 @@ static void intel_crtc_reset(struct drm_crtc *crtc)
 static struct drm_crtc_helper_funcs intel_helper_funcs = {
 	.mode_fixup = intel_crtc_mode_fixup,
 	.mode_set = intel_crtc_mode_set,
-	.mode_set_base = intel_pipe_set_base,
 	.mode_set_base_atomic = intel_pipe_set_base_atomic,
 	.load_lut = intel_crtc_load_lut,
 	.disable = intel_crtc_disable,
@@ -6646,7 +6645,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	bool fb_changed = false; /* if true and !mode_changed just do a flip */
 	struct drm_connector *save_connectors, *connector;
 	int count = 0, ro, fail = 0;
-	struct drm_crtc_helper_funcs *crtc_funcs;
 	struct drm_mode_set save_set;
 	int ret;
 	int i;
@@ -6662,7 +6660,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	if (!set->crtc->helper_private)
 		return -EINVAL;
 
-	crtc_funcs = set->crtc->helper_private;
 
 	if (!set->mode)
 		set->fb = NULL;
@@ -6824,10 +6821,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		}
 	}
 
-	/* mode_set_base is not a required function */
-	if (fb_changed && !crtc_funcs->mode_set_base)
-		mode_changed = true;
-
 	if (mode_changed) {
 		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
 		if (set->crtc->enabled) {
@@ -6860,8 +6853,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		old_fb = set->crtc->fb;
 		if (set->crtc->fb != set->fb)
 			set->crtc->fb = set->fb;
-		ret = crtc_funcs->mode_set_base(set->crtc,
-						set->x, set->y, old_fb);
+		ret = intel_pipe_set_base(set->crtc,
+					  set->x, set->y, old_fb);
 		if (ret != 0) {
 			set->crtc->fb = old_fb;
 			goto fail;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 16/58] drm/i915: inline intel_best_encoder
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (14 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 15/58] drm/i915: call set_base directly Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:18   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 17/58] drm/i915: copy&paste drm_crtc_helper_set_mode Daniel Vetter
                   ` (49 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Also kill the error-path, we have a fixed connector-encoder mapping.

Unfortunately we can't rip out all the ->best_encoder callbacks, these
are all still used by the fb_helper. Neat helper layering violation there.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 18 +++---------------
 1 file changed, 3 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5dbe03a..9d5c575 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6644,7 +6644,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	bool mode_changed = false; /* if true do a full mode set */
 	bool fb_changed = false; /* if true and !mode_changed just do a flip */
 	struct drm_connector *save_connectors, *connector;
-	int count = 0, ro, fail = 0;
+	int count = 0, ro;
 	struct drm_mode_set save_set;
 	int ret;
 	int i;
@@ -6660,7 +6660,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	if (!set->crtc->helper_private)
 		return -EINVAL;
 
-
 	if (!set->mode)
 		set->fb = NULL;
 
@@ -6753,17 +6752,11 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	/* a) traverse passed in connector list and get encoders for them */
 	count = 0;
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		struct drm_connector_helper_funcs *connector_funcs =
-			connector->helper_private;
 		new_encoder = connector->encoder;
 		for (ro = 0; ro < set->num_connectors; ro++) {
 			if (set->connectors[ro] == connector) {
-				new_encoder = connector_funcs->best_encoder(connector);
-				/* if we can't get an encoder for a connector
-				   we are setting now - then fail */
-				if (new_encoder == NULL)
-					/* don't break so fail path works correct */
-					fail = 1;
+				new_encoder =
+					&intel_attached_encoder(connector)->base;
 				break;
 			}
 		}
@@ -6780,11 +6773,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		}
 	}
 
-	if (fail) {
-		ret = -EINVAL;
-		goto fail;
-	}
-
 	count = 0;
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		if (!connector->encoder)
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 17/58] drm/i915: copy&paste drm_crtc_helper_set_mode
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (15 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 16/58] drm/i915: inline intel_best_encoder Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:19   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 18/58] drm/i915: simplify intel_crtc_prepare_encoders Daniel Vetter
                   ` (48 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 162 +++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/i915/intel_dp.c      |   5 +-
 drivers/gpu/drm/i915/intel_drv.h     |   2 +
 drivers/gpu/drm/i915/intel_hdmi.c    |   5 +-
 drivers/gpu/drm/i915/intel_lvds.c    |   4 +-
 drivers/gpu/drm/i915/intel_sdvo.c    |   4 +-
 drivers/gpu/drm/i915/intel_tv.c      |   4 +-
 7 files changed, 168 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9d5c575..3e119a6 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5767,7 +5767,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 		goto fail;
 	}
 
-	if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) {
+	if (!intel_set_mode(crtc, mode, 0, 0, old_fb)) {
 		DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
 		if (old->release_fb)
 			old->release_fb->funcs->destroy(old->release_fb);
@@ -6635,6 +6635,157 @@ intel_crtc_helper_disable(struct drm_crtc *crtc)
 	return 0;
 }
 
+static void
+intel_encoder_disable_helper(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
+
+	if (encoder_funcs->disable)
+		(*encoder_funcs->disable)(encoder);
+	else
+		(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void
+intel_crtc_prepare_encoders(struct drm_device *dev)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	struct drm_encoder *encoder;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		encoder_funcs = encoder->helper_private;
+		/* Disable unused encoders */
+		if (encoder->crtc == NULL)
+			intel_encoder_disable_helper(encoder);
+		/* Disable encoders whose CRTC is about to change */
+		if (encoder_funcs->get_crtc &&
+		    encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
+			intel_encoder_disable_helper(encoder);
+	}
+}
+
+bool intel_set_mode(struct drm_crtc *crtc,
+		    struct drm_display_mode *mode,
+		    int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	int saved_x, saved_y;
+	struct drm_encoder *encoder;
+	bool ret = true;
+
+	crtc->enabled = drm_helper_crtc_in_use(crtc);
+	if (!crtc->enabled)
+		return true;
+
+	adjusted_mode = drm_mode_duplicate(dev, mode);
+	if (!adjusted_mode)
+		return false;
+
+	saved_hwmode = crtc->hwmode;
+	saved_mode = crtc->mode;
+	saved_x = crtc->x;
+	saved_y = crtc->y;
+
+	/* Update crtc values up front so the driver can rely on them for mode
+	 * setting.
+	 */
+	crtc->mode = *mode;
+	crtc->x = x;
+	crtc->y = y;
+
+	/* Pass our mode to the connectors and the CRTC to give them a chance to
+	 * adjust it according to limitations or connector properties, and also
+	 * a chance to reject the mode entirely.
+	 */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+
+		if (encoder->crtc != crtc)
+			continue;
+		encoder_funcs = encoder->helper_private;
+		if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
+						      adjusted_mode))) {
+			DRM_DEBUG_KMS("Encoder fixup failed\n");
+			goto done;
+		}
+	}
+
+	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
+		DRM_DEBUG_KMS("CRTC fixup failed\n");
+		goto done;
+	}
+	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
+
+	/* Prepare the encoders and CRTCs before setting the mode. */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+
+		if (encoder->crtc != crtc)
+			continue;
+		encoder_funcs = encoder->helper_private;
+		/* Disable the encoders as the first thing we do. */
+		encoder_funcs->prepare(encoder);
+	}
+
+	intel_crtc_prepare_encoders(dev);
+
+	crtc_funcs->prepare(crtc);
+
+	/* Set up the DPLL and any encoders state that needs to adjust or depend
+	 * on the DPLL.
+	 */
+	ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+	if (!ret)
+	    goto done;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+
+		if (encoder->crtc != crtc)
+			continue;
+
+		DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
+			encoder->base.id, drm_get_encoder_name(encoder),
+			mode->base.id, mode->name);
+		encoder_funcs = encoder->helper_private;
+		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
+	}
+
+	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
+	crtc_funcs->commit(crtc);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+
+		if (encoder->crtc != crtc)
+			continue;
+
+		encoder_funcs = encoder->helper_private;
+		encoder_funcs->commit(encoder);
+
+	}
+
+	/* Store real post-adjustment hardware mode. */
+	crtc->hwmode = *adjusted_mode;
+
+	/* Calculate and store various constants which
+	 * are later needed by vblank and swap-completion
+	 * timestamping. They are derived from true hwmode.
+	 */
+	drm_calc_timestamping_constants(crtc);
+
+	/* FIXME: add subpixel order */
+done:
+	drm_mode_destroy(dev, adjusted_mode);
+	if (!ret) {
+		crtc->hwmode = saved_hwmode;
+		crtc->mode = saved_mode;
+		crtc->x = saved_x;
+		crtc->y = saved_y;
+	}
+
+	return ret;
+}
+
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
 	struct drm_device *dev;
@@ -6817,9 +6968,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 			drm_mode_debug_printmodeline(set->mode);
 			old_fb = set->crtc->fb;
 			set->crtc->fb = set->fb;
-			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
-						      set->x, set->y,
-						      old_fb)) {
+			if (!intel_set_mode(set->crtc, set->mode,
+					    set->x, set->y, old_fb)) {
 				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
 					  set->crtc->base.id);
 				set->crtc->fb = old_fb;
@@ -6873,8 +7023,8 @@ fail:
 
 	/* Try to restore the config */
 	if (mode_changed &&
-	    !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
-				      save_set.y, save_set.fb))
+	    !intel_set_mode(save_set.crtc, save_set.mode,
+			    save_set.x, save_set.y, save_set.fb))
 		DRM_ERROR("failed to restore config after modeset failure\n");
 
 	kfree(save_connectors);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 7ee954c..2abaaf6 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2312,9 +2312,8 @@ intel_dp_set_property(struct drm_connector *connector,
 done:
 	if (intel_dp->base.base.crtc) {
 		struct drm_crtc *crtc = intel_dp->base.base.crtc;
-		drm_crtc_helper_set_mode(crtc, &crtc->mode,
-					 crtc->x, crtc->y,
-					 crtc->fb);
+		intel_set_mode(crtc, &crtc->mode,
+			       crtc->x, crtc->y, crtc->fb);
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e59cac3..c28fada 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);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index acddaaa..ef84097 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -869,9 +869,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
 done:
 	if (intel_hdmi->base.base.crtc) {
 		struct drm_crtc *crtc = intel_hdmi->base.base.crtc;
-		drm_crtc_helper_set_mode(crtc, &crtc->mode,
-					 crtc->x, crtc->y,
-					 crtc->fb);
+		intel_set_mode(crtc, &crtc->mode,
+			       crtc->x, crtc->y, crtc->fb);
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 3baa224..fad82b2 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -560,8 +560,8 @@ static int intel_lvds_set_property(struct drm_connector *connector,
 			 * If the CRTC is enabled, the display will be changed
 			 * according to the new panel fitting mode.
 			 */
-			drm_crtc_helper_set_mode(crtc, &crtc->mode,
-				crtc->x, crtc->y, crtc->fb);
+			intel_set_mode(crtc, &crtc->mode,
+				       crtc->x, crtc->y, crtc->fb);
 		}
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index a01c470..88fb30d 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1879,8 +1879,8 @@ set_value:
 done:
 	if (intel_sdvo->base.base.crtc) {
 		struct drm_crtc *crtc = intel_sdvo->base.base.crtc;
-		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
-					 crtc->y, crtc->fb);
+		intel_set_mode(crtc, &crtc->mode,
+			       crtc->x, crtc->y, crtc->fb);
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 281e0cf..16cb114 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1471,8 +1471,8 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
 	}
 
 	if (changed && crtc)
-		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
-				crtc->y, crtc->fb);
+		intel_set_mode(crtc, &crtc->mode,
+			       crtc->x, crtc->y, crtc->fb);
 out:
 	return ret;
 }
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 18/58] drm/i915: simplify intel_crtc_prepare_encoders
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (16 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 17/58] drm/i915: copy&paste drm_crtc_helper_set_mode Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:20   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 19/58] drm/i915: rip out encoder->prepare/commit Daniel Vetter
                   ` (47 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

- We don't have the ->get_crtc callback.
- Call intel_encoder->disable directly.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 25 ++++---------------------
 1 file changed, 4 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3e119a6..343f991 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6636,31 +6636,14 @@ intel_crtc_helper_disable(struct drm_crtc *crtc)
 }
 
 static void
-intel_encoder_disable_helper(struct drm_encoder *encoder)
-{
-	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
-
-	if (encoder_funcs->disable)
-		(*encoder_funcs->disable)(encoder);
-	else
-		(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
-}
-
-static void
 intel_crtc_prepare_encoders(struct drm_device *dev)
 {
-	struct drm_encoder_helper_funcs *encoder_funcs;
-	struct drm_encoder *encoder;
+	struct intel_encoder *encoder;
 
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		encoder_funcs = encoder->helper_private;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 		/* Disable unused encoders */
-		if (encoder->crtc == NULL)
-			intel_encoder_disable_helper(encoder);
-		/* Disable encoders whose CRTC is about to change */
-		if (encoder_funcs->get_crtc &&
-		    encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
-			intel_encoder_disable_helper(encoder);
+		if (encoder->base.crtc == NULL)
+			encoder->disable(encoder);
 	}
 }
 
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 19/58] drm/i915: rip out encoder->prepare/commit
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (17 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 18/58] drm/i915: simplify intel_crtc_prepare_encoders Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:21   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 20/58] drm/i915: call crtc functions directly Daniel Vetter
                   ` (46 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

With the new infrastructure we're doing this when enabling/disabling
the entire display pipe.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_crt.c     |  2 --
 drivers/gpu/drm/i915/intel_display.c | 24 ------------------------
 drivers/gpu/drm/i915/intel_dp.c      |  2 --
 drivers/gpu/drm/i915/intel_drv.h     |  1 -
 drivers/gpu/drm/i915/intel_dvo.c     |  2 --
 drivers/gpu/drm/i915/intel_hdmi.c    |  4 ----
 drivers/gpu/drm/i915/intel_lvds.c    |  2 --
 drivers/gpu/drm/i915/intel_sdvo.c    |  2 --
 drivers/gpu/drm/i915/intel_tv.c      |  2 --
 9 files changed, 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 15c1ff8..4ce0b46 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -617,8 +617,6 @@ static void intel_crt_reset(struct drm_connector *connector)
 
 static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
 	.mode_fixup = intel_crt_mode_fixup,
-	.prepare = intel_encoder_noop,
-	.commit = intel_encoder_noop,
 	.mode_set = intel_crt_mode_set,
 	.disable = intel_encoder_disable,
 };
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 343f991..d37a851 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3527,10 +3527,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
 	}
 }
 
-void intel_encoder_noop(struct drm_encoder *encoder)
-{
-}
-
 void intel_encoder_disable(struct drm_encoder *encoder)
 {
 	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
@@ -6701,16 +6697,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	}
 	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 
-	/* Prepare the encoders and CRTCs before setting the mode. */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
-		if (encoder->crtc != crtc)
-			continue;
-		encoder_funcs = encoder->helper_private;
-		/* Disable the encoders as the first thing we do. */
-		encoder_funcs->prepare(encoder);
-	}
-
 	intel_crtc_prepare_encoders(dev);
 
 	crtc_funcs->prepare(crtc);
@@ -6737,16 +6723,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
 	crtc_funcs->commit(crtc);
 
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
-		if (encoder->crtc != crtc)
-			continue;
-
-		encoder_funcs = encoder->helper_private;
-		encoder_funcs->commit(encoder);
-
-	}
-
 	/* Store real post-adjustment hardware mode. */
 	crtc->hwmode = *adjusted_mode;
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 2abaaf6..ff993a0 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2348,9 +2348,7 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
 	.mode_fixup = intel_dp_mode_fixup,
-	.prepare = intel_encoder_noop,
 	.mode_set = intel_dp_mode_set,
-	.commit = intel_encoder_noop,
 	.disable = intel_encoder_disable,
 };
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c28fada..673e8d4 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);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index c55a13e..84c0867 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -318,9 +318,7 @@ static void intel_dvo_destroy(struct drm_connector *connector)
 
 static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
 	.mode_fixup = intel_dvo_mode_fixup,
-	.prepare = intel_encoder_noop,
 	.mode_set = intel_dvo_mode_set,
-	.commit = intel_encoder_noop,
 	.disable = intel_encoder_disable,
 };
 
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index ef84097..c9535ce 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -885,17 +885,13 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
 
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
 	.mode_fixup = intel_hdmi_mode_fixup,
-	.prepare = intel_encoder_noop,
 	.mode_set = intel_ddi_mode_set,
-	.commit = intel_encoder_noop,
 	.disable = intel_encoder_disable,
 };
 
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
 	.mode_fixup = intel_hdmi_mode_fixup,
-	.prepare = intel_encoder_noop,
 	.mode_set = intel_hdmi_mode_set,
-	.commit = intel_encoder_noop,
 	.disable = intel_encoder_disable,
 };
 
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index fad82b2..5fc7abc 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -570,9 +570,7 @@ static int intel_lvds_set_property(struct drm_connector *connector,
 
 static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
 	.mode_fixup = intel_lvds_mode_fixup,
-	.prepare = intel_encoder_noop,
 	.mode_set = intel_lvds_mode_set,
-	.commit = intel_encoder_noop,
 	.disable = intel_encoder_disable,
 };
 
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 88fb30d..8cdc674 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1889,9 +1889,7 @@ done:
 
 static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
 	.mode_fixup = intel_sdvo_mode_fixup,
-	.prepare = intel_encoder_noop,
 	.mode_set = intel_sdvo_mode_set,
-	.commit = intel_encoder_noop,
 	.disable = intel_encoder_disable
 };
 
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 16cb114..5dc08b9 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1479,9 +1479,7 @@ out:
 
 static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
 	.mode_fixup = intel_tv_mode_fixup,
-	.prepare = intel_encoder_noop,
 	.mode_set = intel_tv_mode_set,
-	.commit = intel_encoder_noop,
 	.disable = intel_encoder_disable,
 };
 
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 20/58] drm/i915: call crtc functions directly
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (18 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 19/58] drm/i915: rip out encoder->prepare/commit Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:22   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 21/58] drm/i915: WARN when trying to enabled an unused crtc Daniel Vetter
                   ` (45 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Instead of going through the crtc helper function tables.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d37a851..ca17010 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6578,8 +6578,6 @@ static void intel_crtc_reset(struct drm_crtc *crtc)
 }
 
 static struct drm_crtc_helper_funcs intel_helper_funcs = {
-	.mode_fixup = intel_crtc_mode_fixup,
-	.mode_set = intel_crtc_mode_set,
 	.mode_set_base_atomic = intel_pipe_set_base_atomic,
 	.load_lut = intel_crtc_load_lut,
 	.disable = intel_crtc_disable,
@@ -6648,8 +6646,8 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		    int x, int y, struct drm_framebuffer *old_fb)
 {
 	struct drm_device *dev = crtc->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
-	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	int saved_x, saved_y;
 	struct drm_encoder *encoder;
@@ -6691,7 +6689,7 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		}
 	}
 
-	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
+	if (!(ret = intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) {
 		DRM_DEBUG_KMS("CRTC fixup failed\n");
 		goto done;
 	}
@@ -6699,12 +6697,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
 
 	intel_crtc_prepare_encoders(dev);
 
-	crtc_funcs->prepare(crtc);
+	dev_priv->display.crtc_disable(crtc);
 
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
-	ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
 	if (!ret)
 	    goto done;
 
@@ -6721,7 +6719,7 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	}
 
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
-	crtc_funcs->commit(crtc);
+	dev_priv->display.crtc_enable(crtc);
 
 	/* Store real post-adjustment hardware mode. */
 	crtc->hwmode = *adjusted_mode;
@@ -7055,9 +7053,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	intel_crtc->active = true; /* force the pipe off on setup_init_config */
 	intel_crtc->bpp = 24; /* default for pre-Ironlake */
 
-	intel_helper_funcs.prepare = dev_priv->display.crtc_disable;
-	intel_helper_funcs.commit = dev_priv->display.crtc_enable;
-
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 }
 
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 21/58] drm/i915: WARN when trying to enabled an unused crtc
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (19 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 20/58] drm/i915: call crtc functions directly Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:23   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 22/58] drm/i915: Add interfaces to read out encoder/connector hw state Daniel Vetter
                   ` (44 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c |  4 ++++
 drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ca17010..5ab8694 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3215,6 +3215,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	u32 temp;
 	bool is_pch_port;
 
+	WARN_ON(!crtc->enabled);
+
 	/* XXX: For compatability with the crtc helper code, call the encoder's
 	 * enable function unconditionally for now. */
 	if (intel_crtc->active)
@@ -3391,6 +3393,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
+	WARN_ON(!crtc->enabled);
+
 	/* XXX: For compatability with the crtc helper code, call the encoder's
 	 * enable function unconditionally for now. */
 	if (intel_crtc->active)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 673e8d4..36991de 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;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 22/58] drm/i915: Add interfaces to read out encoder/connector hw state
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (20 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 21/58] drm/i915: WARN when trying to enabled an unused crtc Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:25   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 23/58] drm/i915/dp: implement get_hw_state Daniel Vetter
                   ` (43 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 11 +++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  8 ++++++++
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5ab8694..7e7569b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3584,6 +3584,17 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
 		encoder->connectors_active = false;
 }
 
+/* Simple connector->get_hw_state implementation for encoders that support only
+ * one connector and no cloning and hence the encoder state determines the state
+ * of the connector. */
+bool intel_connector_get_hw_state(struct intel_connector *connector)
+{
+	enum pipe pipe;
+	struct intel_encoder *encoder = connector->encoder;
+
+	return encoder->get_hw_state(encoder, &pipe);
+}
+
 static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
 				  const struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 36991de..c39c705 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)
 {
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 23/58] drm/i915/dp: implement get_hw_state
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (21 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 22/58] drm/i915: Add interfaces to read out encoder/connector hw state Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:26   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 24/58] drm/i915/hdmi: " Daniel Vetter
                   ` (42 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Also add some macros to make the pipe computation a bit easier.

v2: I've mixed up the CPT and !CPT PORT_TO_PIPE macro variants ...

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_reg.h |  2 ++
 drivers/gpu/drm/i915/intel_dp.c | 50 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index fd6a26a..1e5f77a 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4029,6 +4029,8 @@
 #define  PORT_TRANS_C_SEL_CPT	(2<<29)
 #define  PORT_TRANS_SEL_MASK	(3<<29)
 #define  PORT_TRANS_SEL_CPT(pipe)	((pipe) << 29)
+#define  PORT_TO_PIPE(val)	(((val) & (1<<30)) >> 30)
+#define  PORT_TO_PIPE_CPT(val)	(((val) & PORT_TRANS_SEL_MASK) >> 29)
 
 #define TRANS_DP_CTL_A		0xe0300
 #define TRANS_DP_CTL_B		0xe1300
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index ff993a0..e3928b9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1250,6 +1250,54 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
 	}
 }
 
+static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
+				  enum pipe *pipe)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 tmp = I915_READ(intel_dp->output_reg);
+
+	if (!(tmp & DP_PORT_EN))
+		return false;
+
+	if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
+		*pipe = PORT_TO_PIPE_CPT(tmp);
+	} else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
+		*pipe = PORT_TO_PIPE(tmp);
+	} else {
+		u32 trans_sel;
+		u32 trans_dp;
+		int i;
+
+		switch (intel_dp->output_reg) {
+		case PCH_DP_B:
+			trans_sel = TRANS_DP_PORT_SEL_B;
+			break;
+		case PCH_DP_C:
+			trans_sel = TRANS_DP_PORT_SEL_C;
+			break;
+		case PCH_DP_D:
+			trans_sel = TRANS_DP_PORT_SEL_D;
+			break;
+		default:
+			return true;
+		}
+
+		for_each_pipe(i) {
+			trans_dp = I915_READ(TRANS_DP_CTL(i));
+			if ((trans_dp & TRANS_DP_PORT_SEL_MASK) == trans_sel) {
+				*pipe = i;
+				return true;
+			}
+		}
+	}
+
+	DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n", intel_dp->output_reg);
+
+	return true;
+}
+
 static void intel_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -2486,6 +2534,8 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 
 	intel_encoder->enable = intel_enable_dp;
 	intel_encoder->disable = intel_disable_dp;
+	intel_encoder->get_hw_state = intel_dp_get_hw_state;
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	/* Set up the DDC bus. */
 	switch (port) {
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 24/58] drm/i915/hdmi: implement get_hw_state
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (22 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 23/58] drm/i915/dp: implement get_hw_state Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:28   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 25/58] drm/i915/tv: " Daniel Vetter
                   ` (41 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_ddi.c  | 29 +++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h  |  2 ++
 drivers/gpu/drm/i915/intel_hdmi.c | 24 ++++++++++++++++++++++++
 3 files changed, 55 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 38a7006..bfe3754 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -757,6 +757,35 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
+bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
+			    enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	u32 tmp;
+	int i;
+
+	tmp = I915_READ(DDI_BUF_CTL(intel_hdmi->ddi_port));
+
+	if (!(tmp & DDI_BUF_CTL_ENABLE))
+		return false;
+
+	for_each_pipe(i) {
+		tmp = I915_READ(DDI_FUNC_CTL(i));
+
+		if ((tmp & PIPE_DDI_PORT_MASK)
+		    == PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port)) {
+			*pipe = i;
+			return true;
+		}
+	}
+
+	DRM_DEBUG_KMS("No pipe for ddi port %i found\n", intel_hdmi->ddi_port);
+
+	return true;
+}
+
 void intel_enable_ddi(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c39c705..4daa7e6 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);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index c9535ce..e7d5078 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -601,6 +601,27 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 	intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
+static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
+				    enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	u32 tmp;
+
+	tmp = I915_READ(intel_hdmi->sdvox_reg);
+
+	if (!(tmp & SDVO_ENABLE))
+		return false;
+
+	if (HAS_PCH_CPT(dev))
+		*pipe = PORT_TO_PIPE_CPT(tmp);
+	else
+		*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
 static void intel_enable_hdmi(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
@@ -998,14 +1019,17 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 	if (IS_HASWELL(dev)) {
 		intel_encoder->enable = intel_enable_ddi;
 		intel_encoder->disable = intel_disable_ddi;
+		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
 		drm_encoder_helper_add(&intel_encoder->base,
 				       &intel_hdmi_helper_funcs_hsw);
 	} else {
 		intel_encoder->enable = intel_enable_hdmi;
 		intel_encoder->disable = intel_disable_hdmi;
+		intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
 		drm_encoder_helper_add(&intel_encoder->base,
 				       &intel_hdmi_helper_funcs);
 	}
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 
 	intel_hdmi_add_properties(intel_hdmi, connector);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 25/58] drm/i915/tv: implement get_hw_state
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (23 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 24/58] drm/i915/hdmi: " Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:28   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 26/58] drm/i915/lvds: " Daniel Vetter
                   ` (40 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_tv.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 5dc08b9..98ad7fd 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -836,6 +836,21 @@ static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
 			    base);
 }
 
+static bool
+intel_tv_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 tmp = I915_READ(TV_CTL);
+
+	if (!(tmp & TV_ENC_ENABLE))
+		return false;
+
+	*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
 static void
 intel_enable_tv(struct intel_encoder *encoder)
 {
@@ -1616,6 +1631,8 @@ intel_tv_init(struct drm_device *dev)
 
 	intel_encoder->enable = intel_enable_tv;
 	intel_encoder->disable = intel_disable_tv;
+	intel_encoder->get_hw_state = intel_tv_get_hw_state;
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_TVOUT;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 26/58] drm/i915/lvds: implement get_hw_state
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (24 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 25/58] drm/i915/tv: " Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:28   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 27/58] drm/i915/crt: " Daniel Vetter
                   ` (39 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_lvds.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 5fc7abc..52f9e7f 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -65,6 +65,32 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
 			    struct intel_lvds, base);
 }
 
+static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
+				    enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 lvds_reg, tmp;
+
+	if (HAS_PCH_SPLIT(dev)) {
+		lvds_reg = PCH_LVDS;
+	} else {
+		lvds_reg = LVDS;
+	}
+
+	tmp = I915_READ(lvds_reg);
+
+	if (!(tmp & LVDS_PORT_EN))
+		return false;
+
+	if (HAS_PCH_CPT(dev))
+		*pipe = PORT_TO_PIPE_CPT(tmp);
+	else
+		*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
 /**
  * Sets the power state for the panel.
  */
@@ -937,6 +963,8 @@ bool intel_lvds_init(struct drm_device *dev)
 
 	intel_encoder->enable = intel_enable_lvds;
 	intel_encoder->disable = intel_disable_lvds;
+	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_LVDS;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 27/58] drm/i915/crt: implement get_hw_state
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (25 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 26/58] drm/i915/lvds: " Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:29   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 28/58] drm/i915/sdvo: " Daniel Vetter
                   ` (38 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Note that even though this connector is cloneable we still can use the
exact same test to check whether the connector is on or whether the
encoder is enabled - both the dpms code and the encoder disable/enable
frob the exact same hw state.

For dvo/sdvo outputs, this will be different.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_crt.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 4ce0b46..fab54ed 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -61,6 +61,27 @@ static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
 	return container_of(encoder, struct intel_crt, base);
 }
 
+static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
+				   enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+	u32 tmp;
+
+	tmp = I915_READ(crt->adpa_reg);
+
+	if (!(tmp & ADPA_DAC_ENABLE))
+		return false;
+
+	if (HAS_PCH_CPT(dev))
+		*pipe = PORT_TO_PIPE_CPT(tmp);
+	else
+		*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
 static void intel_disable_crt(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
@@ -710,6 +731,8 @@ void intel_crt_init(struct drm_device *dev)
 
 	crt->base.disable = intel_disable_crt;
 	crt->base.enable = intel_enable_crt;
+	crt->base.get_hw_state = intel_crt_get_hw_state;
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs);
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 28/58] drm/i915/sdvo: implement get_hw_state
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (26 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 27/58] drm/i915/crt: " Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:31   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 29/58] drm/i915/dvo: " Daniel Vetter
                   ` (37 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

SDVO is the first real special case - we support multiple outputs on
the same encoder and the encoder dpms state isn't the same as when
just disabling the outputs when the encoder is cloned.

Hence we need a real connector get_hw_state function which inquires
the sdvo encoder about its active outputs.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_sdvo.c | 46 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 8cdc674..4a735a5 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -628,6 +628,14 @@ static bool intel_sdvo_set_active_outputs(struct intel_sdvo *intel_sdvo,
 				    &outputs, sizeof(outputs));
 }
 
+static bool intel_sdvo_get_active_outputs(struct intel_sdvo *intel_sdvo,
+					  u16 *outputs)
+{
+	return intel_sdvo_get_value(intel_sdvo,
+				    SDVO_CMD_GET_ACTIVE_OUTPUTS,
+				    outputs, sizeof(*outputs));
+}
+
 static bool intel_sdvo_set_encoder_power_state(struct intel_sdvo *intel_sdvo,
 					       int mode)
 {
@@ -1142,6 +1150,42 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 	intel_sdvo_write_sdvox(intel_sdvo, sdvox);
 }
 
+static bool intel_sdvo_connector_get_hw_state(struct intel_connector *connector)
+{
+	struct intel_sdvo_connector *intel_sdvo_connector =
+		to_intel_sdvo_connector(&connector->base);
+	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(&connector->base);
+	u16 active_outputs;
+
+	intel_sdvo_get_active_outputs(intel_sdvo, &active_outputs);
+
+	if (active_outputs & intel_sdvo_connector->output_flag)
+		return true;
+	else
+		return false;
+}
+
+static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
+				    enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	u32 tmp;
+
+	tmp = I915_READ(intel_sdvo->sdvo_reg);
+
+	if (!(tmp & SDVO_ENABLE))
+		return false;
+
+	if (HAS_PCH_CPT(dev))
+		*pipe = PORT_TO_PIPE_CPT(tmp);
+	else
+		*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
 static void intel_disable_sdvo(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
@@ -2066,6 +2110,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
 	connector->base.base.interlace_allowed = 1;
 	connector->base.base.doublescan_allowed = 0;
 	connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
+	connector->base.get_hw_state = intel_sdvo_connector_get_hw_state;
 
 	intel_connector_attach_encoder(&connector->base, &encoder->base);
 	drm_sysfs_connector_add(&connector->base.base);
@@ -2619,6 +2664,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 
 	intel_encoder->disable = intel_disable_sdvo;
 	intel_encoder->enable = intel_enable_sdvo;
+	intel_encoder->get_hw_state = intel_sdvo_get_hw_state;
 
 	/* In default case sdvo lvds is false */
 	if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 29/58] drm/i915/dvo: implement get_hw_state
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (27 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 28/58] drm/i915/sdvo: " Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-04 20:32   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 30/58] drm/i915: read out the modeset hw state at load and resume time Daniel Vetter
                   ` (36 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Similar to the sdvo code we poke the dvo encoder whether the output is
active. Safe that dvo encoders are not standardized, so this requires
a new callback into the dvo chip driver.

Hence implement that for all 6 dvo drivers.

v2: With the newly added ns2501 we now have 6 dvo drivers instead of
just 5 ...

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/dvo.h        |  6 ++++++
 drivers/gpu/drm/i915/dvo_ch7017.c | 13 +++++++++++++
 drivers/gpu/drm/i915/dvo_ch7xxx.c | 13 +++++++++++++
 drivers/gpu/drm/i915/dvo_ivch.c   | 15 +++++++++++++++
 drivers/gpu/drm/i915/dvo_ns2501.c | 15 +++++++++++++++
 drivers/gpu/drm/i915/dvo_sil164.c | 16 ++++++++++++++++
 drivers/gpu/drm/i915/dvo_tfp410.c | 14 ++++++++++++++
 drivers/gpu/drm/i915/intel_dvo.c  | 27 +++++++++++++++++++++++++++
 8 files changed, 119 insertions(+)

diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
index 0fa839e..74b5efc 100644
--- a/drivers/gpu/drm/i915/dvo.h
+++ b/drivers/gpu/drm/i915/dvo.h
@@ -114,6 +114,12 @@ struct intel_dvo_dev_ops {
 	 */
 	enum drm_connector_status (*detect)(struct intel_dvo_device *dvo);
 
+	/*
+	 * Probe the current hw status, returning true if the connected output
+	 * is active.
+	 */
+	bool (*get_hw_state)(struct intel_dvo_device *dev);
+
 	/**
 	 * Query the device for the modes it provides.
 	 *
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
index 71e7650..86b27d1 100644
--- a/drivers/gpu/drm/i915/dvo_ch7017.c
+++ b/drivers/gpu/drm/i915/dvo_ch7017.c
@@ -359,6 +359,18 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, bool enable)
 	msleep(20);
 }
 
+static bool ch7017_get_hw_state(struct intel_dvo_device *dvo)
+{
+	uint8_t val;
+
+	ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &val);
+
+	if (val & CH7017_LVDS_POWER_DOWN_EN)
+		return false;
+	else
+		return true;
+}
+
 static void ch7017_dump_regs(struct intel_dvo_device *dvo)
 {
 	uint8_t val;
@@ -396,6 +408,7 @@ struct intel_dvo_dev_ops ch7017_ops = {
 	.mode_valid = ch7017_mode_valid,
 	.mode_set = ch7017_mode_set,
 	.dpms = ch7017_dpms,
+	.get_hw_state = ch7017_get_hw_state,
 	.dump_regs = ch7017_dump_regs,
 	.destroy = ch7017_destroy,
 };
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
index c1dea5b..38f3a6c 100644
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -297,6 +297,18 @@ static void ch7xxx_dpms(struct intel_dvo_device *dvo, bool enable)
 		ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_FPD);
 }
 
+static bool ch7xxx_get_hw_state(struct intel_dvo_device *dvo)
+{
+	u8 val;
+
+	ch7xxx_readb(dvo, CH7xxx_PM, &val);
+
+	if (val & CH7xxx_PM_FPD)
+		return false;
+	else
+		return true;
+}
+
 static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
 {
 	int i;
@@ -326,6 +338,7 @@ struct intel_dvo_dev_ops ch7xxx_ops = {
 	.mode_valid = ch7xxx_mode_valid,
 	.mode_set = ch7xxx_mode_set,
 	.dpms = ch7xxx_dpms,
+	.get_hw_state = ch7xxx_get_hw_state,
 	.dump_regs = ch7xxx_dump_regs,
 	.destroy = ch7xxx_destroy,
 };
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
index fa8ff6b..baaf65b 100644
--- a/drivers/gpu/drm/i915/dvo_ivch.c
+++ b/drivers/gpu/drm/i915/dvo_ivch.c
@@ -323,6 +323,20 @@ static void ivch_dpms(struct intel_dvo_device *dvo, bool enable)
 	udelay(16 * 1000);
 }
 
+static bool ivch_get_hw_state(struct intel_dvo_device *dvo)
+{
+	uint16_t vr01;
+
+	/* Set the new power state of the panel. */
+	if (!ivch_read(dvo, VR01, &vr01))
+		return false;
+
+	if (vr01 & VR01_LCD_ENABLE)
+		return true;
+	else
+		return false;
+}
+
 static void ivch_mode_set(struct intel_dvo_device *dvo,
 			  struct drm_display_mode *mode,
 			  struct drm_display_mode *adjusted_mode)
@@ -413,6 +427,7 @@ static void ivch_destroy(struct intel_dvo_device *dvo)
 struct intel_dvo_dev_ops ivch_ops = {
 	.init = ivch_init,
 	.dpms = ivch_dpms,
+	.get_hw_state = ivch_get_hw_state,
 	.mode_valid = ivch_mode_valid,
 	.mode_set = ivch_mode_set,
 	.detect = ivch_detect,
diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c
index c4d9f2f..c4a255b 100644
--- a/drivers/gpu/drm/i915/dvo_ns2501.c
+++ b/drivers/gpu/drm/i915/dvo_ns2501.c
@@ -493,6 +493,20 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
 }
 
 /* set the NS2501 power state */
+static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
+{
+	unsigned char ch;
+
+	if (!ns2501_readb(dvo, NS2501_REG8, &ch))
+		return false;
+
+	if (ch & NS2501_8_PD)
+		return true;
+	else
+		return false;
+}
+
+/* set the NS2501 power state */
 static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
 {
 	bool ok;
@@ -568,6 +582,7 @@ struct intel_dvo_dev_ops ns2501_ops = {
 	.mode_valid = ns2501_mode_valid,
 	.mode_set = ns2501_mode_set,
 	.dpms = ns2501_dpms,
+	.get_hw_state = ns2501_get_hw_state,
 	.dump_regs = ns2501_dump_regs,
 	.destroy = ns2501_destroy,
 };
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
index cc24c1c..4debd32 100644
--- a/drivers/gpu/drm/i915/dvo_sil164.c
+++ b/drivers/gpu/drm/i915/dvo_sil164.c
@@ -226,6 +226,21 @@ static void sil164_dpms(struct intel_dvo_device *dvo, bool enable)
 	return;
 }
 
+static bool sil164_get_hw_state(struct intel_dvo_device *dvo)
+{
+	int ret;
+	unsigned char ch;
+
+	ret = sil164_readb(dvo, SIL164_REG8, &ch);
+	if (ret == false)
+		return false;
+
+	if (ch & SIL164_8_PD)
+		return true;
+	else
+		return false;
+}
+
 static void sil164_dump_regs(struct intel_dvo_device *dvo)
 {
 	uint8_t val;
@@ -258,6 +273,7 @@ struct intel_dvo_dev_ops sil164_ops = {
 	.mode_valid = sil164_mode_valid,
 	.mode_set = sil164_mode_set,
 	.dpms = sil164_dpms,
+	.get_hw_state = sil164_get_hw_state,
 	.dump_regs = sil164_dump_regs,
 	.destroy = sil164_destroy,
 };
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
index 097b3e8..e17f1b0 100644
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -249,6 +249,19 @@ static void tfp410_dpms(struct intel_dvo_device *dvo, bool enable)
 	tfp410_writeb(dvo, TFP410_CTL_1, ctl1);
 }
 
+static bool tfp410_get_hw_state(struct intel_dvo_device *dvo)
+{
+	uint8_t ctl1;
+
+	if (!tfp410_readb(dvo, TFP410_CTL_1, &ctl1))
+		return false;
+
+	if (ctl1 & TFP410_CTL_1_PD)
+		return true;
+	else
+		return false;
+}
+
 static void tfp410_dump_regs(struct intel_dvo_device *dvo)
 {
 	uint8_t val, val2;
@@ -299,6 +312,7 @@ struct intel_dvo_dev_ops tfp410_ops = {
 	.mode_valid = tfp410_mode_valid,
 	.mode_set = tfp410_mode_set,
 	.dpms = tfp410_dpms,
+	.get_hw_state = tfp410_get_hw_state,
 	.dump_regs = tfp410_dump_regs,
 	.destroy = tfp410_destroy,
 };
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 84c0867..e9397b7 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -105,6 +105,31 @@ static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector)
 			    struct intel_dvo, base);
 }
 
+static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector)
+{
+	struct intel_dvo *intel_dvo = intel_attached_dvo(&connector->base);
+
+	return intel_dvo->dev.dev_ops->get_hw_state(&intel_dvo->dev);
+}
+
+static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
+				   enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	u32 tmp;
+
+	tmp = I915_READ(intel_dvo->dev.dvo_reg);
+
+	if (!(tmp & DVO_ENABLE))
+		return false;
+
+	*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
 static void intel_disable_dvo(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
@@ -414,6 +439,8 @@ void intel_dvo_init(struct drm_device *dev)
 
 	intel_encoder->disable = intel_disable_dvo;
 	intel_encoder->enable = intel_enable_dvo;
+	intel_encoder->get_hw_state = intel_dvo_get_hw_state;
+	intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
 
 	/* Now, try to find a controller */
 	for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 30/58] drm/i915: read out the modeset hw state at load and resume time
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (28 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 29/58] drm/i915/dvo: " Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:14   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 31/58] drm/i915: check connector hw/sw state Daniel Vetter
                   ` (35 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

... instead of resetting a few things and hoping that this will work
out.

To properly disable the output pipelines at the initial modeset after
resume or boot up we need to have an accurate picture of which outputs
are enabled and connected to which crtcs. Otherwise we risk disabling
things at the wrong time, which can lead to hangs (or at least royally
confused panels), both requiring a walk to the reset button to fix.

Hence read out the hw state with the freshly introduce get_hw_state
functions and then sanitize it afterwards.

For a full modeset readout (which would allow us to avoid the initial
modeset at boot up) a few things are still missing:
- Reading out the mode from the pipe, especially the dotclock
  computation is quite some fun.
- Reading out the parameters for the stolen memory framebuffer and
  wrapping it up.
- Reading out the pch pll connections - luckily the disable code
  simply bails out if the crtc doesn't have a pch pll attached (even
  for configurations that would need one).

This patch here turned up tons of smelly stuff around resume: We
restore tons of register in seemingly random way (well, not quite, but
we're not too careful either), which leaves the hw in a rather
ill-defined state: E.g. the port registers are sometimes
unconditionally restore (lvds, crt), leaving us with an active
encoder/connector but no active pipe connected to it. Luckily the hw
state sanitizer detects this madness and fixes things up a bit.

v2: When checking whether an encoder with active connectors has a crtc
wire up to it, check for both the crtc _and_ it's active state.

v3:
- Extract intel_sanitize_encoder.
- Manually disable active encoders without an active pipe.

v4: Correclty fix up the pipe<->plane mapping on machines where we
switch pipes/planes. Noticed by Chris Wilson, who also provided the
fixup.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.c      |   1 +
 drivers/gpu/drm/i915/i915_drv.h      |   1 +
 drivers/gpu/drm/i915/intel_display.c | 278 ++++++++++++++++++++++++++---------
 3 files changed, 214 insertions(+), 66 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 7ebb13b..4abac6d 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -543,6 +543,7 @@ static int i915_drm_thaw(struct drm_device *dev)
 		mutex_unlock(&dev->struct_mutex);
 
 		intel_modeset_init_hw(dev);
+		intel_modeset_setup_hw_state(dev);
 		drm_mode_config_reset(dev);
 		drm_irq_install(dev);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index fb46c6f..9fce782 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1539,6 +1539,7 @@ extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
+extern void intel_modeset_setup_hw_state(struct drm_device *dev);
 extern bool intel_fbc_enabled(struct drm_device *dev);
 extern void intel_disable_fbc(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7e7569b..c258bbc 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3589,7 +3589,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
  * of the connector. */
 bool intel_connector_get_hw_state(struct intel_connector *connector)
 {
-	enum pipe pipe;
+	enum pipe pipe = 0;
 	struct intel_encoder *encoder = connector->encoder;
 
 	return encoder->get_hw_state(encoder, &pipe);
@@ -6533,65 +6533,6 @@ free_work:
 	return ret;
 }
 
-static void intel_sanitize_modesetting(struct drm_device *dev,
-				       int pipe, int plane)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 reg, val;
-	int i;
-
-	/* Clear any frame start delays used for debugging left by the BIOS */
-	for_each_pipe(i) {
-		reg = PIPECONF(i);
-		I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
-	}
-
-	if (HAS_PCH_SPLIT(dev))
-		return;
-
-	/* Who knows what state these registers were left in by the BIOS or
-	 * grub?
-	 *
-	 * If we leave the registers in a conflicting state (e.g. with the
-	 * display plane reading from the other pipe than the one we intend
-	 * to use) then when we attempt to teardown the active mode, we will
-	 * not disable the pipes and planes in the correct order -- leaving
-	 * a plane reading from a disabled pipe and possibly leading to
-	 * undefined behaviour.
-	 */
-
-	reg = DSPCNTR(plane);
-	val = I915_READ(reg);
-
-	if ((val & DISPLAY_PLANE_ENABLE) == 0)
-		return;
-	if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe)
-		return;
-
-	/* This display plane is active and attached to the other CPU pipe. */
-	pipe = !pipe;
-
-	/* Disable the plane and wait for it to stop reading from the pipe. */
-	intel_disable_plane(dev_priv, plane, pipe);
-	intel_disable_pipe(dev_priv, pipe);
-}
-
-static void intel_crtc_reset(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	/* Reset flags back to the 'unknown' status so that they
-	 * will be correctly set on the initial modeset.
-	 */
-	intel_crtc->dpms_mode = -1;
-
-	/* We need to fix up any BIOS configuration that conflicts with
-	 * our expectations.
-	 */
-	intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
-}
-
 static struct drm_crtc_helper_funcs intel_helper_funcs = {
 	.mode_set_base_atomic = intel_pipe_set_base_atomic,
 	.load_lut = intel_crtc_load_lut,
@@ -7006,7 +6947,6 @@ fail:
 }
 
 static const struct drm_crtc_funcs intel_crtc_funcs = {
-	.reset = intel_crtc_reset,
 	.cursor_set = intel_crtc_cursor_set,
 	.cursor_move = intel_crtc_cursor_move,
 	.gamma_set = intel_crtc_gamma_set,
@@ -7064,8 +7004,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
 	dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
 
-	intel_crtc_reset(&intel_crtc->base);
-	intel_crtc->active = true; /* force the pipe off on setup_init_config */
 	intel_crtc->bpp = 24; /* default for pre-Ironlake */
 
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
@@ -7273,9 +7211,6 @@ static void intel_setup_outputs(struct drm_device *dev)
 			intel_encoder_clones(encoder);
 	}
 
-	/* disable all the possible outputs/crtcs before entering KMS mode */
-	drm_helper_disable_unused_functions(dev);
-
 	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
 		ironlake_init_pch_refclk(dev);
 }
@@ -7634,11 +7569,222 @@ void intel_modeset_init(struct drm_device *dev)
 	intel_setup_outputs(dev);
 }
 
+static void
+intel_connector_break_all_links(struct intel_connector *connector)
+{
+	connector->base.dpms = DRM_MODE_DPMS_OFF;
+	connector->base.encoder = NULL;
+	connector->encoder->connectors_active = false;
+	connector->encoder->base.crtc = NULL;
+}
+
+static void intel_sanitize_crtc(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 reg, val;
+
+	/* Clear the dpms state for compatibility with code still using that
+	 * deprecated state variable. */
+	crtc->dpms_mode = -1;
+
+	/* Clear any frame start delays used for debugging left by the BIOS */
+	reg = PIPECONF(crtc->pipe);
+	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+
+	/* We need to sanitize the plane -> pipe mapping first because this will
+	 * disable the crtc (and hence change the state) if it is wrong. */
+	if (!HAS_PCH_SPLIT(dev)) {
+		struct intel_connector *connector;
+		bool plane;
+
+		reg = DSPCNTR(crtc->plane);
+		val = I915_READ(reg);
+
+		if ((val & DISPLAY_PLANE_ENABLE) == 0 &&
+		    (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
+			goto ok;
+
+		DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
+			      crtc->base.base.id);
+
+		/* Pipe has the wrong plane attached and the plane is active.
+		 * Temporarily change the plane mapping and disable everything
+		 * ...  */
+		plane = crtc->plane;
+		crtc->plane = !plane;
+		dev_priv->display.crtc_disable(&crtc->base);
+		crtc->plane = plane;
+
+		/* ... and break all links. */
+		list_for_each_entry(connector, &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->encoder->base.crtc != &crtc->base)
+				continue;
+
+			intel_connector_break_all_links(connector);
+		}
+
+		WARN_ON(crtc->active);
+		crtc->base.enabled = false;
+	}
+ok:
+
+	/* Adjust the state of the output pipe according to whether we
+	 * have active connectors/encoders. */
+	intel_crtc_update_dpms(&crtc->base);
+
+	if (crtc->active != crtc->base.enabled) {
+		struct intel_encoder *encoder;
+
+		/* This can happen either due to bugs in the get_hw_state
+		 * functions or because the pipe is force-enabled due to the
+		 * pipe A quirk. */
+		DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
+			      crtc->base.base.id,
+			      crtc->base.enabled ? "enabled" : "disabled",
+			      crtc->active ? "enabled" : "disabled");
+
+		crtc->base.enabled = crtc->active;
+
+		/* Because we only establish the connector -> encoder ->
+		 * crtc links if something is active, this means the
+		 * crtc is now deactivated. Break the links. connector
+		 * -> encoder links are only establish when things are
+		 *  actually up, hence no need to break them. */
+		WARN_ON(crtc->active);
+
+		for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
+			WARN_ON(encoder->connectors_active);
+			encoder->base.crtc = NULL;
+		}
+	}
+}
+
+static void intel_sanitize_encoder(struct intel_encoder *encoder)
+{
+	struct intel_connector *connector;
+	struct drm_device *dev = encoder->base.dev;
+
+	/* We need to check both for a crtc link (meaning that the
+	 * encoder is active and trying to read from a pipe) and the
+	 * pipe itself being active. */
+	bool has_active_crtc = encoder->base.crtc &&
+		to_intel_crtc(encoder->base.crtc)->active;
+
+	if (encoder->connectors_active && !has_active_crtc) {
+		DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n",
+			      encoder->base.base.id,
+			      drm_get_encoder_name(&encoder->base));
+
+		/* Connector is active, but has no active pipe. This is
+		 * fallout from our resume register restoring. Disable
+		 * the encoder manually again. */
+		if (encoder->base.crtc) {
+			DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
+				      encoder->base.base.id,
+				      drm_get_encoder_name(&encoder->base));
+			encoder->disable(encoder);
+		}
+
+		/* Inconsisten output/port/pipe state happens presumably due to
+		 * a bug in one of the get_hw_state functions. Or someplace else
+		 * in our code, like the register restore mess on resume. Clamp
+		 * things to off as a safer default. */
+		list_for_each_entry(connector,
+				    &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->encoder != encoder)
+				continue;
+
+			intel_connector_break_all_links(connector);
+		}
+	}
+	/* Enabled encoders without active connectors will be fixed in
+	 * the crtc fixup. */
+}
+
+/* Scan out the current hw modeset state, sanitizes it and maps it into the drm
+ * and i915 state tracking structures. */
+void intel_modeset_setup_hw_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum pipe pipe;
+	u32 tmp;
+	struct intel_crtc *crtc;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	for_each_pipe(pipe) {
+		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+
+		tmp = I915_READ(PIPECONF(pipe));
+		if (tmp & PIPECONF_ENABLE)
+			crtc->active = true;
+		else
+			crtc->active = false;
+
+		crtc->base.enabled = crtc->active;
+
+		DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
+			      crtc->base.base.id,
+			      crtc->active ? "enabled" : "disabled");
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		pipe = 0;
+
+		if (encoder->get_hw_state(encoder, &pipe)) {
+			encoder->base.crtc =
+				dev_priv->pipe_to_crtc_mapping[pipe];
+		} else {
+			encoder->base.crtc = NULL;
+		}
+
+		encoder->connectors_active = false;
+		DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe=%i\n",
+			      encoder->base.base.id,
+			      drm_get_encoder_name(&encoder->base),
+			      encoder->base.crtc ? "enabled" : "disabled",
+			      pipe);
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		if (connector->get_hw_state(connector)) {
+			connector->base.dpms = DRM_MODE_DPMS_ON;
+			connector->encoder->connectors_active = true;
+			connector->base.encoder = &connector->encoder->base;
+		} else {
+			connector->base.dpms = DRM_MODE_DPMS_OFF;
+			connector->base.encoder = NULL;
+		}
+		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hw state readout: %s\n",
+			      connector->base.base.id,
+			      drm_get_connector_name(&connector->base),
+			      connector->base.encoder ? "enabled" : "disabled");
+	}
+
+	/* HW state is read out, now we need to sanitize this mess. */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		intel_sanitize_encoder(encoder);
+	}
+
+	for_each_pipe(pipe) {
+		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+		intel_sanitize_crtc(crtc);
+	}
+}
+
 void intel_modeset_gem_init(struct drm_device *dev)
 {
 	intel_modeset_init_hw(dev);
 
 	intel_setup_overlay(dev);
+
+	intel_modeset_setup_hw_state(dev);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 31/58] drm/i915: check connector hw/sw state
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (29 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 30/58] drm/i915: read out the modeset hw state at load and resume time Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:26   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 32/58] drm/i915: rip out intel_crtc->dpms_mode Daniel Vetter
                   ` (34 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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).

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_crt.c     |  2 ++
 drivers/gpu/drm/i915/intel_display.c | 37 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_dp.c      |  2 ++
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 drivers/gpu/drm/i915/intel_dvo.c     |  2 ++
 drivers/gpu/drm/i915/intel_sdvo.c    |  2 ++
 6 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index fab54ed..2855eb7 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -176,6 +176,8 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
 
 		intel_crtc_update_dpms(crtc);
 	}
+
+	intel_connector_check_state(to_intel_connector(connector));
 }
 
 static int intel_crt_mode_valid(struct drm_connector *connector,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c258bbc..6d74e6f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3562,6 +3562,41 @@ void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
 	}
 }
 
+/* Cross check the actual hw state with our own modeset state tracking (and it's
+ * internal consistency). */
+void intel_connector_check_state(struct intel_connector *connector)
+{
+	if (connector->get_hw_state(connector)) {
+		struct intel_encoder *encoder = connector->encoder;
+		struct drm_crtc *crtc;
+		bool encoder_enabled;
+		enum pipe pipe;
+
+		DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+			      connector->base.base.id,
+			      drm_get_connector_name(&connector->base));
+
+		WARN(connector->base.dpms == DRM_MODE_DPMS_OFF,
+		     "wrong connector dpms state\n");
+		WARN(connector->base.encoder != &encoder->base,
+		     "active connector not linked to encoder\n");
+		WARN(!encoder->connectors_active,
+		     "encoder->connectors_active not set\n");
+
+		encoder_enabled = encoder->get_hw_state(encoder, &pipe);
+		WARN(!encoder_enabled, "encoder not enabled\n");
+		if (WARN_ON(!encoder->base.crtc))
+			return;
+
+		crtc = encoder->base.crtc;
+
+		WARN(!crtc->enabled, "crtc not enabled\n");
+		WARN(!to_intel_crtc(crtc)->active, "crtc not active\n");
+		WARN(pipe != to_intel_crtc(crtc)->pipe,
+		     "encoder active on the wrong pipe\n");
+	}
+}
+
 /* Even simpler default implementation, if there's really no special case to
  * consider. */
 void intel_connector_dpms(struct drm_connector *connector, int mode)
@@ -3582,6 +3617,8 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
 		intel_encoder_dpms(encoder, mode);
 	else
 		encoder->connectors_active = false;
+
+	intel_connector_check_state(to_intel_connector(connector));
 }
 
 /* Simple connector->get_hw_state implementation for encoders that support only
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e3928b9..96fd1e7 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1367,6 +1367,8 @@ intel_dp_dpms(struct drm_connector *connector, int mode)
 		intel_encoder_dpms(&intel_dp->base, mode);
 		WARN_ON(intel_dp->dpms_mode != DRM_MODE_DPMS_ON);
 	}
+
+	intel_connector_check_state(to_intel_connector(connector));
 }
 
 /*
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4daa7e6..e2116d9 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)
 {
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index e9397b7..17dc8be 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -188,6 +188,8 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
 
 		intel_crtc_update_dpms(crtc);
 	}
+
+	intel_connector_check_state(to_intel_connector(connector));
 }
 
 static int intel_dvo_mode_valid(struct drm_connector *connector,
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 4a735a5..198bb89 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1274,6 +1274,8 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
 			intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
 		intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
 	}
+
+	intel_connector_check_state(to_intel_connector(connector));
 }
 
 static int intel_sdvo_mode_valid(struct drm_connector *connector,
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 32/58] drm/i915: rip out intel_crtc->dpms_mode
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (30 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 31/58] drm/i915: check connector hw/sw state Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:27   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 33/58] drm/i915: rip out intel_dp->dpms_mode Daniel Vetter
                   ` (33 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 17 -----------------
 drivers/gpu/drm/i915/intel_drv.h     |  1 -
 2 files changed, 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6d74e6f..2cfb397 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3470,18 +3470,10 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc)
 	struct intel_encoder *intel_encoder;
 	int pipe = intel_crtc->pipe;
 	bool enabled, enable = false;
-	int mode;
 
 	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
 		enable |= intel_encoder->connectors_active;
 
-	mode = enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF;
-
-	if (intel_crtc->dpms_mode == mode)
-		return;
-
-	intel_crtc->dpms_mode = mode;
-
 	if (enable)
 		dev_priv->display.crtc_enable(crtc);
 	else
@@ -5037,11 +5029,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 					      x, y, old_fb);
 	drm_vblank_post_modeset(dev, pipe);
 
-	if (ret)
-		intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF;
-	else
-		intel_crtc->dpms_mode = DRM_MODE_DPMS_ON;
-
 	return ret;
 }
 
@@ -7621,10 +7608,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 reg, val;
 
-	/* Clear the dpms state for compatibility with code still using that
-	 * deprecated state variable. */
-	crtc->dpms_mode = -1;
-
 	/* Clear any frame start delays used for debugging left by the BIOS */
 	reg = PIPECONF(crtc->pipe);
 	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e2116d9..a7d79de 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
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 33/58] drm/i915: rip out intel_dp->dpms_mode
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (31 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 32/58] drm/i915: rip out intel_crtc->dpms_mode Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:28   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 34/58] drm/i915: ensure the force pipe A quirk is actually followed Daniel Vetter
                   ` (32 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_dp.c  | 11 ++---------
 drivers/gpu/drm/i915/intel_drv.h |  1 -
 2 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 96fd1e7..b07d4b4 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1309,8 +1309,6 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	ironlake_edp_panel_off(intel_dp);
 	intel_dp_link_down(intel_dp);
-
-	intel_dp->dpms_mode = DRM_MODE_DPMS_OFF;
 }
 
 static void intel_enable_dp(struct intel_encoder *encoder)
@@ -1330,8 +1328,6 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	} else
 		ironlake_edp_panel_vdd_off(intel_dp, false);
 	ironlake_edp_backlight_on(intel_dp);
-
-	intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
 }
 
 static void
@@ -1356,7 +1352,6 @@ intel_dp_dpms(struct drm_connector *connector, int mode)
 
 	if (mode != DRM_MODE_DPMS_ON) {
 		intel_encoder_dpms(&intel_dp->base, mode);
-		WARN_ON(intel_dp->dpms_mode != DRM_MODE_DPMS_OFF);
 
 		if (is_cpu_edp(intel_dp))
 			ironlake_edp_pll_off(&intel_dp->base.base);
@@ -1365,7 +1360,6 @@ intel_dp_dpms(struct drm_connector *connector, int mode)
 			ironlake_edp_pll_on(&intel_dp->base.base);
 
 		intel_encoder_dpms(&intel_dp->base, mode);
-		WARN_ON(intel_dp->dpms_mode != DRM_MODE_DPMS_ON);
 	}
 
 	intel_connector_check_state(to_intel_connector(connector));
@@ -2069,10 +2063,10 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
 	u8 sink_irq_vector;
 	u8 link_status[DP_LINK_STATUS_SIZE];
 
-	if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
+	if (!intel_dp->base.connectors_active)
 		return;
 
-	if (!intel_dp->base.base.crtc)
+	if (WARN_ON(!intel_dp->base.base.crtc))
 		return;
 
 	/* Try to read receiver status if the link appears to be up */
@@ -2490,7 +2484,6 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 
 	intel_dp->output_reg = output_reg;
 	intel_dp->port = port;
-	intel_dp->dpms_mode = -1;
 
 	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a7d79de..c080c829 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];
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 34/58] drm/i915: ensure the force pipe A quirk is actually followed
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (32 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 33/58] drm/i915: rip out intel_dp->dpms_mode Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:32   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 35/58] drm/i915: introduce struct intel_set_config Daniel Vetter
                   ` (31 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Many BIOSen forget to turn on the pipe A after resume (because they
actually don't turn on anything), so we have to do that ourselves when
sanitizing the hw state.

I've discovered this due to the recent addition of a pipe WARN that
takes the force quirk into account.

v2: Actually try to enable the pipe with a proper configuration instead
of simpyl switching it on with whatever random state the bios left it
in after resume.

v3: Fixup rebase conflict - the load_detect functions have lost their
encoder argument.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2cfb397..ab4fa7f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7602,6 +7602,33 @@ intel_connector_break_all_links(struct intel_connector *connector)
 	connector->encoder->base.crtc = NULL;
 }
 
+static void intel_enable_pipe_a(struct drm_device *dev)
+{
+	struct intel_connector *connector;
+	struct drm_connector *crt = NULL;
+	struct intel_load_detect_pipe load_detect_temp;
+
+	/* We can't just switch on the pipe A, we need to set things up with a
+	 * proper mode and output configuration. As a gross hack, enable pipe A
+	 * by enabling the load detect pipe once. */
+	list_for_each_entry(connector,
+			    &dev->mode_config.connector_list,
+			    base.head) {
+		if (connector->encoder->type == INTEL_OUTPUT_ANALOG) {
+			crt = &connector->base;
+			break;
+		}
+	}
+
+	if (!crt)
+		return;
+
+	if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp))
+		intel_release_load_detect_pipe(crt, &load_detect_temp);
+
+
+}
+
 static void intel_sanitize_crtc(struct intel_crtc *crtc)
 {
 	struct drm_device *dev = crtc->base.dev;
@@ -7650,6 +7677,15 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
 	}
 ok:
 
+	if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
+	    crtc->pipe == PIPE_A && !crtc->active) {
+		/* BIOS forgot to enable pipe A, this mostly happens after
+		 * resume. Force-enable the pipe to fix this, the update_dpms
+		 * call below we restore the pipe to the right state, but leave
+		 * the required bits on. */
+		intel_enable_pipe_a(dev);
+	}
+
 	/* Adjust the state of the output pipe according to whether we
 	 * have active connectors/encoders. */
 	intel_crtc_update_dpms(&crtc->base);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 35/58] drm/i915: introduce struct intel_set_config
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (33 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 34/58] drm/i915: ensure the force pipe A quirk is actually followed Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:34   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 36/58] drm/i915: extract modeset config save/restore code Daniel Vetter
                   ` (30 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 73 ++++++++++++++++++++----------------
 drivers/gpu/drm/i915/intel_drv.h     |  6 +++
 2 files changed, 47 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ab4fa7f..63bcc37 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6723,17 +6723,28 @@ done:
 	return ret;
 }
 
+static void intel_set_config_free(struct intel_set_config *config)
+{
+	if (config) {
+		kfree(config->save_connectors);
+		kfree(config->save_encoders);
+		kfree(config->save_crtcs);
+	}
+	kfree(config);
+}
+
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
 	struct drm_device *dev;
-	struct drm_crtc *save_crtcs, *new_crtc, *crtc;
-	struct drm_encoder *save_encoders, *new_encoder, *encoder;
+	struct drm_crtc *new_crtc, *crtc;
+	struct drm_encoder *new_encoder, *encoder;
 	struct drm_framebuffer *old_fb = NULL;
 	bool mode_changed = false; /* if true do a full mode set */
 	bool fb_changed = false; /* if true and !mode_changed just do a flip */
-	struct drm_connector *save_connectors, *connector;
+	struct drm_connector *connector;
 	int count = 0, ro;
 	struct drm_mode_set save_set;
+	struct intel_set_config *config;
 	int ret;
 	int i;
 
@@ -6762,27 +6773,27 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 
 	dev = set->crtc->dev;
 
+	ret = -ENOMEM;
+	config = kzalloc(sizeof(*config), GFP_KERNEL);
+	if (!config)
+		goto out_config;
+
 	/* Allocate space for the backup of all (non-pointer) crtc, encoder and
 	 * connector data. */
-	save_crtcs = kzalloc(dev->mode_config.num_crtc *
-			     sizeof(struct drm_crtc), GFP_KERNEL);
-	if (!save_crtcs)
-		return -ENOMEM;
+	config->save_crtcs = kzalloc(dev->mode_config.num_crtc *
+				     sizeof(struct drm_crtc), GFP_KERNEL);
+	if (!config->save_crtcs)
+		goto out_config;
 
-	save_encoders = kzalloc(dev->mode_config.num_encoder *
-				sizeof(struct drm_encoder), GFP_KERNEL);
-	if (!save_encoders) {
-		kfree(save_crtcs);
-		return -ENOMEM;
-	}
+	config->save_encoders = kzalloc(dev->mode_config.num_encoder *
+					sizeof(struct drm_encoder), GFP_KERNEL);
+	if (!config->save_encoders)
+		goto out_config;
 
-	save_connectors = kzalloc(dev->mode_config.num_connector *
-				sizeof(struct drm_connector), GFP_KERNEL);
-	if (!save_connectors) {
-		kfree(save_crtcs);
-		kfree(save_encoders);
-		return -ENOMEM;
-	}
+	config->save_connectors = kzalloc(dev->mode_config.num_connector *
+					  sizeof(struct drm_connector), GFP_KERNEL);
+	if (!config->save_connectors)
+		goto out_config;
 
 	/* Copy data. Note that driver private data is not affected.
 	 * Should anything bad happen only the expected state is
@@ -6790,17 +6801,17 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	 */
 	count = 0;
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		save_crtcs[count++] = *crtc;
+		config->save_crtcs[count++] = *crtc;
 	}
 
 	count = 0;
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		save_encoders[count++] = *encoder;
+		config->save_encoders[count++] = *encoder;
 	}
 
 	count = 0;
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		save_connectors[count++] = *connector;
+		config->save_connectors[count++] = *connector;
 	}
 
 	save_set.crtc = set->crtc;
@@ -6936,26 +6947,25 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		}
 	}
 
-	kfree(save_connectors);
-	kfree(save_encoders);
-	kfree(save_crtcs);
+	intel_set_config_free(config);
+
 	return 0;
 
 fail:
 	/* Restore all previous data. */
 	count = 0;
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		*crtc = save_crtcs[count++];
+		*crtc = config->save_crtcs[count++];
 	}
 
 	count = 0;
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		*encoder = save_encoders[count++];
+		*encoder = config->save_encoders[count++];
 	}
 
 	count = 0;
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		*connector = save_connectors[count++];
+		*connector = config->save_connectors[count++];
 	}
 
 	/* Try to restore the config */
@@ -6964,9 +6974,8 @@ fail:
 			    save_set.x, save_set.y, save_set.fb))
 		DRM_ERROR("failed to restore config after modeset failure\n");
 
-	kfree(save_connectors);
-	kfree(save_encoders);
-	kfree(save_crtcs);
+out_config:
+	intel_set_config_free(config);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index c080c829..1cb64dd 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);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 36/58] drm/i915: extract modeset config save/restore code
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (34 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 35/58] drm/i915: introduce struct intel_set_config Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:36   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 37/58] drm/i915: extract intel_set_config_compute_mode_changes Daniel Vetter
                   ` (29 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

At the end this won't be of much use to us, but meanwhile just extract
it to get a better overview of what exactly set_config does.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 127 +++++++++++++++++++++--------------
 1 file changed, 76 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 63bcc37..fc4902a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6733,11 +6733,82 @@ static void intel_set_config_free(struct intel_set_config *config)
 	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;
+
+	/* Allocate space for the backup of all (non-pointer) crtc, encoder and
+	 * connector data. */
+	config->save_crtcs = kzalloc(dev->mode_config.num_crtc *
+				     sizeof(struct drm_crtc), GFP_KERNEL);
+	if (!config->save_crtcs)
+		return -ENOMEM;
+
+	config->save_encoders = kzalloc(dev->mode_config.num_encoder *
+					sizeof(struct drm_encoder), GFP_KERNEL);
+	if (!config->save_encoders)
+		return -ENOMEM;
+
+	config->save_connectors = kzalloc(dev->mode_config.num_connector *
+					  sizeof(struct drm_connector), GFP_KERNEL);
+	if (!config->save_connectors)
+		return -ENOMEM;
+
+	/* Copy data. Note that driver private data is not affected.
+	 * 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_crtcs[count++] = *crtc;
+	}
+
+	count = 0;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		config->save_encoders[count++] = *encoder;
+	}
+
+	count = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		config->save_connectors[count++] = *connector;
+	}
+
+	return 0;
+}
+
+static void intel_set_config_restore_state(struct drm_device *dev,
+					   struct intel_set_config *config)
+{
+	struct drm_crtc *crtc;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	int count;
+
+	count = 0;
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		*crtc = config->save_crtcs[count++];
+	}
+
+	count = 0;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		*encoder = config->save_encoders[count++];
+	}
+
+	count = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		*connector = config->save_connectors[count++];
+	}
+}
+
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
 	struct drm_device *dev;
-	struct drm_crtc *new_crtc, *crtc;
-	struct drm_encoder *new_encoder, *encoder;
+	struct drm_crtc *new_crtc;
+	struct drm_encoder *new_encoder;
 	struct drm_framebuffer *old_fb = NULL;
 	bool mode_changed = false; /* if true do a full mode set */
 	bool fb_changed = false; /* if true and !mode_changed just do a flip */
@@ -6778,42 +6849,10 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	if (!config)
 		goto out_config;
 
-	/* Allocate space for the backup of all (non-pointer) crtc, encoder and
-	 * connector data. */
-	config->save_crtcs = kzalloc(dev->mode_config.num_crtc *
-				     sizeof(struct drm_crtc), GFP_KERNEL);
-	if (!config->save_crtcs)
-		goto out_config;
-
-	config->save_encoders = kzalloc(dev->mode_config.num_encoder *
-					sizeof(struct drm_encoder), GFP_KERNEL);
-	if (!config->save_encoders)
-		goto out_config;
-
-	config->save_connectors = kzalloc(dev->mode_config.num_connector *
-					  sizeof(struct drm_connector), GFP_KERNEL);
-	if (!config->save_connectors)
+	ret = intel_set_config_save_state(dev, config);
+	if (ret)
 		goto out_config;
 
-	/* Copy data. Note that driver private data is not affected.
-	 * 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_crtcs[count++] = *crtc;
-	}
-
-	count = 0;
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		config->save_encoders[count++] = *encoder;
-	}
-
-	count = 0;
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		config->save_connectors[count++] = *connector;
-	}
-
 	save_set.crtc = set->crtc;
 	save_set.mode = &set->crtc->mode;
 	save_set.x = set->crtc->x;
@@ -6952,21 +6991,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	return 0;
 
 fail:
-	/* Restore all previous data. */
-	count = 0;
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		*crtc = config->save_crtcs[count++];
-	}
-
-	count = 0;
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		*encoder = config->save_encoders[count++];
-	}
-
-	count = 0;
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		*connector = config->save_connectors[count++];
-	}
+	intel_set_config_restore_state(dev, config);
 
 	/* Try to restore the config */
 	if (mode_changed &&
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 37/58] drm/i915: extract intel_set_config_compute_mode_changes
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (35 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 36/58] drm/i915: extract modeset config save/restore code Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:42   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 38/58] drm/i915: extract intel_set_config_update_output_state Daniel Vetter
                   ` (28 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 81 ++++++++++++++++++++----------------
 drivers/gpu/drm/i915/intel_drv.h     |  3 ++
 2 files changed, 48 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fc4902a..b88a3ec 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6804,14 +6804,46 @@ static void intel_set_config_restore_state(struct drm_device *dev,
 	}
 }
 
+static void
+intel_set_config_compute_mode_changes(struct drm_mode_set *set,
+				      struct intel_set_config *config)
+{
+
+	/* We should be able to check here if the fb has the same properties
+	 * and then just flip_or_move it */
+	if (set->crtc->fb != set->fb) {
+		/* If we have no fb then treat it as a full mode set */
+		if (set->crtc->fb == NULL) {
+			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
+			config->mode_changed = true;
+		} else if (set->fb == NULL) {
+			config->mode_changed = true;
+		} else if (set->fb->depth != set->crtc->fb->depth) {
+			config->mode_changed = true;
+		} else if (set->fb->bits_per_pixel !=
+			   set->crtc->fb->bits_per_pixel) {
+			config->mode_changed = true;
+		} else
+			config->fb_changed = true;
+	}
+
+	if (set->x != set->crtc->x || set->y != set->crtc->y)
+		config->fb_changed = true;
+
+	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
+		DRM_DEBUG_KMS("modes are different, full mode set\n");
+		drm_mode_debug_printmodeline(&set->crtc->mode);
+		drm_mode_debug_printmodeline(set->mode);
+		config->mode_changed = true;
+	}
+}
+
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
 	struct drm_device *dev;
 	struct drm_crtc *new_crtc;
 	struct drm_encoder *new_encoder;
 	struct drm_framebuffer *old_fb = NULL;
-	bool mode_changed = false; /* if true do a full mode set */
-	bool fb_changed = false; /* if true and !mode_changed just do a flip */
 	struct drm_connector *connector;
 	int count = 0, ro;
 	struct drm_mode_set save_set;
@@ -6859,33 +6891,11 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	save_set.y = set->crtc->y;
 	save_set.fb = set->crtc->fb;
 
-	/* We should be able to check here if the fb has the same properties
-	 * and then just flip_or_move it */
-	if (set->crtc->fb != set->fb) {
-		/* If we have no fb then treat it as a full mode set */
-		if (set->crtc->fb == NULL) {
-			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
-			mode_changed = true;
-		} else if (set->fb == NULL) {
-			mode_changed = true;
-		} else if (set->fb->depth != set->crtc->fb->depth) {
-			mode_changed = true;
-		} else if (set->fb->bits_per_pixel !=
-			   set->crtc->fb->bits_per_pixel) {
-			mode_changed = true;
-		} else
-			fb_changed = true;
-	}
-
-	if (set->x != set->crtc->x || set->y != set->crtc->y)
-		fb_changed = true;
-
-	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
-		DRM_DEBUG_KMS("modes are different, full mode set\n");
-		drm_mode_debug_printmodeline(&set->crtc->mode);
-		drm_mode_debug_printmodeline(set->mode);
-		mode_changed = true;
-	}
+	/* Compute whether we need a full modeset, only an fb base update or no
+	 * change at all. In the future we might also check whether only the
+	 * mode changed, e.g. for LVDS where we only change the panel fitter in
+	 * such cases. */
+	intel_set_config_compute_mode_changes(set, config);
 
 	/* a) traverse passed in connector list and get encoders for them */
 	count = 0;
@@ -6901,7 +6911,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 
 		if (new_encoder != connector->encoder) {
 			DRM_DEBUG_KMS("encoder changed, full mode switch\n");
-			mode_changed = true;
+			config->mode_changed = true;
 			/* If the encoder is reused for another connector, then
 			 * the appropriate crtc will be set later.
 			 */
@@ -6929,12 +6939,11 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		/* Make sure the new CRTC will work with the encoder */
 		if (new_crtc &&
 		    !intel_encoder_crtc_ok(connector->encoder, new_crtc)) {
-			ret = -EINVAL;
-			goto fail;
+			return -EINVAL;
 		}
 		if (new_crtc != connector->encoder->crtc) {
 			DRM_DEBUG_KMS("crtc changed, full mode switch\n");
-			mode_changed = true;
+			config->mode_changed = true;
 			connector->encoder->crtc = new_crtc;
 		}
 		if (new_crtc) {
@@ -6947,7 +6956,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		}
 	}
 
-	if (mode_changed) {
+	if (config->mode_changed) {
 		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
 		if (set->crtc->enabled) {
 			DRM_DEBUG_KMS("attempting to set mode from"
@@ -6971,7 +6980,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 			}
 		}
 		drm_helper_disable_unused_functions(dev);
-	} else if (fb_changed) {
+	} else if (config->fb_changed) {
 		set->crtc->x = set->x;
 		set->crtc->y = set->y;
 
@@ -6994,7 +7003,7 @@ fail:
 	intel_set_config_restore_state(dev, config);
 
 	/* Try to restore the config */
-	if (mode_changed &&
+	if (config->mode_changed &&
 	    !intel_set_mode(save_set.crtc, save_set.mode,
 			    save_set.x, save_set.y, save_set.fb))
 		DRM_ERROR("failed to restore config after modeset failure\n");
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1cb64dd..fad11c8 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,
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 38/58] drm/i915: extract intel_set_config_update_output_state
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (36 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 37/58] drm/i915: extract intel_set_config_compute_mode_changes Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:44   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 39/58] drm/i915: implement crtc helper semantics relied upon by the fb helper Daniel Vetter
                   ` (27 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Note that this function already clobbers the mode config state,
so we have to clean things up if something fails.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 121 +++++++++++++++++++----------------
 1 file changed, 67 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b88a3ec..3cedc89 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6838,64 +6838,15 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 	}
 }
 
-static int intel_crtc_set_config(struct drm_mode_set *set)
+static int
+intel_set_config_update_output_state(struct drm_device *dev,
+				     struct drm_mode_set *set,
+				     struct intel_set_config *config)
 {
-	struct drm_device *dev;
 	struct drm_crtc *new_crtc;
 	struct drm_encoder *new_encoder;
-	struct drm_framebuffer *old_fb = NULL;
 	struct drm_connector *connector;
-	int count = 0, ro;
-	struct drm_mode_set save_set;
-	struct intel_set_config *config;
-	int ret;
-	int i;
-
-	DRM_DEBUG_KMS("\n");
-
-	if (!set)
-		return -EINVAL;
-
-	if (!set->crtc)
-		return -EINVAL;
-
-	if (!set->crtc->helper_private)
-		return -EINVAL;
-
-	if (!set->mode)
-		set->fb = NULL;
-
-	if (set->fb) {
-		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
-				set->crtc->base.id, set->fb->base.id,
-				(int)set->num_connectors, set->x, set->y);
-	} else {
-		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
-		return intel_crtc_helper_disable(set->crtc);
-	}
-
-	dev = set->crtc->dev;
-
-	ret = -ENOMEM;
-	config = kzalloc(sizeof(*config), GFP_KERNEL);
-	if (!config)
-		goto out_config;
-
-	ret = intel_set_config_save_state(dev, config);
-	if (ret)
-		goto out_config;
-
-	save_set.crtc = set->crtc;
-	save_set.mode = &set->crtc->mode;
-	save_set.x = set->crtc->x;
-	save_set.y = set->crtc->y;
-	save_set.fb = set->crtc->fb;
-
-	/* Compute whether we need a full modeset, only an fb base update or no
-	 * change at all. In the future we might also check whether only the
-	 * mode changed, e.g. for LVDS where we only change the panel fitter in
-	 * such cases. */
-	intel_set_config_compute_mode_changes(set, config);
+	int count, ro;
 
 	/* a) traverse passed in connector list and get encoders for them */
 	count = 0;
@@ -6956,6 +6907,68 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		}
 	}
 
+	return 0;
+}
+
+static int intel_crtc_set_config(struct drm_mode_set *set)
+{
+	struct drm_device *dev;
+	struct drm_framebuffer *old_fb = NULL;
+	struct drm_mode_set save_set;
+	struct intel_set_config *config;
+	int ret;
+	int i;
+
+	DRM_DEBUG_KMS("\n");
+
+	if (!set)
+		return -EINVAL;
+
+	if (!set->crtc)
+		return -EINVAL;
+
+	if (!set->crtc->helper_private)
+		return -EINVAL;
+
+	if (!set->mode)
+		set->fb = NULL;
+
+	if (set->fb) {
+		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
+				set->crtc->base.id, set->fb->base.id,
+				(int)set->num_connectors, set->x, set->y);
+	} else {
+		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
+		return intel_crtc_helper_disable(set->crtc);
+	}
+
+	dev = set->crtc->dev;
+
+	ret = -ENOMEM;
+	config = kzalloc(sizeof(*config), GFP_KERNEL);
+	if (!config)
+		goto out_config;
+
+	ret = intel_set_config_save_state(dev, config);
+	if (ret)
+		goto out_config;
+
+	save_set.crtc = set->crtc;
+	save_set.mode = &set->crtc->mode;
+	save_set.x = set->crtc->x;
+	save_set.y = set->crtc->y;
+	save_set.fb = set->crtc->fb;
+
+	/* Compute whether we need a full modeset, only an fb base update or no
+	 * change at all. In the future we might also check whether only the
+	 * mode changed, e.g. for LVDS where we only change the panel fitter in
+	 * such cases. */
+	intel_set_config_compute_mode_changes(set, config);
+
+	ret = intel_set_config_update_output_state(dev, set, config);
+	if (ret)
+		goto fail;
+
 	if (config->mode_changed) {
 		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
 		if (set->crtc->enabled) {
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 39/58] drm/i915: implement crtc helper semantics relied upon by the fb helper
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (37 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 38/58] drm/i915: extract intel_set_config_update_output_state Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:45   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 40/58] drm/i915: don't update the fb base if there is no fb Daniel Vetter
                   ` (26 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Yikes!

But yeah, we have to do this until someone volunteers to clean up the
fb helper and rid it of its incetious relationship with the crtc
helper code.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3cedc89..4b2b17f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6933,6 +6933,12 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	if (!set->mode)
 		set->fb = NULL;
 
+	/* The fb helper likes to play gross jokes with ->mode_set_config.
+	 * Unfortunately the crtc helper doesn't do much at all for this case,
+	 * so we have to cope with this madness until the fb helper is fixed up. */
+	if (set->fb && set->num_connectors == 0)
+		return 0;
+
 	if (set->fb) {
 		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
 				set->crtc->base.id, set->fb->base.id,
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 40/58] drm/i915: don't update the fb base if there is no fb
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (38 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 39/58] drm/i915: implement crtc helper semantics relied upon by the fb helper Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:47   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 41/58] drm/i915: convert pointless error checks in set_config to BUGs Daniel Vetter
                   ` (25 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Otherwise we'll set_fb complains pretty loudly if we the crtc is off
and userspace moves the NULL fb around a bit. Yeah, this actually
happens in the wild ...

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4b2b17f..125443a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6827,7 +6827,7 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 			config->fb_changed = true;
 	}
 
-	if (set->x != set->crtc->x || set->y != set->crtc->y)
+	if (set->fb && (set->x != set->crtc->x || set->y != set->crtc->y))
 		config->fb_changed = true;
 
 	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 41/58] drm/i915: convert pointless error checks in set_config to BUGs
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (39 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 40/58] drm/i915: don't update the fb base if there is no fb Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:50   ` Jesse Barnes
  2012-08-19 19:12 ` [PATCH 42/58] drm/i915: don't save all the encoder/crtc state in set_config Daniel Vetter
                   ` (24 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Because they all are, the ioctl command never calls us with any of
these violated. Also drop a equally pointless empty debug message (and
also in set_cursor, while we're at it).

With all these changes, intel_crtc_set_config is neatly condensed down
to it's essence, the actual modeset code (or fb update calling code)

v2: The fb helper code is actually stretching ->set_config semantics a bit,
it calls it with set->mode == NULL but set->fb != NULL.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 125443a..56827d6 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5462,8 +5462,6 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 	uint32_t addr;
 	int ret;
 
-	DRM_DEBUG_KMS("\n");
-
 	/* if we want to turn off the cursor ignore width and height */
 	if (!handle) {
 		DRM_DEBUG_KMS("cursor off\n");
@@ -6919,16 +6917,9 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	int ret;
 	int i;
 
-	DRM_DEBUG_KMS("\n");
-
-	if (!set)
-		return -EINVAL;
-
-	if (!set->crtc)
-		return -EINVAL;
-
-	if (!set->crtc->helper_private)
-		return -EINVAL;
+	BUG_ON(!set);
+	BUG_ON(!set->crtc);
+	BUG_ON(!set->crtc->helper_private);
 
 	if (!set->mode)
 		set->fb = NULL;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 42/58] drm/i915: don't save all the encoder/crtc state in set_config
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (40 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 41/58] drm/i915: convert pointless error checks in set_config to BUGs Daniel Vetter
@ 2012-08-19 19:12 ` Daniel Vetter
  2012-09-05 16:52   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 43/58] drm/i915: stage modeset output changes Daniel Vetter
                   ` (23 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

We actually only touch the connector -> encoder and encoder -> crtc
linking. So it's enough to just save/restore that.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 28 +++++++++++++++-------------
 drivers/gpu/drm/i915/intel_drv.h     |  4 ++--
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 56827d6..24706ca 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6724,8 +6724,8 @@ done:
 static void intel_set_config_free(struct intel_set_config *config)
 {
 	if (config) {
-		kfree(config->save_connectors);
-		kfree(config->save_encoders);
+		kfree(config->save_connector_encoders);
+		kfree(config->save_encoder_crtcs);
 		kfree(config->save_crtcs);
 	}
 	kfree(config);
@@ -6741,19 +6741,21 @@ static int intel_set_config_save_state(struct drm_device *dev,
 
 	/* Allocate space for the backup of all (non-pointer) crtc, encoder and
 	 * connector data. */
-	config->save_crtcs = kzalloc(dev->mode_config.num_crtc *
+	config->save_crtcs = kcalloc(dev->mode_config.num_crtc,
 				     sizeof(struct drm_crtc), GFP_KERNEL);
 	if (!config->save_crtcs)
 		return -ENOMEM;
 
-	config->save_encoders = kzalloc(dev->mode_config.num_encoder *
-					sizeof(struct drm_encoder), GFP_KERNEL);
-	if (!config->save_encoders)
+	config->save_encoder_crtcs =
+		kcalloc(dev->mode_config.num_encoder,
+			sizeof(struct drm_crtc *), GFP_KERNEL);
+	if (!config->save_encoder_crtcs)
 		return -ENOMEM;
 
-	config->save_connectors = kzalloc(dev->mode_config.num_connector *
-					  sizeof(struct drm_connector), GFP_KERNEL);
-	if (!config->save_connectors)
+	config->save_connector_encoders =
+		kcalloc(dev->mode_config.num_connector,
+			sizeof(struct drm_encoder *), GFP_KERNEL);
+	if (!config->save_connector_encoders)
 		return -ENOMEM;
 
 	/* Copy data. Note that driver private data is not affected.
@@ -6767,12 +6769,12 @@ static int intel_set_config_save_state(struct drm_device *dev,
 
 	count = 0;
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		config->save_encoders[count++] = *encoder;
+		config->save_encoder_crtcs[count++] = encoder->crtc;
 	}
 
 	count = 0;
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		config->save_connectors[count++] = *connector;
+		config->save_connector_encoders[count++] = connector->encoder;
 	}
 
 	return 0;
@@ -6793,12 +6795,12 @@ static void intel_set_config_restore_state(struct drm_device *dev,
 
 	count = 0;
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		*encoder = config->save_encoders[count++];
+		encoder->crtc = config->save_encoder_crtcs[count++];
 	}
 
 	count = 0;
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		*connector = config->save_connectors[count++];
+		connector->encoder = config->save_connector_encoders[count++];
 	}
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index fad11c8..4946282 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;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 43/58] drm/i915: stage modeset output changes
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (41 preceding siblings ...)
  2012-08-19 19:12 ` [PATCH 42/58] drm/i915: don't save all the encoder/crtc state in set_config Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 17:51   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 44/58] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
                   ` (22 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 174 ++++++++++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_drv.h     |  16 ++++
 2 files changed, 146 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 24706ca..e6701b4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6619,6 +6619,51 @@ intel_crtc_prepare_encoders(struct drm_device *dev)
 	}
 }
 
+/**
+ * intel_modeset_update_staged_output_state
+ *
+ * Updates the staged output configuration state, e.g. after we've read out the
+ * current hw state.
+ */
+static void intel_modeset_update_staged_output_state(struct drm_device *dev)
+{
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		connector->new_encoder =
+			to_intel_encoder(connector->base.encoder);
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		encoder->new_crtc =
+			to_intel_crtc(encoder->base.crtc);
+	}
+}
+
+/**
+ * intel_modeset_commit_output_state
+ *
+ * This function copies the stage display pipe configuration to the real one.
+ */
+static void intel_modeset_commit_output_state(struct drm_device *dev)
+{
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		connector->base.encoder = &connector->new_encoder->base;
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		encoder->base.crtc = &encoder->new_crtc->base;
+	}
+}
+
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
 		    int x, int y, struct drm_framebuffer *old_fb)
@@ -6784,8 +6829,8 @@ static void intel_set_config_restore_state(struct drm_device *dev,
 					   struct intel_set_config *config)
 {
 	struct drm_crtc *crtc;
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
 	int count;
 
 	count = 0;
@@ -6794,13 +6839,15 @@ static void intel_set_config_restore_state(struct drm_device *dev,
 	}
 
 	count = 0;
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		encoder->crtc = config->save_encoder_crtcs[count++];
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		encoder->new_crtc =
+			to_intel_crtc(config->save_encoder_crtcs[count++]);
 	}
 
 	count = 0;
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		connector->encoder = config->save_connector_encoders[count++];
+	list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) {
+		connector->new_encoder =
+			to_intel_encoder(config->save_connector_encoders[count++]);
 	}
 }
 
@@ -6839,73 +6886,106 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
 }
 
 static int
-intel_set_config_update_output_state(struct drm_device *dev,
-				     struct drm_mode_set *set,
-				     struct intel_set_config *config)
+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 drm_encoder *new_encoder;
-	struct drm_connector *connector;
+	struct intel_connector *connector;
+	struct intel_encoder *encoder;
 	int count, ro;
 
-	/* a) traverse passed in connector list and get encoders for them */
+	/* The upper layers ensure that we either disabl a crtc or have a list
+	 * of connectors. For paranoia, double-check this. */
+	WARN_ON(!set->fb && (set->num_connectors != 0));
+	WARN_ON(set->fb && (set->num_connectors == 0));
+
 	count = 0;
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		new_encoder = connector->encoder;
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		/* Otherwise traverse passed in connector list and get encoders
+		 * for them. */
 		for (ro = 0; ro < set->num_connectors; ro++) {
-			if (set->connectors[ro] == connector) {
-				new_encoder =
-					&intel_attached_encoder(connector)->base;
+			if (set->connectors[ro] == &connector->base) {
+				connector->new_encoder = connector->encoder;
 				break;
 			}
 		}
 
-		if (new_encoder != connector->encoder) {
+		/* If we disable the crtc, disable all its connectors. Also, if
+		 * the connector is on the changing crtc but not on the new
+		 * connector list, disable it. */
+		if ((!set->fb || ro == set->num_connectors) &&
+		    connector->base.encoder &&
+		    connector->base.encoder->crtc == set->crtc) {
+			connector->new_encoder = NULL;
+
+			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
+				connector->base.base.id,
+				drm_get_connector_name(&connector->base));
+		}
+
+
+		if (&connector->new_encoder->base != connector->base.encoder) {
 			DRM_DEBUG_KMS("encoder changed, full mode switch\n");
 			config->mode_changed = true;
-			/* If the encoder is reused for another connector, then
-			 * the appropriate crtc will be set later.
-			 */
-			if (connector->encoder)
-				connector->encoder->crtc = NULL;
-			connector->encoder = new_encoder;
 		}
+
+		/* Disable all disconnected encoders. */
+		if (connector->base.status == connector_status_disconnected)
+			connector->new_encoder = NULL;
 	}
+	/* connector->new_encoder is now updated for all connectors. */
 
+	/* Update crtc of enabled connectors. */
 	count = 0;
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		if (!connector->encoder)
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		if (!connector->new_encoder)
 			continue;
 
-		if (connector->encoder->crtc == set->crtc)
-			new_crtc = NULL;
-		else
-			new_crtc = connector->encoder->crtc;
+		new_crtc = connector->new_encoder->base.crtc;
 
 		for (ro = 0; ro < set->num_connectors; ro++) {
-			if (set->connectors[ro] == connector)
+			if (set->connectors[ro] == &connector->base)
 				new_crtc = set->crtc;
 		}
 
 		/* Make sure the new CRTC will work with the encoder */
-		if (new_crtc &&
-		    !intel_encoder_crtc_ok(connector->encoder, new_crtc)) {
+		if (!intel_encoder_crtc_ok(&connector->new_encoder->base,
+					   new_crtc)) {
 			return -EINVAL;
 		}
-		if (new_crtc != connector->encoder->crtc) {
+		connector->encoder->new_crtc = to_intel_crtc(new_crtc);
+
+		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
+			connector->base.base.id,
+			drm_get_connector_name(&connector->base),
+			new_crtc->base.id);
+	}
+
+	/* Check for any encoders that needs to be disabled. */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		list_for_each_entry(connector,
+				    &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->new_encoder == encoder) {
+				WARN_ON(!connector->new_encoder->new_crtc);
+
+				goto next_encoder;
+			}
+		}
+		encoder->new_crtc = NULL;
+next_encoder:
+		/* Only now check for crtc changes so we don't miss encoders
+		 * that will be disabled. */
+		if (&encoder->new_crtc->base != encoder->base.crtc) {
 			DRM_DEBUG_KMS("crtc changed, full mode switch\n");
 			config->mode_changed = true;
-			connector->encoder->crtc = new_crtc;
-		}
-		if (new_crtc) {
-			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
-				connector->base.id, drm_get_connector_name(connector),
-				new_crtc->base.id);
-		} else {
-			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
-				connector->base.id, drm_get_connector_name(connector));
 		}
 	}
+	/* Now we've also updated encoder->new_crtc for all encoders. */
 
 	return 0;
 }
@@ -6964,11 +7044,13 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	 * such cases. */
 	intel_set_config_compute_mode_changes(set, config);
 
-	ret = intel_set_config_update_output_state(dev, set, config);
+	ret = intel_modeset_stage_output_state(dev, set, config);
 	if (ret)
 		goto fail;
 
 	if (config->mode_changed) {
+		intel_modeset_commit_output_state(dev);
+
 		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
 		if (set->crtc->enabled) {
 			DRM_DEBUG_KMS("attempting to set mode from"
@@ -7014,6 +7096,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 fail:
 	intel_set_config_restore_state(dev, config);
 
+	intel_modeset_commit_output_state(dev);
+
 	/* Try to restore the config */
 	if (config->mode_changed &&
 	    !intel_set_mode(save_set.crtc, save_set.mode,
@@ -7887,6 +7971,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 		intel_sanitize_crtc(crtc);
 	}
+
+	intel_modeset_update_staged_output_state(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4946282..ae807af 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 *);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 44/58] drm/i915: push crtc->fb update into pipe_set_base
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (42 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 43/58] drm/i915: stage modeset output changes Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-04 19:33   ` [PATCH] " Daniel Vetter
  2012-09-05 17:54   ` [PATCH 44/58] " Jesse Barnes
  2012-08-19 19:13 ` [PATCH 45/58] drm/i915: remove crtc disabling special case Daniel Vetter
                   ` (21 subsequent siblings)
  65 siblings, 2 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 84 +++++++++++++++---------------------
 1 file changed, 34 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e6701b4..cd3606c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2201,16 +2201,17 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
 
 static int
 intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
-		    struct drm_framebuffer *old_fb)
+		    struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_framebuffer *old_fb;
 	int ret;
 
 	/* no fb bound */
-	if (!crtc->fb) {
+	if (!fb) {
 		DRM_ERROR("No FB bound\n");
 		return 0;
 	}
@@ -2224,7 +2225,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 
 	mutex_lock(&dev->struct_mutex);
 	ret = intel_pin_and_fence_fb_obj(dev,
-					 to_intel_framebuffer(crtc->fb)->obj,
+					 to_intel_framebuffer(fb)->obj,
 					 NULL);
 	if (ret != 0) {
 		mutex_unlock(&dev->struct_mutex);
@@ -2232,17 +2233,20 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		return ret;
 	}
 
-	if (old_fb)
-		intel_finish_fb(old_fb);
+	if (crtc->fb)
+		intel_finish_fb(crtc->fb);
 
-	ret = dev_priv->display.update_plane(crtc, crtc->fb, x, y);
+	ret = dev_priv->display.update_plane(crtc, fb, x, y);
 	if (ret) {
-		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
+		intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj);
 		mutex_unlock(&dev->struct_mutex);
 		DRM_ERROR("failed to update base address\n");
 		return ret;
 	}
 
+	old_fb = crtc->fb;
+	crtc->fb = fb;
+
 	if (old_fb) {
 		intel_wait_for_vblank(dev, intel_crtc->pipe);
 		intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
@@ -3777,6 +3781,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
  * true if they don't match).
  */
 static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
+					 struct drm_framebuffer *fb,
 					 unsigned int *pipe_bpp,
 					 struct drm_display_mode *mode)
 {
@@ -3846,7 +3851,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
 	 * also stays within the max display bpc discovered above.
 	 */
 
-	switch (crtc->fb->depth) {
+	switch (fb->depth) {
 	case 8:
 		bpc = 8; /* since we go through a colormap */
 		break;
@@ -4265,7 +4270,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 			      struct drm_display_mode *mode,
 			      struct drm_display_mode *adjusted_mode,
 			      int x, int y,
-			      struct drm_framebuffer *old_fb)
+			      struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4455,7 +4460,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), dspcntr);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, old_fb);
+	ret = intel_pipe_set_base(crtc, x, y, fb);
 
 	intel_update_watermarks(dev);
 
@@ -4613,7 +4618,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode,
 				  int x, int y,
-				  struct drm_framebuffer *old_fb)
+				  struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4733,7 +4738,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	/* determine panel color depth */
 	temp = I915_READ(PIPECONF(pipe));
 	temp &= ~PIPE_BPC_MASK;
-	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
+	dither = intel_choose_pipe_bpp_dither(crtc, fb, &pipe_bpp, mode);
 	switch (pipe_bpp) {
 	case 18:
 		temp |= PIPE_6BPC;
@@ -5002,7 +5007,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), dspcntr);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, old_fb);
+	ret = intel_pipe_set_base(crtc, x, y, fb);
 
 	intel_update_watermarks(dev);
 
@@ -5015,7 +5020,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode,
 			       int x, int y,
-			       struct drm_framebuffer *old_fb)
+			       struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5026,7 +5031,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	drm_vblank_pre_modeset(dev, pipe);
 
 	ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
-					      x, y, old_fb);
+					      x, y, fb);
 	drm_vblank_post_modeset(dev, pipe);
 
 	return ret;
@@ -5718,7 +5723,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_crtc *crtc = NULL;
 	struct drm_device *dev = encoder->dev;
-	struct drm_framebuffer *old_fb;
+	struct drm_framebuffer *fb;
 	int i = -1;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
@@ -5779,8 +5784,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 	if (!mode)
 		mode = &load_detect_mode;
 
-	old_fb = crtc->fb;
-
 	/* We need a framebuffer large enough to accommodate all accesses
 	 * that the plane may generate whilst we perform load detection.
 	 * We can not rely on the fbcon either being present (we get called
@@ -5788,19 +5791,19 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 	 * not even exist) or that it is large enough to satisfy the
 	 * requested mode.
 	 */
-	crtc->fb = mode_fits_in_fbdev(dev, mode);
-	if (crtc->fb == NULL) {
+	fb = mode_fits_in_fbdev(dev, mode);
+	if (fb == NULL) {
 		DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
-		crtc->fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
-		old->release_fb = crtc->fb;
+		fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
+		old->release_fb = fb;
 	} else
 		DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
-	if (IS_ERR(crtc->fb)) {
+	if (IS_ERR(fb)) {
 		DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
 		goto fail;
 	}
 
-	if (!intel_set_mode(crtc, mode, 0, 0, old_fb)) {
+	if (!intel_set_mode(crtc, mode, 0, 0, fb)) {
 		DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
 		if (old->release_fb)
 			old->release_fb->funcs->destroy(old->release_fb);
@@ -5814,7 +5817,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 fail:
 	connector->encoder = NULL;
 	encoder->crtc = NULL;
-	crtc->fb = old_fb;
 	return false;
 }
 
@@ -6666,13 +6668,12 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
 
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
-		    int x, int y, struct drm_framebuffer *old_fb)
+		    int x, int y, struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
 	struct drm_encoder_helper_funcs *encoder_funcs;
-	int saved_x, saved_y;
 	struct drm_encoder *encoder;
 	bool ret = true;
 
@@ -6686,15 +6687,11 @@ bool intel_set_mode(struct drm_crtc *crtc,
 
 	saved_hwmode = crtc->hwmode;
 	saved_mode = crtc->mode;
-	saved_x = crtc->x;
-	saved_y = crtc->y;
 
 	/* Update crtc values up front so the driver can rely on them for mode
 	 * setting.
 	 */
 	crtc->mode = *mode;
-	crtc->x = x;
-	crtc->y = y;
 
 	/* Pass our mode to the connectors and the CRTC to give them a chance to
 	 * adjust it according to limitations or connector properties, and also
@@ -6725,7 +6722,7 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
-	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, fb);
 	if (!ret)
 	    goto done;
 
@@ -6741,6 +6738,9 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 	}
 
+	crtc->x = x;
+	crtc->y = y;
+
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
 	dev_priv->display.crtc_enable(crtc);
 
@@ -6759,8 +6759,6 @@ done:
 	if (!ret) {
 		crtc->hwmode = saved_hwmode;
 		crtc->mode = saved_mode;
-		crtc->x = saved_x;
-		crtc->y = saved_y;
 	}
 
 	return ret;
@@ -6993,7 +6991,6 @@ next_encoder:
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
 	struct drm_device *dev;
-	struct drm_framebuffer *old_fb = NULL;
 	struct drm_mode_set save_set;
 	struct intel_set_config *config;
 	int ret;
@@ -7056,13 +7053,10 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 			DRM_DEBUG_KMS("attempting to set mode from"
 					" userspace\n");
 			drm_mode_debug_printmodeline(set->mode);
-			old_fb = set->crtc->fb;
-			set->crtc->fb = set->fb;
 			if (!intel_set_mode(set->crtc, set->mode,
-					    set->x, set->y, old_fb)) {
+					    set->x, set->y, set->fb)) {
 				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
 					  set->crtc->base.id);
-				set->crtc->fb = old_fb;
 				ret = -EINVAL;
 				goto fail;
 			}
@@ -7075,18 +7069,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		}
 		drm_helper_disable_unused_functions(dev);
 	} else if (config->fb_changed) {
-		set->crtc->x = set->x;
-		set->crtc->y = set->y;
-
-		old_fb = set->crtc->fb;
-		if (set->crtc->fb != set->fb)
-			set->crtc->fb = set->fb;
 		ret = intel_pipe_set_base(set->crtc,
-					  set->x, set->y, old_fb);
-		if (ret != 0) {
-			set->crtc->fb = old_fb;
-			goto fail;
-		}
+					  set->x, set->y, set->fb);
 	}
 
 	intel_set_config_free(config);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 45/58] drm/i915: remove crtc disabling special case
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (43 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 44/58] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 17:56   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 46/58] drm/i915: move output commit and crtc disabling into set_mode Daniel Vetter
                   ` (20 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Originally this has been introduced in

commit 6eebd6bb5f1ea04f04019e5c39f87a0f17ffb472
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Mon Nov 28 21:10:05 2011 +0000

    drm: Fix lack of CRTC disable for drm_crtc_helper_set_config(.fb=NULL)

With the improvements of the output state staging and no longer
overwriting crtc->fb before the hw state is updated we can now handle
crtc disabling as part of the normal modeset sequence.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 25 -------------------------
 1 file changed, 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cd3606c..4e72119 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6585,30 +6585,6 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
 	return false;
 }
 
-static int
-intel_crtc_helper_disable(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_connector *connector;
-	struct drm_encoder *encoder;
-
-	/* Decouple all encoders and their attached connectors from this crtc */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		if (encoder->crtc != crtc)
-			continue;
-
-		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-			if (connector->encoder != encoder)
-				continue;
-
-			connector->encoder = NULL;
-		}
-	}
-
-	drm_helper_disable_unused_functions(dev);
-	return 0;
-}
-
 static void
 intel_crtc_prepare_encoders(struct drm_device *dev)
 {
@@ -7015,7 +6991,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 				(int)set->num_connectors, set->x, set->y);
 	} else {
 		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
-		return intel_crtc_helper_disable(set->crtc);
 	}
 
 	dev = set->crtc->dev;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 46/58] drm/i915: move output commit and crtc disabling into set_mode
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (44 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 45/58] drm/i915: remove crtc disabling special case Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 17:58   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 47/58] drm/i915: extract adjusted mode computation Daniel Vetter
                   ` (19 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

It's rather pointless to compute crtc->enabled twice right away ;-)

The only thing we really have to be careful about is that we frob the
dpms state only after a successful modeset and when we've actually
haven't just disabled the crtc.

Hooray for convoluted interfaces ...

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4e72119..348727d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6653,9 +6653,13 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	struct drm_encoder *encoder;
 	bool ret = true;
 
+	intel_modeset_commit_output_state(dev);
+
 	crtc->enabled = drm_helper_crtc_in_use(crtc);
-	if (!crtc->enabled)
+	if (!crtc->enabled) {
+		drm_helper_disable_unused_functions(dev);
 		return true;
+	}
 
 	adjusted_mode = drm_mode_duplicate(dev, mode);
 	if (!adjusted_mode)
@@ -7021,20 +7025,21 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		goto fail;
 
 	if (config->mode_changed) {
-		intel_modeset_commit_output_state(dev);
-
-		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
-		if (set->crtc->enabled) {
+		if (set->mode) {
 			DRM_DEBUG_KMS("attempting to set mode from"
 					" userspace\n");
 			drm_mode_debug_printmodeline(set->mode);
-			if (!intel_set_mode(set->crtc, set->mode,
-					    set->x, set->y, set->fb)) {
-				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
-					  set->crtc->base.id);
-				ret = -EINVAL;
-				goto fail;
-			}
+		}
+
+		if (!intel_set_mode(set->crtc, set->mode,
+				    set->x, set->y, set->fb)) {
+			DRM_ERROR("failed to set mode on [CRTC:%d]\n",
+				  set->crtc->base.id);
+			ret = -EINVAL;
+			goto fail;
+		}
+
+		if (set->crtc->enabled) {
 			DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
 			for (i = 0; i < set->num_connectors; i++) {
 				DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
@@ -7042,7 +7047,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 				set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
 			}
 		}
-		drm_helper_disable_unused_functions(dev);
 	} else if (config->fb_changed) {
 		ret = intel_pipe_set_base(set->crtc,
 					  set->x, set->y, set->fb);
@@ -7055,8 +7059,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 fail:
 	intel_set_config_restore_state(dev, config);
 
-	intel_modeset_commit_output_state(dev);
-
 	/* Try to restore the config */
 	if (config->mode_changed &&
 	    !intel_set_mode(save_set.crtc, save_set.mode,
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 47/58] drm/i915: extract adjusted mode computation
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (45 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 46/58] drm/i915: move output commit and crtc disabling into set_mode Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 18:00   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 48/58] drm/i915: use staged outuput config in tv->mode_fixup Daniel Vetter
                   ` (18 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

While at it, adjust a few things:
- Only assigng the new mode to crtc->mode right before calling the
  mode_set callbacks - none of the previous callbacks depend upon
  this, they all use the mode argument (as they should).
- Check encoder->new_crtc instead of the current crtc to check whether
  the encoder will be used. This prepares for moving the staged output
  committing further down in the sequence. Follow-on patches will fix
  up individual ->mode_fixup callbacks (only tv and lvds are affected
  though).

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 75 ++++++++++++++++++++++--------------
 1 file changed, 47 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 348727d..c7bd573 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6642,6 +6642,48 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
 	}
 }
 
+static struct drm_display_mode *
+intel_modeset_adjusted_mode(struct drm_crtc *crtc,
+			    struct drm_display_mode *mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_display_mode *adjusted_mode;
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	struct intel_encoder *encoder;
+
+	adjusted_mode = drm_mode_duplicate(dev, mode);
+	if (!adjusted_mode)
+		return ERR_PTR(-ENOMEM);
+
+	/* Pass our mode to the connectors and the CRTC to give them a chance to
+	 * adjust it according to limitations or connector properties, and also
+	 * a chance to reject the mode entirely.
+	 */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+
+		if (&encoder->new_crtc->base != crtc)
+			continue;
+		encoder_funcs = encoder->base.helper_private;
+		if (!(encoder_funcs->mode_fixup(&encoder->base, mode,
+						adjusted_mode))) {
+			DRM_DEBUG_KMS("Encoder fixup failed\n");
+			goto fail;
+		}
+	}
+
+	if (!(intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) {
+		DRM_DEBUG_KMS("CRTC fixup failed\n");
+		goto fail;
+	}
+	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
+
+	return adjusted_mode;
+fail:
+	drm_mode_destroy(dev, adjusted_mode);
+	return ERR_PTR(-EINVAL);
+}
+
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
 		    int x, int y, struct drm_framebuffer *fb)
@@ -6661,44 +6703,21 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		return true;
 	}
 
-	adjusted_mode = drm_mode_duplicate(dev, mode);
-	if (!adjusted_mode)
-		return false;
 
 	saved_hwmode = crtc->hwmode;
 	saved_mode = crtc->mode;
 
-	/* Update crtc values up front so the driver can rely on them for mode
-	 * setting.
-	 */
-	crtc->mode = *mode;
-
-	/* Pass our mode to the connectors and the CRTC to give them a chance to
-	 * adjust it according to limitations or connector properties, and also
-	 * a chance to reject the mode entirely.
-	 */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-
-		if (encoder->crtc != crtc)
-			continue;
-		encoder_funcs = encoder->helper_private;
-		if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
-						      adjusted_mode))) {
-			DRM_DEBUG_KMS("Encoder fixup failed\n");
-			goto done;
-		}
-	}
-
-	if (!(ret = intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) {
-		DRM_DEBUG_KMS("CRTC fixup failed\n");
-		goto done;
+	adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
+	if (IS_ERR(adjusted_mode)) {
+		return false;
 	}
-	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 
 	intel_crtc_prepare_encoders(dev);
 
 	dev_priv->display.crtc_disable(crtc);
 
+	crtc->mode = *mode;
+
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 48/58] drm/i915: use staged outuput config in tv->mode_fixup
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (46 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 47/58] drm/i915: extract adjusted mode computation Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 18:02   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 49/58] drm/i915: use staged outuput config in lvds->mode_fixup Daniel Vetter
                   ` (17 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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 ...

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 drivers/gpu/drm/i915/intel_tv.c      |  7 ++-----
 3 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c7bd573..c59569e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6563,6 +6563,28 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = {
 	.disable = intel_crtc_disable,
 };
 
+bool intel_encoder_check_non_cloned(struct intel_encoder *encoder)
+{
+	struct intel_encoder *other_encoder;
+	struct drm_crtc *crtc = &encoder->new_crtc->base;
+
+	if (WARN_ON(!crtc))
+		return true;
+
+	list_for_each_entry(other_encoder,
+			    &crtc->dev->mode_config.encoder_list,
+			    base.head) {
+
+		if (&other_encoder->new_crtc->base != crtc ||
+		    encoder == other_encoder)
+			continue;
+		else
+			return false;
+	}
+
+	return true;
+}
+
 static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
 				  struct drm_crtc *crtc)
 {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ae807af..4aaf75c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -455,6 +455,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_non_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 *);
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 98ad7fd..4def811 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -910,17 +910,14 @@ intel_tv_mode_fixup(struct drm_encoder *encoder,
 		    const struct drm_display_mode *mode,
 		    struct drm_display_mode *adjusted_mode)
 {
-	struct drm_device *dev = encoder->dev;
 	struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
 	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
-	struct intel_encoder *other_encoder;
 
 	if (!tv_mode)
 		return false;
 
-	for_each_encoder_on_crtc(dev, encoder->crtc, other_encoder)
-		if (&other_encoder->base != encoder)
-			return false;
+	if (!intel_encoder_check_non_cloned(&intel_tv->base))
+		return false;
 
 	adjusted_mode->clock = tv_mode->clock;
 	return true;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 49/58] drm/i915: use staged outuput config in lvds->mode_fixup
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (47 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 48/58] drm/i915: use staged outuput config in tv->mode_fixup Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 18:02   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 50/58] drm/i915: compute masks of crtcs affected in set_mode Daniel Vetter
                   ` (16 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

- Use the check_cloned helper from the previous patch.
- Use encoder->new_crtc to check crtc properties.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_lvds.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 52f9e7f..7f730af 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -250,9 +250,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-	struct intel_encoder *tmp_encoder;
+	struct intel_crtc *intel_crtc = intel_lvds->base.new_crtc;
 	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
 	int pipe;
 
@@ -262,14 +261,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 		return false;
 	}
 
-	/* Should never happen!! */
-	for_each_encoder_on_crtc(dev, encoder->crtc, tmp_encoder) {
-		if (&tmp_encoder->base != encoder) {
-			DRM_ERROR("Can't enable LVDS and another "
-			       "encoder on the same pipe\n");
-			return false;
-		}
-	}
+	if (!intel_encoder_check_non_cloned(&intel_lvds->base))
+		return false;
 
 	/*
 	 * We have timings from the BIOS for the panel, put them in
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 50/58] drm/i915: compute masks of crtcs affected in set_mode
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (48 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 49/58] drm/i915: use staged outuput config in lvds->mode_fixup Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-08-29 10:34   ` [PATCH] " Daniel Vetter
  2012-09-05 18:07   ` [PATCH 50/58] " Jesse Barnes
  2012-08-19 19:13 ` [PATCH 51/58] drm/i915: implement new set_mode code flow Daniel Vetter
                   ` (15 subsequent siblings)
  65 siblings, 2 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

This is definetely a bit more generic than currently required, but
if we keep track of all crtcs that need to be disabled/enable (because
they loose an encoder or something similar), crtcs that get completely
disabled and those that we need to do an actual mode change on nicely
prepares us for global modeset operations on multiple crtcs.

The only big thing missing here would be a global resource allocation
step (for e.g. pch plls), which would equally frob these bitmasks if
e.g. a crtc only needs a new pll.

These masks aren't yet put to use in this patch, this will follow in the
next one.

v2-v5: Fix up the computations for good (hopefully).

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 89 ++++++++++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c59569e..4334400 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6706,6 +6706,91 @@ fail:
 	return ERR_PTR(-EINVAL);
 }
 
+/* Computes which crtcs are affected and sets the relevant bits in the mask. For
+ * simplicity we use the crtc's pipe number (because it's easier to obtain). */
+static void
+intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
+			     unsigned *prepare_pipes, unsigned *disable_pipes)
+{
+	struct intel_crtc *intel_crtc;
+	struct drm_device *dev = crtc->dev;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+	struct drm_crtc *tmp_crtc;
+
+	*disable_pipes = *modeset_pipes = *prepare_pipes = 0;
+
+	/* Check which crtcs have changed outputs connected to them, these need
+	 * to be part of the prepare_pipes mask. We don't (yet) support global
+	 * modeset across multiple crtcs, so modeset_pipes will only have one
+	 * bit set at most. */
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		if (connector->base.encoder == &connector->new_encoder->base)
+			continue;
+
+		if (connector->base.encoder) {
+			tmp_crtc = connector->base.encoder->crtc;
+
+			*prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
+		}
+
+		if (connector->new_encoder)
+			*prepare_pipes |=
+				1 << connector->new_encoder->new_crtc->pipe;
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		if (encoder->base.crtc == &encoder->new_crtc->base)
+			continue;
+
+		if (encoder->base.crtc) {
+			tmp_crtc = encoder->base.crtc;
+
+			*prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
+		}
+
+		if (encoder->new_crtc)
+			*prepare_pipes |= 1 << encoder->new_crtc->pipe;
+	}
+
+	/* Check for any pipes that will be fully 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)
+			continue;
+
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+				    base.head) {
+			if (encoder->new_crtc == intel_crtc)
+				used = true;
+		}
+
+		if (!used)
+			*disable_pipes |= 1 << intel_crtc->pipe;
+	}
+
+
+	/* set_mode is also used to update properties on life display pipes. */
+	intel_crtc = to_intel_crtc(crtc);
+	if (!*disable_pipes && crtc->enabled)
+		*prepare_pipes |= 1 << intel_crtc->pipe;
+
+	/* We only support modeset on one single crtc, hence we need to do that
+	 * only for the passed in crtc iff we change anything else than just
+	 * disable crtcs. */
+	if (*prepare_pipes)
+		*modeset_pipes |= 1 << intel_crtc->pipe;
+
+	/* ... and mask these out. */
+	*modeset_pipes &= ~(*disable_pipes);
+	*prepare_pipes &= ~(*disable_pipes);
+}
+
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
 		    int x, int y, struct drm_framebuffer *fb)
@@ -6715,8 +6800,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct drm_encoder *encoder;
+	unsigned disable_pipe, prepare_pipes, modeset_pipes;
 	bool ret = true;
 
+	intel_modeset_affected_pipes(crtc, &modeset_pipes,
+				     &prepare_pipes, &disable_pipe);
+
 	intel_modeset_commit_output_state(dev);
 
 	crtc->enabled = drm_helper_crtc_in_use(crtc);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 51/58] drm/i915: implement new set_mode code flow
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (49 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 50/58] drm/i915: compute masks of crtcs affected in set_mode Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 18:14   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 52/58] drm/i915: push commit_output_state past crtc disabling Daniel Vetter
                   ` (14 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

... using the pipe masks from the previous patch.

Well, not quite:
- We still need to call the disable_unused_functions helper, until
  we've moved the call to commit_output_state further down and
  adjusted intel_crtc_disable a bit. The next patch will do that.
- Because we don't support (yet) mode changes on more than one crtc at
  a time, some of the modeset_pipes checks are a bit hackish - but
  that only needs fixing once we incorporate global modeset support.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 99 +++++++++++++++++++++++-------------
 1 file changed, 63 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4334400..3d99522 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6791,6 +6791,12 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
 	*prepare_pipes &= ~(*disable_pipes);
 }
 
+#define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
+	list_for_each_entry((intel_crtc), \
+			    &(dev)->mode_config.crtc_list, \
+			    base.head) \
+		if (mask & (1 <<(intel_crtc)->pipe)) \
+
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
 		    int x, int y, struct drm_framebuffer *fb)
@@ -6800,73 +6806,92 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct drm_encoder *encoder;
-	unsigned disable_pipe, prepare_pipes, modeset_pipes;
+	struct intel_crtc *intel_crtc;
+	unsigned disable_pipes, prepare_pipes, modeset_pipes;
 	bool ret = true;
 
 	intel_modeset_affected_pipes(crtc, &modeset_pipes,
-				     &prepare_pipes, &disable_pipe);
+				     &prepare_pipes, &disable_pipes);
+
+	DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
+		      modeset_pipes, prepare_pipes, disable_pipes);
 
 	intel_modeset_commit_output_state(dev);
 
 	crtc->enabled = drm_helper_crtc_in_use(crtc);
-	if (!crtc->enabled) {
-		drm_helper_disable_unused_functions(dev);
-		return true;
-	}
 
+	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
+		drm_helper_disable_unused_functions(dev);
 
 	saved_hwmode = crtc->hwmode;
 	saved_mode = crtc->mode;
 
-	adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
-	if (IS_ERR(adjusted_mode)) {
-		return false;
-	}
+	/* Hack: Because we don't (yet) support global modeset on multiple
+	 * crtcs, we don't keep track of the new mode for more than one crtc.
+	 * Hence simply check whether any bit is set in modeset_pipes in all the
+	 * pieces of code that are not yet converted to deal with mutliple crtcs
+	 * changing their mode at the same time. */
+	adjusted_mode = NULL;
+	if (modeset_pipes) {
+		adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
+		if (IS_ERR(adjusted_mode)) {
+			return false;
+		}
 
-	intel_crtc_prepare_encoders(dev);
+		intel_crtc_prepare_encoders(dev);
+	}
 
-	dev_priv->display.crtc_disable(crtc);
+	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
+		dev_priv->display.crtc_disable(&intel_crtc->base);
 
-	crtc->mode = *mode;
+	if (modeset_pipes) {
+		crtc->mode = *mode;
+		crtc->x = x;
+		crtc->y = y;
+	}
 
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
-	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, fb);
-	if (!ret)
-	    goto done;
+	for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
+		ret = !intel_crtc_mode_set(&intel_crtc->base,
+					   mode, adjusted_mode,
+					   x, y, fb);
+		if (!ret)
+		    goto done;
 
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 
-		if (encoder->crtc != crtc)
-			continue;
+			if (encoder->crtc != &intel_crtc->base)
+				continue;
 
-		DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
-			encoder->base.id, drm_get_encoder_name(encoder),
-			mode->base.id, mode->name);
-		encoder_funcs = encoder->helper_private;
-		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
+			DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
+				encoder->base.id, drm_get_encoder_name(encoder),
+				mode->base.id, mode->name);
+			encoder_funcs = encoder->helper_private;
+			encoder_funcs->mode_set(encoder, mode, adjusted_mode);
+		}
 	}
 
-	crtc->x = x;
-	crtc->y = y;
-
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
-	dev_priv->display.crtc_enable(crtc);
+	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
+		dev_priv->display.crtc_enable(&intel_crtc->base);
 
-	/* Store real post-adjustment hardware mode. */
-	crtc->hwmode = *adjusted_mode;
+	if (modeset_pipes) {
+		/* Store real post-adjustment hardware mode. */
+		crtc->hwmode = *adjusted_mode;
 
-	/* Calculate and store various constants which
-	 * are later needed by vblank and swap-completion
-	 * timestamping. They are derived from true hwmode.
-	 */
-	drm_calc_timestamping_constants(crtc);
+		/* Calculate and store various constants which
+		 * are later needed by vblank and swap-completion
+		 * timestamping. They are derived from true hwmode.
+		 */
+		drm_calc_timestamping_constants(crtc);
+	}
 
 	/* FIXME: add subpixel order */
 done:
 	drm_mode_destroy(dev, adjusted_mode);
-	if (!ret) {
+	if (!ret && crtc->enabled) {
 		crtc->hwmode = saved_hwmode;
 		crtc->mode = saved_mode;
 	}
@@ -6874,6 +6899,8 @@ done:
 	return ret;
 }
 
+#undef for_each_intel_crtc_masked
+
 static void intel_set_config_free(struct intel_set_config *config)
 {
 	if (config) {
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 52/58] drm/i915: push commit_output_state past crtc disabling
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (50 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 51/58] drm/i915: implement new set_mode code flow Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 18:17   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 53/58] drm/i915: s/intel_encoder_disable/intel_encoder_noop Daniel Vetter
                   ` (13 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

This requires a few changes
- We still need a noop function for crtc->disable, becuase the fb
  helper is a bit too intimate with the crtc helper.
- We need to clear crtc->fb ourselves in intel_crtc_disable now that
  we no longer rely on the helper's disable_unused_functions to do
  that.
- We need to split out the sare update code, becuase the crtc code
  can't call update_dpms any more, it needs to disable the crtc
  unconditionally. This is because we now keep onto the encoder ->
  crtc mapping of the (still) active output pipe configuration.
- To check that we really disable a crtc that still has encoders,
  insert a WARN_ON(!enabled) in the crtc disable function.
- Lastly, we need to walk over all crtcs to update their enabled state
  after having called commit_output_state - for all disabled crtc the
  crtc helper code has done that for us previously.

v2: Update connector dpms and encoder->connectors_active after
disabling the crtc, too.

v3: Noop-out intel_encoder_disable. Similarly to the crtc disable
callback used by the crtc helper code we can't simply remove all these
encoder callbacks: The fb helper (which we still use) has a rather
incetious relationship with the crtc helper code ...

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 81 +++++++++++++++++++++++-------------
 1 file changed, 53 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3d99522..48d763d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3462,26 +3462,13 @@ static void i9xx_crtc_off(struct drm_crtc *crtc)
 {
 }
 
-/**
- * Sets the power management mode of the pipe and plane.
- */
-void intel_crtc_update_dpms(struct drm_crtc *crtc)
+static void intel_crtc_update_sarea(struct drm_crtc *crtc,
+				    bool enabled)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_encoder *intel_encoder;
 	int pipe = intel_crtc->pipe;
-	bool enabled, enable = false;
-
-	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
-		enable |= intel_encoder->connectors_active;
-
-	if (enable)
-		dev_priv->display.crtc_enable(crtc);
-	else
-		dev_priv->display.crtc_disable(crtc);
 
 	if (!dev->primary->master)
 		return;
@@ -3490,8 +3477,6 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc)
 	if (!master_priv->sarea_priv)
 		return;
 
-	enabled = crtc->enabled && enable;
-
 	switch (pipe) {
 	case 0:
 		master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0;
@@ -3507,14 +3492,42 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc)
 	}
 }
 
+/**
+ * Sets the power management mode of the pipe and plane.
+ */
+void intel_crtc_update_dpms(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *intel_encoder;
+	bool enable = false;
+
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
+		enable |= intel_encoder->connectors_active;
+
+	if (enable)
+		dev_priv->display.crtc_enable(crtc);
+	else
+		dev_priv->display.crtc_disable(crtc);
+
+	intel_crtc_update_sarea(crtc, enable);
+}
+
+static void intel_crtc_noop(struct drm_crtc *crtc)
+{
+}
+
 static void intel_crtc_disable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	/* crtc->disable is only called when we have no encoders, hence this
-	 * will disable the pipe. */
-	intel_crtc_update_dpms(crtc);
+	/* crtc should still be enabled when we disable it. */
+	WARN_ON(!crtc->enabled);
+
+	dev_priv->display.crtc_disable(crtc);
+	intel_crtc_update_sarea(crtc, false);
 	dev_priv->display.off(crtc);
 
 	assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
@@ -3524,14 +3537,24 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
 		mutex_lock(&dev->struct_mutex);
 		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
 		mutex_unlock(&dev->struct_mutex);
+		crtc->fb = NULL;
+	}
+
+	/* Update computed state. */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (!connector->encoder || !connector->encoder->crtc)
+			continue;
+
+		if (connector->encoder->crtc != crtc)
+			continue;
+
+		connector->dpms = DRM_MODE_DPMS_OFF;
+		to_intel_encoder(connector->encoder)->connectors_active = false;
 	}
 }
 
 void intel_encoder_disable(struct drm_encoder *encoder)
 {
-	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
-
-	intel_encoder->disable(intel_encoder);
 }
 
 void intel_encoder_destroy(struct drm_encoder *encoder)
@@ -6560,7 +6583,7 @@ free_work:
 static struct drm_crtc_helper_funcs intel_helper_funcs = {
 	.mode_set_base_atomic = intel_pipe_set_base_atomic,
 	.load_lut = intel_crtc_load_lut,
-	.disable = intel_crtc_disable,
+	.disable = intel_crtc_noop,
 };
 
 bool intel_encoder_check_non_cloned(struct intel_encoder *encoder)
@@ -6816,12 +6839,14 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
 		      modeset_pipes, prepare_pipes, disable_pipes);
 
-	intel_modeset_commit_output_state(dev);
+	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
+		intel_crtc_disable(&intel_crtc->base);
 
-	crtc->enabled = drm_helper_crtc_in_use(crtc);
+	intel_modeset_commit_output_state(dev);
 
-	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
-		drm_helper_disable_unused_functions(dev);
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
+			    base.head)
+		intel_crtc->base.enabled = drm_helper_crtc_in_use(crtc);
 
 	saved_hwmode = crtc->hwmode;
 	saved_mode = crtc->mode;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 53/58] drm/i915: s/intel_encoder_disable/intel_encoder_noop
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (51 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 52/58] drm/i915: push commit_output_state past crtc disabling Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 18:17   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 54/58] drm/i915: WARN if the pipe won't turn off Daniel Vetter
                   ` (12 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_crt.c     | 2 +-
 drivers/gpu/drm/i915/intel_display.c | 2 +-
 drivers/gpu/drm/i915/intel_dp.c      | 2 +-
 drivers/gpu/drm/i915/intel_drv.h     | 2 +-
 drivers/gpu/drm/i915/intel_dvo.c     | 2 +-
 drivers/gpu/drm/i915/intel_hdmi.c    | 4 ++--
 drivers/gpu/drm/i915/intel_lvds.c    | 2 +-
 drivers/gpu/drm/i915/intel_sdvo.c    | 2 +-
 drivers/gpu/drm/i915/intel_tv.c      | 2 +-
 9 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 2855eb7..611564b 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -641,7 +641,7 @@ static void intel_crt_reset(struct drm_connector *connector)
 static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
 	.mode_fixup = intel_crt_mode_fixup,
 	.mode_set = intel_crt_mode_set,
-	.disable = intel_encoder_disable,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 48d763d..a716893 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3553,7 +3553,7 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
 	}
 }
 
-void intel_encoder_disable(struct drm_encoder *encoder)
+void intel_encoder_noop(struct drm_encoder *encoder)
 {
 }
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b07d4b4..3b1c407 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2393,7 +2393,7 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
 	.mode_fixup = intel_dp_mode_fixup,
 	.mode_set = intel_dp_mode_set,
-	.disable = intel_encoder_disable,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4aaf75c..1282bf0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -452,7 +452,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_non_cloned(struct intel_encoder *encoder);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 17dc8be..aa1bf57 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -346,7 +346,7 @@ static void intel_dvo_destroy(struct drm_connector *connector)
 static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
 	.mode_fixup = intel_dvo_mode_fixup,
 	.mode_set = intel_dvo_mode_set,
-	.disable = intel_encoder_disable,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_dvo_connector_funcs = {
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index e7d5078..7acf2d9 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -907,13 +907,13 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
 	.mode_fixup = intel_hdmi_mode_fixup,
 	.mode_set = intel_ddi_mode_set,
-	.disable = intel_encoder_disable,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
 	.mode_fixup = intel_hdmi_mode_fixup,
 	.mode_set = intel_hdmi_mode_set,
-	.disable = intel_encoder_disable,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 7f730af..38ba2e8 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -590,7 +590,7 @@ static int intel_lvds_set_property(struct drm_connector *connector,
 static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
 	.mode_fixup = intel_lvds_mode_fixup,
 	.mode_set = intel_lvds_mode_set,
-	.disable = intel_encoder_disable,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 198bb89..6f53871 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1936,7 +1936,7 @@ done:
 static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
 	.mode_fixup = intel_sdvo_mode_fixup,
 	.mode_set = intel_sdvo_mode_set,
-	.disable = intel_encoder_disable
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 4def811..c9b2fb0 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1492,7 +1492,7 @@ out:
 static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
 	.mode_fixup = intel_tv_mode_fixup,
 	.mode_set = intel_tv_mode_set,
-	.disable = intel_encoder_disable,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_tv_connector_funcs = {
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 54/58] drm/i915: WARN if the pipe won't turn off
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (52 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 53/58] drm/i915: s/intel_encoder_disable/intel_encoder_noop Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 18:18   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 55/58] drm/i915: switch the load detect code to the staged modeset config Daniel Vetter
                   ` (11 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

This seems to be the symptom of a few neat bugs, hence be more
obnoxious when this fails.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a716893..da45d39 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1006,7 +1006,7 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
 		/* Wait for the Pipe State to go off */
 		if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0,
 			     100))
-			DRM_DEBUG_KMS("pipe_off wait timed out\n");
+			WARN(1, "pipe_off wait timed out\n");
 	} else {
 		u32 last_line, line_mask;
 		int reg = PIPEDSL(pipe);
@@ -1024,7 +1024,7 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
 		} while (((I915_READ(reg) & line_mask) != last_line) &&
 			 time_after(timeout, jiffies));
 		if (time_after(jiffies, timeout))
-			DRM_DEBUG_KMS("pipe_off wait timed out\n");
+			WARN(1, "pipe_off wait timed out\n");
 	}
 }
 
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 55/58] drm/i915: switch the load detect code to the staged modeset config
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (53 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 54/58] drm/i915: WARN if the pipe won't turn off Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-09-05 18:19   ` Jesse Barnes
  2012-08-19 19:13 ` [PATCH 56/58] drm/i915: push commit_output_state past the crtc/encoder preparing Daniel Vetter
                   ` (10 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Now that set_mode also disables crtcs and expects it's new
configuration in the staged output links we need to adjust the load
detect code a bit.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index da45d39..5a72a27 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5796,8 +5796,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 		return false;
 	}
 
-	encoder->crtc = crtc;
-	connector->encoder = encoder;
+	intel_encoder->new_crtc = to_intel_crtc(crtc);
+	to_intel_connector(connector)->new_encoder = intel_encoder;
 
 	intel_crtc = to_intel_crtc(crtc);
 	old->dpms_mode = connector->dpms;
@@ -5849,16 +5849,17 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
 	struct intel_encoder *intel_encoder =
 		intel_attached_encoder(connector);
 	struct drm_encoder *encoder = &intel_encoder->base;
-	struct drm_device *dev = encoder->dev;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
 		      connector->base.id, drm_get_connector_name(connector),
 		      encoder->base.id, drm_get_encoder_name(encoder));
 
 	if (old->load_detect_temp) {
-		connector->encoder = NULL;
-		encoder->crtc = NULL;
-		drm_helper_disable_unused_functions(dev);
+		struct drm_crtc *crtc = encoder->crtc;
+
+		to_intel_connector(connector)->new_encoder = NULL;
+		intel_encoder->new_crtc = NULL;
+		intel_set_mode(crtc, NULL, 0, 0, NULL);
 
 		if (old->release_fb)
 			old->release_fb->funcs->destroy(old->release_fb);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 56/58] drm/i915: push commit_output_state past the crtc/encoder preparing
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (54 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 55/58] drm/i915: switch the load detect code to the staged modeset config Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-08-31 18:12   ` [PATCH] " Daniel Vetter
  2012-08-19 19:13 ` [PATCH 57/58] drm/i915: disable all crtcs at suspend time Daniel Vetter
                   ` (9 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 91 +++++++++++++++++++++---------------
 1 file changed, 53 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5a72a27..10e3f9c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3221,10 +3221,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	WARN_ON(!crtc->enabled);
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * enable function unconditionally for now. */
 	if (intel_crtc->active)
-		goto encoders;
+		return;
 
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
@@ -3272,7 +3270,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	intel_crtc_update_cursor(crtc, true);
 
-encoders:
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
 
@@ -3290,14 +3287,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	int plane = intel_crtc->plane;
 	u32 reg, temp;
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * disable function unconditionally for now. */
-	for_each_encoder_on_crtc(dev, crtc, encoder)
-		encoder->disable(encoder);
 
 	if (!intel_crtc->active)
 		return;
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
+
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
@@ -3399,10 +3395,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
 	WARN_ON(!crtc->enabled);
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * enable function unconditionally for now. */
 	if (intel_crtc->active)
-		goto encoders;
+		return;
 
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
@@ -3418,7 +3412,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_dpms_overlay(intel_crtc, true);
 	intel_crtc_update_cursor(crtc, true);
 
-encoders:
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
 }
@@ -3432,14 +3425,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * disable function unconditionally for now. */
-	for_each_encoder_on_crtc(dev, crtc, encoder)
-		encoder->disable(encoder);
 
 	if (!intel_crtc->active)
 		return;
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
+
 	/* Give the overlay scaler a chance to disable if it's on this pipe */
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
@@ -6631,18 +6623,6 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
 	return false;
 }
 
-static void
-intel_crtc_prepare_encoders(struct drm_device *dev)
-{
-	struct intel_encoder *encoder;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
-		/* Disable unused encoders */
-		if (encoder->base.crtc == NULL)
-			encoder->disable(encoder);
-	}
-}
-
 /**
  * intel_modeset_update_staged_output_state
  *
@@ -6815,6 +6795,18 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
 	*prepare_pipes &= ~(*disable_pipes);
 }
 
+static bool intel_crtc_in_use(struct drm_crtc *crtc)
+{
+	struct drm_encoder *encoder;
+	struct drm_device *dev = crtc->dev;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+		if (encoder->crtc == crtc)
+			return true;
+
+	return false;
+}
+
 #define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
 	list_for_each_entry((intel_crtc), \
 			    &(dev)->mode_config.crtc_list, \
@@ -6831,6 +6823,8 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct drm_encoder *encoder;
 	struct intel_crtc *intel_crtc;
+	struct intel_encoder *intel_encoder;
+	struct drm_connector *connector;
 	unsigned disable_pipes, prepare_pipes, modeset_pipes;
 	bool ret = true;
 
@@ -6843,12 +6837,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
 		intel_crtc_disable(&intel_crtc->base);
 
-	intel_modeset_commit_output_state(dev);
-
-	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
-			    base.head)
-		intel_crtc->base.enabled = drm_helper_crtc_in_use(crtc);
-
 	saved_hwmode = crtc->hwmode;
 	saved_mode = crtc->mode;
 
@@ -6863,12 +6851,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		if (IS_ERR(adjusted_mode)) {
 			return false;
 		}
-
-		intel_crtc_prepare_encoders(dev);
 	}
 
-	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
-		dev_priv->display.crtc_disable(&intel_crtc->base);
+	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
+		if (intel_crtc->base.enabled)
+			dev_priv->display.crtc_disable(&intel_crtc->base);
+	}
 
 	if (modeset_pipes) {
 		crtc->mode = *mode;
@@ -6876,6 +6864,33 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		crtc->y = y;
 	}
 
+	/* Only after disabling all output pipelines that will be changed can we
+	 * update the the output configuration. */
+	intel_modeset_commit_output_state(dev);
+
+	/* Update computed 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);
+	}
+
+	list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		intel_encoder->connectors_active = false;
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (!connector->encoder || !connector->encoder->crtc)
+			continue;
+
+		intel_crtc = to_intel_crtc(connector->encoder->crtc);
+
+		if (prepare_pipes & (1 << intel_crtc->pipe))
+			connector->dpms = DRM_MODE_DPMS_ON;
+
+		to_intel_encoder(connector->encoder)->connectors_active = true;
+	}
+
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 57/58] drm/i915: disable all crtcs at suspend time
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (55 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 56/58] drm/i915: push commit_output_state past the crtc/encoder preparing Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-08-29 21:13   ` [PATCH] drm/i915: no longer call drm_helper_resume_force_mode Daniel Vetter
  2012-09-05 18:29   ` [PATCH 57/58] drm/i915: disable all crtcs at suspend time Jesse Barnes
  2012-08-19 19:13 ` [PATCH 58/58] drm/i915: add tons of modeset state checks Daniel Vetter
                   ` (8 subsequent siblings)
  65 siblings, 2 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Conflicts:
	drivers/gpu/drm/i915/intel_drv.h
---
 drivers/gpu/drm/i915/i915_drv.c      |  3 +++
 drivers/gpu/drm/i915/intel_display.c | 10 ++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 3 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 4abac6d..fe7512a 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -470,6 +470,9 @@ static int i915_drm_freeze(struct drm_device *dev)
 				"GEM idle failed, resume might fail\n");
 			return error;
 		}
+
+		intel_modeset_disable(dev);
+
 		drm_irq_uninstall(dev);
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 10e3f9c..95a9f04 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3545,6 +3545,16 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
 	}
 }
 
+void intel_modeset_disable(struct drm_device *dev)
+{
+	struct drm_crtc *crtc;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (crtc->enabled)
+			intel_crtc_disable(crtc);
+	}
+}
+
 void intel_encoder_noop(struct drm_encoder *encoder)
 {
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1282bf0..71c1517 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -450,6 +450,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);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 58/58] drm/i915: add tons of modeset state checks
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (56 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 57/58] drm/i915: disable all crtcs at suspend time Daniel Vetter
@ 2012-08-19 19:13 ` Daniel Vetter
  2012-08-20  8:24   ` [PATCH] " Daniel Vetter
  2012-08-20 12:22   ` Daniel Vetter
  2012-08-20 13:17 ` [PATCH 00/58] modeset-rework, the basic conversion Jani Nikula
                   ` (7 subsequent siblings)
  65 siblings, 2 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-08-19 19:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

... let's see how whether this catches anything earlier and I can
track down a few bugs.

v2: Add more checks and also add DRM_DEBUG_KMS output so that it's
clear which connector/encoder/crtc is being checked atm. Which proved
rather useful for debugging ...

v3: Add a WARN in the common encoder dpms function, now that also
modeset changes properly update the dpms state ...

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 75 +++++++++++++++++++++++++++++++++++-
 1 file changed, 74 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 95a9f04..07e00dd 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3637,7 +3637,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
 	if (encoder->base.crtc)
 		intel_encoder_dpms(encoder, mode);
 	else
-		encoder->connectors_active = false;
+		WARN_ON(encoder->connectors_active != false);
 
 	intel_connector_check_state(to_intel_connector(connector));
 }
@@ -6823,6 +6823,75 @@ static bool intel_crtc_in_use(struct drm_crtc *crtc)
 			    base.head) \
 		if (mask & (1 <<(intel_crtc)->pipe)) \
 
+static void
+intel_modeset_check_state(struct drm_device *dev)
+{
+	struct intel_crtc *crtc;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		/* This also checks the encoder/connector hw state with the
+		 * ->get_hw_state callbacks. */
+		intel_connector_check_state(connector);
+
+		WARN_ON(&connector->new_encoder->base != connector->base.encoder);
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		bool enabled = false;
+		bool active = false;
+		enum pipe pipe;
+
+		DRM_DEBUG_KMS("[ENCODER:%d:%s]\n",
+			      encoder->base.base.id,
+			      drm_get_encoder_name(&encoder->base));
+
+		WARN_ON(&encoder->new_crtc->base != encoder->base.crtc);
+		WARN_ON(encoder->connectors_active && !encoder->base.crtc);
+
+		list_for_each_entry(connector, &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->base.encoder != &encoder->base)
+				continue;
+			enabled = true;
+			if (connector->base.dpms == DRM_MODE_DPMS_ON)
+				active = true;
+		}
+		WARN_ON(!!encoder->base.crtc != enabled);
+		/* dpms on only implies active. */
+		WARN_ON(active && !encoder->base.crtc);
+		WARN_ON(encoder->get_hw_state(encoder, &pipe)
+			&& !encoder->base.crtc);
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		bool enabled = false;
+		bool active = false;
+
+		DRM_DEBUG_KMS("[CRTC:%d]\n",
+			      crtc->base.base.id);
+
+		WARN_ON(crtc->active && !crtc->base.enabled);
+
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+				    base.head) {
+			if (encoder->base.crtc != &crtc->base)
+				continue;
+			enabled = true;
+			if (encoder->connectors_active)
+				active = true;
+		}
+		WARN_ON(active != crtc->active);
+		WARN_ON(enabled != crtc->base.enabled);
+
+		assert_pipe(dev->dev_private, crtc->pipe, crtc->active);
+	}
+}
+
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
 		    int x, int y, struct drm_framebuffer *fb)
@@ -6947,6 +7016,8 @@ done:
 		crtc->mode = saved_mode;
 	}
 
+	intel_modeset_check_state(dev);
+
 	return ret;
 }
 
@@ -8142,6 +8213,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 	}
 
 	intel_modeset_update_staged_output_state(dev);
+
+	intel_modeset_check_state(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH] drm/i915: add tons of modeset state checks
  2012-08-19 19:13 ` [PATCH 58/58] drm/i915: add tons of modeset state checks Daniel Vetter
@ 2012-08-20  8:24   ` Daniel Vetter
  2012-08-20 12:22   ` Daniel Vetter
  1 sibling, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-08-20  8:24 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

... let's see how whether this catches anything earlier and I can
track down a few bugs.

v2: Add more checks and also add DRM_DEBUG_KMS output so that it's
clear which connector/encoder/crtc is being checked atm. Which proved
rather useful for debugging ...

v3: Add a WARN in the common encoder dpms function, now that also
modeset changes properly update the dpms state ...

v4: Properly add a short explanation for each WARN, to avoid the need
to correlate dmesg lines with source lines accurately. Suggested by
Chris Wilson.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 84 +++++++++++++++++++++++++++++++++++-
 1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 95a9f04..5d592f1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3637,7 +3637,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
 	if (encoder->base.crtc)
 		intel_encoder_dpms(encoder, mode);
 	else
-		encoder->connectors_active = false;
+		WARN_ON(encoder->connectors_active != false);
 
 	intel_connector_check_state(to_intel_connector(connector));
 }
@@ -6823,6 +6823,84 @@ static bool intel_crtc_in_use(struct drm_crtc *crtc)
 			    base.head) \
 		if (mask & (1 <<(intel_crtc)->pipe)) \
 
+static void
+intel_modeset_check_state(struct drm_device *dev)
+{
+	struct intel_crtc *crtc;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		/* This also checks the encoder/connector hw state with the
+		 * ->get_hw_state callbacks. */
+		intel_connector_check_state(connector);
+
+		WARN(&connector->new_encoder->base != connector->base.encoder,
+		     "connector's staged encoder doesn't match current encoder\n");
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		bool enabled = false;
+		bool active = false;
+		enum pipe pipe;
+
+		DRM_DEBUG_KMS("[ENCODER:%d:%s]\n",
+			      encoder->base.base.id,
+			      drm_get_encoder_name(&encoder->base));
+
+		WARN(&encoder->new_crtc->base != encoder->base.crtc,
+		     "encoder's stage crtc doesn't match current crtc\n");
+		WARN(encoder->connectors_active && !encoder->base.crtc,
+		     "encoder's active_connectors set, but no crtc\n");
+
+		list_for_each_entry(connector, &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->base.encoder != &encoder->base)
+				continue;
+			enabled = true;
+			if (connector->base.dpms == DRM_MODE_DPMS_ON)
+				active = true;
+		}
+		WARN(!!encoder->base.crtc != enabled,
+		     "encoder's enabled state mismatch\n");
+		/* dpms on only implies active. */
+		WARN(active && !encoder->base.crtc,
+		     "active encoder with no crtc\n");
+		WARN(encoder->get_hw_state(encoder, &pipe)
+		     && !encoder->base.crtc,
+		     "encoder's hw state doesn't match sw tracking\n");
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		bool enabled = false;
+		bool active = false;
+
+		DRM_DEBUG_KMS("[CRTC:%d]\n",
+			      crtc->base.base.id);
+
+		WARN(crtc->active && !crtc->base.enabled,
+		     "active crtc, but not enabled in sw tracking\n");
+
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+				    base.head) {
+			if (encoder->base.crtc != &crtc->base)
+				continue;
+			enabled = true;
+			if (encoder->connectors_active)
+				active = true;
+		}
+		WARN(active != crtc->active,
+		     "crtc's computed active state doesn't match tracked active state\n");
+		WARN(enabled != crtc->base.enabled,
+		     "crtc's computed enabled state doesn't match tracked enabled state\n");
+
+		assert_pipe(dev->dev_private, crtc->pipe, crtc->active);
+	}
+}
+
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
 		    int x, int y, struct drm_framebuffer *fb)
@@ -6947,6 +7025,8 @@ done:
 		crtc->mode = saved_mode;
 	}
 
+	intel_modeset_check_state(dev);
+
 	return ret;
 }
 
@@ -8142,6 +8222,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 	}
 
 	intel_modeset_update_staged_output_state(dev);
+
+	intel_modeset_check_state(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH] drm/i915: add tons of modeset state checks
  2012-08-19 19:13 ` [PATCH 58/58] drm/i915: add tons of modeset state checks Daniel Vetter
  2012-08-20  8:24   ` [PATCH] " Daniel Vetter
@ 2012-08-20 12:22   ` Daniel Vetter
  2012-08-31 18:12     ` [PATCH 1/2] " Daniel Vetter
  1 sibling, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-20 12:22 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

... let's see how whether this catches anything earlier and I can
track down a few bugs.

v2: Add more checks and also add DRM_DEBUG_KMS output so that it's
clear which connector/encoder/crtc is being checked atm. Which proved
rather useful for debugging ...

v3: Add a WARN in the common encoder dpms function, now that also
modeset changes properly update the dpms state ...

v4: Properly add a short explanation for each WARN, to avoid the need
to correlate dmesg lines with source lines accurately. Suggested by
Chris Wilson.

v5: Also dump (expected, found) for state checks (or wherever it's not
apparent from the test what exactly mismatches with expectations).
Again suggested by Chris Wilson.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 90 +++++++++++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 95a9f04..4db7b58 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3637,7 +3637,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
 	if (encoder->base.crtc)
 		intel_encoder_dpms(encoder, mode);
 	else
-		encoder->connectors_active = false;
+		WARN_ON(encoder->connectors_active != false);
 
 	intel_connector_check_state(to_intel_connector(connector));
 }
@@ -6823,6 +6823,90 @@ static bool intel_crtc_in_use(struct drm_crtc *crtc)
 			    base.head) \
 		if (mask & (1 <<(intel_crtc)->pipe)) \
 
+static void
+intel_modeset_check_state(struct drm_device *dev)
+{
+	struct intel_crtc *crtc;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		/* This also checks the encoder/connector hw state with the
+		 * ->get_hw_state callbacks. */
+		intel_connector_check_state(connector);
+
+		WARN(&connector->new_encoder->base != connector->base.encoder,
+		     "connector's staged encoder doesn't match current encoder\n");
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		bool enabled = false;
+		bool active = false;
+		enum pipe pipe;
+
+		DRM_DEBUG_KMS("[ENCODER:%d:%s]\n",
+			      encoder->base.base.id,
+			      drm_get_encoder_name(&encoder->base));
+
+		WARN(&encoder->new_crtc->base != encoder->base.crtc,
+		     "encoder's stage crtc doesn't match current crtc\n");
+		WARN(encoder->connectors_active && !encoder->base.crtc,
+		     "encoder's active_connectors set, but no crtc\n");
+
+		list_for_each_entry(connector, &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->base.encoder != &encoder->base)
+				continue;
+			enabled = true;
+			if (connector->base.dpms == DRM_MODE_DPMS_ON)
+				active = true;
+		}
+		WARN(!!encoder->base.crtc != enabled,
+		     "encoder's enabled state mismatch "
+		     "(expected %i, found %i)\n",
+		     !!encoder->base.crtc, enabled);
+		/* dpms on only implies active. */
+		WARN(active && !encoder->base.crtc,
+		     "active encoder with no crtc\n");
+		WARN(enabled = encoder->get_hw_state(encoder, &pipe)
+		     && !encoder->base.crtc,
+		     "encoder's hw state doesn't match sw tracking "
+		     "(expected %i, found %i)\n",
+		     !!encoder->base.crtc, enabled);
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		bool enabled = false;
+		bool active = false;
+
+		DRM_DEBUG_KMS("[CRTC:%d]\n",
+			      crtc->base.base.id);
+
+		WARN(crtc->active && !crtc->base.enabled,
+		     "active crtc, but not enabled in sw tracking\n");
+
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+				    base.head) {
+			if (encoder->base.crtc != &crtc->base)
+				continue;
+			enabled = true;
+			if (encoder->connectors_active)
+				active = true;
+		}
+		WARN(active != crtc->active,
+		     "crtc's computed active state doesn't match tracked active state "
+		     "(expected %i, found %i)\n", active, crtc->active);
+		WARN(enabled != crtc->base.enabled,
+		     "crtc's computed enabled state doesn't match tracked enabled state "
+		     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
+
+		assert_pipe(dev->dev_private, crtc->pipe, crtc->active);
+	}
+}
+
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
 		    int x, int y, struct drm_framebuffer *fb)
@@ -6947,6 +7031,8 @@ done:
 		crtc->mode = saved_mode;
 	}
 
+	intel_modeset_check_state(dev);
+
 	return ret;
 }
 
@@ -8142,6 +8228,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 	}
 
 	intel_modeset_update_staged_output_state(dev);
+
+	intel_modeset_check_state(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (57 preceding siblings ...)
  2012-08-19 19:13 ` [PATCH 58/58] drm/i915: add tons of modeset state checks Daniel Vetter
@ 2012-08-20 13:17 ` Jani Nikula
  2012-08-21  3:27 ` Ben Widawsky
                   ` (6 subsequent siblings)
  65 siblings, 0 replies; 173+ messages in thread
From: Jani Nikula @ 2012-08-20 13:17 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

On Sun, 19 Aug 2012, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> I'll also plan to put tags for the entire series in the merge commit, so if you
> have tested this on a few machines, read through and agree with the new designs,
> please reply with your tested-by/acked-by/reviewed-by tags.
>
> Flames, comments and test reports highly welcome.
>
> Cheers, Daniel
>
> [1] http://cgit.freedesktop.org/~danvet/drm/log/?h=modeset-rework-base

Tested-by: Jani Nikula <jani.nikula@intel.com>

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (58 preceding siblings ...)
  2012-08-20 13:17 ` [PATCH 00/58] modeset-rework, the basic conversion Jani Nikula
@ 2012-08-21  3:27 ` Ben Widawsky
  2012-08-21 17:48 ` Lespiau, Damien
                   ` (5 subsequent siblings)
  65 siblings, 0 replies; 173+ messages in thread
From: Ben Widawsky @ 2012-08-21  3:27 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:17 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Hi all,
> 
> Changes since last time around:
> - The prep patches are all merged now.
> - I've left out the actual DP fixes/cleanups, I think we should merge
> those in a separte step.
> - A few bugfixes (thanks to Paulo, Jani and Chris).
> - I've also applied a few bikesheds for naming that Paulo suggested
> (but I'm not sure whether I've sent those out already in a previous
> patchbomb).
> 
> Essentially this is just the core rework, which addes the new
> get_hw_state code, refactors all the encoders to use the new
> functions and finally reworks the modeset logic to disable/enable
> entire pipes, always (and with a deterministic order).
> 
> For merging to -next, I plan to pull in everything with a real merge
> commit. For that reason I've put up a modeset-rework-base branch onto
> my private fdo repo[1]. That way I can put a short documentation for
> the new modeset design into the merge commit (stichted together from
> the previous patchbomb cover letters), documenting my folly
> assumptions for eternity.
> 
> I'll also plan to put tags for the entire series in the merge commit,
> so if you have tested this on a few machines, read through and agree
> with the new designs, please reply with your
> tested-by/acked-by/reviewed-by tags.
> 
> Flames, comments and test reports highly welcome.
> 
> Cheers, Daniel

Tested-by: Ben Widawsky <ben@bwidawsk.net> (before the rebase)

> 
> [1] http://cgit.freedesktop.org/~danvet/drm/log/?h=modeset-rework-base
> 
> Daniel Vetter (58):
>   drm/i915: add crtc->enable/disable vfuncs insted of dpms
>   drm/i915: rip out crtc prepare/commit indirection
>   drm/i915: add direct encoder disable/enable infrastructure
>   drm/i915/hdmi: convert to encoder->disable/enable
>   drm/i915/tv: convert to encoder enable/disable
>   drm/i915/lvds: convert to encoder disable/enable
>   drm/i915/dp: convert to encoder disable/enable
>   drm/i915/crt: convert to encoder disable/enable
>   drm/i915/sdvo: convert to encoder disable/enable
>   drm/i915/dvo: convert to encoder disable/enable
>   drm/i915: convert dpms functions of dvo/sdvo/crt
>   drm/i915: rip out encoder->disable/enable checks
>   drm/i915: clean up encoder_prepare/commit
>   drm/i915: copy&paste drm_crtc_helper_set_config
>   drm/i915: call set_base directly
>   drm/i915: inline intel_best_encoder
>   drm/i915: copy&paste drm_crtc_helper_set_mode
>   drm/i915: simplify intel_crtc_prepare_encoders
>   drm/i915: rip out encoder->prepare/commit
>   drm/i915: call crtc functions directly
>   drm/i915: WARN when trying to enabled an unused crtc
>   drm/i915: Add interfaces to read out encoder/connector hw state
>   drm/i915/dp: implement get_hw_state
>   drm/i915/hdmi: implement get_hw_state
>   drm/i915/tv: implement get_hw_state
>   drm/i915/lvds: implement get_hw_state
>   drm/i915/crt: implement get_hw_state
>   drm/i915/sdvo: implement get_hw_state
>   drm/i915/dvo: implement get_hw_state
>   drm/i915: read out the modeset hw state at load and resume time
>   drm/i915: check connector hw/sw state
>   drm/i915: rip out intel_crtc->dpms_mode
>   drm/i915: rip out intel_dp->dpms_mode
>   drm/i915: ensure the force pipe A quirk is actually followed
>   drm/i915: introduce struct intel_set_config
>   drm/i915: extract modeset config save/restore code
>   drm/i915: extract intel_set_config_compute_mode_changes
>   drm/i915: extract intel_set_config_update_output_state
>   drm/i915: implement crtc helper semantics relied upon by the fb
>     helper
>   drm/i915: don't update the fb base if there is no fb
>   drm/i915: convert pointless error checks in set_config to BUGs
>   drm/i915: don't save all the encoder/crtc state in set_config
>   drm/i915: stage modeset output changes
>   drm/i915: push crtc->fb update into pipe_set_base
>   drm/i915: remove crtc disabling special case
>   drm/i915: move output commit and crtc disabling into set_mode
>   drm/i915: extract adjusted mode computation
>   drm/i915: use staged outuput config in tv->mode_fixup
>   drm/i915: use staged outuput config in lvds->mode_fixup
>   drm/i915: compute masks of crtcs affected in set_mode
>   drm/i915: implement new set_mode code flow
>   drm/i915: push commit_output_state past crtc disabling
>   drm/i915: s/intel_encoder_disable/intel_encoder_noop
>   drm/i915: WARN if the pipe won't turn off
>   drm/i915: switch the load detect code to the staged modeset config
>   drm/i915: push commit_output_state past the crtc/encoder preparing
>   drm/i915: disable all crtcs at suspend time
>   drm/i915: add tons of modeset state checks
> 
>  drivers/gpu/drm/i915/dvo.h           |    6 +
>  drivers/gpu/drm/i915/dvo_ch7017.c    |   13 +
>  drivers/gpu/drm/i915/dvo_ch7xxx.c    |   13 +
>  drivers/gpu/drm/i915/dvo_ivch.c      |   15 +
>  drivers/gpu/drm/i915/dvo_ns2501.c    |   15 +
>  drivers/gpu/drm/i915/dvo_sil164.c    |   16 +
>  drivers/gpu/drm/i915/dvo_tfp410.c    |   14 +
>  drivers/gpu/drm/i915/i915_drv.c      |    4 +
>  drivers/gpu/drm/i915/i915_drv.h      |    4 +-
>  drivers/gpu/drm/i915/i915_reg.h      |    2 +
>  drivers/gpu/drm/i915/intel_crt.c     |  136 ++-
>  drivers/gpu/drm/i915/intel_ddi.c     |   59 +-
>  drivers/gpu/drm/i915/intel_display.c | 1499
> ++++++++++++++++++++++++++++------
> drivers/gpu/drm/i915/intel_dp.c      |  144 ++--
> drivers/gpu/drm/i915/intel_drv.h     |   64 +-
> drivers/gpu/drm/i915/intel_dvo.c     |   94 ++-
> drivers/gpu/drm/i915/intel_hdmi.c    |  151 +++-
> drivers/gpu/drm/i915/intel_lvds.c    |   95 +--
> drivers/gpu/drm/i915/intel_sdvo.c    |  164 +++-
> drivers/gpu/drm/i915/intel_tv.c      |   61 +- 20 files changed, 2044
> insertions(+), 525 deletions(-)
> 

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (59 preceding siblings ...)
  2012-08-21  3:27 ` Ben Widawsky
@ 2012-08-21 17:48 ` Lespiau, Damien
  2012-08-21 18:11   ` Daniel Vetter
  2012-08-21 19:48 ` Chris Wilson
                   ` (4 subsequent siblings)
  65 siblings, 1 reply; 173+ messages in thread
From: Lespiau, Damien @ 2012-08-21 17:48 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, Aug 19, 2012 at 8:12 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> I'll also plan to put tags for the entire series in the merge commit, so if you
> have tested this on a few machines, read through and agree with the new designs,
> please reply with your tested-by/acked-by/reviewed-by tags.

Smoke-tested the new modeset-rework branch and found a regression on
my IVB with a pristine f17 userland:

* start with LVDS + VGA
* unplug VGA
* LVDS goes black

I guess the branch has to be quite widely tested, maybe push it to
intel-drm-next at the very start of a cycle?

-- 
Damien

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-21 17:48 ` Lespiau, Damien
@ 2012-08-21 18:11   ` Daniel Vetter
  2012-08-22 10:46     ` Lespiau, Damien
  0 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-21 18:11 UTC (permalink / raw)
  To: Lespiau, Damien; +Cc: Daniel Vetter, Intel Graphics Development

On Tue, Aug 21, 2012 at 06:48:08PM +0100, Lespiau, Damien wrote:
> On Sun, Aug 19, 2012 at 8:12 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> > I'll also plan to put tags for the entire series in the merge commit, so if you
> > have tested this on a few machines, read through and agree with the new designs,
> > please reply with your tested-by/acked-by/reviewed-by tags.
> 
> Smoke-tested the new modeset-rework branch and found a regression on
> my IVB with a pristine f17 userland:
> 
> * start with LVDS + VGA
> * unplug VGA
> * LVDS goes black

Hm, not yet seen this one here. Can you attach a full dmesg with
drm.debug=0xe when this is happening, please?

> I guess the branch has to be quite widely tested, maybe push it to
> intel-drm-next at the very start of a cycle?

Well, it's blocking a pile of eDP fixes I have here and I don't want to
delay it for another 2 weeks, since that will be rather tight for 3.7. I
guess we'll see.

Thanks for testing, Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (60 preceding siblings ...)
  2012-08-21 17:48 ` Lespiau, Damien
@ 2012-08-21 19:48 ` Chris Wilson
  2012-08-27  8:04 ` Vijay Purushothaman
                   ` (3 subsequent siblings)
  65 siblings, 0 replies; 173+ messages in thread
From: Chris Wilson @ 2012-08-21 19:48 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

On Sun, 19 Aug 2012 21:12:17 +0200, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> Hi all,
> 
> Changes since last time around:
> - The prep patches are all merged now.
> - I've left out the actual DP fixes/cleanups, I think we should merge those in a
>   separte step.
> - A few bugfixes (thanks to Paulo, Jani and Chris).
> - I've also applied a few bikesheds for naming that Paulo suggested (but I'm not
>   sure whether I've sent those out already in a previous patchbomb).
> 
> Essentially this is just the core rework, which addes the new get_hw_state code,
> refactors all the encoders to use the new functions and finally reworks the
> modeset logic to disable/enable entire pipes, always (and with a deterministic
> order).
> 
> For merging to -next, I plan to pull in everything with a real merge commit. For
> that reason I've put up a modeset-rework-base branch onto my private fdo repo[1].
> That way I can put a short documentation for the new modeset design into the
> merge commit (stichted together from the previous patchbomb cover letters),
> documenting my folly assumptions for eternity.
> 
> I'll also plan to put tags for the entire series in the merge commit, so if you
> have tested this on a few machines, read through and agree with the new designs,
> please reply with your tested-by/acked-by/reviewed-by tags.
> 
> Flames, comments and test reports highly welcome.

I've had a few read throughs of the patches now. I'm not confident yet to
review each and every one of them. To add to my wishlist alongside
reporting an error from modesetting, I would like for the debug log to tell
the complete story behind each mode change. In particular that every
decision point is instrumented and explained.

I am however happy with the direction it is taking, the extra sanity
checks are a major selling point along with the simple no-nonsense
approach to setting modes.

So Acked-by: Chris Wilson <chris@chris-wilson.co.uk> and I'll keep
working through it. Quite a few of the patches are obvious enough to
r-b, but it is more important that we get some critical review of your
core design.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-21 18:11   ` Daniel Vetter
@ 2012-08-22 10:46     ` Lespiau, Damien
  2012-08-22 11:03       ` Lespiau, Damien
  0 siblings, 1 reply; 173+ messages in thread
From: Lespiau, Damien @ 2012-08-22 10:46 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, Intel Graphics Development

[-- Attachment #1: Type: text/plain, Size: 432 bytes --]

On Tue, Aug 21, 2012 at 7:11 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
>> Smoke-tested the new modeset-rework branch and found a regression on
>> my IVB with a pristine f17 userland:
>>
>> * start with LVDS + VGA
>> * unplug VGA
>> * LVDS goes black
>
> Hm, not yet seen this one here. Can you attach a full dmesg with
> drm.debug=0xe when this is happening, please?

Attached dmesg from the point the VGA is plug out.

-- 
Damien

[-- Attachment #2: vga+lvds-unplug-vga-lvds-fail.dmesg --]
[-- Type: application/octet-stream, Size: 24093 bytes --]

[  177.183598] [drm:i915_hotplug_work_func], running encoder hotplug functions
[  177.183623] [drm:intel_ironlake_crt_detect_hotplug], ironlake hotplug adpa=0xa0f40018, result 0
[  177.183627] [drm:intel_crt_detect], CRT not detected via hotplug
[  177.184723] [drm:gmbus_xfer], GMBUS [i915 gmbus vga] NAK for addr: 0050 r(1)
[  177.184730] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus vga
[  177.184733] [drm:intel_crt_detect_ddc], CRT not detected via DDC:0x50 [no valid EDID found]
[  177.184737] [drm:output_poll_execute], [CONNECTOR:15:VGA-1] status updated from 1 to 2
[  177.192713] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpb
[  177.192718] [drm:output_poll_execute], [CONNECTOR:18:HDMI-A-1] status updated from 2 to 2
[  177.195324] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.199320] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.203315] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.204695] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.204703] [drm:output_poll_execute], [CONNECTOR:21:DP-1] status updated from 2 to 2
[  177.206699] [drm:gmbus_xfer], GMBUS [i915 gmbus dpc] NAK for addr: 0050 r(1)
[  177.206709] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpc
[  177.206714] [drm:output_poll_execute], [CONNECTOR:24:HDMI-A-2] status updated from 2 to 2
[  177.208696] [drm:gmbus_xfer], GMBUS [i915 gmbus dpd] NAK for addr: 0050 r(1)
[  177.208706] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpd
[  177.208711] [drm:output_poll_execute], [CONNECTOR:26:HDMI-A-3] status updated from 2 to 2
[  177.211325] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.215299] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.219278] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.220679] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.220687] [drm:output_poll_execute], [CONNECTOR:27:DP-2] status updated from 2 to 2
[  177.223306] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.227284] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.231279] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.232665] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.232674] [drm:output_poll_execute], [CONNECTOR:29:DP-3] status updated from 2 to 2
[  177.236679] [drm:drm_mode_getconnector], [CONNECTOR:9:?]
[  177.236689] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:9:LVDS-1]
[  177.236708] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:9:LVDS-1] probed modes :
[  177.236712] [drm:drm_mode_debug_printmodeline], Modeline 31:"1366x768" 60 74800 1366 1414 1446 1578 768 770 775 790 0x48 0xa
[  177.236720] [drm:drm_mode_getconnector], [CONNECTOR:9:?]
[  177.236976] [drm:drm_mode_getconnector], [CONNECTOR:15:?]
[  177.236980] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:15:VGA-1]
[  177.236993] [drm:intel_ironlake_crt_detect_hotplug], ironlake hotplug adpa=0xa0f40018, result 0
[  177.236996] [drm:intel_crt_detect], CRT not detected via hotplug
[  177.238690] [drm:gmbus_xfer], GMBUS [i915 gmbus vga] NAK for addr: 0050 r(1)
[  177.238702] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus vga
[  177.238706] [drm:intel_crt_detect_ddc], CRT not detected via DDC:0x50 [no valid EDID found]
[  177.238712] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:15:VGA-1] disconnected
[  177.238719] [drm:drm_mode_debug_printmodeline], Modeline 32:"1920x1080" 60 148500 1920 2008 2052 2200 1080 1084 1089 1125 0x48 0x5
[  177.238724] [drm:drm_mode_prune_invalid], Not using 1920x1080 mode -3
[  177.238727] [drm:drm_mode_debug_printmodeline], Modeline 40:"1600x1200" 60 162000 1600 1664 1856 2160 1200 1201 1204 1250 0x40 0x5
[  177.238732] [drm:drm_mode_prune_invalid], Not using 1600x1200 mode -3
[  177.238735] [drm:drm_mode_debug_printmodeline], Modeline 41:"1680x1050" 60 146250 1680 1784 1960 2240 1050 1053 1059 1089 0x40 0x6
[  177.238739] [drm:drm_mode_prune_invalid], Not using 1680x1050 mode -3
[  177.238741] [drm:drm_mode_debug_printmodeline], Modeline 71:"1680x945" 60 131481 1680 1784 1960 2240 945 946 949 978 0x0 0x6
[  177.238746] [drm:drm_mode_prune_invalid], Not using 1680x945 mode -3
[  177.238749] [drm:drm_mode_debug_printmodeline], Modeline 65:"1400x1050" 60 121750 1400 1488 1632 1864 1050 1053 1057 1089 0x40 0x6
[  177.238753] [drm:drm_mode_prune_invalid], Not using 1400x1050 mode -3
[  177.238756] [drm:drm_mode_debug_printmodeline], Modeline 39:"1600x900" 60 118963 1600 1696 1864 2128 900 901 904 932 0x0 0x6
[  177.238760] [drm:drm_mode_prune_invalid], Not using 1600x900 mode -3
[  177.238762] [drm:drm_mode_debug_printmodeline], Modeline 49:"1280x1024" 75 135000 1280 1296 1440 1688 1024 1025 1028 1066 0x40 0x5
[  177.238767] [drm:drm_mode_prune_invalid], Not using 1280x1024 mode -3
[  177.238770] [drm:drm_mode_debug_printmodeline], Modeline 63:"1280x1024" 60 108000 1280 1328 1440 1688 1024 1025 1028 1066 0x40 0x5
[  177.238774] [drm:drm_mode_prune_invalid], Not using 1280x1024 mode -3
[  177.238776] [drm:drm_mode_debug_printmodeline], Modeline 38:"1440x900" 75 136750 1440 1536 1688 1936 900 903 909 942 0x40 0x6
[  177.238780] [drm:drm_mode_prune_invalid], Not using 1440x900 mode -3
[  177.238783] [drm:drm_mode_debug_printmodeline], Modeline 66:"1440x900" 60 106500 1440 1520 1672 1904 900 903 909 934 0x40 0x6
[  177.238788] [drm:drm_mode_prune_invalid], Not using 1440x900 mode -3
[  177.238790] [drm:drm_mode_debug_printmodeline], Modeline 37:"1280x960" 75 129936 1280 1368 1504 1728 960 961 964 1002 0x0 0x6
[  177.238794] [drm:drm_mode_prune_invalid], Not using 1280x960 mode -3
[  177.238797] [drm:drm_mode_debug_printmodeline], Modeline 62:"1280x960" 60 108000 1280 1376 1488 1800 960 961 964 1000 0x40 0x5
[  177.238801] [drm:drm_mode_prune_invalid], Not using 1280x960 mode -3
[  177.238804] [drm:drm_mode_debug_printmodeline], Modeline 70:"1366x768" 60 85885 1366 1439 1583 1800 768 769 772 795 0x0 0x6
[  177.238808] [drm:drm_mode_prune_invalid], Not using 1366x768 mode -3
[  177.238810] [drm:drm_mode_debug_printmodeline], Modeline 64:"1360x768" 60 85500 1360 1424 1536 1792 768 771 777 795 0x40 0x5
[  177.238814] [drm:drm_mode_prune_invalid], Not using 1360x768 mode -3
[  177.238817] [drm:drm_mode_debug_printmodeline], Modeline 61:"1280x800" 75 106500 1280 1360 1488 1696 800 803 809 838 0x40 0x6
[  177.238821] [drm:drm_mode_prune_invalid], Not using 1280x800 mode -3
[  177.238824] [drm:drm_mode_debug_printmodeline], Modeline 60:"1280x800" 60 83500 1280 1352 1480 1680 800 803 809 831 0x40 0x9
[  177.238828] [drm:drm_mode_prune_invalid], Not using 1280x800 mode -3
[  177.238830] [drm:drm_mode_debug_printmodeline], Modeline 56:"1152x864" 75 108000 1152 1216 1344 1600 864 865 868 900 0x40 0x5
[  177.238834] [drm:drm_mode_prune_invalid], Not using 1152x864 mode -3
[  177.238838] [drm:drm_mode_debug_printmodeline], Modeline 59:"1280x768" 75 102250 1280 1360 1488 1696 768 771 778 805 0x40 0x9
[  177.238842] [drm:drm_mode_prune_invalid], Not using 1280x768 mode -3
[  177.238844] [drm:drm_mode_debug_printmodeline], Modeline 58:"1280x768" 60 79500 1280 1344 1472 1664 768 771 778 798 0x40 0x6
[  177.238848] [drm:drm_mode_prune_invalid], Not using 1280x768 mode -3
[  177.238851] [drm:drm_mode_debug_printmodeline], Modeline 36:"1280x720" 60 74440 1280 1336 1472 1664 720 721 724 746 0x0 0x6
[  177.238855] [drm:drm_mode_prune_invalid], Not using 1280x720 mode -3
[  177.238857] [drm:drm_mode_debug_printmodeline], Modeline 50:"1024x768" 75 78800 1024 1040 1136 1312 768 769 772 800 0x40 0x5
[  177.238861] [drm:drm_mode_prune_invalid], Not using 1024x768 mode -3
[  177.238864] [drm:drm_mode_debug_printmodeline], Modeline 51:"1024x768" 70 75000 1024 1048 1184 1328 768 771 777 806 0x40 0xa
[  177.238868] [drm:drm_mode_prune_invalid], Not using 1024x768 mode -3
[  177.238871] [drm:drm_mode_debug_printmodeline], Modeline 52:"1024x768" 60 65000 1024 1048 1184 1344 768 771 777 806 0x40 0xa
[  177.238875] [drm:drm_mode_prune_invalid], Not using 1024x768 mode -3
[  177.238877] [drm:drm_mode_debug_printmodeline], Modeline 67:"1024x576" 60 46970 1024 1064 1168 1312 576 577 580 597 0x0 0x6
[  177.238881] [drm:drm_mode_prune_invalid], Not using 1024x576 mode -3
[  177.238884] [drm:drm_mode_debug_printmodeline], Modeline 53:"832x624" 75 57284 832 864 928 1152 624 625 628 667 0x40 0xa
[  177.238888] [drm:drm_mode_prune_invalid], Not using 832x624 mode -3
[  177.238891] [drm:drm_mode_debug_printmodeline], Modeline 55:"800x600" 72 50000 800 856 976 1040 600 637 643 666 0x40 0x5
[  177.238895] [drm:drm_mode_prune_invalid], Not using 800x600 mode -3
[  177.238898] [drm:drm_mode_debug_printmodeline], Modeline 54:"800x600" 75 49500 800 816 896 1056 600 601 604 625 0x40 0x5
[  177.238902] [drm:drm_mode_prune_invalid], Not using 800x600 mode -3
[  177.238904] [drm:drm_mode_debug_printmodeline], Modeline 42:"800x600" 60 40000 800 840 968 1056 600 601 605 628 0x40 0x5
[  177.238908] [drm:drm_mode_prune_invalid], Not using 800x600 mode -3
[  177.238911] [drm:drm_mode_debug_printmodeline], Modeline 43:"800x600" 56 36000 800 824 896 1024 600 601 603 625 0x40 0x5
[  177.238915] [drm:drm_mode_prune_invalid], Not using 800x600 mode -3
[  177.238917] [drm:drm_mode_debug_printmodeline], Modeline 57:"848x480" 60 33750 848 864 976 1088 480 486 494 517 0x40 0x5
[  177.238921] [drm:drm_mode_prune_invalid], Not using 848x480 mode -3
[  177.238924] [drm:drm_mode_debug_printmodeline], Modeline 45:"640x480" 73 31500 640 664 704 832 480 489 491 520 0x40 0xa
[  177.238928] [drm:drm_mode_prune_invalid], Not using 640x480 mode -3
[  177.238930] [drm:drm_mode_debug_printmodeline], Modeline 44:"640x480" 75 31500 640 656 720 840 480 481 484 500 0x40 0xa
[  177.238934] [drm:drm_mode_prune_invalid], Not using 640x480 mode -3
[  177.238937] [drm:drm_mode_debug_printmodeline], Modeline 46:"640x480" 67 30240 640 704 768 864 480 483 486 525 0x40 0xa
[  177.238941] [drm:drm_mode_prune_invalid], Not using 640x480 mode -3
[  177.238943] [drm:drm_mode_debug_printmodeline], Modeline 47:"640x480" 60 25200 640 656 752 800 480 490 492 525 0x40 0xa
[  177.238947] [drm:drm_mode_prune_invalid], Not using 640x480 mode -3
[  177.238950] [drm:drm_mode_debug_printmodeline], Modeline 48:"720x400" 70 28320 720 738 846 900 400 412 414 449 0x40 0x6
[  177.238954] [drm:drm_mode_prune_invalid], Not using 720x400 mode -3
[  177.238980] [drm:drm_mode_getconnector], [CONNECTOR:15:?]
[  177.238984] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:15:VGA-1]
[  177.238991] [drm:intel_ironlake_crt_detect_hotplug], ironlake hotplug adpa=0xa0f40018, result 0
[  177.238994] [drm:intel_crt_detect], CRT not detected via hotplug
[  177.240666] [drm:gmbus_xfer], GMBUS [i915 gmbus vga] NAK for addr: 0050 r(1)
[  177.240676] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus vga
[  177.240680] [drm:intel_crt_detect_ddc], CRT not detected via DDC:0x50 [no valid EDID found]
[  177.240688] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:15:VGA-1] disconnected
[  177.240767] [drm:drm_mode_getconnector], [CONNECTOR:18:?]
[  177.243345] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.248316] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.253273] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.255684] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.255715] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:18:HDMI-A-1]
[  177.263630] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpb
[  177.263637] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:18:HDMI-A-1] disconnected
[  177.263660] [drm:drm_mode_getconnector], [CONNECTOR:18:?]
[  177.263664] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:18:HDMI-A-1]
[  177.271619] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpb
[  177.271623] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:18:HDMI-A-1] disconnected
[  177.271660] [drm:drm_mode_getconnector], [CONNECTOR:21:?]
[  177.271664] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:21:DP-1]
[  177.274278] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.278301] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.282238] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.283626] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.283639] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:21:DP-1] disconnected
[  177.283668] [drm:drm_mode_getconnector], [CONNECTOR:21:?]
[  177.283673] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:21:DP-1]
[  177.286290] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.290225] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.294235] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.295654] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.295668] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:21:DP-1] disconnected
[  177.295716] [drm:drm_mode_getconnector], [CONNECTOR:24:?]
[  177.298350] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.302210] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.306208] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.307595] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.307654] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:24:HDMI-A-2]
[  177.310607] [drm:gmbus_xfer], GMBUS [i915 gmbus dpc] NAK for addr: 0050 r(1)
[  177.310618] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpc
[  177.310626] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:24:HDMI-A-2] disconnected
[  177.310655] [drm:drm_mode_getconnector], [CONNECTOR:24:?]
[  177.310660] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:24:HDMI-A-2]
[  177.313609] [drm:gmbus_xfer], GMBUS [i915 gmbus dpc] NAK for addr: 0050 r(1)
[  177.313620] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpc
[  177.313628] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:24:HDMI-A-2] disconnected
[  177.313672] [drm:drm_mode_getconnector], [CONNECTOR:26:?]
[  177.313678] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:26:HDMI-A-3]
[  177.315609] [drm:gmbus_xfer], GMBUS [i915 gmbus dpd] NAK for addr: 0050 r(1)
[  177.315619] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpd
[  177.315627] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:26:HDMI-A-3] disconnected
[  177.315655] [drm:drm_mode_getconnector], [CONNECTOR:26:?]
[  177.315660] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:26:HDMI-A-3]
[  177.317565] [drm:gmbus_xfer], GMBUS [i915 gmbus dpd] NAK for addr: 0050 r(1)
[  177.317575] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpd
[  177.317582] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:26:HDMI-A-3] disconnected
[  177.317624] [drm:drm_mode_getconnector], [CONNECTOR:27:?]
[  177.320247] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.324213] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.328219] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.329572] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.329631] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:27:DP-2]
[  177.332271] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.336166] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.340160] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.341556] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.341569] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:27:DP-2] disconnected
[  177.341599] [drm:drm_mode_getconnector], [CONNECTOR:27:?]
[  177.341603] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:27:DP-2]
[  177.344216] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.348191] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.352137] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.353541] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.353554] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:27:DP-2] disconnected
[  177.353598] [drm:drm_mode_getconnector], [CONNECTOR:29:?]
[  177.353604] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:29:DP-3]
[  177.356235] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.360146] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.364148] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.365561] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.365574] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:29:DP-3] disconnected
[  177.365605] [drm:drm_mode_getconnector], [CONNECTOR:29:?]
[  177.365610] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:29:DP-3]
[  177.368225] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.372155] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.376129] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  177.377505] [drm:intel_dp_detect], DPCD: 0000000000000000
[  177.377518] [drm:drm_helper_probe_single_connector_modes], [CONNECTOR:29:DP-3] disconnected
[  177.385474] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpb
[  177.387473] [drm:gmbus_xfer], GMBUS [i915 gmbus dpc] NAK for addr: 0050 r(1)
[  177.387484] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpc
[  177.389463] [drm:gmbus_xfer], GMBUS [i915 gmbus dpd] NAK for addr: 0050 r(1)
[  177.389470] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpd
[  177.389592] [drm:intel_ironlake_crt_detect_hotplug], ironlake hotplug adpa=0xa0f40018, result 0
[  177.389597] [drm:intel_crt_detect], CRT not detected via hotplug
[  177.391471] [drm:gmbus_xfer], GMBUS [i915 gmbus vga] NAK for addr: 0050 r(1)
[  177.391478] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus vga
[  177.391482] [drm:intel_crt_detect_ddc], CRT not detected via DDC:0x50 [no valid EDID found]
[  177.499298] [drm:intel_prepare_page_flip], preparing flip with no unpin work?
[  177.533343] [drm:intel_disable_pch_pll], disable PCH PLL c6018 (active 1, on? 1) for crtc 5
[  177.533352] [drm:intel_disable_pch_pll], disabling PCH PLL c6018
[  177.533773] [drm:sandybridge_update_wm], FIFO watermarks For pipe A - plane 8, cursor: 6
[  177.533776] [drm:sandybridge_update_wm], FIFO watermarks For pipe B - plane 14, cursor: 6
[  177.534220] [drm:intel_crtc_cursor_set], cursor off
[  177.537810] [drm:drm_mode_addfb], [FB:12]
[  177.537870] [drm:drm_mode_setcrtc], [CRTC:3]
[  177.537876] [drm:drm_mode_setcrtc], [CONNECTOR:9:LVDS-1]
[  177.537879] [drm:intel_crtc_set_config], [CRTC:3] [FB:12] #connectors=1 (x y) (0 0)
[  177.537890] [drm:intel_modeset_stage_output_state], [CONNECTOR:9:LVDS-1] to [CRTC:3]
[  177.537893] [drm:intel_modeset_stage_output_state], crtc changed, full mode switch
[  177.537895] [drm:intel_crtc_set_config], attempting to set mode from userspace
[  177.537898] [drm:drm_mode_debug_printmodeline], Modeline 32:"" 0 74800 1366 1414 1446 1578 768 770 775 790 0x0 0xa
[  177.537904] [drm:intel_set_mode], set mode pipe masks: modeset: 1, prepare: 0, disable: 2
[  177.537913] [drm:intel_modeset_adjusted_mode], [CRTC:3]
[  177.537923] [drm:ironlake_get_refclk], using SSC reference clock of 120 MHz
[  177.537968] [drm:intel_choose_pipe_bpp_dither], clamping display bpc (was -1) to LVDS (6)
[  177.537970] [drm:intel_choose_pipe_bpp_dither], setting pipe bpc to 8 (max display bpc 6)
[  177.537976] [drm:ironlake_crtc_mode_set], Mode for pipe 0:
[  177.537978] [drm:drm_mode_debug_printmodeline], Modeline 32:"" 0 74800 1366 1414 1446 1578 768 770 775 790 0x0 0xa
[  177.537983] [drm:intel_get_pch_pll], CRTC:3 reusing existing PCH PLL c6014
[  177.537985] [drm:intel_get_pch_pll], switching PLL c6014 off
[  177.590254] [drm:ironlake_wait_for_vblank], vblank wait timed out
[  177.596181] [drm:ironlake_update_plane], Writing base 025CF000 00000000 0 0 5632
[  177.648141] [drm:ironlake_wait_for_vblank], vblank wait timed out
[  177.648155] [drm:sandybridge_update_wm], FIFO watermarks For pipe A - plane 8, cursor: 6
[  177.648160] [drm:ironlake_check_srwm], watermark 1: display plane 12, fbc lines 3, cursor 6
[  177.648164] [drm:ironlake_check_srwm], watermark 2: display plane 40, fbc lines 3, cursor 6
[  177.648168] [drm:ironlake_check_srwm], watermark 3: display plane 77, fbc lines 3, cursor 6
[  177.648174] [drm:intel_crtc_mode_set], [ENCODER:10:LVDS-10] set [MODE:32:]
[  177.648188] [drm:intel_connector_check_state], [CONNECTOR:9:LVDS-1]
[  177.648200] [drm:intel_modeset_check_state], [ENCODER:10:LVDS-10]
[  177.648205] [drm:intel_modeset_check_state], [ENCODER:16:DAC-16]
[  177.648209] [drm:intel_modeset_check_state], [ENCODER:17:TMDS-17]
[  177.648213] [drm:intel_modeset_check_state], [ENCODER:22:TMDS-22]
[  177.648217] [drm:intel_modeset_check_state], [ENCODER:23:TMDS-23]
[  177.648222] [drm:intel_modeset_check_state], [ENCODER:25:TMDS-25]
[  177.648226] [drm:intel_modeset_check_state], [ENCODER:28:TMDS-28]
[  177.648230] [drm:intel_modeset_check_state], [ENCODER:30:TMDS-30]
[  177.648234] [drm:intel_modeset_check_state], [CRTC:3]
[  177.648237] [drm:intel_modeset_check_state], [CRTC:5]
[  177.648239] [drm:intel_modeset_check_state], [CRTC:7]
[  187.229041] [drm:intel_ironlake_crt_detect_hotplug], ironlake hotplug adpa=0x20f40018, result 0
[  187.229050] [drm:intel_crt_detect], CRT not detected via hotplug
[  187.230757] [drm:gmbus_xfer], GMBUS [i915 gmbus vga] NAK for addr: 0050 r(1)
[  187.230766] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus vga
[  187.230769] [drm:intel_crt_detect_ddc], CRT not detected via DDC:0x50 [no valid EDID found]
[  187.230774] [drm:output_poll_execute], [CONNECTOR:15:VGA-1] status updated from 2 to 2
[  187.238745] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpb
[  187.238749] [drm:output_poll_execute], [CONNECTOR:18:HDMI-A-1] status updated from 2 to 2
[  187.241359] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  187.245334] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  187.249328] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  187.250712] [drm:intel_dp_detect], DPCD: 0000000000000000
[  187.250717] [drm:output_poll_execute], [CONNECTOR:21:DP-1] status updated from 2 to 2
[  187.252734] [drm:gmbus_xfer], GMBUS [i915 gmbus dpc] NAK for addr: 0050 r(1)
[  187.252743] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpc
[  187.252748] [drm:output_poll_execute], [CONNECTOR:24:HDMI-A-2] status updated from 2 to 2
[  187.254723] [drm:gmbus_xfer], GMBUS [i915 gmbus dpd] NAK for addr: 0050 r(1)
[  187.254732] [drm:drm_do_probe_ddc_edid], drm: skipping non-existent adapter i915 gmbus dpd
[  187.254738] [drm:output_poll_execute], [CONNECTOR:26:HDMI-A-3] status updated from 2 to 2
[  187.257356] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  187.261319] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  187.265331] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  187.266711] [drm:intel_dp_detect], DPCD: 0000000000000000
[  187.266719] [drm:output_poll_execute], [CONNECTOR:27:DP-2] status updated from 2 to 2
[  187.269341] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  187.273318] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  187.277313] [drm:intel_dp_aux_ch], dp_aux_ch timeout status 0x5145003f
[  187.278695] [drm:intel_dp_detect], DPCD: 0000000000000000
[  187.278703] [drm:output_poll_execute], [CONNECTOR:29:DP-3] status updated from 2 to 2

[-- Attachment #3: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-22 10:46     ` Lespiau, Damien
@ 2012-08-22 11:03       ` Lespiau, Damien
  2012-08-22 19:13         ` Lespiau, Damien
  0 siblings, 1 reply; 173+ messages in thread
From: Lespiau, Damien @ 2012-08-22 11:03 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, Intel Graphics Development

[-- Attachment #1: Type: text/plain, Size: 531 bytes --]

On Wed, Aug 22, 2012 at 11:46 AM, Lespiau, Damien
<damien.lespiau@intel.com> wrote:
> On Tue, Aug 21, 2012 at 7:11 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
>>> Smoke-tested the new modeset-rework branch and found a regression on
>>> my IVB with a pristine f17 userland:
>>>
>>> * start with LVDS + VGA
>>> * unplug VGA
>>> * LVDS goes black
>>
>> Hm, not yet seen this one here. Can you attach a full dmesg with
>> drm.debug=0xe when this is happening, please?

Also tested with dinq, it works there, dmesg attached.

-- 
Damien

[-- Attachment #2: vga+lvds-unplug-vga-lvds-ok.dmesg.bz2 --]
[-- Type: application/x-bzip2, Size: 3286 bytes --]

[-- Attachment #3: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-22 11:03       ` Lespiau, Damien
@ 2012-08-22 19:13         ` Lespiau, Damien
  2012-08-22 21:21           ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Lespiau, Damien @ 2012-08-22 19:13 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Wed, Aug 22, 2012 at 12:03 PM, Lespiau, Damien
<damien.lespiau@intel.com> wrote:
> On Wed, Aug 22, 2012 at 11:46 AM, Lespiau, Damien
> <damien.lespiau@intel.com> wrote:
>> On Tue, Aug 21, 2012 at 7:11 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
>>>> Smoke-tested the new modeset-rework branch and found a regression on
>>>> my IVB with a pristine f17 userland:
>>>>
>>>> * start with LVDS + VGA
>>>> * unplug VGA
>>>> * LVDS goes black
>>>
>>> Hm, not yet seen this one here. Can you attach a full dmesg with
>>> drm.debug=0xe when this is happening, please?

Adding more information to track this regression, a diff between the
failure state and bringing back the panel with a off/on cycle (note
the disabled DPLL).

$ diff -u vga-out-lvds-fail.dump vga-out-lvds-off-on.dump
--- vga-out-lvds-fail.dump      2012-08-22 14:05:44.732293487 +0100
+++ vga-out-lvds-off-on.dump    2012-08-22 14:06:21.690275915 +0100
@@ -28,10 +28,10 @@
                  PIPEA_LINK_N1: 0x00041eb0 (val 0x41eb0 270000)
                  PIPEA_LINK_M2: 0x00000000 (val 0x0 0)
                  PIPEA_LINK_N2: 0x00000000 (val 0x0 0)
-                      DSPACNTR: 0x58004400 (disabled)
+                      DSPACNTR: 0xd8004400 (enabled)
                       DSPABASE: 0x00000000
                     DSPASTRIDE: 0x00001600 (88)
-                      DSPASURF: 0x041c6008
+                      DSPASURF: 0x0155c008
                    DSPATILEOFF: 0x00000000 (0, 0)
                      PIPEBCONF: 0x00000000 (disabled, inactive,
pf-pd, rotate 0, 8bpc)
                       HTOTAL_B: 0x0897077f (1920 active, 2200 total)
@@ -102,7 +102,7 @@
             PCH_SSC4_AUX_PARMS: 0x000029c5
                   PCH_DPLL_SEL: 0x00000008 (TransA DPLL enable (DPLL
A), TransB DPLL disable (DPLL (null)))
            PCH_DPLL_ANALOG_CTL: 0x00008000
-                    PCH_DPLL_A: 0x08046004 (disable, sdvo high speed
no, mode LVDS, p2 Div 14, FPA0 P1 3, FPA1 P1 3, refclk SSC, sdvo/hdmi
mul 1)
+                    PCH_DPLL_A: 0x88046004 (enable, sdvo high speed
no, mode LVDS, p2 Div 14, FPA0 P1 3, FPA1 P1 3, refclk SSC, sdvo/hdmi
mul 1)
                     PCH_DPLL_B: 0x04020002 (disable, sdvo high speed
no, mode (null), p2 (null), FPA0 P1 2, FPA1 P1 2, refclk default
120Mhz, sdvo/hdmi mul 1)
                       PCH_FPA0: 0x00021108 (n = 2, m1 = 17, m2 = 8)
                       PCH_FPA1: 0x00021108 (n = 2, m1 = 17, m2 = 8)

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-22 19:13         ` Lespiau, Damien
@ 2012-08-22 21:21           ` Daniel Vetter
  2012-08-23 12:26             ` Lespiau, Damien
  0 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-22 21:21 UTC (permalink / raw)
  To: Lespiau, Damien; +Cc: Intel Graphics Development

On Wed, Aug 22, 2012 at 08:13:37PM +0100, Lespiau, Damien wrote:
> On Wed, Aug 22, 2012 at 12:03 PM, Lespiau, Damien
> <damien.lespiau@intel.com> wrote:
> > On Wed, Aug 22, 2012 at 11:46 AM, Lespiau, Damien
> > <damien.lespiau@intel.com> wrote:
> >> On Tue, Aug 21, 2012 at 7:11 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> >>>> Smoke-tested the new modeset-rework branch and found a regression on
> >>>> my IVB with a pristine f17 userland:
> >>>>
> >>>> * start with LVDS + VGA
> >>>> * unplug VGA
> >>>> * LVDS goes black
> >>>
> >>> Hm, not yet seen this one here. Can you attach a full dmesg with
> >>> drm.debug=0xe when this is happening, please?
> 
> Adding more information to track this regression, a diff between the
> failure state and bringing back the panel with a off/on cycle (note
> the disabled DPLL).

Please test the for-damien branch in my personal fdo git repo. I'm rather
positive that the patch there should fix this (but in the least it should
unearth the real culprit).
-Daniel

> 
> $ diff -u vga-out-lvds-fail.dump vga-out-lvds-off-on.dump
> --- vga-out-lvds-fail.dump      2012-08-22 14:05:44.732293487 +0100
> +++ vga-out-lvds-off-on.dump    2012-08-22 14:06:21.690275915 +0100
> @@ -28,10 +28,10 @@
>                   PIPEA_LINK_N1: 0x00041eb0 (val 0x41eb0 270000)
>                   PIPEA_LINK_M2: 0x00000000 (val 0x0 0)
>                   PIPEA_LINK_N2: 0x00000000 (val 0x0 0)
> -                      DSPACNTR: 0x58004400 (disabled)
> +                      DSPACNTR: 0xd8004400 (enabled)
>                        DSPABASE: 0x00000000
>                      DSPASTRIDE: 0x00001600 (88)
> -                      DSPASURF: 0x041c6008
> +                      DSPASURF: 0x0155c008
>                     DSPATILEOFF: 0x00000000 (0, 0)
>                       PIPEBCONF: 0x00000000 (disabled, inactive,
> pf-pd, rotate 0, 8bpc)
>                        HTOTAL_B: 0x0897077f (1920 active, 2200 total)
> @@ -102,7 +102,7 @@
>              PCH_SSC4_AUX_PARMS: 0x000029c5
>                    PCH_DPLL_SEL: 0x00000008 (TransA DPLL enable (DPLL
> A), TransB DPLL disable (DPLL (null)))
>             PCH_DPLL_ANALOG_CTL: 0x00008000
> -                    PCH_DPLL_A: 0x08046004 (disable, sdvo high speed
> no, mode LVDS, p2 Div 14, FPA0 P1 3, FPA1 P1 3, refclk SSC, sdvo/hdmi
> mul 1)
> +                    PCH_DPLL_A: 0x88046004 (enable, sdvo high speed
> no, mode LVDS, p2 Div 14, FPA0 P1 3, FPA1 P1 3, refclk SSC, sdvo/hdmi
> mul 1)
>                      PCH_DPLL_B: 0x04020002 (disable, sdvo high speed
> no, mode (null), p2 (null), FPA0 P1 2, FPA1 P1 2, refclk default
> 120Mhz, sdvo/hdmi mul 1)
>                        PCH_FPA0: 0x00021108 (n = 2, m1 = 17, m2 = 8)
>                        PCH_FPA1: 0x00021108 (n = 2, m1 = 17, m2 = 8)

-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-22 21:21           ` Daniel Vetter
@ 2012-08-23 12:26             ` Lespiau, Damien
  2012-08-23 22:39               ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Lespiau, Damien @ 2012-08-23 12:26 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Wed, Aug 22, 2012 at 10:21 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> Please test the for-damien branch in my personal fdo git repo. I'm rather
> positive that the patch there should fix this (but in the least it should
> unearth the real culprit).

The branch works, but so does HEAD^ on that branch.

After cherry-picking the PLL commit on top of the modeset-rework
branch, plugging out the VGA cable still turns off the PLL for LVDS,
but now triggers the newly introduced asserts see:
http://damien.lespiau.name/files/temp/vga+lvds-unplug-vga-lvds-fail-full-2.dmesg.bz2

I can have a look myself as well, but probably not before Tuesday.

-- 
Damien

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-23 12:26             ` Lespiau, Damien
@ 2012-08-23 22:39               ` Daniel Vetter
  2012-08-29 12:26                 ` Lespiau, Damien
  0 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-23 22:39 UTC (permalink / raw)
  To: Lespiau, Damien; +Cc: Intel Graphics Development

On Thu, Aug 23, 2012 at 01:26:39PM +0100, Lespiau, Damien wrote:
> On Wed, Aug 22, 2012 at 10:21 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> > Please test the for-damien branch in my personal fdo git repo. I'm rather
> > positive that the patch there should fix this (but in the least it should
> > unearth the real culprit).
> 
> The branch works, but so does HEAD^ on that branch.
> 
> After cherry-picking the PLL commit on top of the modeset-rework
> branch, plugging out the VGA cable still turns off the PLL for LVDS,
> but now triggers the newly introduced asserts see:
> http://damien.lespiau.name/files/temp/vga+lvds-unplug-vga-lvds-fail-full-2.dmesg.bz2

Yeah, the pll changes are just something I've noticed that looks strange,
the real fix is tip. And that one is a real change wrt what the crtc
helper does, so I need to think about it some more.

> I can have a look myself as well, but probably not before Tuesday.

Hm, if you have that dmesg from the branch I've pushed, we hit the WARN
for the case where we grab a fresh pch pll, but somehow think it's still
on. I have a feeling there's something fishy going on. But like I've said
before, the pll stuff is simply something I've noticed while reading
through your dmesg.

Thanks for testing, Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (61 preceding siblings ...)
  2012-08-21 19:48 ` Chris Wilson
@ 2012-08-27  8:04 ` Vijay Purushothaman
  2012-09-03 17:50 ` Paulo Zanoni
                   ` (2 subsequent siblings)
  65 siblings, 0 replies; 173+ messages in thread
From: Vijay Purushothaman @ 2012-08-27  8:04 UTC (permalink / raw)
  To: intel-gfx

On 8/20/2012 12:42 AM, Daniel Vetter wrote:
> Hi all,
>
> Changes since last time around:
> - The prep patches are all merged now.
> - I've left out the actual DP fixes/cleanups, I think we should merge those in a
>    separte step.
> - A few bugfixes (thanks to Paulo, Jani and Chris).
> - I've also applied a few bikesheds for naming that Paulo suggested (but I'm not
>    sure whether I've sent those out already in a previous patchbomb).
>
> Essentially this is just the core rework, which addes the new get_hw_state code,
> refactors all the encoders to use the new functions and finally reworks the
> modeset logic to disable/enable entire pipes, always (and with a deterministic
> order).
>
> For merging to -next, I plan to pull in everything with a real merge commit. For
> that reason I've put up a modeset-rework-base branch onto my private fdo repo[1].
> That way I can put a short documentation for the new modeset design into the
> merge commit (stichted together from the previous patchbomb cover letters),
> documenting my folly assumptions for eternity.
>
> I'll also plan to put tags for the entire series in the merge commit, so if you
> have tested this on a few machines, read through and agree with the new designs,
> please reply with your tested-by/acked-by/reviewed-by tags.
>
> Flames, comments and test reports highly welcome.
>
> Cheers, Daniel
>
> [1] http://cgit.freedesktop.org/~danvet/drm/log/?h=modeset-rework-base

Tested Valleyview X0 eDP, DP, HDMI and VGA before the rebase.

Dual display is still work in progress for Valleyview. So, i did not 
test the combinations like VGA+HDMI or VGA+DP.

Tested-by: Vijay Purushothaman <vijay.a.purushothaman@intel.com>
Acked-by: Vijay Purushothaman <vijay.a.purushothaman@intel.com>


Thanks,
Vijay

> Daniel Vetter (58):
>    drm/i915: add crtc->enable/disable vfuncs insted of dpms
>    drm/i915: rip out crtc prepare/commit indirection
>    drm/i915: add direct encoder disable/enable infrastructure
>    drm/i915/hdmi: convert to encoder->disable/enable
>    drm/i915/tv: convert to encoder enable/disable
>    drm/i915/lvds: convert to encoder disable/enable
>    drm/i915/dp: convert to encoder disable/enable
>    drm/i915/crt: convert to encoder disable/enable
>    drm/i915/sdvo: convert to encoder disable/enable
>    drm/i915/dvo: convert to encoder disable/enable
>    drm/i915: convert dpms functions of dvo/sdvo/crt
>    drm/i915: rip out encoder->disable/enable checks
>    drm/i915: clean up encoder_prepare/commit
>    drm/i915: copy&paste drm_crtc_helper_set_config
>    drm/i915: call set_base directly
>    drm/i915: inline intel_best_encoder
>    drm/i915: copy&paste drm_crtc_helper_set_mode
>    drm/i915: simplify intel_crtc_prepare_encoders
>    drm/i915: rip out encoder->prepare/commit
>    drm/i915: call crtc functions directly
>    drm/i915: WARN when trying to enabled an unused crtc
>    drm/i915: Add interfaces to read out encoder/connector hw state
>    drm/i915/dp: implement get_hw_state
>    drm/i915/hdmi: implement get_hw_state
>    drm/i915/tv: implement get_hw_state
>    drm/i915/lvds: implement get_hw_state
>    drm/i915/crt: implement get_hw_state
>    drm/i915/sdvo: implement get_hw_state
>    drm/i915/dvo: implement get_hw_state
>    drm/i915: read out the modeset hw state at load and resume time
>    drm/i915: check connector hw/sw state
>    drm/i915: rip out intel_crtc->dpms_mode
>    drm/i915: rip out intel_dp->dpms_mode
>    drm/i915: ensure the force pipe A quirk is actually followed
>    drm/i915: introduce struct intel_set_config
>    drm/i915: extract modeset config save/restore code
>    drm/i915: extract intel_set_config_compute_mode_changes
>    drm/i915: extract intel_set_config_update_output_state
>    drm/i915: implement crtc helper semantics relied upon by the fb
>      helper
>    drm/i915: don't update the fb base if there is no fb
>    drm/i915: convert pointless error checks in set_config to BUGs
>    drm/i915: don't save all the encoder/crtc state in set_config
>    drm/i915: stage modeset output changes
>    drm/i915: push crtc->fb update into pipe_set_base
>    drm/i915: remove crtc disabling special case
>    drm/i915: move output commit and crtc disabling into set_mode
>    drm/i915: extract adjusted mode computation
>    drm/i915: use staged outuput config in tv->mode_fixup
>    drm/i915: use staged outuput config in lvds->mode_fixup
>    drm/i915: compute masks of crtcs affected in set_mode
>    drm/i915: implement new set_mode code flow
>    drm/i915: push commit_output_state past crtc disabling
>    drm/i915: s/intel_encoder_disable/intel_encoder_noop
>    drm/i915: WARN if the pipe won't turn off
>    drm/i915: switch the load detect code to the staged modeset config
>    drm/i915: push commit_output_state past the crtc/encoder preparing
>    drm/i915: disable all crtcs at suspend time
>    drm/i915: add tons of modeset state checks
>
>   drivers/gpu/drm/i915/dvo.h           |    6 +
>   drivers/gpu/drm/i915/dvo_ch7017.c    |   13 +
>   drivers/gpu/drm/i915/dvo_ch7xxx.c    |   13 +
>   drivers/gpu/drm/i915/dvo_ivch.c      |   15 +
>   drivers/gpu/drm/i915/dvo_ns2501.c    |   15 +
>   drivers/gpu/drm/i915/dvo_sil164.c    |   16 +
>   drivers/gpu/drm/i915/dvo_tfp410.c    |   14 +
>   drivers/gpu/drm/i915/i915_drv.c      |    4 +
>   drivers/gpu/drm/i915/i915_drv.h      |    4 +-
>   drivers/gpu/drm/i915/i915_reg.h      |    2 +
>   drivers/gpu/drm/i915/intel_crt.c     |  136 ++-
>   drivers/gpu/drm/i915/intel_ddi.c     |   59 +-
>   drivers/gpu/drm/i915/intel_display.c | 1499 ++++++++++++++++++++++++++++------
>   drivers/gpu/drm/i915/intel_dp.c      |  144 ++--
>   drivers/gpu/drm/i915/intel_drv.h     |   64 +-
>   drivers/gpu/drm/i915/intel_dvo.c     |   94 ++-
>   drivers/gpu/drm/i915/intel_hdmi.c    |  151 +++-
>   drivers/gpu/drm/i915/intel_lvds.c    |   95 +--
>   drivers/gpu/drm/i915/intel_sdvo.c    |  164 +++-
>   drivers/gpu/drm/i915/intel_tv.c      |   61 +-
>   20 files changed, 2044 insertions(+), 525 deletions(-)
>

^ permalink raw reply	[flat|nested] 173+ messages in thread

* [PATCH] drm/i915: convert dpms functions of dvo/sdvo/crt
  2012-08-19 19:12 ` [PATCH 11/58] drm/i915: convert dpms functions of dvo/sdvo/crt Daniel Vetter
@ 2012-08-29  7:12   ` Daniel Vetter
  2012-09-04 20:10     ` Jesse Barnes
  0 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-29  7:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_crt.c     | 97 +++++++++++++++++++-----------------
 drivers/gpu/drm/i915/intel_display.c | 37 +++++++-------
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 drivers/gpu/drm/i915/intel_dvo.c     | 39 +++++++++++----
 drivers/gpu/drm/i915/intel_sdvo.c    | 60 ++++++++++------------
 5 files changed, 122 insertions(+), 112 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 543ea40..76646c7 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -84,13 +84,17 @@ static void intel_enable_crt(struct intel_encoder *encoder)
 	I915_WRITE(crt->adpa_reg, temp);
 }
 
-static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
+/* Note: The caller is required to filter out dpms modes not supported by the
+ * platform. */
+static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
 	u32 temp;
 
-	temp = I915_READ(PCH_ADPA);
+	temp = I915_READ(crt->adpa_reg);
+	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
 	temp &= ~ADPA_DAC_ENABLE;
 
 	switch (mode) {
@@ -98,44 +102,59 @@ static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
 		temp |= ADPA_DAC_ENABLE;
 		break;
 	case DRM_MODE_DPMS_STANDBY:
+		temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
+		break;
 	case DRM_MODE_DPMS_SUSPEND:
+		temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
+		break;
 	case DRM_MODE_DPMS_OFF:
-		/* Just leave port enable cleared */
+		temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
 		break;
 	}
 
-	I915_WRITE(PCH_ADPA, temp);
+	I915_WRITE(crt->adpa_reg, temp);
 }
 
-static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
+static void intel_crt_dpms(struct drm_connector *connector, int mode)
 {
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 temp;
-
-	temp = I915_READ(ADPA);
-	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
-	temp &= ~ADPA_DAC_ENABLE;
+	struct drm_device *dev = connector->dev;
+	struct intel_encoder *encoder = intel_attached_encoder(connector);
+	struct drm_crtc *crtc;
+	int old_dpms;
 
-	if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON)
+	/* PCH platforms and VLV only support on/off. */
+	if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
 		mode = DRM_MODE_DPMS_OFF;
 
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		temp |= ADPA_DAC_ENABLE;
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-		temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
-		break;
-	case DRM_MODE_DPMS_SUSPEND:
-		temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
-		break;
-	case DRM_MODE_DPMS_OFF:
-		temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
-		break;
+	if (mode == connector->dpms)
+		return;
+
+	old_dpms = connector->dpms;
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	crtc = encoder->base.crtc;
+	if (!crtc) {
+		encoder->connectors_active = false;
+		return;
 	}
 
-	I915_WRITE(ADPA, temp);
+	/* We need the pipe to run for anything but OFF. */
+	if (mode == DRM_MODE_DPMS_OFF)
+		encoder->connectors_active = false;
+	else
+		encoder->connectors_active = true;
+
+	if (mode < old_dpms) {
+		/* From off to on, enable the pipe first. */
+		intel_crtc_update_dpms(crtc);
+
+		intel_crt_set_dpms(encoder, mode);
+	} else {
+		intel_crt_set_dpms(encoder, mode);
+
+		intel_crtc_update_dpms(crtc);
+	}
 }
 
 static int intel_crt_mode_valid(struct drm_connector *connector,
@@ -596,27 +615,17 @@ static void intel_crt_reset(struct drm_connector *connector)
  * Routines for controlling stuff on the analog port
  */
 
-static const struct drm_encoder_helper_funcs pch_encoder_funcs = {
-	.mode_fixup = intel_crt_mode_fixup,
-	.prepare = intel_encoder_noop,
-	.commit = intel_encoder_noop,
-	.mode_set = intel_crt_mode_set,
-	.dpms = pch_crt_dpms,
-	.disable = intel_encoder_disable,
-};
-
-static const struct drm_encoder_helper_funcs gmch_encoder_funcs = {
+static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
 	.mode_fixup = intel_crt_mode_fixup,
 	.prepare = intel_encoder_noop,
 	.commit = intel_encoder_noop,
 	.mode_set = intel_crt_mode_set,
-	.dpms = gmch_crt_dpms,
 	.disable = intel_encoder_disable,
 };
 
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
 	.reset = intel_crt_reset,
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_crt_dpms,
 	.detect = intel_crt_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = intel_crt_destroy,
@@ -657,7 +666,6 @@ void intel_crt_init(struct drm_device *dev)
 	struct intel_crt *crt;
 	struct intel_connector *intel_connector;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	const struct drm_encoder_helper_funcs *encoder_helper_funcs;
 
 	/* Skip machines without VGA that falsely report hotplug events */
 	if (dmi_check_system(intel_no_crt))
@@ -696,11 +704,6 @@ void intel_crt_init(struct drm_device *dev)
 	connector->doublescan_allowed = 0;
 
 	if (HAS_PCH_SPLIT(dev))
-		encoder_helper_funcs = &pch_encoder_funcs;
-	else
-		encoder_helper_funcs = &gmch_encoder_funcs;
-
-	if (HAS_PCH_SPLIT(dev))
 		crt->adpa_reg = PCH_ADPA;
 	else if (IS_VALLEYVIEW(dev))
 		crt->adpa_reg = VLV_ADPA;
@@ -710,7 +713,7 @@ void intel_crt_init(struct drm_device *dev)
 	crt->base.disable = intel_disable_crt;
 	crt->base.enable = intel_enable_crt;
 
-	drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs);
+	drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs);
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
 	drm_sysfs_connector_add(connector);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cbd356f..0d48ebe 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3462,34 +3462,31 @@ static void i9xx_crtc_off(struct drm_crtc *crtc)
 /**
  * Sets the power management mode of the pipe and plane.
  */
-static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
+void intel_crtc_update_dpms(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *intel_encoder;
 	int pipe = intel_crtc->pipe;
-	bool enabled;
+	bool enabled, enable = false;
+	int mode;
+
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
+		enable |= intel_encoder->connectors_active;
+
+	mode = enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF;
 
 	if (intel_crtc->dpms_mode == mode)
 		return;
 
 	intel_crtc->dpms_mode = mode;
 
-	/* XXX: When our outputs are all unaware of DPMS modes other than off
-	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
-	 */
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
+	if (enable)
 		dev_priv->display.crtc_enable(crtc);
-		break;
-
-	case DRM_MODE_DPMS_OFF:
+	else
 		dev_priv->display.crtc_disable(crtc);
-		break;
-	}
 
 	if (!dev->primary->master)
 		return;
@@ -3498,7 +3495,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 	if (!master_priv->sarea_priv)
 		return;
 
-	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
+	enabled = crtc->enabled && enable;
 
 	switch (pipe) {
 	case 0:
@@ -3517,11 +3514,12 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 
 static void intel_crtc_disable(struct drm_crtc *crtc)
 {
-	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+	/* crtc->disable is only called when we have no encoders, hence this
+	 * will disable the pipe. */
+	intel_crtc_update_dpms(crtc);
 	dev_priv->display.off(crtc);
 
 	assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
@@ -3581,11 +3579,11 @@ void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
 	if (mode == DRM_MODE_DPMS_ON) {
 		encoder->connectors_active = true;
 
-		intel_crtc_dpms(encoder->base.crtc, DRM_MODE_DPMS_ON);
+		intel_crtc_update_dpms(encoder->base.crtc);
 	} else {
 		encoder->connectors_active = false;
 
-		intel_crtc_dpms(encoder->base.crtc, DRM_MODE_DPMS_OFF);
+		intel_crtc_update_dpms(encoder->base.crtc);
 	}
 }
 
@@ -6609,7 +6607,6 @@ static void intel_crtc_reset(struct drm_crtc *crtc)
 }
 
 static struct drm_crtc_helper_funcs intel_helper_funcs = {
-	.dpms = intel_crtc_dpms,
 	.mode_fixup = intel_crtc_mode_fixup,
 	.mode_set = intel_crtc_mode_set,
 	.mode_set_base = intel_pipe_set_base,
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 759dcba..2456245 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);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 4ad988f..c55a13e 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -129,21 +129,39 @@ static void intel_enable_dvo(struct intel_encoder *encoder)
 	intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
 }
 
-static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
+static void intel_dvo_dpms(struct drm_connector *connector, int mode)
 {
-	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
-	struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
-	u32 dvo_reg = intel_dvo->dev.dvo_reg;
-	u32 temp = I915_READ(dvo_reg);
+	struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
+	struct drm_crtc *crtc;
+
+	/* dvo supports only 2 dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == connector->dpms)
+		return;
+
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	crtc = intel_dvo->base.base.crtc;
+	if (!crtc) {
+		intel_dvo->base.connectors_active = false;
+		return;
+	}
 
 	if (mode == DRM_MODE_DPMS_ON) {
-		I915_WRITE(dvo_reg, temp | DVO_ENABLE);
-		I915_READ(dvo_reg);
+		intel_dvo->base.connectors_active = true;
+
+		intel_crtc_update_dpms(crtc);
+
 		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
 	} else {
 		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
-		I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
-		I915_READ(dvo_reg);
+
+		intel_dvo->base.connectors_active = false;
+
+		intel_crtc_update_dpms(crtc);
 	}
 }
 
@@ -299,7 +317,6 @@ static void intel_dvo_destroy(struct drm_connector *connector)
 }
 
 static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
-	.dpms = intel_dvo_dpms,
 	.mode_fixup = intel_dvo_mode_fixup,
 	.prepare = intel_encoder_noop,
 	.mode_set = intel_dvo_mode_set,
@@ -308,7 +325,7 @@ static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
 };
 
 static const struct drm_connector_funcs intel_dvo_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_dvo_dpms,
 	.detect = intel_dvo_detect,
 	.destroy = intel_dvo_destroy,
 	.fill_modes = drm_helper_probe_single_connector_modes,
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 20feaa3..a01c470 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1192,51 +1192,44 @@ static void intel_enable_sdvo(struct intel_encoder *encoder)
 	intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
 }
 
-static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
+static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
 {
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-	u32 temp;
+	struct drm_crtc *crtc;
+	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
+
+	/* dvo supports only 2 dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == connector->dpms)
+		return;
+
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	crtc = intel_sdvo->base.base.crtc;
+	if (!crtc) {
+		intel_sdvo->base.connectors_active = false;
+		return;
+	}
 
 	if (mode != DRM_MODE_DPMS_ON) {
 		intel_sdvo_set_active_outputs(intel_sdvo, 0);
 		if (0)
 			intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
 
-		if (mode == DRM_MODE_DPMS_OFF) {
-			temp = I915_READ(intel_sdvo->sdvo_reg);
-			if ((temp & SDVO_ENABLE) != 0) {
-				intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE);
-			}
-		}
+		intel_sdvo->base.connectors_active = false;
+
+		intel_crtc_update_dpms(crtc);
 	} else {
-		bool input1, input2;
-		int i;
-		u8 status;
-
-		temp = I915_READ(intel_sdvo->sdvo_reg);
-		if ((temp & SDVO_ENABLE) == 0)
-			intel_sdvo_write_sdvox(intel_sdvo, temp | SDVO_ENABLE);
-		for (i = 0; i < 2; i++)
-			intel_wait_for_vblank(dev, intel_crtc->pipe);
-
-		status = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2);
-		/* Warn if the device reported failure to sync.
-		 * A lot of SDVO devices fail to notify of sync, but it's
-		 * a given it the status is a success, we succeeded.
-		 */
-		if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
-			DRM_DEBUG_KMS("First %s output reported failure to "
-					"sync\n", SDVO_NAME(intel_sdvo));
-		}
+		intel_sdvo->base.connectors_active = true;
+
+		intel_crtc_update_dpms(crtc);
 
 		if (0)
 			intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
 		intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
 	}
-	return;
 }
 
 static int intel_sdvo_mode_valid(struct drm_connector *connector,
@@ -1895,7 +1888,6 @@ done:
 }
 
 static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
-	.dpms = intel_sdvo_dpms,
 	.mode_fixup = intel_sdvo_mode_fixup,
 	.prepare = intel_encoder_noop,
 	.mode_set = intel_sdvo_mode_set,
@@ -1904,7 +1896,7 @@ static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
 };
 
 static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_sdvo_dpms,
 	.detect = intel_sdvo_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_sdvo_set_property,
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH] drm/i915: compute masks of crtcs affected in set_mode
  2012-08-19 19:13 ` [PATCH 50/58] drm/i915: compute masks of crtcs affected in set_mode Daniel Vetter
@ 2012-08-29 10:34   ` Daniel Vetter
  2012-09-05 18:09     ` Jesse Barnes
  2012-09-05 18:07   ` [PATCH 50/58] " Jesse Barnes
  1 sibling, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-29 10:34 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

This is definetely a bit more generic than currently required, but
if we keep track of all crtcs that need to be disabled/enable (because
they loose an encoder or something similar), crtcs that get completely
disabled and those that we need to do an actual mode change on nicely
prepares us for global modeset operations on multiple crtcs.

The only big thing missing here would be a global resource allocation
step (for e.g. pch plls), which would equally frob these bitmasks if
e.g. a crtc only needs a new pll.

These masks aren't yet put to use in this patch, this will follow in the
next one.

v2-v5: Fix up the computations for good (hopefully).

v6: Fixup a confusion reported by Damien Lespiau: I've conserved the
(imo braindead) behaviour of the crtc helper to disable _any_
disconnected outputs if we do a modeset, even when that newly disabled
connector isn't connected to the crtc being changed by the modeset.

The effect of that is that we could disable an arbitrary number of
unrelated crtcs, which I haven't taken into account when writing this
code. Fix this up.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 96 ++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c59569e..8f71957 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6706,6 +6706,98 @@ fail:
 	return ERR_PTR(-EINVAL);
 }
 
+/* Computes which crtcs are affected and sets the relevant bits in the mask. For
+ * simplicity we use the crtc's pipe number (because it's easier to obtain). */
+static void
+intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
+			     unsigned *prepare_pipes, unsigned *disable_pipes)
+{
+	struct intel_crtc *intel_crtc;
+	struct drm_device *dev = crtc->dev;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+	struct drm_crtc *tmp_crtc;
+
+	*disable_pipes = *modeset_pipes = *prepare_pipes = 0;
+
+	/* Check which crtcs have changed outputs connected to them, these need
+	 * to be part of the prepare_pipes mask. We don't (yet) support global
+	 * modeset across multiple crtcs, so modeset_pipes will only have one
+	 * bit set at most. */
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		if (connector->base.encoder == &connector->new_encoder->base)
+			continue;
+
+		if (connector->base.encoder) {
+			tmp_crtc = connector->base.encoder->crtc;
+
+			*prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
+		}
+
+		if (connector->new_encoder)
+			*prepare_pipes |=
+				1 << connector->new_encoder->new_crtc->pipe;
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		if (encoder->base.crtc == &encoder->new_crtc->base)
+			continue;
+
+		if (encoder->base.crtc) {
+			tmp_crtc = encoder->base.crtc;
+
+			*prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
+		}
+
+		if (encoder->new_crtc)
+			*prepare_pipes |= 1 << encoder->new_crtc->pipe;
+	}
+
+	/* Check for any pipes that will be fully 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)
+			continue;
+
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+				    base.head) {
+			if (encoder->new_crtc == intel_crtc)
+				used = true;
+		}
+
+		if (!used)
+			*disable_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)
+		*prepare_pipes |= 1 << intel_crtc->pipe;
+
+	/* We only support modeset on one single crtc, hence we need to do that
+	 * only for the passed in crtc iff we change anything else than just
+	 * disable crtcs.
+	 *
+	 * This is actually not true, to be fully compatible with the old crtc
+	 * helper we automatically disable _any_ output (i.e. doesn't need to be
+	 * connected to the crtc we're modesetting on) if it's disconnected.
+	 * Which is a rather nutty api (since changed the output configuration
+	 * without userspace's explicit request can lead to confusion), but
+	 * alas. Hence we currently need to modeset on all pipes we prepare. */
+	if (*prepare_pipes)
+		*modeset_pipes = *prepare_pipes;
+
+	/* ... and mask these out. */
+	*modeset_pipes &= ~(*disable_pipes);
+	*prepare_pipes &= ~(*disable_pipes);
+}
+
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
 		    int x, int y, struct drm_framebuffer *fb)
@@ -6715,8 +6807,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct drm_encoder *encoder;
+	unsigned disable_pipe, prepare_pipes, modeset_pipes;
 	bool ret = true;
 
+	intel_modeset_affected_pipes(crtc, &modeset_pipes,
+				     &prepare_pipes, &disable_pipe);
+
 	intel_modeset_commit_output_state(dev);
 
 	crtc->enabled = drm_helper_crtc_in_use(crtc);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-23 22:39               ` Daniel Vetter
@ 2012-08-29 12:26                 ` Lespiau, Damien
  2012-08-30 10:40                   ` Rodrigo Vivi
  0 siblings, 1 reply; 173+ messages in thread
From: Lespiau, Damien @ 2012-08-29 12:26 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Thu, Aug 23, 2012 at 11:39 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Thu, Aug 23, 2012 at 01:26:39PM +0100, Lespiau, Damien wrote:
>> On Wed, Aug 22, 2012 at 10:21 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
>> > Please test the for-damien branch in my personal fdo git repo. I'm rather
>> > positive that the patch there should fix this (but in the least it should
>> > unearth the real culprit).

After a bit of back and forth and the updated 50/58 patch, does not
regress any more here with the testing done on an IVB system.

Tested-by:  Damien Lespiau <damien.lespiau@intel.com>

-- 
Damien

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 01/58] drm/i915: add crtc->enable/disable vfuncs insted of dpms
  2012-08-19 19:12 ` [PATCH 01/58] drm/i915: add crtc->enable/disable vfuncs insted of dpms Daniel Vetter
@ 2012-08-29 17:51   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-08-29 17:51 UTC (permalink / raw)
  To: intel-gfx

On Sun, 19 Aug 2012 21:12:18 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Because that's what we're essentially calling. This is the first step
> in untangling the crtc_helper induced dpms handling mess we have - at
> the crtc level we only have 2 states and the magic is just in
> selecting which one (and atm there isn't even much magic, but on
> recent platforms where not even the crt output has more than 2 states
> we could do better).
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      |  3 +-
>  drivers/gpu/drm/i915/intel_display.c | 62
> +++++++++++------------------------- 2 files changed, 20
> insertions(+), 45 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h
> b/drivers/gpu/drm/i915/i915_drv.h index ed3ba70..fb46c6f 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -240,7 +240,6 @@ struct drm_i915_error_state {
>  };
>  
>  struct drm_i915_display_funcs {
> -	void (*dpms)(struct drm_crtc *crtc, int mode);
>  	bool (*fbc_enabled)(struct drm_device *dev);
>  	void (*enable_fbc)(struct drm_crtc *crtc, unsigned long
> interval); void (*disable_fbc)(struct drm_device *dev);
> @@ -256,6 +255,8 @@ struct drm_i915_display_funcs {
>  			     struct drm_display_mode *adjusted_mode,
>  			     int x, int y,
>  			     struct drm_framebuffer *old_fb);
> +	void (*crtc_enable)(struct drm_crtc *crtc);
> +	void (*crtc_disable)(struct drm_crtc *crtc);
>  	void (*off)(struct drm_crtc *crtc);
>  	void (*write_eld)(struct drm_connector *connector,
>  			  struct drm_crtc *crtc);
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c index 42c5758..adc9868 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3342,30 +3342,6 @@ static void ironlake_crtc_disable(struct
> drm_crtc *crtc) mutex_unlock(&dev->struct_mutex);
>  }
>  
> -static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
> -{
> -	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	int pipe = intel_crtc->pipe;
> -	int plane = intel_crtc->plane;
> -
> -	/* XXX: When our outputs are all unaware of DPMS modes other
> than off
> -	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in
> the CRTC.
> -	 */
> -	switch (mode) {
> -	case DRM_MODE_DPMS_ON:
> -	case DRM_MODE_DPMS_STANDBY:
> -	case DRM_MODE_DPMS_SUSPEND:
> -		DRM_DEBUG_KMS("crtc %d/%d dpms on\n", pipe, plane);
> -		ironlake_crtc_enable(crtc);
> -		break;
> -
> -	case DRM_MODE_DPMS_OFF:
> -		DRM_DEBUG_KMS("crtc %d/%d dpms off\n", pipe, plane);
> -		ironlake_crtc_disable(crtc);
> -		break;
> -	}
> -}
> -
>  static void ironlake_crtc_off(struct drm_crtc *crtc)
>  {
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> @@ -3445,23 +3421,6 @@ static void i9xx_crtc_disable(struct drm_crtc
> *crtc) intel_update_watermarks(dev);
>  }
>  
> -static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
> -{
> -	/* XXX: When our outputs are all unaware of DPMS modes other
> than off
> -	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in
> the CRTC.
> -	 */
> -	switch (mode) {
> -	case DRM_MODE_DPMS_ON:
> -	case DRM_MODE_DPMS_STANDBY:
> -	case DRM_MODE_DPMS_SUSPEND:
> -		i9xx_crtc_enable(crtc);
> -		break;
> -	case DRM_MODE_DPMS_OFF:
> -		i9xx_crtc_disable(crtc);
> -		break;
> -	}
> -}
> -
>  static void i9xx_crtc_off(struct drm_crtc *crtc)
>  {
>  }
> @@ -3483,7 +3442,20 @@ static void intel_crtc_dpms(struct drm_crtc
> *crtc, int mode) 
>  	intel_crtc->dpms_mode = mode;
>  
> -	dev_priv->display.dpms(crtc, mode);
> +	/* XXX: When our outputs are all unaware of DPMS modes other
> than off
> +	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in
> the CRTC.
> +	 */
> +	switch (mode) {
> +	case DRM_MODE_DPMS_ON:
> +	case DRM_MODE_DPMS_STANDBY:
> +	case DRM_MODE_DPMS_SUSPEND:
> +		dev_priv->display.crtc_enable(crtc);
> +		break;
> +
> +	case DRM_MODE_DPMS_OFF:
> +		dev_priv->display.crtc_disable(crtc);
> +		break;
> +	}
>  
>  	if (!dev->primary->master)
>  		return;
> @@ -6971,13 +6943,15 @@ static void intel_init_display(struct
> drm_device *dev) 
>  	/* We always want a DPMS function */
>  	if (HAS_PCH_SPLIT(dev)) {
> -		dev_priv->display.dpms = ironlake_crtc_dpms;
>  		dev_priv->display.crtc_mode_set =
> ironlake_crtc_mode_set;
> +		dev_priv->display.crtc_enable = ironlake_crtc_enable;
> +		dev_priv->display.crtc_disable =
> ironlake_crtc_disable; dev_priv->display.off = ironlake_crtc_off;
>  		dev_priv->display.update_plane =
> ironlake_update_plane; } else {
> -		dev_priv->display.dpms = i9xx_crtc_dpms;
>  		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
> +		dev_priv->display.crtc_enable = i9xx_crtc_enable;
> +		dev_priv->display.crtc_disable = i9xx_crtc_disable;
>  		dev_priv->display.off = i9xx_crtc_off;
>  		dev_priv->display.update_plane = i9xx_update_plane;
>  	}


R-b still applies here.

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 02/58] drm/i915: rip out crtc prepare/commit indirection
  2012-08-19 19:12 ` [PATCH 02/58] drm/i915: rip out crtc prepare/commit indirection Daniel Vetter
@ 2012-08-29 17:52   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-08-29 17:52 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:19 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Just impendance matching with the the crtc helper stuff.
> 
> ... and somehow the design of this all ended up in this commit here,
> too ;-)
> 
> The big plan is that this new set of crtc display_funcs take full
> responsibility of modeset operations for the entire display output
> pipeline (by calling down into object-specific callbacks and
> functions). The platform-specific callbacks simply know best what the
> proper order is.
> 
> This has the drawback that we can't do minimal change-overs any more
> if a modeset just disables one encoder in a cloned configuration
> (because we will only expose a disable/enable action that takes
> down/sets up the entire crtc including all encoders). Imo that's the
> only sane way to do it though:
> - The use-case for this is pretty minimal, even when presenting (at
>   least sane people) should use a dual-screen output so that you can
>   see your notes on your panel. Clone mode is imo BS.
> - With all the clone mode constrains, shared resources, and special
>   ordering requirements (which differ even on the same platform
>   sometimes for different outputs) there's no way we'd get this right
>   for all cases. Especially since this is a under-used feature.
> - And to top it off: On haswell even dp link re-training requires us
>   to take down the entire display pipe - otherwise the chip dies.
> 
> So the only sane way is to do a full modeset on every crtc where the
> output config changes in any way.
> 
> To support global modeset (i.e. set the configuration for all crtcs at
> once) we'd then add one more function to allocate global and shared
> objects in the best ways (e.g. fdi links, pch plls, ...). The crtc
> functions would then simply use the pre-allocated stuff (and shouldn't
> be able to fail, ever). We could even do all the object pinning in
> there (and maybe try to defragment the global gtt if we fail)!
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 37
> ++---------------------------------- 1 file changed, 2 insertions(+),
> 35 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c index adc9868..04bec4b 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3500,34 +3500,6 @@ static void intel_crtc_disable(struct drm_crtc
> *crtc) }
>  }
>  
> -/* Prepare for a mode set.
> - *
> - * Note we could be a lot smarter here.  We need to figure out which
> outputs
> - * will be enabled, which disabled (in short, how the config will
> changes)
> - * and perform the minimum necessary steps to accomplish that, e.g.
> updating
> - * watermarks, FBC configuration, making sure PLLs are programmed
> correctly,
> - * panel fitting is in the proper state, etc.
> - */
> -static void i9xx_crtc_prepare(struct drm_crtc *crtc)
> -{
> -	i9xx_crtc_disable(crtc);
> -}
> -
> -static void i9xx_crtc_commit(struct drm_crtc *crtc)
> -{
> -	i9xx_crtc_enable(crtc);
> -}
> -
> -static void ironlake_crtc_prepare(struct drm_crtc *crtc)
> -{
> -	ironlake_crtc_disable(crtc);
> -}
> -
> -static void ironlake_crtc_commit(struct drm_crtc *crtc)
> -{
> -	ironlake_crtc_enable(crtc);
> -}
> -
>  void intel_encoder_prepare(struct drm_encoder *encoder)
>  {
>  	struct drm_encoder_helper_funcs *encoder_funcs =
> encoder->helper_private; @@ -6626,13 +6598,8 @@ static void
> intel_crtc_init(struct drm_device *dev, int pipe) intel_crtc->active
> = true; /* force the pipe off on setup_init_config */ intel_crtc->bpp
> = 24; /* default for pre-Ironlake */ 
> -	if (HAS_PCH_SPLIT(dev)) {
> -		intel_helper_funcs.prepare = ironlake_crtc_prepare;
> -		intel_helper_funcs.commit = ironlake_crtc_commit;
> -	} else {
> -		intel_helper_funcs.prepare = i9xx_crtc_prepare;
> -		intel_helper_funcs.commit = i9xx_crtc_commit;
> -	}
> +	intel_helper_funcs.prepare = dev_priv->display.crtc_disable;
> +	intel_helper_funcs.commit = dev_priv->display.crtc_enable;
>  
>  	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
>  }


Looks fine.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 03/58] drm/i915: add direct encoder disable/enable infrastructure
  2012-08-19 19:12 ` [PATCH 03/58] drm/i915: add direct encoder disable/enable infrastructure Daniel Vetter
@ 2012-08-29 18:01   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-08-29 18:01 UTC (permalink / raw)
  To: intel-gfx

On Sun, 19 Aug 2012 21:12:20 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 38
> ++++++++++++++++++++++++++++++++++--
> drivers/gpu/drm/i915/intel_drv.h     |  2 ++ 2 files changed, 38
> insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c index 04bec4b..82aaded 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3209,13 +3209,16 @@ static void ironlake_crtc_enable(struct
> drm_crtc *crtc) struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	struct intel_encoder *encoder;
>  	int pipe = intel_crtc->pipe;
>  	int plane = intel_crtc->plane;
>  	u32 temp;
>  	bool is_pch_port;
>  
> +	/* XXX: For compatability with the crtc helper code, call
> the encoder's
> +	 * enable function unconditionally for now. */
>  	if (intel_crtc->active)
> -		return;
> +		goto encoders;
>  
>  	intel_crtc->active = true;
>  	intel_update_watermarks(dev);
> @@ -3262,6 +3265,12 @@ static void ironlake_crtc_enable(struct
> drm_crtc *crtc) mutex_unlock(&dev->struct_mutex);
>  
>  	intel_crtc_update_cursor(crtc, true);
> +
> +encoders:
> +	for_each_encoder_on_crtc(dev, crtc, encoder) {
> +		if (encoder->enable)
> +			encoder->enable(encoder);
> +	}
>  }
>  
>  static void ironlake_crtc_disable(struct drm_crtc *crtc)
> @@ -3269,10 +3278,18 @@ static void ironlake_crtc_disable(struct
> drm_crtc *crtc) struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	struct intel_encoder *encoder;
>  	int pipe = intel_crtc->pipe;
>  	int plane = intel_crtc->plane;
>  	u32 reg, temp;
>  
> +	/* XXX: For compatability with the crtc helper code, call
> the encoder's
> +	 * disable function unconditionally for now. */
> +	for_each_encoder_on_crtc(dev, crtc, encoder) {
> +		if (encoder->disable)
> +			encoder->disable(encoder);
> +	}
> +
>  	if (!intel_crtc->active)
>  		return;
>  
> @@ -3371,11 +3388,14 @@ static void i9xx_crtc_enable(struct drm_crtc
> *crtc) struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	struct intel_encoder *encoder;
>  	int pipe = intel_crtc->pipe;
>  	int plane = intel_crtc->plane;
>  
> +	/* XXX: For compatability with the crtc helper code, call
> the encoder's
> +	 * enable function unconditionally for now. */
>  	if (intel_crtc->active)
> -		return;
> +		goto encoders;
>  
>  	intel_crtc->active = true;
>  	intel_update_watermarks(dev);
> @@ -3390,6 +3410,12 @@ static void i9xx_crtc_enable(struct drm_crtc
> *crtc) /* Give the overlay scaler a chance to enable if it's on this
> pipe */ intel_crtc_dpms_overlay(intel_crtc, true);
>  	intel_crtc_update_cursor(crtc, true);
> +
> +encoders:
> +	for_each_encoder_on_crtc(dev, crtc, encoder) {
> +		if (encoder->enable)
> +			encoder->enable(encoder);
> +	}
>  }
>  
>  static void i9xx_crtc_disable(struct drm_crtc *crtc)
> @@ -3397,9 +3423,17 @@ static void i9xx_crtc_disable(struct drm_crtc
> *crtc) struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	struct intel_encoder *encoder;
>  	int pipe = intel_crtc->pipe;
>  	int plane = intel_crtc->plane;
>  
> +	/* XXX: For compatability with the crtc helper code, call
> the encoder's
> +	 * disable function unconditionally for now. */
> +	for_each_encoder_on_crtc(dev, crtc, encoder) {
> +		if (encoder->disable)
> +			encoder->disable(encoder);
> +	}
> +
>  	if (!intel_crtc->active)
>  		return;
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h
> b/drivers/gpu/drm/i915/intel_drv.h index 95f635b..9a5adcc 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;
>  };
>  


Yep, looks good.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

^ permalink raw reply	[flat|nested] 173+ messages in thread

* [PATCH] drm/i915: no longer call drm_helper_resume_force_mode
  2012-08-19 19:13 ` [PATCH 57/58] drm/i915: disable all crtcs at suspend time Daniel Vetter
@ 2012-08-29 21:13   ` Daniel Vetter
  2012-09-05 18:31     ` Jesse Barnes
  2012-09-05 18:29   ` [PATCH 57/58] drm/i915: disable all crtcs at suspend time Jesse Barnes
  1 sibling, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-29 21:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Since this only calls crtc helper functions, of which a shocking
amount are NULL.

Now the curious thing is how the new modeset code worked with this
function call still present:

Thanks to the hw state readout and the suspend fixes to properly
quiescent the register state, nothing is actually enabled at resume
(if the bios doesn't set up anything). Which means resume_force_mode
doesn't actually do anything and hence nothing blows up at resume
time.

The other reason things do work is that the fbcon layer has it's own
resume notifier callback, which restores the mode. And thanks to the
force vt switch at suspend/resume, that then forces X to restore it's
own mode.

Hence everything still worked (as long as the bios doesn't enable
anything). And we can just kill the call to resume_force_mode.

The upside of both this patch and the preceeding patch to quiescent
the modeset state is that our resume path is much simpler:
- We now longer restore bogus register values (which most often would
  enable the backlight a bit and a few ports), causing flickering.
- We now longer call resume_force_mode to restore a mode that the
  fbcon layer would overwrite right away anyway.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index fe7512a..cd6697c 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -549,11 +549,6 @@ static int i915_drm_thaw(struct drm_device *dev)
 		intel_modeset_setup_hw_state(dev);
 		drm_mode_config_reset(dev);
 		drm_irq_install(dev);
-
-		/* Resume the modeset for every activated CRTC */
-		mutex_lock(&dev->mode_config.mutex);
-		drm_helper_resume_force_mode(dev);
-		mutex_unlock(&dev->mode_config.mutex);
 	}
 
 	intel_opregion_init(dev);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-29 12:26                 ` Lespiau, Damien
@ 2012-08-30 10:40                   ` Rodrigo Vivi
  0 siblings, 0 replies; 173+ messages in thread
From: Rodrigo Vivi @ 2012-08-30 10:40 UTC (permalink / raw)
  To: Lespiau, Damien; +Cc: Intel Graphics Development

I forgot to say that I tested tv out here on 945GME Express and
82945G/GZ and it worked fine as well. No regression.

On Wed, Aug 29, 2012 at 9:26 AM, Lespiau, Damien
<damien.lespiau@intel.com> wrote:
> On Thu, Aug 23, 2012 at 11:39 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
>> On Thu, Aug 23, 2012 at 01:26:39PM +0100, Lespiau, Damien wrote:
>>> On Wed, Aug 22, 2012 at 10:21 PM, Daniel Vetter <daniel@ffwll.ch> wrote:
>>> > Please test the for-damien branch in my personal fdo git repo. I'm rather
>>> > positive that the patch there should fix this (but in the least it should
>>> > unearth the real culprit).
>
> After a bit of back and forth and the updated 50/58 patch, does not
> regress any more here with the testing done on an IVB system.
>
> Tested-by:  Damien Lespiau <damien.lespiau@intel.com>
>
> --
> Damien
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br

^ permalink raw reply	[flat|nested] 173+ messages in thread

* [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing
  2012-08-19 19:13 ` [PATCH 56/58] drm/i915: push commit_output_state past the crtc/encoder preparing Daniel Vetter
@ 2012-08-31 18:12   ` Daniel Vetter
  2012-09-04 19:32     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-31 18:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 108 +++++++++++++++++++++++------------
 1 file changed, 70 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index dd2098a..991f8e8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3221,10 +3221,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	WARN_ON(!crtc->enabled);
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * enable function unconditionally for now. */
 	if (intel_crtc->active)
-		goto encoders;
+		return;
 
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
@@ -3272,7 +3270,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	intel_crtc_update_cursor(crtc, true);
 
-encoders:
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
 
@@ -3290,14 +3287,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	int plane = intel_crtc->plane;
 	u32 reg, temp;
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * disable function unconditionally for now. */
-	for_each_encoder_on_crtc(dev, crtc, encoder)
-		encoder->disable(encoder);
 
 	if (!intel_crtc->active)
 		return;
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
+
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
@@ -3399,10 +3395,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
 	WARN_ON(!crtc->enabled);
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * enable function unconditionally for now. */
 	if (intel_crtc->active)
-		goto encoders;
+		return;
 
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
@@ -3418,7 +3412,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_dpms_overlay(intel_crtc, true);
 	intel_crtc_update_cursor(crtc, true);
 
-encoders:
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
 }
@@ -3432,14 +3425,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * disable function unconditionally for now. */
-	for_each_encoder_on_crtc(dev, crtc, encoder)
-		encoder->disable(encoder);
 
 	if (!intel_crtc->active)
 		return;
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
+
 	/* Give the overlay scaler a chance to disable if it's on this pipe */
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
@@ -6631,18 +6623,6 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
 	return false;
 }
 
-static void
-intel_crtc_prepare_encoders(struct drm_device *dev)
-{
-	struct intel_encoder *encoder;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
-		/* Disable unused encoders */
-		if (encoder->base.crtc == NULL)
-			encoder->disable(encoder);
-	}
-}
-
 /**
  * intel_modeset_update_staged_output_state
  *
@@ -6822,6 +6802,60 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
 	*prepare_pipes &= ~(*disable_pipes);
 }
 
+static bool intel_crtc_in_use(struct drm_crtc *crtc)
+{
+	struct drm_encoder *encoder;
+	struct drm_device *dev = crtc->dev;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+		if (encoder->crtc == crtc)
+			return true;
+
+	return false;
+}
+
+static void
+intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
+{
+	struct intel_encoder *intel_encoder;
+	struct intel_crtc *intel_crtc;
+	struct drm_connector *connector;
+
+	list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		if (!intel_encoder->base.crtc)
+			continue;
+
+		intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
+
+		if (prepare_pipes & (1 << intel_crtc->pipe))
+			intel_encoder->connectors_active = false;
+	}
+
+	intel_modeset_commit_output_state(dev);
+
+	/* Update computed 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);
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (!connector->encoder || !connector->encoder->crtc)
+			continue;
+
+		intel_crtc = to_intel_crtc(connector->encoder->crtc);
+
+		if (prepare_pipes & (1 << intel_crtc->pipe)) {
+			connector->dpms = DRM_MODE_DPMS_ON;
+
+			intel_encoder = to_intel_encoder(connector->encoder);
+			intel_encoder->connectors_active = true;
+		}
+	}
+
+}
+
 #define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
 	list_for_each_entry((intel_crtc), \
 			    &(dev)->mode_config.crtc_list, \
@@ -6850,12 +6884,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
 		intel_crtc_disable(&intel_crtc->base);
 
-	intel_modeset_commit_output_state(dev);
-
-	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
-			    base.head)
-		intel_crtc->base.enabled = drm_helper_crtc_in_use(crtc);
-
 	saved_hwmode = crtc->hwmode;
 	saved_mode = crtc->mode;
 
@@ -6870,12 +6898,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		if (IS_ERR(adjusted_mode)) {
 			return false;
 		}
-
-		intel_crtc_prepare_encoders(dev);
 	}
 
-	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
-		dev_priv->display.crtc_disable(&intel_crtc->base);
+	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
+		if (intel_crtc->base.enabled)
+			dev_priv->display.crtc_disable(&intel_crtc->base);
+	}
 
 	if (modeset_pipes) {
 		crtc->mode = *mode;
@@ -6883,6 +6911,10 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		crtc->y = y;
 	}
 
+	/* Only after disabling all output pipelines that will be changed can we
+	 * update the the output configuration. */
+	intel_modeset_update_state(dev, prepare_pipes);
+
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 1/2] drm/i915: add tons of modeset state checks
  2012-08-20 12:22   ` Daniel Vetter
@ 2012-08-31 18:12     ` Daniel Vetter
  2012-08-31 18:12       ` [PATCH 2/2] drm/i915: improve modeset state checking after dpms calls Daniel Vetter
  2012-09-05 18:33       ` [PATCH 1/2] drm/i915: add tons of modeset state checks Jesse Barnes
  0 siblings, 2 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-08-31 18:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

... let's see whether this catches anything earlier and I can track
down a few bugs.

v2: Add more checks and also add DRM_DEBUG_KMS output so that it's
clear which connector/encoder/crtc is being checked atm. Which proved
rather useful for debugging ...

v3: Add a WARN in the common encoder dpms function, now that also
modeset changes properly update the dpms state ...

v4: Properly add a short explanation for each WARN, to avoid the need
to correlate dmesg lines with source lines accurately. Suggested by
Chris Wilson.

v5: Also dump (expected, found) for state checks (or wherever it's not
apparent from the test what exactly mismatches with expectations).
Again suggested by Chris Wilson.

v6: Due to an issue reported by Paulo Zanoni I've noticed that the
encoder checking is by far not as strict as it could and should be.
Improve this.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 104 ++++++++++++++++++++++++++++++++++-
 1 file changed, 103 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5c672ed..e703413 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3637,7 +3637,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
 	if (encoder->base.crtc)
 		intel_encoder_dpms(encoder, mode);
 	else
-		encoder->connectors_active = false;
+		WARN_ON(encoder->connectors_active != false);
 
 	intel_connector_check_state(to_intel_connector(connector));
 }
@@ -6872,6 +6872,104 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 			    base.head) \
 		if (mask & (1 <<(intel_crtc)->pipe)) \
 
+static void
+intel_modeset_check_state(struct drm_device *dev)
+{
+	struct intel_crtc *crtc;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		/* This also checks the encoder/connector hw state with the
+		 * ->get_hw_state callbacks. */
+		intel_connector_check_state(connector);
+
+		WARN(&connector->new_encoder->base != connector->base.encoder,
+		     "connector's staged encoder doesn't match current encoder\n");
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		bool enabled = false;
+		bool active = false;
+		enum pipe pipe, tracked_pipe;
+
+		DRM_DEBUG_KMS("[ENCODER:%d:%s]\n",
+			      encoder->base.base.id,
+			      drm_get_encoder_name(&encoder->base));
+
+		WARN(&encoder->new_crtc->base != encoder->base.crtc,
+		     "encoder's stage crtc doesn't match current crtc\n");
+		WARN(encoder->connectors_active && !encoder->base.crtc,
+		     "encoder's active_connectors set, but no crtc\n");
+
+		list_for_each_entry(connector, &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->base.encoder != &encoder->base)
+				continue;
+			enabled = true;
+			if (connector->base.dpms != DRM_MODE_DPMS_OFF)
+				active = true;
+		}
+		WARN(!!encoder->base.crtc != enabled,
+		     "encoder's enabled state mismatch "
+		     "(expected %i, found %i)\n",
+		     !!encoder->base.crtc, enabled);
+		WARN(active && !encoder->base.crtc,
+		     "active encoder with no crtc\n");
+
+		WARN(encoder->connectors_active != active,
+		     "encoder's computed active state doesn't match tracked active state "
+		     "(expected %i, found %i)\n", active, encoder->connectors_active);
+
+		active = encoder->get_hw_state(encoder, &pipe);
+		WARN(active != encoder->connectors_active,
+		     "encoder's hw state doesn't match sw tracking "
+		     "(expected %i, found %i)\n",
+		     encoder->connectors_active, active);
+
+		if (!encoder->base.crtc)
+			continue;
+
+		tracked_pipe = to_intel_crtc(encoder->base.crtc)->pipe;
+		WARN(active && pipe != tracked_pipe,
+		     "active encoder's pipe doesn't match"
+		     "(expected %i, found %i)\n",
+		     tracked_pipe, pipe);
+
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		bool enabled = false;
+		bool active = false;
+
+		DRM_DEBUG_KMS("[CRTC:%d]\n",
+			      crtc->base.base.id);
+
+		WARN(crtc->active && !crtc->base.enabled,
+		     "active crtc, but not enabled in sw tracking\n");
+
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+				    base.head) {
+			if (encoder->base.crtc != &crtc->base)
+				continue;
+			enabled = true;
+			if (encoder->connectors_active)
+				active = true;
+		}
+		WARN(active != crtc->active,
+		     "crtc's computed active state doesn't match tracked active state "
+		     "(expected %i, found %i)\n", active, crtc->active);
+		WARN(enabled != crtc->base.enabled,
+		     "crtc's computed enabled state doesn't match tracked enabled state "
+		     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
+
+		assert_pipe(dev->dev_private, crtc->pipe, crtc->active);
+	}
+}
+
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
 		    int x, int y, struct drm_framebuffer *fb)
@@ -6969,6 +7067,8 @@ done:
 	if (!ret && crtc->enabled) {
 		crtc->hwmode = saved_hwmode;
 		crtc->mode = saved_mode;
+	} else {
+		intel_modeset_check_state(dev);
 	}
 
 	return ret;
@@ -8166,6 +8266,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
 	}
 
 	intel_modeset_update_staged_output_state(dev);
+
+	intel_modeset_check_state(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* [PATCH 2/2] drm/i915: improve modeset state checking after dpms calls
  2012-08-31 18:12     ` [PATCH 1/2] " Daniel Vetter
@ 2012-08-31 18:12       ` Daniel Vetter
  2012-09-05 18:34         ` Jesse Barnes
  2012-09-05 18:33       ` [PATCH 1/2] drm/i915: add tons of modeset state checks Jesse Barnes
  1 sibling, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-08-31 18:12 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Now that we have solid modeset state tracking and checking code in
place, we can do the Full Monty also after dpms calls.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_crt.c     | 2 +-
 drivers/gpu/drm/i915/intel_display.c | 6 +++---
 drivers/gpu/drm/i915/intel_dp.c      | 2 +-
 drivers/gpu/drm/i915/intel_drv.h     | 3 ++-
 drivers/gpu/drm/i915/intel_dvo.c     | 2 +-
 drivers/gpu/drm/i915/intel_sdvo.c    | 2 +-
 6 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index cca266f..b9f08f6 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -177,7 +177,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
 		intel_crtc_update_dpms(crtc);
 	}
 
-	intel_connector_check_state(to_intel_connector(connector));
+	intel_modeset_check_state(connector->dev);
 }
 
 static int intel_crt_mode_valid(struct drm_connector *connector,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e703413..77191d8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3585,7 +3585,7 @@ void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
 
 /* Cross check the actual hw state with our own modeset state tracking (and it's
  * internal consistency). */
-void intel_connector_check_state(struct intel_connector *connector)
+static void intel_connector_check_state(struct intel_connector *connector)
 {
 	if (connector->get_hw_state(connector)) {
 		struct intel_encoder *encoder = connector->encoder;
@@ -3639,7 +3639,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
 	else
 		WARN_ON(encoder->connectors_active != false);
 
-	intel_connector_check_state(to_intel_connector(connector));
+	intel_modeset_check_state(connector->dev);
 }
 
 /* Simple connector->get_hw_state implementation for encoders that support only
@@ -6872,7 +6872,7 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 			    base.head) \
 		if (mask & (1 <<(intel_crtc)->pipe)) \
 
-static void
+void
 intel_modeset_check_state(struct drm_device *dev)
 {
 	struct intel_crtc *crtc;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3b1c407..d391e67 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1362,7 +1362,7 @@ intel_dp_dpms(struct drm_connector *connector, int mode)
 		intel_encoder_dpms(&intel_dp->base, mode);
 	}
 
-	intel_connector_check_state(to_intel_connector(connector));
+	intel_modeset_check_state(connector->dev);
 }
 
 /*
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 71c1517..1225bc5 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -459,7 +459,8 @@ extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode);
 extern bool intel_encoder_check_non_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)
 {
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index aa1bf57..4f1fdcc 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -189,7 +189,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
 		intel_crtc_update_dpms(crtc);
 	}
 
-	intel_connector_check_state(to_intel_connector(connector));
+	intel_modeset_check_state(connector->dev);
 }
 
 static int intel_dvo_mode_valid(struct drm_connector *connector,
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 6f53871..07d3921 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1275,7 +1275,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
 		intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
 	}
 
-	intel_connector_check_state(to_intel_connector(connector));
+	intel_modeset_check_state(connector->dev);
 }
 
 static int intel_sdvo_mode_valid(struct drm_connector *connector,
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (62 preceding siblings ...)
  2012-08-27  8:04 ` Vijay Purushothaman
@ 2012-09-03 17:50 ` Paulo Zanoni
  2012-09-05 23:23 ` Jesse Barnes
  2012-09-06 21:00 ` Daniel Vetter
  65 siblings, 0 replies; 173+ messages in thread
From: Paulo Zanoni @ 2012-09-03 17:50 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

Hi

2012/8/19 Daniel Vetter <daniel.vetter@ffwll.ch>:
> Hi all,
>
> Changes since last time around:
> - The prep patches are all merged now.
> - I've left out the actual DP fixes/cleanups, I think we should merge those in a
>   separte step.
> - A few bugfixes (thanks to Paulo, Jani and Chris).
> - I've also applied a few bikesheds for naming that Paulo suggested (but I'm not
>   sure whether I've sent those out already in a previous patchbomb).
>
> Essentially this is just the core rework, which addes the new get_hw_state code,
> refactors all the encoders to use the new functions and finally reworks the
> modeset logic to disable/enable entire pipes, always (and with a deterministic
> order).
>
> For merging to -next, I plan to pull in everything with a real merge commit. For
> that reason I've put up a modeset-rework-base branch onto my private fdo repo[1].
> That way I can put a short documentation for the new modeset design into the
> merge commit (stichted together from the previous patchbomb cover letters),
> documenting my folly assumptions for eternity.
>
> I'll also plan to put tags for the entire series in the merge commit, so if you
> have tested this on a few machines, read through and agree with the new designs,
> please reply with your tested-by/acked-by/reviewed-by tags.
>
> Flames, comments and test reports highly welcome.

I am currently using this branch and developing patches on top of it,
so I'm reporting the problems I'm finding to Daniel and he's fixing
them :)

So for now I guess we can say:
Being-tested-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

I read some of the patches and some of the code, but I did not
carefully review all the patches (although I am developing display
stuff on top of the branch), and I do like the idea of the branch, so
at least:
Acked-by: Paulo Zanoni <paulo.r.zanoni@intel.com>


>
> Cheers, Daniel
>
> [1] http://cgit.freedesktop.org/~danvet/drm/log/?h=modeset-rework-base
>
> Daniel Vetter (58):
>   drm/i915: add crtc->enable/disable vfuncs insted of dpms
>   drm/i915: rip out crtc prepare/commit indirection
>   drm/i915: add direct encoder disable/enable infrastructure
>   drm/i915/hdmi: convert to encoder->disable/enable
>   drm/i915/tv: convert to encoder enable/disable
>   drm/i915/lvds: convert to encoder disable/enable
>   drm/i915/dp: convert to encoder disable/enable
>   drm/i915/crt: convert to encoder disable/enable
>   drm/i915/sdvo: convert to encoder disable/enable
>   drm/i915/dvo: convert to encoder disable/enable
>   drm/i915: convert dpms functions of dvo/sdvo/crt
>   drm/i915: rip out encoder->disable/enable checks
>   drm/i915: clean up encoder_prepare/commit
>   drm/i915: copy&paste drm_crtc_helper_set_config
>   drm/i915: call set_base directly
>   drm/i915: inline intel_best_encoder
>   drm/i915: copy&paste drm_crtc_helper_set_mode
>   drm/i915: simplify intel_crtc_prepare_encoders
>   drm/i915: rip out encoder->prepare/commit
>   drm/i915: call crtc functions directly
>   drm/i915: WARN when trying to enabled an unused crtc
>   drm/i915: Add interfaces to read out encoder/connector hw state
>   drm/i915/dp: implement get_hw_state
>   drm/i915/hdmi: implement get_hw_state
>   drm/i915/tv: implement get_hw_state
>   drm/i915/lvds: implement get_hw_state
>   drm/i915/crt: implement get_hw_state
>   drm/i915/sdvo: implement get_hw_state
>   drm/i915/dvo: implement get_hw_state
>   drm/i915: read out the modeset hw state at load and resume time
>   drm/i915: check connector hw/sw state
>   drm/i915: rip out intel_crtc->dpms_mode
>   drm/i915: rip out intel_dp->dpms_mode
>   drm/i915: ensure the force pipe A quirk is actually followed
>   drm/i915: introduce struct intel_set_config
>   drm/i915: extract modeset config save/restore code
>   drm/i915: extract intel_set_config_compute_mode_changes
>   drm/i915: extract intel_set_config_update_output_state
>   drm/i915: implement crtc helper semantics relied upon by the fb
>     helper
>   drm/i915: don't update the fb base if there is no fb
>   drm/i915: convert pointless error checks in set_config to BUGs
>   drm/i915: don't save all the encoder/crtc state in set_config
>   drm/i915: stage modeset output changes
>   drm/i915: push crtc->fb update into pipe_set_base
>   drm/i915: remove crtc disabling special case
>   drm/i915: move output commit and crtc disabling into set_mode
>   drm/i915: extract adjusted mode computation
>   drm/i915: use staged outuput config in tv->mode_fixup
>   drm/i915: use staged outuput config in lvds->mode_fixup
>   drm/i915: compute masks of crtcs affected in set_mode
>   drm/i915: implement new set_mode code flow
>   drm/i915: push commit_output_state past crtc disabling
>   drm/i915: s/intel_encoder_disable/intel_encoder_noop
>   drm/i915: WARN if the pipe won't turn off
>   drm/i915: switch the load detect code to the staged modeset config
>   drm/i915: push commit_output_state past the crtc/encoder preparing
>   drm/i915: disable all crtcs at suspend time
>   drm/i915: add tons of modeset state checks
>
>  drivers/gpu/drm/i915/dvo.h           |    6 +
>  drivers/gpu/drm/i915/dvo_ch7017.c    |   13 +
>  drivers/gpu/drm/i915/dvo_ch7xxx.c    |   13 +
>  drivers/gpu/drm/i915/dvo_ivch.c      |   15 +
>  drivers/gpu/drm/i915/dvo_ns2501.c    |   15 +
>  drivers/gpu/drm/i915/dvo_sil164.c    |   16 +
>  drivers/gpu/drm/i915/dvo_tfp410.c    |   14 +
>  drivers/gpu/drm/i915/i915_drv.c      |    4 +
>  drivers/gpu/drm/i915/i915_drv.h      |    4 +-
>  drivers/gpu/drm/i915/i915_reg.h      |    2 +
>  drivers/gpu/drm/i915/intel_crt.c     |  136 ++-
>  drivers/gpu/drm/i915/intel_ddi.c     |   59 +-
>  drivers/gpu/drm/i915/intel_display.c | 1499 ++++++++++++++++++++++++++++------
>  drivers/gpu/drm/i915/intel_dp.c      |  144 ++--
>  drivers/gpu/drm/i915/intel_drv.h     |   64 +-
>  drivers/gpu/drm/i915/intel_dvo.c     |   94 ++-
>  drivers/gpu/drm/i915/intel_hdmi.c    |  151 +++-
>  drivers/gpu/drm/i915/intel_lvds.c    |   95 +--
>  drivers/gpu/drm/i915/intel_sdvo.c    |  164 +++-
>  drivers/gpu/drm/i915/intel_tv.c      |   61 +-
>  20 files changed, 2044 insertions(+), 525 deletions(-)
>
> --
> 1.7.11.2
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 04/58] drm/i915/hdmi: convert to encoder->disable/enable
  2012-08-19 19:12 ` [PATCH 04/58] drm/i915/hdmi: convert to encoder->disable/enable Daniel Vetter
@ 2012-09-04 19:24   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 19:24 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:21 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> +/* Even simpler default implementation, if there's really no special case to
> + * consider. */
> +void intel_connector_dpms(struct drm_connector *connector, int mode)
> +{
> +	struct intel_encoder *encoder = intel_attached_encoder(connector);
> +
> +	/* All the simple cases only support two dpms states. */
> +	if (mode != DRM_MODE_DPMS_ON)
> +		mode = DRM_MODE_DPMS_OFF;
> +
> +	if (mode == connector->dpms)
> +		return;
> +
> +	connector->dpms = mode;
> +
> +	/* Only need to change hw state when actually enabled */
> +	if (encoder->base.crtc)
> +		intel_encoder_dpms(encoder, mode);
> +	else
> +		encoder->connectors_active = false;
> +}

We only ever call this under the mode_config lock right?

> +
>  static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
>  				  const struct drm_display_mode *mode,
>  				  struct drm_display_mode *adjusted_mode)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 9a5adcc..759dcba 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);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index e4c37bb..acddaaa 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -601,11 +601,11 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
>  	intel_hdmi->set_infoframes(encoder, adjusted_mode);
>  }
>  
> -static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
> +static void intel_enable_hdmi(struct intel_encoder *encoder)
>  {
> -	struct drm_device *dev = encoder->dev;
> +	struct drm_device *dev = encoder->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
> +	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
>  	u32 temp;
>  	u32 enable_bits = SDVO_ENABLE;
>  
> @@ -617,31 +617,12 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
>  	/* HW workaround for IBX, we need to move the port to transcoder A
>  	 * before disabling it. */
>  	if (HAS_PCH_IBX(dev)) {
> -		struct drm_crtc *crtc = encoder->crtc;
> +		struct drm_crtc *crtc = encoder->base.crtc;
>  		int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
>  
> -		if (mode != DRM_MODE_DPMS_ON) {
> -			if (temp & SDVO_PIPE_B_SELECT) {
> -				temp &= ~SDVO_PIPE_B_SELECT;
> -				I915_WRITE(intel_hdmi->sdvox_reg, temp);
> -				POSTING_READ(intel_hdmi->sdvox_reg);
> -
> -				/* Again we need to write this twice. */
> -				I915_WRITE(intel_hdmi->sdvox_reg, temp);
> -				POSTING_READ(intel_hdmi->sdvox_reg);
> -
> -				/* Transcoder selection bits only update
> -				 * effectively on vblank. */
> -				if (crtc)
> -					intel_wait_for_vblank(dev, pipe);
> -				else
> -					msleep(50);
> -			}
> -		} else {
> -			/* Restore the transcoder select bit. */
> -			if (pipe == PIPE_B)
> -				enable_bits |= SDVO_PIPE_B_SELECT;
> -		}
> +		/* Restore the transcoder select bit. */
> +		if (pipe == PIPE_B)
> +			enable_bits |= SDVO_PIPE_B_SELECT;
>  	}
>  
>  	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
> @@ -652,12 +633,67 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
>  		POSTING_READ(intel_hdmi->sdvox_reg);
>  	}
>  
> -	if (mode != DRM_MODE_DPMS_ON) {
> -		temp &= ~enable_bits;
> -	} else {
> -		temp |= enable_bits;
> +	temp |= enable_bits;
> +
> +	I915_WRITE(intel_hdmi->sdvox_reg, temp);
> +	POSTING_READ(intel_hdmi->sdvox_reg);
> +
> +	/* HW workaround, need to write this twice for issue that may result
> +	 * in first write getting masked.
> +	 */
> +	if (HAS_PCH_SPLIT(dev)) {
> +		I915_WRITE(intel_hdmi->sdvox_reg, temp);
> +		POSTING_READ(intel_hdmi->sdvox_reg);
> +	}
> +}
> +
> +static void intel_disable_hdmi(struct intel_encoder *encoder)
> +{
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
> +	u32 temp;
> +	u32 enable_bits = SDVO_ENABLE;
> +
> +	if (intel_hdmi->has_audio)
> +		enable_bits |= SDVO_AUDIO_ENABLE;
> +
> +	temp = I915_READ(intel_hdmi->sdvox_reg);
> +
> +	/* HW workaround for IBX, we need to move the port to transcoder A
> +	 * before disabling it. */
> +	if (HAS_PCH_IBX(dev)) {
> +		struct drm_crtc *crtc = encoder->base.crtc;
> +		int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
> +
> +		if (temp & SDVO_PIPE_B_SELECT) {
> +			temp &= ~SDVO_PIPE_B_SELECT;
> +			I915_WRITE(intel_hdmi->sdvox_reg, temp);
> +			POSTING_READ(intel_hdmi->sdvox_reg);
> +
> +			/* Again we need to write this twice. */
> +			I915_WRITE(intel_hdmi->sdvox_reg, temp);
> +			POSTING_READ(intel_hdmi->sdvox_reg);
> +
> +			/* Transcoder selection bits only update
> +			 * effectively on vblank. */
> +			if (crtc)
> +				intel_wait_for_vblank(dev, pipe);
> +			else
> +				msleep(50);
> +		}
>  	}

The IBX stuff can be split out into a separate function hook with a
later patch...

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 05/58] drm/i915/tv: convert to encoder enable/disable
  2012-08-19 19:12 ` [PATCH 05/58] drm/i915/tv: convert to encoder enable/disable Daniel Vetter
@ 2012-09-04 19:25   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 19:25 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:22 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Like hdmi tv outputs are simple: They only have 2 states and can't be
> cloned. Hence give it the same treatment.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_tv.c | 35 +++++++++++++++++++----------------
>  1 file changed, 19 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
> index 95653a5..281e0cf 100644
> --- a/drivers/gpu/drm/i915/intel_tv.c
> +++ b/drivers/gpu/drm/i915/intel_tv.c
> @@ -837,21 +837,21 @@ static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
>  }
>  
>  static void
> -intel_tv_dpms(struct drm_encoder *encoder, int mode)
> +intel_enable_tv(struct intel_encoder *encoder)
>  {
> -	struct drm_device *dev = encoder->dev;
> +	struct drm_device *dev = encoder->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> -	switch (mode) {
> -	case DRM_MODE_DPMS_ON:
> -		I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
> -		break;
> -	case DRM_MODE_DPMS_STANDBY:
> -	case DRM_MODE_DPMS_SUSPEND:
> -	case DRM_MODE_DPMS_OFF:
> -		I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE);
> -		break;
> -	}
> +	I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
> +}
> +
> +static void
> +intel_disable_tv(struct intel_encoder *encoder)
> +{
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE);
>  }
>  
>  static const struct tv_mode *
> @@ -1478,15 +1478,15 @@ out:
>  }
>  
>  static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
> -	.dpms = intel_tv_dpms,
>  	.mode_fixup = intel_tv_mode_fixup,
> -	.prepare = intel_encoder_prepare,
> +	.prepare = intel_encoder_noop,
>  	.mode_set = intel_tv_mode_set,
> -	.commit = intel_encoder_commit,
> +	.commit = intel_encoder_noop,
> +	.disable = intel_encoder_disable,
>  };
>  
>  static const struct drm_connector_funcs intel_tv_connector_funcs = {
> -	.dpms = drm_helper_connector_dpms,
> +	.dpms = intel_connector_dpms,
>  	.detect = intel_tv_detect,
>  	.destroy = intel_tv_destroy,
>  	.set_property = intel_tv_set_property,
> @@ -1616,6 +1616,9 @@ intel_tv_init(struct drm_device *dev)
>  	drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
>  			 DRM_MODE_ENCODER_TVDAC);
>  
> +	intel_encoder->enable = intel_enable_tv;
> +	intel_encoder->disable = intel_disable_tv;
> +
>  	intel_connector_attach_encoder(intel_connector, intel_encoder);
>  	intel_encoder->type = INTEL_OUTPUT_TVOUT;
>  	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 06/58] drm/i915/lvds: convert to encoder disable/enable
  2012-08-19 19:12 ` [PATCH 06/58] drm/i915/lvds: convert to encoder disable/enable Daniel Vetter
@ 2012-09-04 19:26   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 19:26 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:23 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> With the previous patch LVDS is also a simple case. Treat it
> accordingly.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_lvds.c | 52 +++++++++++----------------------------
>  1 file changed, 14 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index d789fda..3baa224 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -68,10 +68,11 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
>  /**
>   * Sets the power state for the panel.
>   */
> -static void intel_lvds_enable(struct intel_lvds *intel_lvds)
> +static void intel_enable_lvds(struct intel_encoder *encoder)
>  {
> -	struct drm_device *dev = intel_lvds->base.base.dev;
> -	struct intel_crtc *intel_crtc = to_intel_crtc(intel_lvds->base.base.crtc);
> +	struct drm_device *dev = encoder->base.dev;
> +	struct intel_lvds *intel_lvds = to_intel_lvds(&encoder->base);
> +	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	u32 ctl_reg, lvds_reg, stat_reg;
>  
> @@ -111,9 +112,10 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds)
>  	intel_panel_enable_backlight(dev, intel_crtc->pipe);
>  }
>  
> -static void intel_lvds_disable(struct intel_lvds *intel_lvds)
> +static void intel_disable_lvds(struct intel_encoder *encoder)
>  {
> -	struct drm_device *dev = intel_lvds->base.base.dev;
> +	struct drm_device *dev = encoder->base.dev;
> +	struct intel_lvds *intel_lvds = to_intel_lvds(&encoder->base);
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	u32 ctl_reg, lvds_reg, stat_reg;
>  
> @@ -142,18 +144,6 @@ static void intel_lvds_disable(struct intel_lvds *intel_lvds)
>  	POSTING_READ(lvds_reg);
>  }
>  
> -static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
> -{
> -	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
> -
> -	if (mode == DRM_MODE_DPMS_ON)
> -		intel_lvds_enable(intel_lvds);
> -	else
> -		intel_lvds_disable(intel_lvds);
> -
> -	/* XXX: We never power down the LVDS pairs. */
> -}
> -
>  static int intel_lvds_mode_valid(struct drm_connector *connector,
>  				 struct drm_display_mode *mode)
>  {
> @@ -405,23 +395,6 @@ out:
>  	return true;
>  }
>  
> -static void intel_lvds_prepare(struct drm_encoder *encoder)
> -{
> -	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
> -
> -	intel_lvds_disable(intel_lvds);
> -}
> -
> -static void intel_lvds_commit(struct drm_encoder *encoder)
> -{
> -	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
> -
> -	/* Always do a full power on as we do not know what state
> -	 * we were left in.
> -	 */
> -	intel_lvds_enable(intel_lvds);
> -}
> -
>  static void intel_lvds_mode_set(struct drm_encoder *encoder,
>  				struct drm_display_mode *mode,
>  				struct drm_display_mode *adjusted_mode)
> @@ -596,11 +569,11 @@ static int intel_lvds_set_property(struct drm_connector *connector,
>  }
>  
>  static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
> -	.dpms = intel_lvds_dpms,
>  	.mode_fixup = intel_lvds_mode_fixup,
> -	.prepare = intel_lvds_prepare,
> +	.prepare = intel_encoder_noop,
>  	.mode_set = intel_lvds_mode_set,
> -	.commit = intel_lvds_commit,
> +	.commit = intel_encoder_noop,
> +	.disable = intel_encoder_disable,
>  };
>  
>  static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
> @@ -610,7 +583,7 @@ static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs
>  };
>  
>  static const struct drm_connector_funcs intel_lvds_connector_funcs = {
> -	.dpms = drm_helper_connector_dpms,
> +	.dpms = intel_connector_dpms,
>  	.detect = intel_lvds_detect,
>  	.fill_modes = drm_helper_probe_single_connector_modes,
>  	.set_property = intel_lvds_set_property,
> @@ -964,6 +937,9 @@ bool intel_lvds_init(struct drm_device *dev)
>  	drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
>  			 DRM_MODE_ENCODER_LVDS);
>  
> +	intel_encoder->enable = intel_enable_lvds;
> +	intel_encoder->disable = intel_disable_lvds;
> +
>  	intel_connector_attach_encoder(intel_connector, intel_encoder);
>  	intel_encoder->type = INTEL_OUTPUT_LVDS;
>  

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing
  2012-08-31 18:12   ` [PATCH] " Daniel Vetter
@ 2012-09-04 19:32     ` Daniel Vetter
  2012-09-05 18:28       ` Jesse Barnes
  0 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-09-04 19:32 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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 <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 108 +++++++++++++++++++++++------------
 drivers/gpu/drm/i915/intel_drv.h     |   3 -
 2 files changed, 70 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2c2b4873..c3ab86b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3221,10 +3221,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	WARN_ON(!crtc->enabled);
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * enable function unconditionally for now. */
 	if (intel_crtc->active)
-		goto encoders;
+		return;
 
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
@@ -3272,7 +3270,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	intel_crtc_update_cursor(crtc, true);
 
-encoders:
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
 
@@ -3290,14 +3287,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	int plane = intel_crtc->plane;
 	u32 reg, temp;
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * disable function unconditionally for now. */
-	for_each_encoder_on_crtc(dev, crtc, encoder)
-		encoder->disable(encoder);
 
 	if (!intel_crtc->active)
 		return;
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
+
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
@@ -3399,10 +3395,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 
 	WARN_ON(!crtc->enabled);
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * enable function unconditionally for now. */
 	if (intel_crtc->active)
-		goto encoders;
+		return;
 
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
@@ -3418,7 +3412,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_dpms_overlay(intel_crtc, true);
 	intel_crtc_update_cursor(crtc, true);
 
-encoders:
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->enable(encoder);
 }
@@ -3432,14 +3425,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
-	/* XXX: For compatability with the crtc helper code, call the encoder's
-	 * disable function unconditionally for now. */
-	for_each_encoder_on_crtc(dev, crtc, encoder)
-		encoder->disable(encoder);
 
 	if (!intel_crtc->active)
 		return;
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
+
 	/* Give the overlay scaler a chance to disable if it's on this pipe */
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
@@ -6631,18 +6623,6 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
 	return false;
 }
 
-static void
-intel_crtc_prepare_encoders(struct drm_device *dev)
-{
-	struct intel_encoder *encoder;
-
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
-		/* Disable unused encoders */
-		if (encoder->base.crtc == NULL)
-			encoder->disable(encoder);
-	}
-}
-
 /**
  * intel_modeset_update_staged_output_state
  *
@@ -6822,6 +6802,60 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
 	*prepare_pipes &= ~(*disable_pipes);
 }
 
+static bool intel_crtc_in_use(struct drm_crtc *crtc)
+{
+	struct drm_encoder *encoder;
+	struct drm_device *dev = crtc->dev;
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+		if (encoder->crtc == crtc)
+			return true;
+
+	return false;
+}
+
+static void
+intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
+{
+	struct intel_encoder *intel_encoder;
+	struct intel_crtc *intel_crtc;
+	struct drm_connector *connector;
+
+	list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		if (!intel_encoder->base.crtc)
+			continue;
+
+		intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
+
+		if (prepare_pipes & (1 << intel_crtc->pipe))
+			intel_encoder->connectors_active = false;
+	}
+
+	intel_modeset_commit_output_state(dev);
+
+	/* Update computed 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);
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (!connector->encoder || !connector->encoder->crtc)
+			continue;
+
+		intel_crtc = to_intel_crtc(connector->encoder->crtc);
+
+		if (prepare_pipes & (1 << intel_crtc->pipe)) {
+			connector->dpms = DRM_MODE_DPMS_ON;
+
+			intel_encoder = to_intel_encoder(connector->encoder);
+			intel_encoder->connectors_active = true;
+		}
+	}
+
+}
+
 #define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
 	list_for_each_entry((intel_crtc), \
 			    &(dev)->mode_config.crtc_list, \
@@ -6850,12 +6884,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
 		intel_crtc_disable(&intel_crtc->base);
 
-	intel_modeset_commit_output_state(dev);
-
-	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
-			    base.head)
-		intel_crtc->base.enabled = drm_helper_crtc_in_use(crtc);
-
 	saved_hwmode = crtc->hwmode;
 	saved_mode = crtc->mode;
 
@@ -6870,12 +6898,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		if (IS_ERR(adjusted_mode)) {
 			return false;
 		}
-
-		intel_crtc_prepare_encoders(dev);
 	}
 
-	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
-		dev_priv->display.crtc_disable(&intel_crtc->base);
+	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
+		if (intel_crtc->base.enabled)
+			dev_priv->display.crtc_disable(&intel_crtc->base);
+	}
 
 	if (modeset_pipes) {
 		crtc->mode = *mode;
@@ -6883,6 +6911,10 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		crtc->y = y;
 	}
 
+	/* Only after disabling all output pipelines that will be changed can we
+	 * update the the output configuration. */
+	intel_modeset_update_state(dev, prepare_pipes);
+
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1282bf0..3e6feae 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? */
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* Re: [PATCH 07/58] drm/i915/dp: convert to encoder disable/enable
  2012-08-19 19:12 ` [PATCH 07/58] drm/i915/dp: " Daniel Vetter
@ 2012-09-04 19:33   ` Jesse Barnes
  2012-09-04 19:42     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 19:33 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:24 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> -static void intel_dp_prepare(struct drm_encoder *encoder)
> +static void intel_disable_dp(struct intel_encoder *encoder)
>  {
> -	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -
> +	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
>  
>  	/* Make sure the panel is off before trying to change the mode. But also
>  	 * ensure that we have vdd while we switch off the panel. */
> @@ -1262,62 +1261,64 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
>  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
>  	ironlake_edp_panel_off(intel_dp);
>  	intel_dp_link_down(intel_dp);
> +
> +	intel_dp->dpms_mode = DRM_MODE_DPMS_OFF;

Is this redundant?  At init time we'll have cleared this, and at
prepare time it ought to be off already right?

>  }
>  
> -static void intel_dp_commit(struct drm_encoder *encoder)
> +static void intel_enable_dp(struct intel_encoder *encoder)
>  {
> -	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -	struct drm_device *dev = encoder->dev;
> -	struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
> +	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
>  
>  	ironlake_edp_panel_vdd_on(intel_dp);
>  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> -	intel_dp_start_link_train(intel_dp);
> -	ironlake_edp_panel_on(intel_dp);
> -	ironlake_edp_panel_vdd_off(intel_dp, true);
> -	intel_dp_complete_link_train(intel_dp);
> +	if (!(dp_reg & DP_PORT_EN)) {
> +		intel_dp_start_link_train(intel_dp);
> +		ironlake_edp_panel_on(intel_dp);
> +		ironlake_edp_panel_vdd_off(intel_dp, true);
> +		intel_dp_complete_link_train(intel_dp);
> +	} else
> +		ironlake_edp_panel_vdd_off(intel_dp, false);

Hm so if we call enable on an already on DP port, we'll just disable
VDD?  But shouldn't it already have been off?

>  	ironlake_edp_backlight_on(intel_dp);
>  
>  	intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
> -
> -	if (HAS_PCH_CPT(dev))
> -		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
>  }
>  
>  static void
> -intel_dp_dpms(struct drm_encoder *encoder, int mode)
> +intel_dp_dpms(struct drm_connector *connector, int mode)
>  {
> -	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -	struct drm_device *dev = encoder->dev;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
> +	struct intel_dp *intel_dp = intel_attached_dp(connector);
> +
> +	/* DP supports only 2 dpms states. */
> +	if (mode != DRM_MODE_DPMS_ON)
> +		mode = DRM_MODE_DPMS_OFF;
> +
> +	if (mode == connector->dpms)
> +		return;
> +
> +	connector->dpms = mode;
> +
> +	/* Only need to change hw state when actually enabled */
> +	if (!intel_dp->base.base.crtc) {
> +		intel_dp->base.connectors_active = false;
> +		return;
> +	}
>  
>  	if (mode != DRM_MODE_DPMS_ON) {
> -		/* Switching the panel off requires vdd. */
> -		ironlake_edp_panel_vdd_on(intel_dp);
> -		ironlake_edp_backlight_off(intel_dp);
> -		intel_dp_sink_dpms(intel_dp, mode);
> -		ironlake_edp_panel_off(intel_dp);
> -		intel_dp_link_down(intel_dp);
> +		intel_encoder_dpms(&intel_dp->base, mode);
> +		WARN_ON(intel_dp->dpms_mode != DRM_MODE_DPMS_OFF);
>  
>  		if (is_cpu_edp(intel_dp))
> -			ironlake_edp_pll_off(encoder);
> +			ironlake_edp_pll_off(&intel_dp->base.base);
>  	} else {
>  		if (is_cpu_edp(intel_dp))
> -			ironlake_edp_pll_on(encoder);
> +			ironlake_edp_pll_on(&intel_dp->base.base);
>  
> -		ironlake_edp_panel_vdd_on(intel_dp);
> -		intel_dp_sink_dpms(intel_dp, mode);
> -		if (!(dp_reg & DP_PORT_EN)) {
> -			intel_dp_start_link_train(intel_dp);
> -			ironlake_edp_panel_on(intel_dp);
> -			ironlake_edp_panel_vdd_off(intel_dp, true);
> -			intel_dp_complete_link_train(intel_dp);
> -		} else
> -			ironlake_edp_panel_vdd_off(intel_dp, false);
> -		ironlake_edp_backlight_on(intel_dp);
> +		intel_encoder_dpms(&intel_dp->base, mode);
> +		WARN_ON(intel_dp->dpms_mode != DRM_MODE_DPMS_ON);
>  	}
> -	intel_dp->dpms_mode = mode;
>  }
>  
>  /*
> @@ -2347,15 +2348,15 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  }
>  
>  static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
> -	.dpms = intel_dp_dpms,
>  	.mode_fixup = intel_dp_mode_fixup,
> -	.prepare = intel_dp_prepare,
> +	.prepare = intel_encoder_noop,
>  	.mode_set = intel_dp_mode_set,
> -	.commit = intel_dp_commit,
> +	.commit = intel_encoder_noop,
> +	.disable = intel_encoder_disable,
>  };
>  
>  static const struct drm_connector_funcs intel_dp_connector_funcs = {
> -	.dpms = drm_helper_connector_dpms,
> +	.dpms = intel_dp_dpms,
>  	.detect = intel_dp_detect,
>  	.fill_modes = drm_helper_probe_single_connector_modes,
>  	.set_property = intel_dp_set_property,
> @@ -2486,6 +2487,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
>  	intel_connector_attach_encoder(intel_connector, intel_encoder);
>  	drm_sysfs_connector_add(connector);
>  
> +	intel_encoder->enable = intel_enable_dp;
> +	intel_encoder->disable = intel_disable_dp;
> +
>  	/* Set up the DDC bus. */
>  	switch (port) {
>  	case PORT_A:

Assuming the above questions are answered:
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* [PATCH] drm/i915: push crtc->fb update into pipe_set_base
  2012-08-19 19:13 ` [PATCH 44/58] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
@ 2012-09-04 19:33   ` Daniel Vetter
  2012-09-05 17:55     ` Jesse Barnes
  2012-09-05 17:54   ` [PATCH 44/58] " Jesse Barnes
  1 sibling, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-09-04 19:33 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 90 ++++++++++++++----------------------
 1 file changed, 34 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index eb9616b..4423cd5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2201,16 +2201,17 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
 
 static int
 intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
-		    struct drm_framebuffer *old_fb)
+		    struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_framebuffer *old_fb;
 	int ret;
 
 	/* no fb bound */
-	if (!crtc->fb) {
+	if (!fb) {
 		DRM_ERROR("No FB bound\n");
 		return 0;
 	}
@@ -2224,7 +2225,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 
 	mutex_lock(&dev->struct_mutex);
 	ret = intel_pin_and_fence_fb_obj(dev,
-					 to_intel_framebuffer(crtc->fb)->obj,
+					 to_intel_framebuffer(fb)->obj,
 					 NULL);
 	if (ret != 0) {
 		mutex_unlock(&dev->struct_mutex);
@@ -2232,17 +2233,20 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		return ret;
 	}
 
-	if (old_fb)
-		intel_finish_fb(old_fb);
+	if (crtc->fb)
+		intel_finish_fb(crtc->fb);
 
-	ret = dev_priv->display.update_plane(crtc, crtc->fb, x, y);
+	ret = dev_priv->display.update_plane(crtc, fb, x, y);
 	if (ret) {
-		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
+		intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj);
 		mutex_unlock(&dev->struct_mutex);
 		DRM_ERROR("failed to update base address\n");
 		return ret;
 	}
 
+	old_fb = crtc->fb;
+	crtc->fb = fb;
+
 	if (old_fb) {
 		intel_wait_for_vblank(dev, intel_crtc->pipe);
 		intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
@@ -3777,6 +3781,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
  * true if they don't match).
  */
 static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
+					 struct drm_framebuffer *fb,
 					 unsigned int *pipe_bpp,
 					 struct drm_display_mode *mode)
 {
@@ -3846,7 +3851,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
 	 * also stays within the max display bpc discovered above.
 	 */
 
-	switch (crtc->fb->depth) {
+	switch (fb->depth) {
 	case 8:
 		bpc = 8; /* since we go through a colormap */
 		break;
@@ -4265,7 +4270,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 			      struct drm_display_mode *mode,
 			      struct drm_display_mode *adjusted_mode,
 			      int x, int y,
-			      struct drm_framebuffer *old_fb)
+			      struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4455,7 +4460,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), dspcntr);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, old_fb);
+	ret = intel_pipe_set_base(crtc, x, y, fb);
 
 	intel_update_watermarks(dev);
 
@@ -4613,7 +4618,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode,
 				  int x, int y,
-				  struct drm_framebuffer *old_fb)
+				  struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4733,7 +4738,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	/* determine panel color depth */
 	temp = I915_READ(PIPECONF(pipe));
 	temp &= ~PIPE_BPC_MASK;
-	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
+	dither = intel_choose_pipe_bpp_dither(crtc, fb, &pipe_bpp, mode);
 	switch (pipe_bpp) {
 	case 18:
 		temp |= PIPE_6BPC;
@@ -5002,7 +5007,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), dspcntr);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, old_fb);
+	ret = intel_pipe_set_base(crtc, x, y, fb);
 
 	intel_update_watermarks(dev);
 
@@ -5015,7 +5020,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode,
 			       int x, int y,
-			       struct drm_framebuffer *old_fb)
+			       struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5026,7 +5031,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	drm_vblank_pre_modeset(dev, pipe);
 
 	ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
-					      x, y, old_fb);
+					      x, y, fb);
 	drm_vblank_post_modeset(dev, pipe);
 
 	return ret;
@@ -5718,7 +5723,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_crtc *crtc = NULL;
 	struct drm_device *dev = encoder->dev;
-	struct drm_framebuffer *old_fb;
+	struct drm_framebuffer *fb;
 	int i = -1;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
@@ -5779,8 +5784,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 	if (!mode)
 		mode = &load_detect_mode;
 
-	old_fb = crtc->fb;
-
 	/* We need a framebuffer large enough to accommodate all accesses
 	 * that the plane may generate whilst we perform load detection.
 	 * We can not rely on the fbcon either being present (we get called
@@ -5788,19 +5791,19 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 	 * not even exist) or that it is large enough to satisfy the
 	 * requested mode.
 	 */
-	crtc->fb = mode_fits_in_fbdev(dev, mode);
-	if (crtc->fb == NULL) {
+	fb = mode_fits_in_fbdev(dev, mode);
+	if (fb == NULL) {
 		DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
-		crtc->fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
-		old->release_fb = crtc->fb;
+		fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
+		old->release_fb = fb;
 	} else
 		DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
-	if (IS_ERR(crtc->fb)) {
+	if (IS_ERR(fb)) {
 		DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
 		goto fail;
 	}
 
-	if (!intel_set_mode(crtc, mode, 0, 0, old_fb)) {
+	if (!intel_set_mode(crtc, mode, 0, 0, fb)) {
 		DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
 		if (old->release_fb)
 			old->release_fb->funcs->destroy(old->release_fb);
@@ -5814,7 +5817,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 fail:
 	connector->encoder = NULL;
 	encoder->crtc = NULL;
-	crtc->fb = old_fb;
 	return false;
 }
 
@@ -6666,13 +6668,12 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
 
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
-		    int x, int y, struct drm_framebuffer *old_fb)
+		    int x, int y, struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
 	struct drm_encoder_helper_funcs *encoder_funcs;
-	int saved_x, saved_y;
 	struct drm_encoder *encoder;
 	bool ret = true;
 
@@ -6686,15 +6687,11 @@ bool intel_set_mode(struct drm_crtc *crtc,
 
 	saved_hwmode = crtc->hwmode;
 	saved_mode = crtc->mode;
-	saved_x = crtc->x;
-	saved_y = crtc->y;
 
 	/* Update crtc values up front so the driver can rely on them for mode
 	 * setting.
 	 */
 	crtc->mode = *mode;
-	crtc->x = x;
-	crtc->y = y;
 
 	/* Pass our mode to the connectors and the CRTC to give them a chance to
 	 * adjust it according to limitations or connector properties, and also
@@ -6725,7 +6722,7 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
-	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, fb);
 	if (!ret)
 	    goto done;
 
@@ -6741,6 +6738,9 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 	}
 
+	crtc->x = x;
+	crtc->y = y;
+
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
 	dev_priv->display.crtc_enable(crtc);
 
@@ -6759,8 +6759,6 @@ done:
 	if (!ret) {
 		crtc->hwmode = saved_hwmode;
 		crtc->mode = saved_mode;
-		crtc->x = saved_x;
-		crtc->y = saved_y;
 	}
 
 	return ret;
@@ -6828,17 +6826,11 @@ 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 drm_crtc *crtc;
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
 	int count;
 
 	count = 0;
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		*crtc = config->save_crtcs[count++];
-	}
-
-	count = 0;
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 		encoder->new_crtc =
 			to_intel_crtc(config->save_encoder_crtcs[count++]);
@@ -6993,7 +6985,6 @@ next_encoder:
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
 	struct drm_device *dev;
-	struct drm_framebuffer *old_fb = NULL;
 	struct drm_mode_set save_set;
 	struct intel_set_config *config;
 	int ret;
@@ -7056,13 +7047,10 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 			DRM_DEBUG_KMS("attempting to set mode from"
 					" userspace\n");
 			drm_mode_debug_printmodeline(set->mode);
-			old_fb = set->crtc->fb;
-			set->crtc->fb = set->fb;
 			if (!intel_set_mode(set->crtc, set->mode,
-					    set->x, set->y, old_fb)) {
+					    set->x, set->y, set->fb)) {
 				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
 					  set->crtc->base.id);
-				set->crtc->fb = old_fb;
 				ret = -EINVAL;
 				goto fail;
 			}
@@ -7075,18 +7063,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		}
 		drm_helper_disable_unused_functions(dev);
 	} else if (config->fb_changed) {
-		set->crtc->x = set->x;
-		set->crtc->y = set->y;
-
-		old_fb = set->crtc->fb;
-		if (set->crtc->fb != set->fb)
-			set->crtc->fb = set->fb;
 		ret = intel_pipe_set_base(set->crtc,
-					  set->x, set->y, old_fb);
-		if (ret != 0) {
-			set->crtc->fb = old_fb;
-			goto fail;
-		}
+					  set->x, set->y, set->fb);
 	}
 
 	intel_set_config_free(config);
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* Re: [PATCH 07/58] drm/i915/dp: convert to encoder disable/enable
  2012-09-04 19:33   ` Jesse Barnes
@ 2012-09-04 19:42     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-04 19:42 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Tue, Sep 4, 2012 at 9:33 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Sun, 19 Aug 2012 21:12:24 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
>
>> -static void intel_dp_prepare(struct drm_encoder *encoder)
>> +static void intel_disable_dp(struct intel_encoder *encoder)
>>  {
>> -     struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>> -
>> +     struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
>>
>>       /* Make sure the panel is off before trying to change the mode. But also
>>        * ensure that we have vdd while we switch off the panel. */
>> @@ -1262,62 +1261,64 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
>>       intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
>>       ironlake_edp_panel_off(intel_dp);
>>       intel_dp_link_down(intel_dp);
>> +
>> +     intel_dp->dpms_mode = DRM_MODE_DPMS_OFF;
>
> Is this redundant?  At init time we'll have cleared this, and at
> prepare time it ought to be off already right?

If my understanding is correct, we use intel_dp->dpms_mode to decide
whether we need to retrain the link. Yes, it's redundant, and a
follow-up patch on top of this series will rip it out. But for the
conversion I've decided that I'll painstakingly keep any and all funny
piece of code in the low-level hw frobbery, just to reduce the risk.
Hence I sometimes add "stupid" bits&pieces, just to keep the existing
stupid going for a little longer ;-)

After all, a patch should do one thing, and one thing only.

>>  }
>>
>> -static void intel_dp_commit(struct drm_encoder *encoder)
>> +static void intel_enable_dp(struct intel_encoder *encoder)
>>  {
>> -     struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>> -     struct drm_device *dev = encoder->dev;
>> -     struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
>> +     struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
>> +     struct drm_device *dev = encoder->base.dev;
>> +     struct drm_i915_private *dev_priv = dev->dev_private;
>> +     uint32_t dp_reg = I915_READ(intel_dp->output_reg);
>>
>>       ironlake_edp_panel_vdd_on(intel_dp);
>>       intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
>> -     intel_dp_start_link_train(intel_dp);
>> -     ironlake_edp_panel_on(intel_dp);
>> -     ironlake_edp_panel_vdd_off(intel_dp, true);
>> -     intel_dp_complete_link_train(intel_dp);
>> +     if (!(dp_reg & DP_PORT_EN)) {
>> +             intel_dp_start_link_train(intel_dp);
>> +             ironlake_edp_panel_on(intel_dp);
>> +             ironlake_edp_panel_vdd_off(intel_dp, true);
>> +             intel_dp_complete_link_train(intel_dp);
>> +     } else
>> +             ironlake_edp_panel_vdd_off(intel_dp, false);
>
> Hm so if we call enable on an already on DP port, we'll just disable
> VDD?  But shouldn't it already have been off?

Same reason, this bogus check will disappear. I /think/ this was to
properly cope with take-over from the bios. Again I just painstakingly
replicate what's already there (this time from the dpms function).

Cheers, Daniel

>
>>       ironlake_edp_backlight_on(intel_dp);
>>
>>       intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
>> -
>> -     if (HAS_PCH_CPT(dev))
>> -             intel_cpt_verify_modeset(dev, intel_crtc->pipe);
>>  }
>>
>>  static void
>> -intel_dp_dpms(struct drm_encoder *encoder, int mode)
>> +intel_dp_dpms(struct drm_connector *connector, int mode)
>>  {
>> -     struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>> -     struct drm_device *dev = encoder->dev;
>> -     struct drm_i915_private *dev_priv = dev->dev_private;
>> -     uint32_t dp_reg = I915_READ(intel_dp->output_reg);
>> +     struct intel_dp *intel_dp = intel_attached_dp(connector);
>> +
>> +     /* DP supports only 2 dpms states. */
>> +     if (mode != DRM_MODE_DPMS_ON)
>> +             mode = DRM_MODE_DPMS_OFF;
>> +
>> +     if (mode == connector->dpms)
>> +             return;
>> +
>> +     connector->dpms = mode;
>> +
>> +     /* Only need to change hw state when actually enabled */
>> +     if (!intel_dp->base.base.crtc) {
>> +             intel_dp->base.connectors_active = false;
>> +             return;
>> +     }
>>
>>       if (mode != DRM_MODE_DPMS_ON) {
>> -             /* Switching the panel off requires vdd. */
>> -             ironlake_edp_panel_vdd_on(intel_dp);
>> -             ironlake_edp_backlight_off(intel_dp);
>> -             intel_dp_sink_dpms(intel_dp, mode);
>> -             ironlake_edp_panel_off(intel_dp);
>> -             intel_dp_link_down(intel_dp);
>> +             intel_encoder_dpms(&intel_dp->base, mode);
>> +             WARN_ON(intel_dp->dpms_mode != DRM_MODE_DPMS_OFF);
>>
>>               if (is_cpu_edp(intel_dp))
>> -                     ironlake_edp_pll_off(encoder);
>> +                     ironlake_edp_pll_off(&intel_dp->base.base);
>>       } else {
>>               if (is_cpu_edp(intel_dp))
>> -                     ironlake_edp_pll_on(encoder);
>> +                     ironlake_edp_pll_on(&intel_dp->base.base);
>>
>> -             ironlake_edp_panel_vdd_on(intel_dp);
>> -             intel_dp_sink_dpms(intel_dp, mode);
>> -             if (!(dp_reg & DP_PORT_EN)) {
>> -                     intel_dp_start_link_train(intel_dp);
>> -                     ironlake_edp_panel_on(intel_dp);
>> -                     ironlake_edp_panel_vdd_off(intel_dp, true);
>> -                     intel_dp_complete_link_train(intel_dp);
>> -             } else
>> -                     ironlake_edp_panel_vdd_off(intel_dp, false);
>> -             ironlake_edp_backlight_on(intel_dp);
>> +             intel_encoder_dpms(&intel_dp->base, mode);
>> +             WARN_ON(intel_dp->dpms_mode != DRM_MODE_DPMS_ON);
>>       }
>> -     intel_dp->dpms_mode = mode;
>>  }
>>
>>  /*
>> @@ -2347,15 +2348,15 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>>  }
>>
>>  static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
>> -     .dpms = intel_dp_dpms,
>>       .mode_fixup = intel_dp_mode_fixup,
>> -     .prepare = intel_dp_prepare,
>> +     .prepare = intel_encoder_noop,
>>       .mode_set = intel_dp_mode_set,
>> -     .commit = intel_dp_commit,
>> +     .commit = intel_encoder_noop,
>> +     .disable = intel_encoder_disable,
>>  };
>>
>>  static const struct drm_connector_funcs intel_dp_connector_funcs = {
>> -     .dpms = drm_helper_connector_dpms,
>> +     .dpms = intel_dp_dpms,
>>       .detect = intel_dp_detect,
>>       .fill_modes = drm_helper_probe_single_connector_modes,
>>       .set_property = intel_dp_set_property,
>> @@ -2486,6 +2487,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
>>       intel_connector_attach_encoder(intel_connector, intel_encoder);
>>       drm_sysfs_connector_add(connector);
>>
>> +     intel_encoder->enable = intel_enable_dp;
>> +     intel_encoder->disable = intel_disable_dp;
>> +
>>       /* Set up the DDC bus. */
>>       switch (port) {
>>       case PORT_A:
>
> Assuming the above questions are answered:
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
>
> --
> Jesse Barnes, Intel Open Source Technology Center



-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 08/58] drm/i915/crt: convert to encoder disable/enable
  2012-08-19 19:12 ` [PATCH 08/58] drm/i915/crt: " Daniel Vetter
@ 2012-09-04 19:50   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 19:50 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:25 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> CRT is the first output which can be cloned, hence we cannot (yet)
> move the dpms handling over to disable/enable. This requires some more
> smarts in intel_crtc_dpms first to set the display pipe status
> depening upon encoder->connectors_active of all connected encoders.
> 
> Because that will happen in a separate step, don't touch the dpms
> functions, yet.
> 
> v2: Be careful about clearing the _DISABLE flags for intermediate dpms
> modes - otherwise we might clobber the crt state when another (cloned)
> connector gets enabled.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_crt.c | 36 ++++++++++++++++++++++++++++++++----
>  1 file changed, 32 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index 1d05b2d..543ea40 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -61,6 +61,29 @@ static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
>  	return container_of(encoder, struct intel_crt, base);
>  }
>  
> +static void intel_disable_crt(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> +	struct intel_crt *crt = intel_encoder_to_crt(encoder);
> +	u32 temp;
> +
> +	temp = I915_READ(crt->adpa_reg);
> +	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
> +	temp &= ~ADPA_DAC_ENABLE;
> +	I915_WRITE(crt->adpa_reg, temp);
> +}
> +
> +static void intel_enable_crt(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> +	struct intel_crt *crt = intel_encoder_to_crt(encoder);
> +	u32 temp;
> +
> +	temp = I915_READ(crt->adpa_reg);
> +	temp |= ADPA_DAC_ENABLE;
> +	I915_WRITE(crt->adpa_reg, temp);
> +}
> +
>  static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
>  {
>  	struct drm_device *dev = encoder->dev;
> @@ -575,18 +598,20 @@ static void intel_crt_reset(struct drm_connector *connector)
>  
>  static const struct drm_encoder_helper_funcs pch_encoder_funcs = {
>  	.mode_fixup = intel_crt_mode_fixup,
> -	.prepare = intel_encoder_prepare,
> -	.commit = intel_encoder_commit,
> +	.prepare = intel_encoder_noop,
> +	.commit = intel_encoder_noop,
>  	.mode_set = intel_crt_mode_set,
>  	.dpms = pch_crt_dpms,
> +	.disable = intel_encoder_disable,
>  };
>  
>  static const struct drm_encoder_helper_funcs gmch_encoder_funcs = {
>  	.mode_fixup = intel_crt_mode_fixup,
> -	.prepare = intel_encoder_prepare,
> -	.commit = intel_encoder_commit,
> +	.prepare = intel_encoder_noop,
> +	.commit = intel_encoder_noop,
>  	.mode_set = intel_crt_mode_set,
>  	.dpms = gmch_crt_dpms,
> +	.disable = intel_encoder_disable,
>  };
>  
>  static const struct drm_connector_funcs intel_crt_connector_funcs = {
> @@ -682,6 +707,9 @@ void intel_crt_init(struct drm_device *dev)
>  	else
>  		crt->adpa_reg = ADPA;
>  
> +	crt->base.disable = intel_disable_crt;
> +	crt->base.enable = intel_enable_crt;
> +
>  	drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs);
>  	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
>  

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 09/58] drm/i915/sdvo: convert to encoder disable/enable
  2012-08-19 19:12 ` [PATCH 09/58] drm/i915/sdvo: " Daniel Vetter
@ 2012-09-04 19:52   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 19:52 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:26 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Similar to crt, this doesn't convert the dpms functions.
> Also similar to crt, we don't switch of the display pipe
> for the intermediate modes, only DPMS_OFF is truely off.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_sdvo.c | 58 +++++++++++++++++++++++++++++++++++++--
>  1 file changed, 56 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index f3762f8..20feaa3 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -1142,6 +1142,56 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
>  	intel_sdvo_write_sdvox(intel_sdvo, sdvox);
>  }
>  
> +static void intel_disable_sdvo(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> +	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
> +	u32 temp;
> +
> +	intel_sdvo_set_active_outputs(intel_sdvo, 0);
> +	if (0)
> +		intel_sdvo_set_encoder_power_state(intel_sdvo,
> +						   DRM_MODE_DPMS_OFF);
> +
> +	temp = I915_READ(intel_sdvo->sdvo_reg);
> +	if ((temp & SDVO_ENABLE) != 0) {
> +		intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE);
> +	}
> +}
> +
> +static void intel_enable_sdvo(struct intel_encoder *encoder)
> +{
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
> +	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
> +	u32 temp;
> +	bool input1, input2;
> +	int i;
> +	u8 status;
> +
> +	temp = I915_READ(intel_sdvo->sdvo_reg);
> +	if ((temp & SDVO_ENABLE) == 0)
> +		intel_sdvo_write_sdvox(intel_sdvo, temp | SDVO_ENABLE);
> +	for (i = 0; i < 2; i++)
> +		intel_wait_for_vblank(dev, intel_crtc->pipe);
> +
> +	status = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2);
> +	/* Warn if the device reported failure to sync.
> +	 * A lot of SDVO devices fail to notify of sync, but it's
> +	 * a given it the status is a success, we succeeded.
> +	 */
> +	if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
> +		DRM_DEBUG_KMS("First %s output reported failure to "
> +				"sync\n", SDVO_NAME(intel_sdvo));
> +	}
> +
> +	if (0)
> +		intel_sdvo_set_encoder_power_state(intel_sdvo,
> +						   DRM_MODE_DPMS_ON);
> +	intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
> +}
> +
>  static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
>  {
>  	struct drm_device *dev = encoder->dev;
> @@ -1847,9 +1897,10 @@ done:
>  static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
>  	.dpms = intel_sdvo_dpms,
>  	.mode_fixup = intel_sdvo_mode_fixup,
> -	.prepare = intel_encoder_prepare,
> +	.prepare = intel_encoder_noop,
>  	.mode_set = intel_sdvo_mode_set,
> -	.commit = intel_encoder_commit,
> +	.commit = intel_encoder_noop,
> +	.disable = intel_encoder_disable
>  };
>  
>  static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
> @@ -2576,6 +2627,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
>  
>  	drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
>  
> +	intel_encoder->disable = intel_disable_sdvo;
> +	intel_encoder->enable = intel_enable_sdvo;
> +
>  	/* In default case sdvo lvds is false */
>  	if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
>  		goto err;

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 10/58] drm/i915/dvo: convert to encoder disable/enable
  2012-08-19 19:12 ` [PATCH 10/58] drm/i915/dvo: " Daniel Vetter
@ 2012-09-04 19:53   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 19:53 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:27 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Similar to the sdvo conversion.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_dvo.c | 32 ++++++++++++++++++++++++++++++--
>  1 file changed, 30 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index 227551f..4ad988f 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -105,6 +105,30 @@ static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector)
>  			    struct intel_dvo, base);
>  }
>  
> +static void intel_disable_dvo(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> +	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
> +	u32 dvo_reg = intel_dvo->dev.dvo_reg;
> +	u32 temp = I915_READ(dvo_reg);
> +
> +	intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
> +	I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
> +	I915_READ(dvo_reg);
> +}
> +
> +static void intel_enable_dvo(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> +	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
> +	u32 dvo_reg = intel_dvo->dev.dvo_reg;
> +	u32 temp = I915_READ(dvo_reg);
> +
> +	I915_WRITE(dvo_reg, temp | DVO_ENABLE);
> +	I915_READ(dvo_reg);
> +	intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
> +}
> +
>  static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
>  {
>  	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
> @@ -277,9 +301,10 @@ static void intel_dvo_destroy(struct drm_connector *connector)
>  static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
>  	.dpms = intel_dvo_dpms,
>  	.mode_fixup = intel_dvo_mode_fixup,
> -	.prepare = intel_encoder_prepare,
> +	.prepare = intel_encoder_noop,
>  	.mode_set = intel_dvo_mode_set,
> -	.commit = intel_encoder_commit,
> +	.commit = intel_encoder_noop,
> +	.disable = intel_encoder_disable,
>  };
>  
>  static const struct drm_connector_funcs intel_dvo_connector_funcs = {
> @@ -372,6 +397,9 @@ void intel_dvo_init(struct drm_device *dev)
>  	drm_encoder_init(dev, &intel_encoder->base,
>  			 &intel_dvo_enc_funcs, encoder_type);
>  
> +	intel_encoder->disable = intel_disable_dvo;
> +	intel_encoder->enable = intel_enable_dvo;
> +
>  	/* Now, try to find a controller */
>  	for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
>  		struct drm_connector *connector = &intel_connector->base;

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: convert dpms functions of dvo/sdvo/crt
  2012-08-29  7:12   ` [PATCH] " Daniel Vetter
@ 2012-09-04 20:10     ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:10 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Wed, 29 Aug 2012 09:12:23 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_crt.c     | 97 +++++++++++++++++++-----------------
>  drivers/gpu/drm/i915/intel_display.c | 37 +++++++-------
>  drivers/gpu/drm/i915/intel_drv.h     |  1 +
>  drivers/gpu/drm/i915/intel_dvo.c     | 39 +++++++++++----
>  drivers/gpu/drm/i915/intel_sdvo.c    | 60 ++++++++++------------
>  5 files changed, 122 insertions(+), 112 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index 543ea40..76646c7 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -84,13 +84,17 @@ static void intel_enable_crt(struct intel_encoder *encoder)
>  	I915_WRITE(crt->adpa_reg, temp);
>  }
>  
> -static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
> +/* Note: The caller is required to filter out dpms modes not supported by the
> + * platform. */
> +static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
>  {
> -	struct drm_device *dev = encoder->dev;
> +	struct drm_device *dev = encoder->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_crt *crt = intel_encoder_to_crt(encoder);
>  	u32 temp;
>  
> -	temp = I915_READ(PCH_ADPA);
> +	temp = I915_READ(crt->adpa_reg);
> +	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
>  	temp &= ~ADPA_DAC_ENABLE;
>  
>  	switch (mode) {
> @@ -98,44 +102,59 @@ static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
>  		temp |= ADPA_DAC_ENABLE;
>  		break;
>  	case DRM_MODE_DPMS_STANDBY:
> +		temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
> +		break;
>  	case DRM_MODE_DPMS_SUSPEND:
> +		temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
> +		break;
>  	case DRM_MODE_DPMS_OFF:
> -		/* Just leave port enable cleared */
> +		temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
>  		break;
>  	}
>  
> -	I915_WRITE(PCH_ADPA, temp);
> +	I915_WRITE(crt->adpa_reg, temp);
>  }
>  
> -static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
> +static void intel_crt_dpms(struct drm_connector *connector, int mode)
>  {
> -	struct drm_device *dev = encoder->dev;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	u32 temp;
> -
> -	temp = I915_READ(ADPA);
> -	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
> -	temp &= ~ADPA_DAC_ENABLE;
> +	struct drm_device *dev = connector->dev;
> +	struct intel_encoder *encoder = intel_attached_encoder(connector);
> +	struct drm_crtc *crtc;
> +	int old_dpms;
>  
> -	if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON)
> +	/* PCH platforms and VLV only support on/off. */
> +	if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
>  		mode = DRM_MODE_DPMS_OFF;
>  
> -	switch (mode) {
> -	case DRM_MODE_DPMS_ON:
> -		temp |= ADPA_DAC_ENABLE;
> -		break;
> -	case DRM_MODE_DPMS_STANDBY:
> -		temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
> -		break;
> -	case DRM_MODE_DPMS_SUSPEND:
> -		temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
> -		break;
> -	case DRM_MODE_DPMS_OFF:
> -		temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
> -		break;
> +	if (mode == connector->dpms)
> +		return;
> +
> +	old_dpms = connector->dpms;
> +	connector->dpms = mode;
> +
> +	/* Only need to change hw state when actually enabled */
> +	crtc = encoder->base.crtc;
> +	if (!crtc) {
> +		encoder->connectors_active = false;
> +		return;
>  	}
>  
> -	I915_WRITE(ADPA, temp);
> +	/* We need the pipe to run for anything but OFF. */
> +	if (mode == DRM_MODE_DPMS_OFF)
> +		encoder->connectors_active = false;
> +	else
> +		encoder->connectors_active = true;
> +
> +	if (mode < old_dpms) {
> +		/* From off to on, enable the pipe first. */
> +		intel_crtc_update_dpms(crtc);
> +
> +		intel_crt_set_dpms(encoder, mode);
> +	} else {
> +		intel_crt_set_dpms(encoder, mode);
> +
> +		intel_crtc_update_dpms(crtc);
> +	}
>  }
>  
>  static int intel_crt_mode_valid(struct drm_connector *connector,
> @@ -596,27 +615,17 @@ static void intel_crt_reset(struct drm_connector *connector)
>   * Routines for controlling stuff on the analog port
>   */
>  
> -static const struct drm_encoder_helper_funcs pch_encoder_funcs = {
> -	.mode_fixup = intel_crt_mode_fixup,
> -	.prepare = intel_encoder_noop,
> -	.commit = intel_encoder_noop,
> -	.mode_set = intel_crt_mode_set,
> -	.dpms = pch_crt_dpms,
> -	.disable = intel_encoder_disable,
> -};
> -
> -static const struct drm_encoder_helper_funcs gmch_encoder_funcs = {
> +static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
>  	.mode_fixup = intel_crt_mode_fixup,
>  	.prepare = intel_encoder_noop,
>  	.commit = intel_encoder_noop,
>  	.mode_set = intel_crt_mode_set,
> -	.dpms = gmch_crt_dpms,
>  	.disable = intel_encoder_disable,
>  };
>  
>  static const struct drm_connector_funcs intel_crt_connector_funcs = {
>  	.reset = intel_crt_reset,
> -	.dpms = drm_helper_connector_dpms,
> +	.dpms = intel_crt_dpms,
>  	.detect = intel_crt_detect,
>  	.fill_modes = drm_helper_probe_single_connector_modes,
>  	.destroy = intel_crt_destroy,
> @@ -657,7 +666,6 @@ void intel_crt_init(struct drm_device *dev)
>  	struct intel_crt *crt;
>  	struct intel_connector *intel_connector;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	const struct drm_encoder_helper_funcs *encoder_helper_funcs;
>  
>  	/* Skip machines without VGA that falsely report hotplug events */
>  	if (dmi_check_system(intel_no_crt))
> @@ -696,11 +704,6 @@ void intel_crt_init(struct drm_device *dev)
>  	connector->doublescan_allowed = 0;
>  
>  	if (HAS_PCH_SPLIT(dev))
> -		encoder_helper_funcs = &pch_encoder_funcs;
> -	else
> -		encoder_helper_funcs = &gmch_encoder_funcs;
> -
> -	if (HAS_PCH_SPLIT(dev))
>  		crt->adpa_reg = PCH_ADPA;
>  	else if (IS_VALLEYVIEW(dev))
>  		crt->adpa_reg = VLV_ADPA;
> @@ -710,7 +713,7 @@ void intel_crt_init(struct drm_device *dev)
>  	crt->base.disable = intel_disable_crt;
>  	crt->base.enable = intel_enable_crt;
>  
> -	drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs);
> +	drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs);
>  	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
>  
>  	drm_sysfs_connector_add(connector);
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index cbd356f..0d48ebe 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3462,34 +3462,31 @@ static void i9xx_crtc_off(struct drm_crtc *crtc)
>  /**
>   * Sets the power management mode of the pipe and plane.
>   */
> -static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
> +void intel_crtc_update_dpms(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct drm_i915_master_private *master_priv;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	struct intel_encoder *intel_encoder;
>  	int pipe = intel_crtc->pipe;
> -	bool enabled;
> +	bool enabled, enable = false;
> +	int mode;
> +
> +	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
> +		enable |= intel_encoder->connectors_active;
> +
> +	mode = enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF;
>  
>  	if (intel_crtc->dpms_mode == mode)
>  		return;
>  
>  	intel_crtc->dpms_mode = mode;
>  
> -	/* XXX: When our outputs are all unaware of DPMS modes other than off
> -	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
> -	 */
> -	switch (mode) {
> -	case DRM_MODE_DPMS_ON:
> -	case DRM_MODE_DPMS_STANDBY:
> -	case DRM_MODE_DPMS_SUSPEND:
> +	if (enable)
>  		dev_priv->display.crtc_enable(crtc);
> -		break;
> -
> -	case DRM_MODE_DPMS_OFF:
> +	else
>  		dev_priv->display.crtc_disable(crtc);
> -		break;
> -	}
>  
>  	if (!dev->primary->master)
>  		return;
> @@ -3498,7 +3495,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
>  	if (!master_priv->sarea_priv)
>  		return;
>  
> -	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
> +	enabled = crtc->enabled && enable;
>  
>  	switch (pipe) {
>  	case 0:
> @@ -3517,11 +3514,12 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
>  
>  static void intel_crtc_disable(struct drm_crtc *crtc)
>  {
> -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> -	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
> +	/* crtc->disable is only called when we have no encoders, hence this
> +	 * will disable the pipe. */
> +	intel_crtc_update_dpms(crtc);
>  	dev_priv->display.off(crtc);
>  
>  	assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
> @@ -3581,11 +3579,11 @@ void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
>  	if (mode == DRM_MODE_DPMS_ON) {
>  		encoder->connectors_active = true;
>  
> -		intel_crtc_dpms(encoder->base.crtc, DRM_MODE_DPMS_ON);
> +		intel_crtc_update_dpms(encoder->base.crtc);
>  	} else {
>  		encoder->connectors_active = false;
>  
> -		intel_crtc_dpms(encoder->base.crtc, DRM_MODE_DPMS_OFF);
> +		intel_crtc_update_dpms(encoder->base.crtc);
>  	}
>  }
>  
> @@ -6609,7 +6607,6 @@ static void intel_crtc_reset(struct drm_crtc *crtc)
>  }
>  
>  static struct drm_crtc_helper_funcs intel_helper_funcs = {
> -	.dpms = intel_crtc_dpms,
>  	.mode_fixup = intel_crtc_mode_fixup,
>  	.mode_set = intel_crtc_mode_set,
>  	.mode_set_base = intel_pipe_set_base,
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 759dcba..2456245 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);
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index 4ad988f..c55a13e 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -129,21 +129,39 @@ static void intel_enable_dvo(struct intel_encoder *encoder)
>  	intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
>  }
>  
> -static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
> +static void intel_dvo_dpms(struct drm_connector *connector, int mode)
>  {
> -	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
> -	struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
> -	u32 dvo_reg = intel_dvo->dev.dvo_reg;
> -	u32 temp = I915_READ(dvo_reg);
> +	struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
> +	struct drm_crtc *crtc;
> +
> +	/* dvo supports only 2 dpms states. */
> +	if (mode != DRM_MODE_DPMS_ON)
> +		mode = DRM_MODE_DPMS_OFF;
> +
> +	if (mode == connector->dpms)
> +		return;
> +
> +	connector->dpms = mode;
> +
> +	/* Only need to change hw state when actually enabled */
> +	crtc = intel_dvo->base.base.crtc;
> +	if (!crtc) {
> +		intel_dvo->base.connectors_active = false;
> +		return;
> +	}
>  
>  	if (mode == DRM_MODE_DPMS_ON) {
> -		I915_WRITE(dvo_reg, temp | DVO_ENABLE);
> -		I915_READ(dvo_reg);
> +		intel_dvo->base.connectors_active = true;
> +
> +		intel_crtc_update_dpms(crtc);
> +
>  		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
>  	} else {
>  		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
> -		I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
> -		I915_READ(dvo_reg);
> +
> +		intel_dvo->base.connectors_active = false;
> +
> +		intel_crtc_update_dpms(crtc);
>  	}
>  }
>  
> @@ -299,7 +317,6 @@ static void intel_dvo_destroy(struct drm_connector *connector)
>  }
>  
>  static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
> -	.dpms = intel_dvo_dpms,
>  	.mode_fixup = intel_dvo_mode_fixup,
>  	.prepare = intel_encoder_noop,
>  	.mode_set = intel_dvo_mode_set,
> @@ -308,7 +325,7 @@ static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
>  };
>  
>  static const struct drm_connector_funcs intel_dvo_connector_funcs = {
> -	.dpms = drm_helper_connector_dpms,
> +	.dpms = intel_dvo_dpms,
>  	.detect = intel_dvo_detect,
>  	.destroy = intel_dvo_destroy,
>  	.fill_modes = drm_helper_probe_single_connector_modes,
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index 20feaa3..a01c470 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -1192,51 +1192,44 @@ static void intel_enable_sdvo(struct intel_encoder *encoder)
>  	intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
>  }
>  
> -static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
> +static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
>  {
> -	struct drm_device *dev = encoder->dev;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
> -	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
> -	u32 temp;
> +	struct drm_crtc *crtc;
> +	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
> +
> +	/* dvo supports only 2 dpms states. */
> +	if (mode != DRM_MODE_DPMS_ON)
> +		mode = DRM_MODE_DPMS_OFF;
> +
> +	if (mode == connector->dpms)
> +		return;
> +
> +	connector->dpms = mode;
> +
> +	/* Only need to change hw state when actually enabled */
> +	crtc = intel_sdvo->base.base.crtc;
> +	if (!crtc) {
> +		intel_sdvo->base.connectors_active = false;
> +		return;
> +	}
>  
>  	if (mode != DRM_MODE_DPMS_ON) {
>  		intel_sdvo_set_active_outputs(intel_sdvo, 0);
>  		if (0)
>  			intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
>  
> -		if (mode == DRM_MODE_DPMS_OFF) {
> -			temp = I915_READ(intel_sdvo->sdvo_reg);
> -			if ((temp & SDVO_ENABLE) != 0) {
> -				intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE);
> -			}
> -		}
> +		intel_sdvo->base.connectors_active = false;
> +
> +		intel_crtc_update_dpms(crtc);
>  	} else {
> -		bool input1, input2;
> -		int i;
> -		u8 status;
> -
> -		temp = I915_READ(intel_sdvo->sdvo_reg);
> -		if ((temp & SDVO_ENABLE) == 0)
> -			intel_sdvo_write_sdvox(intel_sdvo, temp | SDVO_ENABLE);
> -		for (i = 0; i < 2; i++)
> -			intel_wait_for_vblank(dev, intel_crtc->pipe);
> -
> -		status = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2);
> -		/* Warn if the device reported failure to sync.
> -		 * A lot of SDVO devices fail to notify of sync, but it's
> -		 * a given it the status is a success, we succeeded.
> -		 */
> -		if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
> -			DRM_DEBUG_KMS("First %s output reported failure to "
> -					"sync\n", SDVO_NAME(intel_sdvo));
> -		}
> +		intel_sdvo->base.connectors_active = true;
> +
> +		intel_crtc_update_dpms(crtc);
>  
>  		if (0)
>  			intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
>  		intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
>  	}
> -	return;
>  }
>  
>  static int intel_sdvo_mode_valid(struct drm_connector *connector,
> @@ -1895,7 +1888,6 @@ done:
>  }
>  
>  static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
> -	.dpms = intel_sdvo_dpms,
>  	.mode_fixup = intel_sdvo_mode_fixup,
>  	.prepare = intel_encoder_noop,
>  	.mode_set = intel_sdvo_mode_set,
> @@ -1904,7 +1896,7 @@ static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
>  };
>  
>  static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
> -	.dpms = drm_helper_connector_dpms,
> +	.dpms = intel_sdvo_dpms,
>  	.detect = intel_sdvo_detect,
>  	.fill_modes = drm_helper_probe_single_connector_modes,
>  	.set_property = intel_sdvo_set_property,

Only comment here is that having code that writes reserved bits being
shared between platforms that handle those bits and those that don't
will make me look twice everytime... (just like the existing code makes
you check the gen & VLV bit everytime). But maybe that gets fixed in a
later patch.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 12/58] drm/i915: rip out encoder->disable/enable checks
  2012-08-19 19:12 ` [PATCH 12/58] drm/i915: rip out encoder->disable/enable checks Daniel Vetter
@ 2012-09-04 20:11   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:11 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:29 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> All encoders are now converted so there's no need for these checks any
> more.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 24 ++++++++----------------
>  1 file changed, 8 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 0d48ebe..4805385 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3267,10 +3267,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  	intel_crtc_update_cursor(crtc, true);
>  
>  encoders:
> -	for_each_encoder_on_crtc(dev, crtc, encoder) {
> -		if (encoder->enable)
> -			encoder->enable(encoder);
> -	}
> +	for_each_encoder_on_crtc(dev, crtc, encoder)
> +		encoder->enable(encoder);
>  }
>  
>  static void ironlake_crtc_disable(struct drm_crtc *crtc)
> @@ -3285,10 +3283,8 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
>  
>  	/* XXX: For compatability with the crtc helper code, call the encoder's
>  	 * disable function unconditionally for now. */
> -	for_each_encoder_on_crtc(dev, crtc, encoder) {
> -		if (encoder->disable)
> -			encoder->disable(encoder);
> -	}
> +	for_each_encoder_on_crtc(dev, crtc, encoder)
> +		encoder->disable(encoder);
>  
>  	if (!intel_crtc->active)
>  		return;
> @@ -3412,10 +3408,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
>  	intel_crtc_update_cursor(crtc, true);
>  
>  encoders:
> -	for_each_encoder_on_crtc(dev, crtc, encoder) {
> -		if (encoder->enable)
> -			encoder->enable(encoder);
> -	}
> +	for_each_encoder_on_crtc(dev, crtc, encoder)
> +		encoder->enable(encoder);
>  }
>  
>  static void i9xx_crtc_disable(struct drm_crtc *crtc)
> @@ -3429,10 +3423,8 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
>  
>  	/* XXX: For compatability with the crtc helper code, call the encoder's
>  	 * disable function unconditionally for now. */
> -	for_each_encoder_on_crtc(dev, crtc, encoder) {
> -		if (encoder->disable)
> -			encoder->disable(encoder);
> -	}
> +	for_each_encoder_on_crtc(dev, crtc, encoder)
> +		encoder->disable(encoder);
>  
>  	if (!intel_crtc->active)
>  		return;

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 13/58] drm/i915: clean up encoder_prepare/commit
  2012-08-19 19:12 ` [PATCH 13/58] drm/i915: clean up encoder_prepare/commit Daniel Vetter
@ 2012-09-04 20:12   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:12 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:30 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 23 +++--------------------
>  drivers/gpu/drm/i915/intel_drv.h     |  2 --
>  2 files changed, 3 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 4805385..07077b1 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3269,6 +3269,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  encoders:
>  	for_each_encoder_on_crtc(dev, crtc, encoder)
>  		encoder->enable(encoder);
> +
> +	if (HAS_PCH_CPT(dev))
> +		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
>  }
>  
>  static void ironlake_crtc_disable(struct drm_crtc *crtc)
> @@ -3524,26 +3527,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
>  	}
>  }
>  
> -void intel_encoder_prepare(struct drm_encoder *encoder)
> -{
> -	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
> -	/* lvds has its own version of prepare see intel_lvds_prepare */
> -	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
> -}
> -
> -void intel_encoder_commit(struct drm_encoder *encoder)
> -{
> -	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
> -	struct drm_device *dev = encoder->dev;
> -	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
> -
> -	/* lvds has its own version of commit see intel_lvds_commit */
> -	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
> -
> -	if (HAS_PCH_CPT(dev))
> -		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
> -}
> -
>  void intel_encoder_noop(struct drm_encoder *encoder)
>  {
>  }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 2456245..e59cac3 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);

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 14/58] drm/i915: copy&paste drm_crtc_helper_set_config
  2012-08-19 19:12 ` [PATCH 14/58] drm/i915: copy&paste drm_crtc_helper_set_config Daniel Vetter
@ 2012-09-04 20:13   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:13 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:31 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> And the following static functions required by it:
> drm_encoder_crtc_ok, drm_crtc_helper_disable
> 
> No changes safe for the s/drm/intel prefix change.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 314 ++++++++++++++++++++++++++++++++++-
>  1 file changed, 313 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 07077b1..33a5191 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6590,12 +6590,324 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = {
>  	.disable = intel_crtc_disable,
>  };
>  
> +static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
> +				  struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev;
> +	struct drm_crtc *tmp;
> +	int crtc_mask = 1;
> +
> +	WARN(!crtc, "checking null crtc?\n");
> +
> +	dev = crtc->dev;
> +
> +	list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
> +		if (tmp == crtc)
> +			break;
> +		crtc_mask <<= 1;
> +	}
> +
> +	if (encoder->possible_crtcs & crtc_mask)
> +		return true;
> +	return false;
> +}
> +
> +static int
> +intel_crtc_helper_disable(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_connector *connector;
> +	struct drm_encoder *encoder;
> +
> +	/* Decouple all encoders and their attached connectors from this crtc */
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> +		if (encoder->crtc != crtc)
> +			continue;
> +
> +		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +			if (connector->encoder != encoder)
> +				continue;
> +
> +			connector->encoder = NULL;
> +		}
> +	}
> +
> +	drm_helper_disable_unused_functions(dev);
> +	return 0;
> +}
> +
> +static int intel_crtc_set_config(struct drm_mode_set *set)
> +{
> +	struct drm_device *dev;
> +	struct drm_crtc *save_crtcs, *new_crtc, *crtc;
> +	struct drm_encoder *save_encoders, *new_encoder, *encoder;
> +	struct drm_framebuffer *old_fb = NULL;
> +	bool mode_changed = false; /* if true do a full mode set */
> +	bool fb_changed = false; /* if true and !mode_changed just do a flip */
> +	struct drm_connector *save_connectors, *connector;
> +	int count = 0, ro, fail = 0;
> +	struct drm_crtc_helper_funcs *crtc_funcs;
> +	struct drm_mode_set save_set;
> +	int ret;
> +	int i;
> +
> +	DRM_DEBUG_KMS("\n");
> +
> +	if (!set)
> +		return -EINVAL;
> +
> +	if (!set->crtc)
> +		return -EINVAL;
> +
> +	if (!set->crtc->helper_private)
> +		return -EINVAL;
> +
> +	crtc_funcs = set->crtc->helper_private;
> +
> +	if (!set->mode)
> +		set->fb = NULL;
> +
> +	if (set->fb) {
> +		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
> +				set->crtc->base.id, set->fb->base.id,
> +				(int)set->num_connectors, set->x, set->y);
> +	} else {
> +		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
> +		return intel_crtc_helper_disable(set->crtc);
> +	}
> +
> +	dev = set->crtc->dev;
> +
> +	/* Allocate space for the backup of all (non-pointer) crtc, encoder and
> +	 * connector data. */
> +	save_crtcs = kzalloc(dev->mode_config.num_crtc *
> +			     sizeof(struct drm_crtc), GFP_KERNEL);
> +	if (!save_crtcs)
> +		return -ENOMEM;
> +
> +	save_encoders = kzalloc(dev->mode_config.num_encoder *
> +				sizeof(struct drm_encoder), GFP_KERNEL);
> +	if (!save_encoders) {
> +		kfree(save_crtcs);
> +		return -ENOMEM;
> +	}
> +
> +	save_connectors = kzalloc(dev->mode_config.num_connector *
> +				sizeof(struct drm_connector), GFP_KERNEL);
> +	if (!save_connectors) {
> +		kfree(save_crtcs);
> +		kfree(save_encoders);
> +		return -ENOMEM;
> +	}
> +
> +	/* Copy data. Note that driver private data is not affected.
> +	 * 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) {
> +		save_crtcs[count++] = *crtc;
> +	}
> +
> +	count = 0;
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> +		save_encoders[count++] = *encoder;
> +	}
> +
> +	count = 0;
> +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +		save_connectors[count++] = *connector;
> +	}
> +
> +	save_set.crtc = set->crtc;
> +	save_set.mode = &set->crtc->mode;
> +	save_set.x = set->crtc->x;
> +	save_set.y = set->crtc->y;
> +	save_set.fb = set->crtc->fb;
> +
> +	/* We should be able to check here if the fb has the same properties
> +	 * and then just flip_or_move it */
> +	if (set->crtc->fb != set->fb) {
> +		/* If we have no fb then treat it as a full mode set */
> +		if (set->crtc->fb == NULL) {
> +			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
> +			mode_changed = true;
> +		} else if (set->fb == NULL) {
> +			mode_changed = true;
> +		} else if (set->fb->depth != set->crtc->fb->depth) {
> +			mode_changed = true;
> +		} else if (set->fb->bits_per_pixel !=
> +			   set->crtc->fb->bits_per_pixel) {
> +			mode_changed = true;
> +		} else
> +			fb_changed = true;
> +	}
> +
> +	if (set->x != set->crtc->x || set->y != set->crtc->y)
> +		fb_changed = true;
> +
> +	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
> +		DRM_DEBUG_KMS("modes are different, full mode set\n");
> +		drm_mode_debug_printmodeline(&set->crtc->mode);
> +		drm_mode_debug_printmodeline(set->mode);
> +		mode_changed = true;
> +	}
> +
> +	/* a) traverse passed in connector list and get encoders for them */
> +	count = 0;
> +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +		struct drm_connector_helper_funcs *connector_funcs =
> +			connector->helper_private;
> +		new_encoder = connector->encoder;
> +		for (ro = 0; ro < set->num_connectors; ro++) {
> +			if (set->connectors[ro] == connector) {
> +				new_encoder = connector_funcs->best_encoder(connector);
> +				/* if we can't get an encoder for a connector
> +				   we are setting now - then fail */
> +				if (new_encoder == NULL)
> +					/* don't break so fail path works correct */
> +					fail = 1;
> +				break;
> +			}
> +		}
> +
> +		if (new_encoder != connector->encoder) {
> +			DRM_DEBUG_KMS("encoder changed, full mode switch\n");
> +			mode_changed = true;
> +			/* If the encoder is reused for another connector, then
> +			 * the appropriate crtc will be set later.
> +			 */
> +			if (connector->encoder)
> +				connector->encoder->crtc = NULL;
> +			connector->encoder = new_encoder;
> +		}
> +	}
> +
> +	if (fail) {
> +		ret = -EINVAL;
> +		goto fail;
> +	}
> +
> +	count = 0;
> +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +		if (!connector->encoder)
> +			continue;
> +
> +		if (connector->encoder->crtc == set->crtc)
> +			new_crtc = NULL;
> +		else
> +			new_crtc = connector->encoder->crtc;
> +
> +		for (ro = 0; ro < set->num_connectors; ro++) {
> +			if (set->connectors[ro] == connector)
> +				new_crtc = set->crtc;
> +		}
> +
> +		/* Make sure the new CRTC will work with the encoder */
> +		if (new_crtc &&
> +		    !intel_encoder_crtc_ok(connector->encoder, new_crtc)) {
> +			ret = -EINVAL;
> +			goto fail;
> +		}
> +		if (new_crtc != connector->encoder->crtc) {
> +			DRM_DEBUG_KMS("crtc changed, full mode switch\n");
> +			mode_changed = true;
> +			connector->encoder->crtc = new_crtc;
> +		}
> +		if (new_crtc) {
> +			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
> +				connector->base.id, drm_get_connector_name(connector),
> +				new_crtc->base.id);
> +		} else {
> +			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
> +				connector->base.id, drm_get_connector_name(connector));
> +		}
> +	}
> +
> +	/* mode_set_base is not a required function */
> +	if (fb_changed && !crtc_funcs->mode_set_base)
> +		mode_changed = true;
> +
> +	if (mode_changed) {
> +		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
> +		if (set->crtc->enabled) {
> +			DRM_DEBUG_KMS("attempting to set mode from"
> +					" userspace\n");
> +			drm_mode_debug_printmodeline(set->mode);
> +			old_fb = set->crtc->fb;
> +			set->crtc->fb = set->fb;
> +			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
> +						      set->x, set->y,
> +						      old_fb)) {
> +				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
> +					  set->crtc->base.id);
> +				set->crtc->fb = old_fb;
> +				ret = -EINVAL;
> +				goto fail;
> +			}
> +			DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
> +			for (i = 0; i < set->num_connectors; i++) {
> +				DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
> +					      drm_get_connector_name(set->connectors[i]));
> +				set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
> +			}
> +		}
> +		drm_helper_disable_unused_functions(dev);
> +	} else if (fb_changed) {
> +		set->crtc->x = set->x;
> +		set->crtc->y = set->y;
> +
> +		old_fb = set->crtc->fb;
> +		if (set->crtc->fb != set->fb)
> +			set->crtc->fb = set->fb;
> +		ret = crtc_funcs->mode_set_base(set->crtc,
> +						set->x, set->y, old_fb);
> +		if (ret != 0) {
> +			set->crtc->fb = old_fb;
> +			goto fail;
> +		}
> +	}
> +
> +	kfree(save_connectors);
> +	kfree(save_encoders);
> +	kfree(save_crtcs);
> +	return 0;
> +
> +fail:
> +	/* Restore all previous data. */
> +	count = 0;
> +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> +		*crtc = save_crtcs[count++];
> +	}
> +
> +	count = 0;
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> +		*encoder = save_encoders[count++];
> +	}
> +
> +	count = 0;
> +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +		*connector = save_connectors[count++];
> +	}
> +
> +	/* Try to restore the config */
> +	if (mode_changed &&
> +	    !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
> +				      save_set.y, save_set.fb))
> +		DRM_ERROR("failed to restore config after modeset failure\n");
> +
> +	kfree(save_connectors);
> +	kfree(save_encoders);
> +	kfree(save_crtcs);
> +	return ret;
> +}
> +
>  static const struct drm_crtc_funcs intel_crtc_funcs = {
>  	.reset = intel_crtc_reset,
>  	.cursor_set = intel_crtc_cursor_set,
>  	.cursor_move = intel_crtc_cursor_move,
>  	.gamma_set = intel_crtc_gamma_set,
> -	.set_config = drm_crtc_helper_set_config,
> +	.set_config = intel_crtc_set_config,
>  	.destroy = intel_crtc_destroy,
>  	.page_flip = intel_crtc_page_flip,
>  };

Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org> (I did not check
line-by-line but it looks like the right shape :).

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 15/58] drm/i915: call set_base directly
  2012-08-19 19:12 ` [PATCH 15/58] drm/i915: call set_base directly Daniel Vetter
@ 2012-09-04 20:15   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:15 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:32 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> And drop the check, we always have it.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 11 ++---------
>  1 file changed, 2 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 33a5191..5dbe03a 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6584,7 +6584,6 @@ static void intel_crtc_reset(struct drm_crtc *crtc)
>  static struct drm_crtc_helper_funcs intel_helper_funcs = {
>  	.mode_fixup = intel_crtc_mode_fixup,
>  	.mode_set = intel_crtc_mode_set,
> -	.mode_set_base = intel_pipe_set_base,
>  	.mode_set_base_atomic = intel_pipe_set_base_atomic,
>  	.load_lut = intel_crtc_load_lut,
>  	.disable = intel_crtc_disable,
> @@ -6646,7 +6645,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  	bool fb_changed = false; /* if true and !mode_changed just do a flip */
>  	struct drm_connector *save_connectors, *connector;
>  	int count = 0, ro, fail = 0;
> -	struct drm_crtc_helper_funcs *crtc_funcs;
>  	struct drm_mode_set save_set;
>  	int ret;
>  	int i;
> @@ -6662,7 +6660,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  	if (!set->crtc->helper_private)
>  		return -EINVAL;
>  
> -	crtc_funcs = set->crtc->helper_private;
>  
>  	if (!set->mode)
>  		set->fb = NULL;
> @@ -6824,10 +6821,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  		}
>  	}
>  
> -	/* mode_set_base is not a required function */
> -	if (fb_changed && !crtc_funcs->mode_set_base)
> -		mode_changed = true;
> -
>  	if (mode_changed) {
>  		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
>  		if (set->crtc->enabled) {
> @@ -6860,8 +6853,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  		old_fb = set->crtc->fb;
>  		if (set->crtc->fb != set->fb)
>  			set->crtc->fb = set->fb;
> -		ret = crtc_funcs->mode_set_base(set->crtc,
> -						set->x, set->y, old_fb);
> +		ret = intel_pipe_set_base(set->crtc,
> +					  set->x, set->y, old_fb);
>  		if (ret != 0) {
>  			set->crtc->fb = old_fb;
>  			goto fail;

Woo.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 16/58] drm/i915: inline intel_best_encoder
  2012-08-19 19:12 ` [PATCH 16/58] drm/i915: inline intel_best_encoder Daniel Vetter
@ 2012-09-04 20:18   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:18 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:33 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Also kill the error-path, we have a fixed connector-encoder mapping.
> 
> Unfortunately we can't rip out all the ->best_encoder callbacks, these
> are all still used by the fb_helper. Neat helper layering violation there.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 18 +++---------------
>  1 file changed, 3 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 5dbe03a..9d5c575 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6644,7 +6644,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  	bool mode_changed = false; /* if true do a full mode set */
>  	bool fb_changed = false; /* if true and !mode_changed just do a flip */
>  	struct drm_connector *save_connectors, *connector;
> -	int count = 0, ro, fail = 0;
> +	int count = 0, ro;
>  	struct drm_mode_set save_set;
>  	int ret;
>  	int i;
> @@ -6660,7 +6660,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  	if (!set->crtc->helper_private)
>  		return -EINVAL;
>  
> -
>  	if (!set->mode)
>  		set->fb = NULL;
>  
> @@ -6753,17 +6752,11 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  	/* a) traverse passed in connector list and get encoders for them */
>  	count = 0;
>  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> -		struct drm_connector_helper_funcs *connector_funcs =
> -			connector->helper_private;
>  		new_encoder = connector->encoder;
>  		for (ro = 0; ro < set->num_connectors; ro++) {
>  			if (set->connectors[ro] == connector) {
> -				new_encoder = connector_funcs->best_encoder(connector);
> -				/* if we can't get an encoder for a connector
> -				   we are setting now - then fail */
> -				if (new_encoder == NULL)
> -					/* don't break so fail path works correct */
> -					fail = 1;
> +				new_encoder =
> +					&intel_attached_encoder(connector)->base;
>  				break;
>  			}
>  		}
> @@ -6780,11 +6773,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  		}
>  	}
>  
> -	if (fail) {
> -		ret = -EINVAL;
> -		goto fail;
> -	}
> -
>  	count = 0;
>  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
>  		if (!connector->encoder)

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 17/58] drm/i915: copy&paste drm_crtc_helper_set_mode
  2012-08-19 19:12 ` [PATCH 17/58] drm/i915: copy&paste drm_crtc_helper_set_mode Daniel Vetter
@ 2012-09-04 20:19   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:19 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:34 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 162 +++++++++++++++++++++++++++++++++--
>  drivers/gpu/drm/i915/intel_dp.c      |   5 +-
>  drivers/gpu/drm/i915/intel_drv.h     |   2 +
>  drivers/gpu/drm/i915/intel_hdmi.c    |   5 +-
>  drivers/gpu/drm/i915/intel_lvds.c    |   4 +-
>  drivers/gpu/drm/i915/intel_sdvo.c    |   4 +-
>  drivers/gpu/drm/i915/intel_tv.c      |   4 +-
>  7 files changed, 168 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 9d5c575..3e119a6 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5767,7 +5767,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
>  		goto fail;
>  	}
>  
> -	if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) {
> +	if (!intel_set_mode(crtc, mode, 0, 0, old_fb)) {
>  		DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
>  		if (old->release_fb)
>  			old->release_fb->funcs->destroy(old->release_fb);
> @@ -6635,6 +6635,157 @@ intel_crtc_helper_disable(struct drm_crtc *crtc)
>  	return 0;
>  }
>  
> +static void
> +intel_encoder_disable_helper(struct drm_encoder *encoder)
> +{
> +	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
> +
> +	if (encoder_funcs->disable)
> +		(*encoder_funcs->disable)(encoder);
> +	else
> +		(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
> +}
> +
> +static void
> +intel_crtc_prepare_encoders(struct drm_device *dev)
> +{
> +	struct drm_encoder_helper_funcs *encoder_funcs;
> +	struct drm_encoder *encoder;
> +
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> +		encoder_funcs = encoder->helper_private;
> +		/* Disable unused encoders */
> +		if (encoder->crtc == NULL)
> +			intel_encoder_disable_helper(encoder);
> +		/* Disable encoders whose CRTC is about to change */
> +		if (encoder_funcs->get_crtc &&
> +		    encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
> +			intel_encoder_disable_helper(encoder);
> +	}
> +}
> +
> +bool intel_set_mode(struct drm_crtc *crtc,
> +		    struct drm_display_mode *mode,
> +		    int x, int y, struct drm_framebuffer *old_fb)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
> +	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
> +	struct drm_encoder_helper_funcs *encoder_funcs;
> +	int saved_x, saved_y;
> +	struct drm_encoder *encoder;
> +	bool ret = true;
> +
> +	crtc->enabled = drm_helper_crtc_in_use(crtc);
> +	if (!crtc->enabled)
> +		return true;
> +
> +	adjusted_mode = drm_mode_duplicate(dev, mode);
> +	if (!adjusted_mode)
> +		return false;
> +
> +	saved_hwmode = crtc->hwmode;
> +	saved_mode = crtc->mode;
> +	saved_x = crtc->x;
> +	saved_y = crtc->y;
> +
> +	/* Update crtc values up front so the driver can rely on them for mode
> +	 * setting.
> +	 */
> +	crtc->mode = *mode;
> +	crtc->x = x;
> +	crtc->y = y;
> +
> +	/* Pass our mode to the connectors and the CRTC to give them a chance to
> +	 * adjust it according to limitations or connector properties, and also
> +	 * a chance to reject the mode entirely.
> +	 */
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> +
> +		if (encoder->crtc != crtc)
> +			continue;
> +		encoder_funcs = encoder->helper_private;
> +		if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
> +						      adjusted_mode))) {
> +			DRM_DEBUG_KMS("Encoder fixup failed\n");
> +			goto done;
> +		}
> +	}
> +
> +	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
> +		DRM_DEBUG_KMS("CRTC fixup failed\n");
> +		goto done;
> +	}
> +	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
> +
> +	/* Prepare the encoders and CRTCs before setting the mode. */
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> +
> +		if (encoder->crtc != crtc)
> +			continue;
> +		encoder_funcs = encoder->helper_private;
> +		/* Disable the encoders as the first thing we do. */
> +		encoder_funcs->prepare(encoder);
> +	}
> +
> +	intel_crtc_prepare_encoders(dev);
> +
> +	crtc_funcs->prepare(crtc);
> +
> +	/* Set up the DPLL and any encoders state that needs to adjust or depend
> +	 * on the DPLL.
> +	 */
> +	ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
> +	if (!ret)
> +	    goto done;
> +
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> +
> +		if (encoder->crtc != crtc)
> +			continue;
> +
> +		DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
> +			encoder->base.id, drm_get_encoder_name(encoder),
> +			mode->base.id, mode->name);
> +		encoder_funcs = encoder->helper_private;
> +		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
> +	}
> +
> +	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
> +	crtc_funcs->commit(crtc);
> +
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> +
> +		if (encoder->crtc != crtc)
> +			continue;
> +
> +		encoder_funcs = encoder->helper_private;
> +		encoder_funcs->commit(encoder);
> +
> +	}
> +
> +	/* Store real post-adjustment hardware mode. */
> +	crtc->hwmode = *adjusted_mode;
> +
> +	/* Calculate and store various constants which
> +	 * are later needed by vblank and swap-completion
> +	 * timestamping. They are derived from true hwmode.
> +	 */
> +	drm_calc_timestamping_constants(crtc);
> +
> +	/* FIXME: add subpixel order */
> +done:
> +	drm_mode_destroy(dev, adjusted_mode);
> +	if (!ret) {
> +		crtc->hwmode = saved_hwmode;
> +		crtc->mode = saved_mode;
> +		crtc->x = saved_x;
> +		crtc->y = saved_y;
> +	}
> +
> +	return ret;
> +}
> +
>  static int intel_crtc_set_config(struct drm_mode_set *set)
>  {
>  	struct drm_device *dev;
> @@ -6817,9 +6968,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  			drm_mode_debug_printmodeline(set->mode);
>  			old_fb = set->crtc->fb;
>  			set->crtc->fb = set->fb;
> -			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
> -						      set->x, set->y,
> -						      old_fb)) {
> +			if (!intel_set_mode(set->crtc, set->mode,
> +					    set->x, set->y, old_fb)) {
>  				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
>  					  set->crtc->base.id);
>  				set->crtc->fb = old_fb;
> @@ -6873,8 +7023,8 @@ fail:
>  
>  	/* Try to restore the config */
>  	if (mode_changed &&
> -	    !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
> -				      save_set.y, save_set.fb))
> +	    !intel_set_mode(save_set.crtc, save_set.mode,
> +			    save_set.x, save_set.y, save_set.fb))
>  		DRM_ERROR("failed to restore config after modeset failure\n");
>  
>  	kfree(save_connectors);
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 7ee954c..2abaaf6 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2312,9 +2312,8 @@ intel_dp_set_property(struct drm_connector *connector,
>  done:
>  	if (intel_dp->base.base.crtc) {
>  		struct drm_crtc *crtc = intel_dp->base.base.crtc;
> -		drm_crtc_helper_set_mode(crtc, &crtc->mode,
> -					 crtc->x, crtc->y,
> -					 crtc->fb);
> +		intel_set_mode(crtc, &crtc->mode,
> +			       crtc->x, crtc->y, crtc->fb);
>  	}
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index e59cac3..c28fada 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);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index acddaaa..ef84097 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -869,9 +869,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
>  done:
>  	if (intel_hdmi->base.base.crtc) {
>  		struct drm_crtc *crtc = intel_hdmi->base.base.crtc;
> -		drm_crtc_helper_set_mode(crtc, &crtc->mode,
> -					 crtc->x, crtc->y,
> -					 crtc->fb);
> +		intel_set_mode(crtc, &crtc->mode,
> +			       crtc->x, crtc->y, crtc->fb);
>  	}
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 3baa224..fad82b2 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -560,8 +560,8 @@ static int intel_lvds_set_property(struct drm_connector *connector,
>  			 * If the CRTC is enabled, the display will be changed
>  			 * according to the new panel fitting mode.
>  			 */
> -			drm_crtc_helper_set_mode(crtc, &crtc->mode,
> -				crtc->x, crtc->y, crtc->fb);
> +			intel_set_mode(crtc, &crtc->mode,
> +				       crtc->x, crtc->y, crtc->fb);
>  		}
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index a01c470..88fb30d 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -1879,8 +1879,8 @@ set_value:
>  done:
>  	if (intel_sdvo->base.base.crtc) {
>  		struct drm_crtc *crtc = intel_sdvo->base.base.crtc;
> -		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
> -					 crtc->y, crtc->fb);
> +		intel_set_mode(crtc, &crtc->mode,
> +			       crtc->x, crtc->y, crtc->fb);
>  	}
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
> index 281e0cf..16cb114 100644
> --- a/drivers/gpu/drm/i915/intel_tv.c
> +++ b/drivers/gpu/drm/i915/intel_tv.c
> @@ -1471,8 +1471,8 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
>  	}
>  
>  	if (changed && crtc)
> -		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
> -				crtc->y, crtc->fb);
> +		intel_set_mode(crtc, &crtc->mode,
> +			       crtc->x, crtc->y, crtc->fb);
>  out:
>  	return ret;
>  }

Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 18/58] drm/i915: simplify intel_crtc_prepare_encoders
  2012-08-19 19:12 ` [PATCH 18/58] drm/i915: simplify intel_crtc_prepare_encoders Daniel Vetter
@ 2012-09-04 20:20   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:20 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:35 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> - We don't have the ->get_crtc callback.
> - Call intel_encoder->disable directly.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 25 ++++---------------------
>  1 file changed, 4 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3e119a6..343f991 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6636,31 +6636,14 @@ intel_crtc_helper_disable(struct drm_crtc *crtc)
>  }
>  
>  static void
> -intel_encoder_disable_helper(struct drm_encoder *encoder)
> -{
> -	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
> -
> -	if (encoder_funcs->disable)
> -		(*encoder_funcs->disable)(encoder);
> -	else
> -		(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
> -}
> -
> -static void
>  intel_crtc_prepare_encoders(struct drm_device *dev)
>  {
> -	struct drm_encoder_helper_funcs *encoder_funcs;
> -	struct drm_encoder *encoder;
> +	struct intel_encoder *encoder;
>  
> -	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> -		encoder_funcs = encoder->helper_private;
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
>  		/* Disable unused encoders */
> -		if (encoder->crtc == NULL)
> -			intel_encoder_disable_helper(encoder);
> -		/* Disable encoders whose CRTC is about to change */
> -		if (encoder_funcs->get_crtc &&
> -		    encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
> -			intel_encoder_disable_helper(encoder);
> +		if (encoder->base.crtc == NULL)
> +			encoder->disable(encoder);
>  	}
>  }
>  

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 19/58] drm/i915: rip out encoder->prepare/commit
  2012-08-19 19:12 ` [PATCH 19/58] drm/i915: rip out encoder->prepare/commit Daniel Vetter
@ 2012-09-04 20:21   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:21 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:36 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> With the new infrastructure we're doing this when enabling/disabling
> the entire display pipe.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_crt.c     |  2 --
>  drivers/gpu/drm/i915/intel_display.c | 24 ------------------------
>  drivers/gpu/drm/i915/intel_dp.c      |  2 --
>  drivers/gpu/drm/i915/intel_drv.h     |  1 -
>  drivers/gpu/drm/i915/intel_dvo.c     |  2 --
>  drivers/gpu/drm/i915/intel_hdmi.c    |  4 ----
>  drivers/gpu/drm/i915/intel_lvds.c    |  2 --
>  drivers/gpu/drm/i915/intel_sdvo.c    |  2 --
>  drivers/gpu/drm/i915/intel_tv.c      |  2 --
>  9 files changed, 41 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index 15c1ff8..4ce0b46 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -617,8 +617,6 @@ static void intel_crt_reset(struct drm_connector *connector)
>  
>  static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
>  	.mode_fixup = intel_crt_mode_fixup,
> -	.prepare = intel_encoder_noop,
> -	.commit = intel_encoder_noop,
>  	.mode_set = intel_crt_mode_set,
>  	.disable = intel_encoder_disable,
>  };
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 343f991..d37a851 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3527,10 +3527,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
>  	}
>  }
>  
> -void intel_encoder_noop(struct drm_encoder *encoder)
> -{
> -}
> -
>  void intel_encoder_disable(struct drm_encoder *encoder)
>  {
>  	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
> @@ -6701,16 +6697,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  	}
>  	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
>  
> -	/* Prepare the encoders and CRTCs before setting the mode. */
> -	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> -
> -		if (encoder->crtc != crtc)
> -			continue;
> -		encoder_funcs = encoder->helper_private;
> -		/* Disable the encoders as the first thing we do. */
> -		encoder_funcs->prepare(encoder);
> -	}
> -
>  	intel_crtc_prepare_encoders(dev);
>  
>  	crtc_funcs->prepare(crtc);
> @@ -6737,16 +6723,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
>  	crtc_funcs->commit(crtc);
>  
> -	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> -
> -		if (encoder->crtc != crtc)
> -			continue;
> -
> -		encoder_funcs = encoder->helper_private;
> -		encoder_funcs->commit(encoder);
> -
> -	}
> -
>  	/* Store real post-adjustment hardware mode. */
>  	crtc->hwmode = *adjusted_mode;
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 2abaaf6..ff993a0 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2348,9 +2348,7 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  
>  static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
>  	.mode_fixup = intel_dp_mode_fixup,
> -	.prepare = intel_encoder_noop,
>  	.mode_set = intel_dp_mode_set,
> -	.commit = intel_encoder_noop,
>  	.disable = intel_encoder_disable,
>  };
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index c28fada..673e8d4 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);
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index c55a13e..84c0867 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -318,9 +318,7 @@ static void intel_dvo_destroy(struct drm_connector *connector)
>  
>  static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
>  	.mode_fixup = intel_dvo_mode_fixup,
> -	.prepare = intel_encoder_noop,
>  	.mode_set = intel_dvo_mode_set,
> -	.commit = intel_encoder_noop,
>  	.disable = intel_encoder_disable,
>  };
>  
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index ef84097..c9535ce 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -885,17 +885,13 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
>  
>  static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
>  	.mode_fixup = intel_hdmi_mode_fixup,
> -	.prepare = intel_encoder_noop,
>  	.mode_set = intel_ddi_mode_set,
> -	.commit = intel_encoder_noop,
>  	.disable = intel_encoder_disable,
>  };
>  
>  static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
>  	.mode_fixup = intel_hdmi_mode_fixup,
> -	.prepare = intel_encoder_noop,
>  	.mode_set = intel_hdmi_mode_set,
> -	.commit = intel_encoder_noop,
>  	.disable = intel_encoder_disable,
>  };
>  
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index fad82b2..5fc7abc 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -570,9 +570,7 @@ static int intel_lvds_set_property(struct drm_connector *connector,
>  
>  static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
>  	.mode_fixup = intel_lvds_mode_fixup,
> -	.prepare = intel_encoder_noop,
>  	.mode_set = intel_lvds_mode_set,
> -	.commit = intel_encoder_noop,
>  	.disable = intel_encoder_disable,
>  };
>  
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index 88fb30d..8cdc674 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -1889,9 +1889,7 @@ done:
>  
>  static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
>  	.mode_fixup = intel_sdvo_mode_fixup,
> -	.prepare = intel_encoder_noop,
>  	.mode_set = intel_sdvo_mode_set,
> -	.commit = intel_encoder_noop,
>  	.disable = intel_encoder_disable
>  };
>  
> diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
> index 16cb114..5dc08b9 100644
> --- a/drivers/gpu/drm/i915/intel_tv.c
> +++ b/drivers/gpu/drm/i915/intel_tv.c
> @@ -1479,9 +1479,7 @@ out:
>  
>  static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
>  	.mode_fixup = intel_tv_mode_fixup,
> -	.prepare = intel_encoder_noop,
>  	.mode_set = intel_tv_mode_set,
> -	.commit = intel_encoder_noop,
>  	.disable = intel_encoder_disable,
>  };
>  

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 20/58] drm/i915: call crtc functions directly
  2012-08-19 19:12 ` [PATCH 20/58] drm/i915: call crtc functions directly Daniel Vetter
@ 2012-09-04 20:22   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:22 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:37 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Instead of going through the crtc helper function tables.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 15 +++++----------
>  1 file changed, 5 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index d37a851..ca17010 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6578,8 +6578,6 @@ static void intel_crtc_reset(struct drm_crtc *crtc)
>  }
>  
>  static struct drm_crtc_helper_funcs intel_helper_funcs = {
> -	.mode_fixup = intel_crtc_mode_fixup,
> -	.mode_set = intel_crtc_mode_set,
>  	.mode_set_base_atomic = intel_pipe_set_base_atomic,
>  	.load_lut = intel_crtc_load_lut,
>  	.disable = intel_crtc_disable,
> @@ -6648,8 +6646,8 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  		    int x, int y, struct drm_framebuffer *old_fb)
>  {
>  	struct drm_device *dev = crtc->dev;
> +	drm_i915_private_t *dev_priv = dev->dev_private;
>  	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
> -	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
>  	struct drm_encoder_helper_funcs *encoder_funcs;
>  	int saved_x, saved_y;
>  	struct drm_encoder *encoder;
> @@ -6691,7 +6689,7 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  		}
>  	}
>  
> -	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
> +	if (!(ret = intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) {
>  		DRM_DEBUG_KMS("CRTC fixup failed\n");
>  		goto done;
>  	}
> @@ -6699,12 +6697,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  
>  	intel_crtc_prepare_encoders(dev);
>  
> -	crtc_funcs->prepare(crtc);
> +	dev_priv->display.crtc_disable(crtc);
>  
>  	/* Set up the DPLL and any encoders state that needs to adjust or depend
>  	 * on the DPLL.
>  	 */
> -	ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
> +	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
>  	if (!ret)
>  	    goto done;
>  
> @@ -6721,7 +6719,7 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  	}
>  
>  	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
> -	crtc_funcs->commit(crtc);
> +	dev_priv->display.crtc_enable(crtc);
>  
>  	/* Store real post-adjustment hardware mode. */
>  	crtc->hwmode = *adjusted_mode;
> @@ -7055,9 +7053,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
>  	intel_crtc->active = true; /* force the pipe off on setup_init_config */
>  	intel_crtc->bpp = 24; /* default for pre-Ironlake */
>  
> -	intel_helper_funcs.prepare = dev_priv->display.crtc_disable;
> -	intel_helper_funcs.commit = dev_priv->display.crtc_enable;
> -
>  	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
>  }
>  

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 21/58] drm/i915: WARN when trying to enabled an unused crtc
  2012-08-19 19:12 ` [PATCH 21/58] drm/i915: WARN when trying to enabled an unused crtc Daniel Vetter
@ 2012-09-04 20:23   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:23 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:38 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c |  4 ++++
>  drivers/gpu/drm/i915/intel_drv.h     | 10 +++++++++-
>  2 files changed, 13 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ca17010..5ab8694 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3215,6 +3215,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  	u32 temp;
>  	bool is_pch_port;
>  
> +	WARN_ON(!crtc->enabled);
> +
>  	/* XXX: For compatability with the crtc helper code, call the encoder's
>  	 * enable function unconditionally for now. */
>  	if (intel_crtc->active)
> @@ -3391,6 +3393,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
>  	int pipe = intel_crtc->pipe;
>  	int plane = intel_crtc->plane;
>  
> +	WARN_ON(!crtc->enabled);
> +
>  	/* XXX: For compatability with the crtc helper code, call the encoder's
>  	 * enable function unconditionally for now. */
>  	if (intel_crtc->active)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 673e8d4..36991de 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;

Looking forward to seeing this cleaned up.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 22/58] drm/i915: Add interfaces to read out encoder/connector hw state
  2012-08-19 19:12 ` [PATCH 22/58] drm/i915: Add interfaces to read out encoder/connector hw state Daniel Vetter
@ 2012-09-04 20:25   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:25 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:39 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 11 +++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |  8 ++++++++
>  2 files changed, 19 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 5ab8694..7e7569b 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3584,6 +3584,17 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
>  		encoder->connectors_active = false;
>  }
>  
> +/* Simple connector->get_hw_state implementation for encoders that support only
> + * one connector and no cloning and hence the encoder state determines the state
> + * of the connector. */
> +bool intel_connector_get_hw_state(struct intel_connector *connector)
> +{
> +	enum pipe pipe;
> +	struct intel_encoder *encoder = connector->encoder;
> +
> +	return encoder->get_hw_state(encoder, &pipe);
> +}
> +
>  static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
>  				  const struct drm_display_mode *mode,
>  				  struct drm_display_mode *adjusted_mode)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 36991de..c39c705 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)
>  {

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 23/58] drm/i915/dp: implement get_hw_state
  2012-08-19 19:12 ` [PATCH 23/58] drm/i915/dp: implement get_hw_state Daniel Vetter
@ 2012-09-04 20:26   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:26 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:40 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Also add some macros to make the pipe computation a bit easier.
> 
> v2: I've mixed up the CPT and !CPT PORT_TO_PIPE macro variants ...
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/i915_reg.h |  2 ++
>  drivers/gpu/drm/i915/intel_dp.c | 50 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 52 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index fd6a26a..1e5f77a 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -4029,6 +4029,8 @@
>  #define  PORT_TRANS_C_SEL_CPT	(2<<29)
>  #define  PORT_TRANS_SEL_MASK	(3<<29)
>  #define  PORT_TRANS_SEL_CPT(pipe)	((pipe) << 29)
> +#define  PORT_TO_PIPE(val)	(((val) & (1<<30)) >> 30)
> +#define  PORT_TO_PIPE_CPT(val)	(((val) & PORT_TRANS_SEL_MASK) >> 29)
>  
>  #define TRANS_DP_CTL_A		0xe0300
>  #define TRANS_DP_CTL_B		0xe1300
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index ff993a0..e3928b9 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1250,6 +1250,54 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
>  	}
>  }
>  
> +static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
> +				  enum pipe *pipe)
> +{
> +	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u32 tmp = I915_READ(intel_dp->output_reg);
> +
> +	if (!(tmp & DP_PORT_EN))
> +		return false;
> +
> +	if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
> +		*pipe = PORT_TO_PIPE_CPT(tmp);
> +	} else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
> +		*pipe = PORT_TO_PIPE(tmp);
> +	} else {
> +		u32 trans_sel;
> +		u32 trans_dp;
> +		int i;
> +
> +		switch (intel_dp->output_reg) {
> +		case PCH_DP_B:
> +			trans_sel = TRANS_DP_PORT_SEL_B;
> +			break;
> +		case PCH_DP_C:
> +			trans_sel = TRANS_DP_PORT_SEL_C;
> +			break;
> +		case PCH_DP_D:
> +			trans_sel = TRANS_DP_PORT_SEL_D;
> +			break;
> +		default:
> +			return true;
> +		}
> +
> +		for_each_pipe(i) {
> +			trans_dp = I915_READ(TRANS_DP_CTL(i));
> +			if ((trans_dp & TRANS_DP_PORT_SEL_MASK) == trans_sel) {
> +				*pipe = i;
> +				return true;
> +			}
> +		}
> +	}
> +
> +	DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n", intel_dp->output_reg);
> +
> +	return true;
> +}
> +
>  static void intel_disable_dp(struct intel_encoder *encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> @@ -2486,6 +2534,8 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
>  
>  	intel_encoder->enable = intel_enable_dp;
>  	intel_encoder->disable = intel_disable_dp;
> +	intel_encoder->get_hw_state = intel_dp_get_hw_state;
> +	intel_connector->get_hw_state = intel_connector_get_hw_state;
>  
>  	/* Set up the DDC bus. */
>  	switch (port) {

Why did the hw guys change the regs between PCH and CPU, and then
change them again...

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 24/58] drm/i915/hdmi: implement get_hw_state
  2012-08-19 19:12 ` [PATCH 24/58] drm/i915/hdmi: " Daniel Vetter
@ 2012-09-04 20:28   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:28 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:41 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c  | 29 +++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h  |  2 ++
>  drivers/gpu/drm/i915/intel_hdmi.c | 24 ++++++++++++++++++++++++
>  3 files changed, 55 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 38a7006..bfe3754 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -757,6 +757,35 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
>  	intel_hdmi->set_infoframes(encoder, adjusted_mode);
>  }
>  
> +bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
> +			    enum pipe *pipe)
> +{
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
> +	u32 tmp;
> +	int i;
> +
> +	tmp = I915_READ(DDI_BUF_CTL(intel_hdmi->ddi_port));
> +
> +	if (!(tmp & DDI_BUF_CTL_ENABLE))
> +		return false;
> +
> +	for_each_pipe(i) {
> +		tmp = I915_READ(DDI_FUNC_CTL(i));
> +
> +		if ((tmp & PIPE_DDI_PORT_MASK)
> +		    == PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port)) {
> +			*pipe = i;
> +			return true;
> +		}
> +	}
> +
> +	DRM_DEBUG_KMS("No pipe for ddi port %i found\n", intel_hdmi->ddi_port);
> +
> +	return true;
> +}
> +
>  void intel_enable_ddi(struct intel_encoder *encoder)
>  {
>  	struct drm_device *dev = encoder->base.dev;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index c39c705..4daa7e6 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);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index c9535ce..e7d5078 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -601,6 +601,27 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
>  	intel_hdmi->set_infoframes(encoder, adjusted_mode);
>  }
>  
> +static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
> +				    enum pipe *pipe)
> +{
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
> +	u32 tmp;
> +
> +	tmp = I915_READ(intel_hdmi->sdvox_reg);
> +
> +	if (!(tmp & SDVO_ENABLE))
> +		return false;
> +
> +	if (HAS_PCH_CPT(dev))
> +		*pipe = PORT_TO_PIPE_CPT(tmp);
> +	else
> +		*pipe = PORT_TO_PIPE(tmp);
> +
> +	return true;
> +}
> +
>  static void intel_enable_hdmi(struct intel_encoder *encoder)
>  {
>  	struct drm_device *dev = encoder->base.dev;
> @@ -998,14 +1019,17 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
>  	if (IS_HASWELL(dev)) {
>  		intel_encoder->enable = intel_enable_ddi;
>  		intel_encoder->disable = intel_disable_ddi;
> +		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
>  		drm_encoder_helper_add(&intel_encoder->base,
>  				       &intel_hdmi_helper_funcs_hsw);
>  	} else {
>  		intel_encoder->enable = intel_enable_hdmi;
>  		intel_encoder->disable = intel_disable_hdmi;
> +		intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
>  		drm_encoder_helper_add(&intel_encoder->base,
>  				       &intel_hdmi_helper_funcs);
>  	}
> +	intel_connector->get_hw_state = intel_connector_get_hw_state;
>  
>  
>  	intel_hdmi_add_properties(intel_hdmi, connector);

Should DDI be split out and come first?

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 25/58] drm/i915/tv: implement get_hw_state
  2012-08-19 19:12 ` [PATCH 25/58] drm/i915/tv: " Daniel Vetter
@ 2012-09-04 20:28   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:28 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:42 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_tv.c | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
> index 5dc08b9..98ad7fd 100644
> --- a/drivers/gpu/drm/i915/intel_tv.c
> +++ b/drivers/gpu/drm/i915/intel_tv.c
> @@ -836,6 +836,21 @@ static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
>  			    base);
>  }
>  
> +static bool
> +intel_tv_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe)
> +{
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u32 tmp = I915_READ(TV_CTL);
> +
> +	if (!(tmp & TV_ENC_ENABLE))
> +		return false;
> +
> +	*pipe = PORT_TO_PIPE(tmp);
> +
> +	return true;
> +}
> +
>  static void
>  intel_enable_tv(struct intel_encoder *encoder)
>  {
> @@ -1616,6 +1631,8 @@ intel_tv_init(struct drm_device *dev)
>  
>  	intel_encoder->enable = intel_enable_tv;
>  	intel_encoder->disable = intel_disable_tv;
> +	intel_encoder->get_hw_state = intel_tv_get_hw_state;
> +	intel_connector->get_hw_state = intel_connector_get_hw_state;
>  
>  	intel_connector_attach_encoder(intel_connector, intel_encoder);
>  	intel_encoder->type = INTEL_OUTPUT_TVOUT;

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 26/58] drm/i915/lvds: implement get_hw_state
  2012-08-19 19:12 ` [PATCH 26/58] drm/i915/lvds: " Daniel Vetter
@ 2012-09-04 20:28   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:28 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:43 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_lvds.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 5fc7abc..52f9e7f 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -65,6 +65,32 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
>  			    struct intel_lvds, base);
>  }
>  
> +static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
> +				    enum pipe *pipe)
> +{
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u32 lvds_reg, tmp;
> +
> +	if (HAS_PCH_SPLIT(dev)) {
> +		lvds_reg = PCH_LVDS;
> +	} else {
> +		lvds_reg = LVDS;
> +	}
> +
> +	tmp = I915_READ(lvds_reg);
> +
> +	if (!(tmp & LVDS_PORT_EN))
> +		return false;
> +
> +	if (HAS_PCH_CPT(dev))
> +		*pipe = PORT_TO_PIPE_CPT(tmp);
> +	else
> +		*pipe = PORT_TO_PIPE(tmp);
> +
> +	return true;
> +}
> +
>  /**
>   * Sets the power state for the panel.
>   */
> @@ -937,6 +963,8 @@ bool intel_lvds_init(struct drm_device *dev)
>  
>  	intel_encoder->enable = intel_enable_lvds;
>  	intel_encoder->disable = intel_disable_lvds;
> +	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
> +	intel_connector->get_hw_state = intel_connector_get_hw_state;
>  
>  	intel_connector_attach_encoder(intel_connector, intel_encoder);
>  	intel_encoder->type = INTEL_OUTPUT_LVDS;

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 27/58] drm/i915/crt: implement get_hw_state
  2012-08-19 19:12 ` [PATCH 27/58] drm/i915/crt: " Daniel Vetter
@ 2012-09-04 20:29   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:29 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:44 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Note that even though this connector is cloneable we still can use the
> exact same test to check whether the connector is on or whether the
> encoder is enabled - both the dpms code and the encoder disable/enable
> frob the exact same hw state.
> 
> For dvo/sdvo outputs, this will be different.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_crt.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index 4ce0b46..fab54ed 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -61,6 +61,27 @@ static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
>  	return container_of(encoder, struct intel_crt, base);
>  }
>  
> +static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
> +				   enum pipe *pipe)
> +{
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_crt *crt = intel_encoder_to_crt(encoder);
> +	u32 tmp;
> +
> +	tmp = I915_READ(crt->adpa_reg);
> +
> +	if (!(tmp & ADPA_DAC_ENABLE))
> +		return false;
> +
> +	if (HAS_PCH_CPT(dev))
> +		*pipe = PORT_TO_PIPE_CPT(tmp);
> +	else
> +		*pipe = PORT_TO_PIPE(tmp);
> +
> +	return true;
> +}
> +
>  static void intel_disable_crt(struct intel_encoder *encoder)
>  {
>  	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> @@ -710,6 +731,8 @@ void intel_crt_init(struct drm_device *dev)
>  
>  	crt->base.disable = intel_disable_crt;
>  	crt->base.enable = intel_enable_crt;
> +	crt->base.get_hw_state = intel_crt_get_hw_state;
> +	intel_connector->get_hw_state = intel_connector_get_hw_state;
>  
>  	drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs);
>  	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 28/58] drm/i915/sdvo: implement get_hw_state
  2012-08-19 19:12 ` [PATCH 28/58] drm/i915/sdvo: " Daniel Vetter
@ 2012-09-04 20:31   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:31 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:45 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> SDVO is the first real special case - we support multiple outputs on
> the same encoder and the encoder dpms state isn't the same as when
> just disabling the outputs when the encoder is cloned.
> 
> Hence we need a real connector get_hw_state function which inquires
> the sdvo encoder about its active outputs.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_sdvo.c | 46 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 46 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index 8cdc674..4a735a5 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -628,6 +628,14 @@ static bool intel_sdvo_set_active_outputs(struct intel_sdvo *intel_sdvo,
>  				    &outputs, sizeof(outputs));
>  }
>  
> +static bool intel_sdvo_get_active_outputs(struct intel_sdvo *intel_sdvo,
> +					  u16 *outputs)
> +{
> +	return intel_sdvo_get_value(intel_sdvo,
> +				    SDVO_CMD_GET_ACTIVE_OUTPUTS,
> +				    outputs, sizeof(*outputs));
> +}
> +
>  static bool intel_sdvo_set_encoder_power_state(struct intel_sdvo *intel_sdvo,
>  					       int mode)
>  {
> @@ -1142,6 +1150,42 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
>  	intel_sdvo_write_sdvox(intel_sdvo, sdvox);
>  }
>  
> +static bool intel_sdvo_connector_get_hw_state(struct intel_connector *connector)
> +{
> +	struct intel_sdvo_connector *intel_sdvo_connector =
> +		to_intel_sdvo_connector(&connector->base);
> +	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(&connector->base);
> +	u16 active_outputs;
> +
> +	intel_sdvo_get_active_outputs(intel_sdvo, &active_outputs);
> +
> +	if (active_outputs & intel_sdvo_connector->output_flag)
> +		return true;
> +	else
> +		return false;
> +}
> +
> +static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
> +				    enum pipe *pipe)
> +{
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
> +	u32 tmp;
> +
> +	tmp = I915_READ(intel_sdvo->sdvo_reg);
> +
> +	if (!(tmp & SDVO_ENABLE))
> +		return false;
> +
> +	if (HAS_PCH_CPT(dev))
> +		*pipe = PORT_TO_PIPE_CPT(tmp);
> +	else
> +		*pipe = PORT_TO_PIPE(tmp);
> +
> +	return true;
> +}
> +
>  static void intel_disable_sdvo(struct intel_encoder *encoder)
>  {
>  	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> @@ -2066,6 +2110,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
>  	connector->base.base.interlace_allowed = 1;
>  	connector->base.base.doublescan_allowed = 0;
>  	connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
> +	connector->base.get_hw_state = intel_sdvo_connector_get_hw_state;
>  
>  	intel_connector_attach_encoder(&connector->base, &encoder->base);
>  	drm_sysfs_connector_add(&connector->base.base);
> @@ -2619,6 +2664,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
>  
>  	intel_encoder->disable = intel_disable_sdvo;
>  	intel_encoder->enable = intel_enable_sdvo;
> +	intel_encoder->get_hw_state = intel_sdvo_get_hw_state;
>  
>  	/* In default case sdvo lvds is false */
>  	if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 29/58] drm/i915/dvo: implement get_hw_state
  2012-08-19 19:12 ` [PATCH 29/58] drm/i915/dvo: " Daniel Vetter
@ 2012-09-04 20:32   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-04 20:32 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:46 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Similar to the sdvo code we poke the dvo encoder whether the output is
> active. Safe that dvo encoders are not standardized, so this requires
> a new callback into the dvo chip driver.
> 
> Hence implement that for all 6 dvo drivers.
> 
> v2: With the newly added ns2501 we now have 6 dvo drivers instead of
> just 5 ...
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/dvo.h        |  6 ++++++
>  drivers/gpu/drm/i915/dvo_ch7017.c | 13 +++++++++++++
>  drivers/gpu/drm/i915/dvo_ch7xxx.c | 13 +++++++++++++
>  drivers/gpu/drm/i915/dvo_ivch.c   | 15 +++++++++++++++
>  drivers/gpu/drm/i915/dvo_ns2501.c | 15 +++++++++++++++
>  drivers/gpu/drm/i915/dvo_sil164.c | 16 ++++++++++++++++
>  drivers/gpu/drm/i915/dvo_tfp410.c | 14 ++++++++++++++
>  drivers/gpu/drm/i915/intel_dvo.c  | 27 +++++++++++++++++++++++++++
>  8 files changed, 119 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
> index 0fa839e..74b5efc 100644
> --- a/drivers/gpu/drm/i915/dvo.h
> +++ b/drivers/gpu/drm/i915/dvo.h
> @@ -114,6 +114,12 @@ struct intel_dvo_dev_ops {
>  	 */
>  	enum drm_connector_status (*detect)(struct intel_dvo_device *dvo);
>  
> +	/*
> +	 * Probe the current hw status, returning true if the connected output
> +	 * is active.
> +	 */
> +	bool (*get_hw_state)(struct intel_dvo_device *dev);
> +
>  	/**
>  	 * Query the device for the modes it provides.
>  	 *
> diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
> index 71e7650..86b27d1 100644
> --- a/drivers/gpu/drm/i915/dvo_ch7017.c
> +++ b/drivers/gpu/drm/i915/dvo_ch7017.c
> @@ -359,6 +359,18 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, bool enable)
>  	msleep(20);
>  }
>  
> +static bool ch7017_get_hw_state(struct intel_dvo_device *dvo)
> +{
> +	uint8_t val;
> +
> +	ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &val);
> +
> +	if (val & CH7017_LVDS_POWER_DOWN_EN)
> +		return false;
> +	else
> +		return true;
> +}
> +
>  static void ch7017_dump_regs(struct intel_dvo_device *dvo)
>  {
>  	uint8_t val;
> @@ -396,6 +408,7 @@ struct intel_dvo_dev_ops ch7017_ops = {
>  	.mode_valid = ch7017_mode_valid,
>  	.mode_set = ch7017_mode_set,
>  	.dpms = ch7017_dpms,
> +	.get_hw_state = ch7017_get_hw_state,
>  	.dump_regs = ch7017_dump_regs,
>  	.destroy = ch7017_destroy,
>  };
> diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
> index c1dea5b..38f3a6c 100644
> --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
> +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
> @@ -297,6 +297,18 @@ static void ch7xxx_dpms(struct intel_dvo_device *dvo, bool enable)
>  		ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_FPD);
>  }
>  
> +static bool ch7xxx_get_hw_state(struct intel_dvo_device *dvo)
> +{
> +	u8 val;
> +
> +	ch7xxx_readb(dvo, CH7xxx_PM, &val);
> +
> +	if (val & CH7xxx_PM_FPD)
> +		return false;
> +	else
> +		return true;
> +}
> +
>  static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
>  {
>  	int i;
> @@ -326,6 +338,7 @@ struct intel_dvo_dev_ops ch7xxx_ops = {
>  	.mode_valid = ch7xxx_mode_valid,
>  	.mode_set = ch7xxx_mode_set,
>  	.dpms = ch7xxx_dpms,
> +	.get_hw_state = ch7xxx_get_hw_state,
>  	.dump_regs = ch7xxx_dump_regs,
>  	.destroy = ch7xxx_destroy,
>  };
> diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
> index fa8ff6b..baaf65b 100644
> --- a/drivers/gpu/drm/i915/dvo_ivch.c
> +++ b/drivers/gpu/drm/i915/dvo_ivch.c
> @@ -323,6 +323,20 @@ static void ivch_dpms(struct intel_dvo_device *dvo, bool enable)
>  	udelay(16 * 1000);
>  }
>  
> +static bool ivch_get_hw_state(struct intel_dvo_device *dvo)
> +{
> +	uint16_t vr01;
> +
> +	/* Set the new power state of the panel. */
> +	if (!ivch_read(dvo, VR01, &vr01))
> +		return false;
> +
> +	if (vr01 & VR01_LCD_ENABLE)
> +		return true;
> +	else
> +		return false;
> +}
> +
>  static void ivch_mode_set(struct intel_dvo_device *dvo,
>  			  struct drm_display_mode *mode,
>  			  struct drm_display_mode *adjusted_mode)
> @@ -413,6 +427,7 @@ static void ivch_destroy(struct intel_dvo_device *dvo)
>  struct intel_dvo_dev_ops ivch_ops = {
>  	.init = ivch_init,
>  	.dpms = ivch_dpms,
> +	.get_hw_state = ivch_get_hw_state,
>  	.mode_valid = ivch_mode_valid,
>  	.mode_set = ivch_mode_set,
>  	.detect = ivch_detect,
> diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c
> index c4d9f2f..c4a255b 100644
> --- a/drivers/gpu/drm/i915/dvo_ns2501.c
> +++ b/drivers/gpu/drm/i915/dvo_ns2501.c
> @@ -493,6 +493,20 @@ static void ns2501_mode_set(struct intel_dvo_device *dvo,
>  }
>  
>  /* set the NS2501 power state */
> +static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
> +{
> +	unsigned char ch;
> +
> +	if (!ns2501_readb(dvo, NS2501_REG8, &ch))
> +		return false;
> +
> +	if (ch & NS2501_8_PD)
> +		return true;
> +	else
> +		return false;
> +}
> +
> +/* set the NS2501 power state */
>  static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
>  {
>  	bool ok;
> @@ -568,6 +582,7 @@ struct intel_dvo_dev_ops ns2501_ops = {
>  	.mode_valid = ns2501_mode_valid,
>  	.mode_set = ns2501_mode_set,
>  	.dpms = ns2501_dpms,
> +	.get_hw_state = ns2501_get_hw_state,
>  	.dump_regs = ns2501_dump_regs,
>  	.destroy = ns2501_destroy,
>  };
> diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
> index cc24c1c..4debd32 100644
> --- a/drivers/gpu/drm/i915/dvo_sil164.c
> +++ b/drivers/gpu/drm/i915/dvo_sil164.c
> @@ -226,6 +226,21 @@ static void sil164_dpms(struct intel_dvo_device *dvo, bool enable)
>  	return;
>  }
>  
> +static bool sil164_get_hw_state(struct intel_dvo_device *dvo)
> +{
> +	int ret;
> +	unsigned char ch;
> +
> +	ret = sil164_readb(dvo, SIL164_REG8, &ch);
> +	if (ret == false)
> +		return false;
> +
> +	if (ch & SIL164_8_PD)
> +		return true;
> +	else
> +		return false;
> +}
> +
>  static void sil164_dump_regs(struct intel_dvo_device *dvo)
>  {
>  	uint8_t val;
> @@ -258,6 +273,7 @@ struct intel_dvo_dev_ops sil164_ops = {
>  	.mode_valid = sil164_mode_valid,
>  	.mode_set = sil164_mode_set,
>  	.dpms = sil164_dpms,
> +	.get_hw_state = sil164_get_hw_state,
>  	.dump_regs = sil164_dump_regs,
>  	.destroy = sil164_destroy,
>  };
> diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
> index 097b3e8..e17f1b0 100644
> --- a/drivers/gpu/drm/i915/dvo_tfp410.c
> +++ b/drivers/gpu/drm/i915/dvo_tfp410.c
> @@ -249,6 +249,19 @@ static void tfp410_dpms(struct intel_dvo_device *dvo, bool enable)
>  	tfp410_writeb(dvo, TFP410_CTL_1, ctl1);
>  }
>  
> +static bool tfp410_get_hw_state(struct intel_dvo_device *dvo)
> +{
> +	uint8_t ctl1;
> +
> +	if (!tfp410_readb(dvo, TFP410_CTL_1, &ctl1))
> +		return false;
> +
> +	if (ctl1 & TFP410_CTL_1_PD)
> +		return true;
> +	else
> +		return false;
> +}
> +
>  static void tfp410_dump_regs(struct intel_dvo_device *dvo)
>  {
>  	uint8_t val, val2;
> @@ -299,6 +312,7 @@ struct intel_dvo_dev_ops tfp410_ops = {
>  	.mode_valid = tfp410_mode_valid,
>  	.mode_set = tfp410_mode_set,
>  	.dpms = tfp410_dpms,
> +	.get_hw_state = tfp410_get_hw_state,
>  	.dump_regs = tfp410_dump_regs,
>  	.destroy = tfp410_destroy,
>  };
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index 84c0867..e9397b7 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -105,6 +105,31 @@ static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector)
>  			    struct intel_dvo, base);
>  }
>  
> +static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector)
> +{
> +	struct intel_dvo *intel_dvo = intel_attached_dvo(&connector->base);
> +
> +	return intel_dvo->dev.dev_ops->get_hw_state(&intel_dvo->dev);
> +}
> +
> +static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
> +				   enum pipe *pipe)
> +{
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
> +	u32 tmp;
> +
> +	tmp = I915_READ(intel_dvo->dev.dvo_reg);
> +
> +	if (!(tmp & DVO_ENABLE))
> +		return false;
> +
> +	*pipe = PORT_TO_PIPE(tmp);
> +
> +	return true;
> +}
> +
>  static void intel_disable_dvo(struct intel_encoder *encoder)
>  {
>  	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
> @@ -414,6 +439,8 @@ void intel_dvo_init(struct drm_device *dev)
>  
>  	intel_encoder->disable = intel_disable_dvo;
>  	intel_encoder->enable = intel_enable_dvo;
> +	intel_encoder->get_hw_state = intel_dvo_get_hw_state;
> +	intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
>  
>  	/* Now, try to find a controller */
>  	for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {

Uhh yes.

Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 30/58] drm/i915: read out the modeset hw state at load and resume time
  2012-08-19 19:12 ` [PATCH 30/58] drm/i915: read out the modeset hw state at load and resume time Daniel Vetter
@ 2012-09-05 16:14   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:14 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:47 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> +static void
> +intel_connector_break_all_links(struct intel_connector *connector)
> +{
> +	connector->base.dpms = DRM_MODE_DPMS_OFF;
> +	connector->base.encoder = NULL;
> +	connector->encoder->connectors_active = false;
> +	connector->encoder->base.crtc = NULL;
> +}

Maybe connector_clear_state() or init_state()? instead?

> +
> +static void intel_sanitize_crtc(struct intel_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u32 reg, val;
> +
> +	/* Clear the dpms state for compatibility with code still using that
> +	 * deprecated state variable. */
> +	crtc->dpms_mode = -1;
> +
> +	/* Clear any frame start delays used for debugging left by the BIOS */
> +	reg = PIPECONF(crtc->pipe);
> +	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
> +
> +	/* We need to sanitize the plane -> pipe mapping first because this will
> +	 * disable the crtc (and hence change the state) if it is wrong. */
> +	if (!HAS_PCH_SPLIT(dev)) {
> +		struct intel_connector *connector;
> +		bool plane;
> +
> +		reg = DSPCNTR(crtc->plane);
> +		val = I915_READ(reg);
> +
> +		if ((val & DISPLAY_PLANE_ENABLE) == 0 &&
> +		    (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
> +			goto ok;
> +
> +		DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
> +			      crtc->base.base.id);
> +
> +		/* Pipe has the wrong plane attached and the plane is active.
> +		 * Temporarily change the plane mapping and disable everything
> +		 * ...  */
> +		plane = crtc->plane;
> +		crtc->plane = !plane;
> +		dev_priv->display.crtc_disable(&crtc->base);
> +		crtc->plane = plane;
> +
> +		/* ... and break all links. */
> +		list_for_each_entry(connector, &dev->mode_config.connector_list,
> +				    base.head) {
> +			if (connector->encoder->base.crtc != &crtc->base)
> +				continue;
> +
> +			intel_connector_break_all_links(connector);
> +		}
> +
> +		WARN_ON(crtc->active);
> +		crtc->base.enabled = false;
> +	}
> +ok:
> +
> +	/* Adjust the state of the output pipe according to whether we
> +	 * have active connectors/encoders. */
> +	intel_crtc_update_dpms(&crtc->base);
> +
> +	if (crtc->active != crtc->base.enabled) {
> +		struct intel_encoder *encoder;
> +
> +		/* This can happen either due to bugs in the get_hw_state
> +		 * functions or because the pipe is force-enabled due to the
> +		 * pipe A quirk. */
> +		DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
> +			      crtc->base.base.id,
> +			      crtc->base.enabled ? "enabled" : "disabled",
> +			      crtc->active ? "enabled" : "disabled");
> +
> +		crtc->base.enabled = crtc->active;
> +
> +		/* Because we only establish the connector -> encoder ->
> +		 * crtc links if something is active, this means the
> +		 * crtc is now deactivated. Break the links. connector
> +		 * -> encoder links are only establish when things are
> +		 *  actually up, hence no need to break them. */
> +		WARN_ON(crtc->active);
> +
> +		for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
> +			WARN_ON(encoder->connectors_active);
> +			encoder->base.crtc = NULL;
> +		}
> +	}
> +}
> +
> +static void intel_sanitize_encoder(struct intel_encoder *encoder)
> +{
> +	struct intel_connector *connector;
> +	struct drm_device *dev = encoder->base.dev;
> +
> +	/* We need to check both for a crtc link (meaning that the
> +	 * encoder is active and trying to read from a pipe) and the
> +	 * pipe itself being active. */
> +	bool has_active_crtc = encoder->base.crtc &&
> +		to_intel_crtc(encoder->base.crtc)->active;
> +
> +	if (encoder->connectors_active && !has_active_crtc) {
> +		DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n",
> +			      encoder->base.base.id,
> +			      drm_get_encoder_name(&encoder->base));
> +
> +		/* Connector is active, but has no active pipe. This is
> +		 * fallout from our resume register restoring. Disable
> +		 * the encoder manually again. */
> +		if (encoder->base.crtc) {
> +			DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
> +				      encoder->base.base.id,
> +				      drm_get_encoder_name(&encoder->base));
> +			encoder->disable(encoder);
> +		}
> +
> +		/* Inconsisten output/port/pipe state happens presumably due to
> +		 * a bug in one of the get_hw_state functions. Or someplace else
> +		 * in our code, like the register restore mess on resume. Clamp
> +		 * things to off as a safer default. */
> +		list_for_each_entry(connector,
> +				    &dev->mode_config.connector_list,
> +				    base.head) {
> +			if (connector->encoder != encoder)
> +				continue;
> +
> +			intel_connector_break_all_links(connector);
> +		}
> +	}
> +	/* Enabled encoders without active connectors will be fixed in
> +	 * the crtc fixup. */
> +}
> +
> +/* Scan out the current hw modeset state, sanitizes it and maps it into the drm
> + * and i915 state tracking structures. */
> +void intel_modeset_setup_hw_state(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	enum pipe pipe;
> +	u32 tmp;
> +	struct intel_crtc *crtc;
> +	struct intel_encoder *encoder;
> +	struct intel_connector *connector;
> +
> +	for_each_pipe(pipe) {
> +		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
> +
> +		tmp = I915_READ(PIPECONF(pipe));
> +		if (tmp & PIPECONF_ENABLE)
> +			crtc->active = true;
> +		else
> +			crtc->active = false;
> +
> +		crtc->base.enabled = crtc->active;
> +
> +		DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
> +			      crtc->base.base.id,
> +			      crtc->active ? "enabled" : "disabled");
> +	}
> +
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
> +			    base.head) {
> +		pipe = 0;
> +
> +		if (encoder->get_hw_state(encoder, &pipe)) {
> +			encoder->base.crtc =
> +				dev_priv->pipe_to_crtc_mapping[pipe];
> +		} else {
> +			encoder->base.crtc = NULL;
> +		}
> +
> +		encoder->connectors_active = false;
> +		DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe=%i\n",
> +			      encoder->base.base.id,
> +			      drm_get_encoder_name(&encoder->base),
> +			      encoder->base.crtc ? "enabled" : "disabled",
> +			      pipe);
> +	}
> +
> +	list_for_each_entry(connector, &dev->mode_config.connector_list,
> +			    base.head) {
> +		if (connector->get_hw_state(connector)) {
> +			connector->base.dpms = DRM_MODE_DPMS_ON;
> +			connector->encoder->connectors_active = true;
> +			connector->base.encoder = &connector->encoder->base;
> +		} else {
> +			connector->base.dpms = DRM_MODE_DPMS_OFF;
> +			connector->base.encoder = NULL;
> +		}
> +		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hw state readout: %s\n",
> +			      connector->base.base.id,
> +			      drm_get_connector_name(&connector->base),
> +			      connector->base.encoder ? "enabled" : "disabled");
> +	}
> +
> +	/* HW state is read out, now we need to sanitize this mess. */
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
> +			    base.head) {
> +		intel_sanitize_encoder(encoder);
> +	}
> +
> +	for_each_pipe(pipe) {
> +		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
> +		intel_sanitize_crtc(crtc);
> +	}
> +}

I was going to suggest calling this fetch_hw_state or something, but it
really does do some sanitizing, so maybe setup_hw_state is ok...

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 31/58] drm/i915: check connector hw/sw state
  2012-08-19 19:12 ` [PATCH 31/58] drm/i915: check connector hw/sw state Daniel Vetter
@ 2012-09-05 16:26   ` Jesse Barnes
  2012-09-05 19:10     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:26 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:48 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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).

Nice.  Only comment is that we may want to call it assert_state() to
match our other assertions.  But no biggie.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 32/58] drm/i915: rip out intel_crtc->dpms_mode
  2012-08-19 19:12 ` [PATCH 32/58] drm/i915: rip out intel_crtc->dpms_mode Daniel Vetter
@ 2012-09-05 16:27   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:27 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:49 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.

Yay!

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 33/58] drm/i915: rip out intel_dp->dpms_mode
  2012-08-19 19:12 ` [PATCH 33/58] drm/i915: rip out intel_dp->dpms_mode Daniel Vetter
@ 2012-09-05 16:28   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:28 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:50 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.

Yay2!

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 34/58] drm/i915: ensure the force pipe A quirk is actually followed
  2012-08-19 19:12 ` [PATCH 34/58] drm/i915: ensure the force pipe A quirk is actually followed Daniel Vetter
@ 2012-09-05 16:32   ` Jesse Barnes
  2012-09-05 19:12     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:32 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:51 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Many BIOSen forget to turn on the pipe A after resume (because they
> actually don't turn on anything), so we have to do that ourselves when
> sanitizing the hw state.
> 
> I've discovered this due to the recent addition of a pipe WARN that
> takes the force quirk into account.
> 
> v2: Actually try to enable the pipe with a proper configuration instead
> of simpyl switching it on with whatever random state the bios left it
> in after resume.
> 
> v3: Fixup rebase conflict - the load_detect functions have lost their
> encoder argument.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 36 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 2cfb397..ab4fa7f 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -7602,6 +7602,33 @@ intel_connector_break_all_links(struct intel_connector *connector)
>  	connector->encoder->base.crtc = NULL;
>  }
>  
> +static void intel_enable_pipe_a(struct drm_device *dev)
> +{
> +	struct intel_connector *connector;
> +	struct drm_connector *crt = NULL;
> +	struct intel_load_detect_pipe load_detect_temp;
> +
> +	/* We can't just switch on the pipe A, we need to set things up with a
> +	 * proper mode and output configuration. As a gross hack, enable pipe A
> +	 * by enabling the load detect pipe once. */
> +	list_for_each_entry(connector,
> +			    &dev->mode_config.connector_list,
> +			    base.head) {
> +		if (connector->encoder->type == INTEL_OUTPUT_ANALOG) {
> +			crt = &connector->base;
> +			break;
> +		}
> +	}
> +
> +	if (!crt)
> +		return;
> +
> +	if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp))
> +		intel_release_load_detect_pipe(crt, &load_detect_temp);

Should we shout if this fails?  Other than that:
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 35/58] drm/i915: introduce struct intel_set_config
  2012-08-19 19:12 ` [PATCH 35/58] drm/i915: introduce struct intel_set_config Daniel Vetter
@ 2012-09-05 16:34   ` Jesse Barnes
  2012-09-05 19:27     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:34 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:52 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 73 ++++++++++++++++++++----------------
>  drivers/gpu/drm/i915/intel_drv.h     |  6 +++
>  2 files changed, 47 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ab4fa7f..63bcc37 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6723,17 +6723,28 @@ done:
>  	return ret;
>  }
>  
> +static void intel_set_config_free(struct intel_set_config *config)
> +{
> +	if (config) {
> +		kfree(config->save_connectors);
> +		kfree(config->save_encoders);
> +		kfree(config->save_crtcs);
> +	}
> +	kfree(config);
> +}

	if (!config)
		return;
?

My eyes always hurt a little when I see if blocks that take up the
whole function. :)  Just a nit pick though.

> +
>  static int intel_crtc_set_config(struct drm_mode_set *set)
>  {
>  	struct drm_device *dev;
> -	struct drm_crtc *save_crtcs, *new_crtc, *crtc;
> -	struct drm_encoder *save_encoders, *new_encoder, *encoder;
> +	struct drm_crtc *new_crtc, *crtc;
> +	struct drm_encoder *new_encoder, *encoder;
>  	struct drm_framebuffer *old_fb = NULL;
>  	bool mode_changed = false; /* if true do a full mode set */
>  	bool fb_changed = false; /* if true and !mode_changed just do a flip */
> -	struct drm_connector *save_connectors, *connector;
> +	struct drm_connector *connector;
>  	int count = 0, ro;
>  	struct drm_mode_set save_set;
> +	struct intel_set_config *config;
>  	int ret;
>  	int i;
>  
> @@ -6762,27 +6773,27 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  
>  	dev = set->crtc->dev;
>  
> +	ret = -ENOMEM;
> +	config = kzalloc(sizeof(*config), GFP_KERNEL);
> +	if (!config)
> +		goto out_config;
> +
>  	/* Allocate space for the backup of all (non-pointer) crtc, encoder and
>  	 * connector data. */
> -	save_crtcs = kzalloc(dev->mode_config.num_crtc *
> -			     sizeof(struct drm_crtc), GFP_KERNEL);
> -	if (!save_crtcs)
> -		return -ENOMEM;
> +	config->save_crtcs = kzalloc(dev->mode_config.num_crtc *
> +				     sizeof(struct drm_crtc), GFP_KERNEL);
> +	if (!config->save_crtcs)
> +		goto out_config;
>  
> -	save_encoders = kzalloc(dev->mode_config.num_encoder *
> -				sizeof(struct drm_encoder), GFP_KERNEL);
> -	if (!save_encoders) {
> -		kfree(save_crtcs);
> -		return -ENOMEM;
> -	}
> +	config->save_encoders = kzalloc(dev->mode_config.num_encoder *
> +					sizeof(struct drm_encoder), GFP_KERNEL);
> +	if (!config->save_encoders)
> +		goto out_config;
>  
> -	save_connectors = kzalloc(dev->mode_config.num_connector *
> -				sizeof(struct drm_connector), GFP_KERNEL);
> -	if (!save_connectors) {
> -		kfree(save_crtcs);
> -		kfree(save_encoders);
> -		return -ENOMEM;
> -	}
> +	config->save_connectors = kzalloc(dev->mode_config.num_connector *
> +					  sizeof(struct drm_connector), GFP_KERNEL);
> +	if (!config->save_connectors)
> +		goto out_config;
>  
>  	/* Copy data. Note that driver private data is not affected.
>  	 * Should anything bad happen only the expected state is
> @@ -6790,17 +6801,17 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  	 */
>  	count = 0;
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> -		save_crtcs[count++] = *crtc;
> +		config->save_crtcs[count++] = *crtc;
>  	}
>  
>  	count = 0;
>  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> -		save_encoders[count++] = *encoder;
> +		config->save_encoders[count++] = *encoder;
>  	}
>  
>  	count = 0;
>  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> -		save_connectors[count++] = *connector;
> +		config->save_connectors[count++] = *connector;
>  	}
>  
>  	save_set.crtc = set->crtc;
> @@ -6936,26 +6947,25 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  		}
>  	}
>  
> -	kfree(save_connectors);
> -	kfree(save_encoders);
> -	kfree(save_crtcs);
> +	intel_set_config_free(config);
> +
>  	return 0;
>  
>  fail:
>  	/* Restore all previous data. */
>  	count = 0;
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> -		*crtc = save_crtcs[count++];
> +		*crtc = config->save_crtcs[count++];
>  	}
>  
>  	count = 0;
>  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> -		*encoder = save_encoders[count++];
> +		*encoder = config->save_encoders[count++];
>  	}
>  
>  	count = 0;
>  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> -		*connector = save_connectors[count++];
> +		*connector = config->save_connectors[count++];
>  	}
>  
>  	/* Try to restore the config */
> @@ -6964,9 +6974,8 @@ fail:
>  			    save_set.x, save_set.y, save_set.fb))
>  		DRM_ERROR("failed to restore config after modeset failure\n");
>  
> -	kfree(save_connectors);
> -	kfree(save_encoders);
> -	kfree(save_crtcs);
> +out_config:
> +	intel_set_config_free(config);
>  	return ret;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index c080c829..1cb64dd 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);

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 36/58] drm/i915: extract modeset config save/restore code
  2012-08-19 19:12 ` [PATCH 36/58] drm/i915: extract modeset config save/restore code Daniel Vetter
@ 2012-09-05 16:36   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:36 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:53 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> At the end this won't be of much use to us, but meanwhile just extract
> it to get a better overview of what exactly set_config does.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 127 +++++++++++++++++++++--------------
>  1 file changed, 76 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 63bcc37..fc4902a 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6733,11 +6733,82 @@ static void intel_set_config_free(struct intel_set_config *config)
>  	kfree(config);
>  }

FWIW these last two would be handy in the helper code, but since we're
abandoning it I guess we can just let it rot. :)

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 37/58] drm/i915: extract intel_set_config_compute_mode_changes
  2012-08-19 19:12 ` [PATCH 37/58] drm/i915: extract intel_set_config_compute_mode_changes Daniel Vetter
@ 2012-09-05 16:42   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:42 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:54 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.

Yeah this can definitely be improved when it's part of the driver.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 38/58] drm/i915: extract intel_set_config_update_output_state
  2012-08-19 19:12 ` [PATCH 38/58] drm/i915: extract intel_set_config_update_output_state Daniel Vetter
@ 2012-09-05 16:44   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:44 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:55 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Note that this function already clobbers the mode config state,
> so we have to clean things up if something fails.
> 

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 39/58] drm/i915: implement crtc helper semantics relied upon by the fb helper
  2012-08-19 19:12 ` [PATCH 39/58] drm/i915: implement crtc helper semantics relied upon by the fb helper Daniel Vetter
@ 2012-09-05 16:45   ` Jesse Barnes
  2012-09-05 19:15     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:45 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:56 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Yikes!
> 
> But yeah, we have to do this until someone volunteers to clean up the
> fb helper and rid it of its incetious relationship with the crtc
> helper code.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3cedc89..4b2b17f 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6933,6 +6933,12 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  	if (!set->mode)
>  		set->fb = NULL;
>  
> +	/* The fb helper likes to play gross jokes with ->mode_set_config.
> +	 * Unfortunately the crtc helper doesn't do much at all for this case,
> +	 * so we have to cope with this madness until the fb helper is fixed up. */
> +	if (set->fb && set->num_connectors == 0)
> +		return 0;
> +
>  	if (set->fb) {
>  		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
>  				set->crtc->base.id, set->fb->base.id,

I wonder if this belongs earlier in the series?  But either way:
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 40/58] drm/i915: don't update the fb base if there is no fb
  2012-08-19 19:12 ` [PATCH 40/58] drm/i915: don't update the fb base if there is no fb Daniel Vetter
@ 2012-09-05 16:47   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:47 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:57 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Otherwise we'll set_fb complains pretty loudly if we the crtc is off
> and userspace moves the NULL fb around a bit. Yeah, this actually
> happens in the wild ...
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 4b2b17f..125443a 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6827,7 +6827,7 @@ intel_set_config_compute_mode_changes(struct drm_mode_set *set,
>  			config->fb_changed = true;
>  	}
>  
> -	if (set->x != set->crtc->x || set->y != set->crtc->y)
> +	if (set->fb && (set->x != set->crtc->x || set->y != set->crtc->y))
>  		config->fb_changed = true;
>  
>  	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 41/58] drm/i915: convert pointless error checks in set_config to BUGs
  2012-08-19 19:12 ` [PATCH 41/58] drm/i915: convert pointless error checks in set_config to BUGs Daniel Vetter
@ 2012-09-05 16:50   ` Jesse Barnes
  2012-09-05 19:19     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:50 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:58 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Because they all are, the ioctl command never calls us with any of
> these violated. Also drop a equally pointless empty debug message (and
> also in set_cursor, while we're at it).
> 
> With all these changes, intel_crtc_set_config is neatly condensed down
> to it's essence, the actual modeset code (or fb update calling code)
> 
> v2: The fb helper code is actually stretching ->set_config semantics a bit,
> it calls it with set->mode == NULL but set->fb != NULL.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 15 +++------------
>  1 file changed, 3 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 125443a..56827d6 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5462,8 +5462,6 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
>  	uint32_t addr;
>  	int ret;
>  
> -	DRM_DEBUG_KMS("\n");
> -
>  	/* if we want to turn off the cursor ignore width and height */
>  	if (!handle) {
>  		DRM_DEBUG_KMS("cursor off\n");
> @@ -6919,16 +6917,9 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  	int ret;
>  	int i;
>  
> -	DRM_DEBUG_KMS("\n");
> -
> -	if (!set)
> -		return -EINVAL;
> -
> -	if (!set->crtc)
> -		return -EINVAL;
> -
> -	if (!set->crtc->helper_private)
> -		return -EINVAL;
> +	BUG_ON(!set);
> +	BUG_ON(!set->crtc);
> +	BUG_ON(!set->crtc->helper_private);
>  
>  	if (!set->mode)
>  		set->fb = NULL;

The BUG_ONs are probably superfluous too, but this is an improvement.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 42/58] drm/i915: don't save all the encoder/crtc state in set_config
  2012-08-19 19:12 ` [PATCH 42/58] drm/i915: don't save all the encoder/crtc state in set_config Daniel Vetter
@ 2012-09-05 16:52   ` Jesse Barnes
  2012-09-05 19:21     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 16:52 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:59 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> We actually only touch the connector -> encoder and encoder -> crtc
> linking. So it's enough to just save/restore that.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 28 +++++++++++++++-------------
>  drivers/gpu/drm/i915/intel_drv.h     |  4 ++--
>  2 files changed, 17 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 56827d6..24706ca 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6724,8 +6724,8 @@ done:
>  static void intel_set_config_free(struct intel_set_config *config)
>  {
>  	if (config) {
> -		kfree(config->save_connectors);
> -		kfree(config->save_encoders);
> +		kfree(config->save_connector_encoders);
> +		kfree(config->save_encoder_crtcs);
>  		kfree(config->save_crtcs);
>  	}
>  	kfree(config);
> @@ -6741,19 +6741,21 @@ static int intel_set_config_save_state(struct drm_device *dev,
>  
>  	/* Allocate space for the backup of all (non-pointer) crtc, encoder and
>  	 * connector data. */
> -	config->save_crtcs = kzalloc(dev->mode_config.num_crtc *
> +	config->save_crtcs = kcalloc(dev->mode_config.num_crtc,
>  				     sizeof(struct drm_crtc), GFP_KERNEL);
>  	if (!config->save_crtcs)
>  		return -ENOMEM;
>  
> -	config->save_encoders = kzalloc(dev->mode_config.num_encoder *
> -					sizeof(struct drm_encoder), GFP_KERNEL);
> -	if (!config->save_encoders)
> +	config->save_encoder_crtcs =
> +		kcalloc(dev->mode_config.num_encoder,
> +			sizeof(struct drm_crtc *), GFP_KERNEL);
> +	if (!config->save_encoder_crtcs)
>  		return -ENOMEM;
>  
> -	config->save_connectors = kzalloc(dev->mode_config.num_connector *
> -					  sizeof(struct drm_connector), GFP_KERNEL);
> -	if (!config->save_connectors)
> +	config->save_connector_encoders =
> +		kcalloc(dev->mode_config.num_connector,
> +			sizeof(struct drm_encoder *), GFP_KERNEL);
> +	if (!config->save_connector_encoders)
>  		return -ENOMEM;
>  
>  	/* Copy data. Note that driver private data is not affected.
> @@ -6767,12 +6769,12 @@ static int intel_set_config_save_state(struct drm_device *dev,
>  
>  	count = 0;
>  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> -		config->save_encoders[count++] = *encoder;
> +		config->save_encoder_crtcs[count++] = encoder->crtc;
>  	}
>  
>  	count = 0;
>  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> -		config->save_connectors[count++] = *connector;
> +		config->save_connector_encoders[count++] = connector->encoder;
>  	}
>  
>  	return 0;
> @@ -6793,12 +6795,12 @@ static void intel_set_config_restore_state(struct drm_device *dev,
>  
>  	count = 0;
>  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> -		*encoder = config->save_encoders[count++];
> +		encoder->crtc = config->save_encoder_crtcs[count++];
>  	}
>  
>  	count = 0;
>  	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> -		*connector = config->save_connectors[count++];
> +		connector->encoder = config->save_connector_encoders[count++];
>  	}
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index fad11c8..4946282 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;

Sneaky that you moved to kcalloc too :)

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 43/58] drm/i915: stage modeset output changes
  2012-08-19 19:13 ` [PATCH 43/58] drm/i915: stage modeset output changes Daniel Vetter
@ 2012-09-05 17:51   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 17:51 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:00 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 44/58] drm/i915: push crtc->fb update into pipe_set_base
  2012-08-19 19:13 ` [PATCH 44/58] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
  2012-09-04 19:33   ` [PATCH] " Daniel Vetter
@ 2012-09-05 17:54   ` Jesse Barnes
  1 sibling, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 17:54 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:01 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 84 +++++++++++++++---------------------
>  1 file changed, 34 insertions(+), 50 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index e6701b4..cd3606c 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2201,16 +2201,17 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
>  
>  static int
>  intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
> -		    struct drm_framebuffer *old_fb)
> +		    struct drm_framebuffer *fb)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct drm_i915_master_private *master_priv;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	struct drm_framebuffer *old_fb;
>  	int ret;
>  
>  	/* no fb bound */
> -	if (!crtc->fb) {
> +	if (!fb) {
>  		DRM_ERROR("No FB bound\n");
>  		return 0;
>  	}
> @@ -2224,7 +2225,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>  
>  	mutex_lock(&dev->struct_mutex);
>  	ret = intel_pin_and_fence_fb_obj(dev,
> -					 to_intel_framebuffer(crtc->fb)->obj,
> +					 to_intel_framebuffer(fb)->obj,
>  					 NULL);
>  	if (ret != 0) {
>  		mutex_unlock(&dev->struct_mutex);
> @@ -2232,17 +2233,20 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
>  		return ret;
>  	}
>  
> -	if (old_fb)
> -		intel_finish_fb(old_fb);
> +	if (crtc->fb)
> +		intel_finish_fb(crtc->fb);
>  
> -	ret = dev_priv->display.update_plane(crtc, crtc->fb, x, y);
> +	ret = dev_priv->display.update_plane(crtc, fb, x, y);
>  	if (ret) {
> -		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
> +		intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj);
>  		mutex_unlock(&dev->struct_mutex);
>  		DRM_ERROR("failed to update base address\n");
>  		return ret;
>  	}
>  
> +	old_fb = crtc->fb;
> +	crtc->fb = fb;
> +
>  	if (old_fb) {
>  		intel_wait_for_vblank(dev, intel_crtc->pipe);
>  		intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
> @@ -3777,6 +3781,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
>   * true if they don't match).
>   */
>  static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
> +					 struct drm_framebuffer *fb,
>  					 unsigned int *pipe_bpp,
>  					 struct drm_display_mode *mode)
>  {
> @@ -3846,7 +3851,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
>  	 * also stays within the max display bpc discovered above.
>  	 */
>  
> -	switch (crtc->fb->depth) {
> +	switch (fb->depth) {
>  	case 8:
>  		bpc = 8; /* since we go through a colormap */
>  		break;
> @@ -4265,7 +4270,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
>  			      struct drm_display_mode *mode,
>  			      struct drm_display_mode *adjusted_mode,
>  			      int x, int y,
> -			      struct drm_framebuffer *old_fb)
> +			      struct drm_framebuffer *fb)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -4455,7 +4460,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
>  	I915_WRITE(DSPCNTR(plane), dspcntr);
>  	POSTING_READ(DSPCNTR(plane));
>  
> -	ret = intel_pipe_set_base(crtc, x, y, old_fb);
> +	ret = intel_pipe_set_base(crtc, x, y, fb);
>  
>  	intel_update_watermarks(dev);
>  
> @@ -4613,7 +4618,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
>  				  struct drm_display_mode *mode,
>  				  struct drm_display_mode *adjusted_mode,
>  				  int x, int y,
> -				  struct drm_framebuffer *old_fb)
> +				  struct drm_framebuffer *fb)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -4733,7 +4738,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
>  	/* determine panel color depth */
>  	temp = I915_READ(PIPECONF(pipe));
>  	temp &= ~PIPE_BPC_MASK;
> -	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
> +	dither = intel_choose_pipe_bpp_dither(crtc, fb, &pipe_bpp, mode);
>  	switch (pipe_bpp) {
>  	case 18:
>  		temp |= PIPE_6BPC;
> @@ -5002,7 +5007,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
>  	I915_WRITE(DSPCNTR(plane), dspcntr);
>  	POSTING_READ(DSPCNTR(plane));
>  
> -	ret = intel_pipe_set_base(crtc, x, y, old_fb);
> +	ret = intel_pipe_set_base(crtc, x, y, fb);
>  
>  	intel_update_watermarks(dev);
>  
> @@ -5015,7 +5020,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
>  			       struct drm_display_mode *mode,
>  			       struct drm_display_mode *adjusted_mode,
>  			       int x, int y,
> -			       struct drm_framebuffer *old_fb)
> +			       struct drm_framebuffer *fb)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -5026,7 +5031,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
>  	drm_vblank_pre_modeset(dev, pipe);
>  
>  	ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
> -					      x, y, old_fb);
> +					      x, y, fb);
>  	drm_vblank_post_modeset(dev, pipe);
>  
>  	return ret;
> @@ -5718,7 +5723,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
>  	struct drm_encoder *encoder = &intel_encoder->base;
>  	struct drm_crtc *crtc = NULL;
>  	struct drm_device *dev = encoder->dev;
> -	struct drm_framebuffer *old_fb;
> +	struct drm_framebuffer *fb;
>  	int i = -1;
>  
>  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
> @@ -5779,8 +5784,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
>  	if (!mode)
>  		mode = &load_detect_mode;
>  
> -	old_fb = crtc->fb;
> -
>  	/* We need a framebuffer large enough to accommodate all accesses
>  	 * that the plane may generate whilst we perform load detection.
>  	 * We can not rely on the fbcon either being present (we get called
> @@ -5788,19 +5791,19 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
>  	 * not even exist) or that it is large enough to satisfy the
>  	 * requested mode.
>  	 */
> -	crtc->fb = mode_fits_in_fbdev(dev, mode);
> -	if (crtc->fb == NULL) {
> +	fb = mode_fits_in_fbdev(dev, mode);
> +	if (fb == NULL) {
>  		DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
> -		crtc->fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
> -		old->release_fb = crtc->fb;
> +		fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
> +		old->release_fb = fb;
>  	} else
>  		DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
> -	if (IS_ERR(crtc->fb)) {
> +	if (IS_ERR(fb)) {
>  		DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
>  		goto fail;
>  	}
>  
> -	if (!intel_set_mode(crtc, mode, 0, 0, old_fb)) {
> +	if (!intel_set_mode(crtc, mode, 0, 0, fb)) {
>  		DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
>  		if (old->release_fb)
>  			old->release_fb->funcs->destroy(old->release_fb);
> @@ -5814,7 +5817,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
>  fail:
>  	connector->encoder = NULL;
>  	encoder->crtc = NULL;
> -	crtc->fb = old_fb;
>  	return false;
>  }
>  
> @@ -6666,13 +6668,12 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
>  
>  bool intel_set_mode(struct drm_crtc *crtc,
>  		    struct drm_display_mode *mode,
> -		    int x, int y, struct drm_framebuffer *old_fb)
> +		    int x, int y, struct drm_framebuffer *fb)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	drm_i915_private_t *dev_priv = dev->dev_private;
>  	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
>  	struct drm_encoder_helper_funcs *encoder_funcs;
> -	int saved_x, saved_y;
>  	struct drm_encoder *encoder;
>  	bool ret = true;
>  
> @@ -6686,15 +6687,11 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  
>  	saved_hwmode = crtc->hwmode;
>  	saved_mode = crtc->mode;
> -	saved_x = crtc->x;
> -	saved_y = crtc->y;
>  
>  	/* Update crtc values up front so the driver can rely on them for mode
>  	 * setting.
>  	 */
>  	crtc->mode = *mode;
> -	crtc->x = x;
> -	crtc->y = y;
>  
>  	/* Pass our mode to the connectors and the CRTC to give them a chance to
>  	 * adjust it according to limitations or connector properties, and also
> @@ -6725,7 +6722,7 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  	/* Set up the DPLL and any encoders state that needs to adjust or depend
>  	 * on the DPLL.
>  	 */
> -	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
> +	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, fb);
>  	if (!ret)
>  	    goto done;
>  
> @@ -6741,6 +6738,9 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
>  	}
>  
> +	crtc->x = x;
> +	crtc->y = y;
> +
>  	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
>  	dev_priv->display.crtc_enable(crtc);
>  
> @@ -6759,8 +6759,6 @@ done:
>  	if (!ret) {
>  		crtc->hwmode = saved_hwmode;
>  		crtc->mode = saved_mode;
> -		crtc->x = saved_x;
> -		crtc->y = saved_y;
>  	}
>  
>  	return ret;
> @@ -6993,7 +6991,6 @@ next_encoder:
>  static int intel_crtc_set_config(struct drm_mode_set *set)
>  {
>  	struct drm_device *dev;
> -	struct drm_framebuffer *old_fb = NULL;
>  	struct drm_mode_set save_set;
>  	struct intel_set_config *config;
>  	int ret;
> @@ -7056,13 +7053,10 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  			DRM_DEBUG_KMS("attempting to set mode from"
>  					" userspace\n");
>  			drm_mode_debug_printmodeline(set->mode);
> -			old_fb = set->crtc->fb;
> -			set->crtc->fb = set->fb;
>  			if (!intel_set_mode(set->crtc, set->mode,
> -					    set->x, set->y, old_fb)) {
> +					    set->x, set->y, set->fb)) {
>  				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
>  					  set->crtc->base.id);
> -				set->crtc->fb = old_fb;
>  				ret = -EINVAL;
>  				goto fail;
>  			}
> @@ -7075,18 +7069,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  		}
>  		drm_helper_disable_unused_functions(dev);
>  	} else if (config->fb_changed) {
> -		set->crtc->x = set->x;
> -		set->crtc->y = set->y;
> -
> -		old_fb = set->crtc->fb;
> -		if (set->crtc->fb != set->fb)
> -			set->crtc->fb = set->fb;
>  		ret = intel_pipe_set_base(set->crtc,
> -					  set->x, set->y, old_fb);
> -		if (ret != 0) {
> -			set->crtc->fb = old_fb;
> -			goto fail;
> -		}
> +					  set->x, set->y, set->fb);
>  	}
>  
>  	intel_set_config_free(config);

I never liked how we passed the old ones around and polluted the
callees with knowledge of potential cleanup.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: push crtc->fb update into pipe_set_base
  2012-09-04 19:33   ` [PATCH] " Daniel Vetter
@ 2012-09-05 17:55     ` Jesse Barnes
  2012-09-05 19:59       ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 17:55 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Tue,  4 Sep 2012 21:33:22 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.

Ok obviously missed the leak.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 45/58] drm/i915: remove crtc disabling special case
  2012-08-19 19:13 ` [PATCH 45/58] drm/i915: remove crtc disabling special case Daniel Vetter
@ 2012-09-05 17:56   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 17:56 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:02 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Originally this has been introduced in
> 
> commit 6eebd6bb5f1ea04f04019e5c39f87a0f17ffb472
> Author: Chris Wilson <chris@chris-wilson.co.uk>
> Date:   Mon Nov 28 21:10:05 2011 +0000
> 
>     drm: Fix lack of CRTC disable for drm_crtc_helper_set_config(.fb=NULL)
> 
> With the improvements of the output state staging and no longer
> overwriting crtc->fb before the hw state is updated we can now handle
> crtc disabling as part of the normal modeset sequence.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 46/58] drm/i915: move output commit and crtc disabling into set_mode
  2012-08-19 19:13 ` [PATCH 46/58] drm/i915: move output commit and crtc disabling into set_mode Daniel Vetter
@ 2012-09-05 17:58   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 17:58 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:03 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> It's rather pointless to compute crtc->enabled twice right away ;-)
> 
> The only thing we really have to be careful about is that we frob the
> dpms state only after a successful modeset and when we've actually
> haven't just disabled the crtc.
> 
> Hooray for convoluted interfaces ...
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 32 +++++++++++++++++---------------
>  1 file changed, 17 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 4e72119..348727d 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6653,9 +6653,13 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  	struct drm_encoder *encoder;
>  	bool ret = true;
>  
> +	intel_modeset_commit_output_state(dev);
> +
>  	crtc->enabled = drm_helper_crtc_in_use(crtc);
> -	if (!crtc->enabled)
> +	if (!crtc->enabled) {
> +		drm_helper_disable_unused_functions(dev);
>  		return true;
> +	}
>  
>  	adjusted_mode = drm_mode_duplicate(dev, mode);
>  	if (!adjusted_mode)
> @@ -7021,20 +7025,21 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  		goto fail;
>  
>  	if (config->mode_changed) {
> -		intel_modeset_commit_output_state(dev);
> -
> -		set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
> -		if (set->crtc->enabled) {
> +		if (set->mode) {
>  			DRM_DEBUG_KMS("attempting to set mode from"
>  					" userspace\n");
>  			drm_mode_debug_printmodeline(set->mode);
> -			if (!intel_set_mode(set->crtc, set->mode,
> -					    set->x, set->y, set->fb)) {
> -				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
> -					  set->crtc->base.id);
> -				ret = -EINVAL;
> -				goto fail;
> -			}
> +		}
> +
> +		if (!intel_set_mode(set->crtc, set->mode,
> +				    set->x, set->y, set->fb)) {
> +			DRM_ERROR("failed to set mode on [CRTC:%d]\n",
> +				  set->crtc->base.id);
> +			ret = -EINVAL;
> +			goto fail;
> +		}
> +
> +		if (set->crtc->enabled) {
>  			DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
>  			for (i = 0; i < set->num_connectors; i++) {
>  				DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
> @@ -7042,7 +7047,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  				set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
>  			}
>  		}
> -		drm_helper_disable_unused_functions(dev);
>  	} else if (config->fb_changed) {
>  		ret = intel_pipe_set_base(set->crtc,
>  					  set->x, set->y, set->fb);
> @@ -7055,8 +7059,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>  fail:
>  	intel_set_config_restore_state(dev, config);
>  
> -	intel_modeset_commit_output_state(dev);
> -
>  	/* Try to restore the config */
>  	if (config->mode_changed &&
>  	    !intel_set_mode(save_set.crtc, save_set.mode,

I *think* this should work... will test.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 47/58] drm/i915: extract adjusted mode computation
  2012-08-19 19:13 ` [PATCH 47/58] drm/i915: extract adjusted mode computation Daniel Vetter
@ 2012-09-05 18:00   ` Jesse Barnes
  2012-09-05 19:30     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:00 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:04 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> While at it, adjust a few things:
> - Only assigng the new mode to crtc->mode right before calling the
>   mode_set callbacks - none of the previous callbacks depend upon
>   this, they all use the mode argument (as they should).
> - Check encoder->new_crtc instead of the current crtc to check whether
>   the encoder will be used. This prepares for moving the staged output
>   committing further down in the sequence. Follow-on patches will fix
>   up individual ->mode_fixup callbacks (only tv and lvds are affected
>   though).
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 75 ++++++++++++++++++++++--------------
>  1 file changed, 47 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 348727d..c7bd573 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6642,6 +6642,48 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
>  	}
>  }
>  
> +static struct drm_display_mode *
> +intel_modeset_adjusted_mode(struct drm_crtc *crtc,
> +			    struct drm_display_mode *mode)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_display_mode *adjusted_mode;
> +	struct drm_encoder_helper_funcs *encoder_funcs;
> +	struct intel_encoder *encoder;
> +
> +	adjusted_mode = drm_mode_duplicate(dev, mode);
> +	if (!adjusted_mode)
> +		return ERR_PTR(-ENOMEM);
> +
> +	/* Pass our mode to the connectors and the CRTC to give them a chance to
> +	 * adjust it according to limitations or connector properties, and also
> +	 * a chance to reject the mode entirely.
> +	 */
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
> +			    base.head) {
> +
> +		if (&encoder->new_crtc->base != crtc)
> +			continue;
> +		encoder_funcs = encoder->base.helper_private;
> +		if (!(encoder_funcs->mode_fixup(&encoder->base, mode,
> +						adjusted_mode))) {
> +			DRM_DEBUG_KMS("Encoder fixup failed\n");
> +			goto fail;
> +		}
> +	}
> +
> +	if (!(intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) {
> +		DRM_DEBUG_KMS("CRTC fixup failed\n");
> +		goto fail;
> +	}
> +	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
> +
> +	return adjusted_mode;
> +fail:
> +	drm_mode_destroy(dev, adjusted_mode);
> +	return ERR_PTR(-EINVAL);
> +}
> +
>  bool intel_set_mode(struct drm_crtc *crtc,
>  		    struct drm_display_mode *mode,
>  		    int x, int y, struct drm_framebuffer *fb)
> @@ -6661,44 +6703,21 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  		return true;
>  	}
>  
> -	adjusted_mode = drm_mode_duplicate(dev, mode);
> -	if (!adjusted_mode)
> -		return false;
>  
>  	saved_hwmode = crtc->hwmode;
>  	saved_mode = crtc->mode;
>  
> -	/* Update crtc values up front so the driver can rely on them for mode
> -	 * setting.
> -	 */
> -	crtc->mode = *mode;
> -
> -	/* Pass our mode to the connectors and the CRTC to give them a chance to
> -	 * adjust it according to limitations or connector properties, and also
> -	 * a chance to reject the mode entirely.
> -	 */
> -	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> -
> -		if (encoder->crtc != crtc)
> -			continue;
> -		encoder_funcs = encoder->helper_private;
> -		if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
> -						      adjusted_mode))) {
> -			DRM_DEBUG_KMS("Encoder fixup failed\n");
> -			goto done;
> -		}
> -	}
> -
> -	if (!(ret = intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) {
> -		DRM_DEBUG_KMS("CRTC fixup failed\n");
> -		goto done;
> +	adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
> +	if (IS_ERR(adjusted_mode)) {
> +		return false;
>  	}
> -	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
>  
>  	intel_crtc_prepare_encoders(dev);
>  
>  	dev_priv->display.crtc_disable(crtc);
>  
> +	crtc->mode = *mode;
> +
>  	/* Set up the DPLL and any encoders state that needs to adjust or depend
>  	 * on the DPLL.
>  	 */

Fancy, using ERR_PTR even. :)

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 48/58] drm/i915: use staged outuput config in tv->mode_fixup
  2012-08-19 19:13 ` [PATCH 48/58] drm/i915: use staged outuput config in tv->mode_fixup Daniel Vetter
@ 2012-09-05 18:02   ` Jesse Barnes
  2012-09-06  7:30     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:02 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:05 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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 ...
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |  1 +
>  drivers/gpu/drm/i915/intel_tv.c      |  7 ++-----
>  3 files changed, 25 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c7bd573..c59569e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6563,6 +6563,28 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = {
>  	.disable = intel_crtc_disable,
>  };
>  
> +bool intel_encoder_check_non_cloned(struct intel_encoder *encoder)
> +{
> +	struct intel_encoder *other_encoder;
> +	struct drm_crtc *crtc = &encoder->new_crtc->base;
> +
> +	if (WARN_ON(!crtc))
> +		return true;
> +
> +	list_for_each_entry(other_encoder,
> +			    &crtc->dev->mode_config.encoder_list,
> +			    base.head) {
> +
> +		if (&other_encoder->new_crtc->base != crtc ||
> +		    encoder == other_encoder)
> +			continue;
> +		else
> +			return false;
> +	}
> +
> +	return true;
> +}

encoder_is_cloned() would make the callers more readable and avoid the
double negative...

Otherwise,
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 49/58] drm/i915: use staged outuput config in lvds->mode_fixup
  2012-08-19 19:13 ` [PATCH 49/58] drm/i915: use staged outuput config in lvds->mode_fixup Daniel Vetter
@ 2012-09-05 18:02   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:02 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:06 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> - Use the check_cloned helper from the previous patch.
> - Use encoder->new_crtc to check crtc properties.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_lvds.c | 13 +++----------
>  1 file changed, 3 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 52f9e7f..7f730af 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -250,9 +250,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
>  {
>  	struct drm_device *dev = encoder->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
>  	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
> -	struct intel_encoder *tmp_encoder;
> +	struct intel_crtc *intel_crtc = intel_lvds->base.new_crtc;
>  	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
>  	int pipe;
>  
> @@ -262,14 +261,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
>  		return false;
>  	}
>  
> -	/* Should never happen!! */
> -	for_each_encoder_on_crtc(dev, encoder->crtc, tmp_encoder) {
> -		if (&tmp_encoder->base != encoder) {
> -			DRM_ERROR("Can't enable LVDS and another "
> -			       "encoder on the same pipe\n");
> -			return false;
> -		}
> -	}
> +	if (!intel_encoder_check_non_cloned(&intel_lvds->base))
> +		return false;
>  
>  	/*
>  	 * We have timings from the BIOS for the panel, put them in

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 50/58] drm/i915: compute masks of crtcs affected in set_mode
  2012-08-19 19:13 ` [PATCH 50/58] drm/i915: compute masks of crtcs affected in set_mode Daniel Vetter
  2012-08-29 10:34   ` [PATCH] " Daniel Vetter
@ 2012-09-05 18:07   ` Jesse Barnes
  1 sibling, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:07 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:07 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> This is definetely a bit more generic than currently required, but
> if we keep track of all crtcs that need to be disabled/enable (because
> they loose an encoder or something similar), crtcs that get completely
> disabled and those that we need to do an actual mode change on nicely
> prepares us for global modeset operations on multiple crtcs.
> 
> The only big thing missing here would be a global resource allocation
> step (for e.g. pch plls), which would equally frob these bitmasks if
> e.g. a crtc only needs a new pll.
> 
> These masks aren't yet put to use in this patch, this will follow in the
> next one.
> 
> v2-v5: Fix up the computations for good (hopefully).
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 89 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 89 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index c59569e..4334400 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6706,6 +6706,91 @@ fail:
>  	return ERR_PTR(-EINVAL);
>  }
>  
> +/* Computes which crtcs are affected and sets the relevant bits in the mask. For
> + * simplicity we use the crtc's pipe number (because it's easier to obtain). */
> +static void
> +intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
> +			     unsigned *prepare_pipes, unsigned *disable_pipes)
> +{
> +	struct intel_crtc *intel_crtc;
> +	struct drm_device *dev = crtc->dev;
> +	struct intel_encoder *encoder;
> +	struct intel_connector *connector;
> +	struct drm_crtc *tmp_crtc;
> +
> +	*disable_pipes = *modeset_pipes = *prepare_pipes = 0;
> +
> +	/* Check which crtcs have changed outputs connected to them, these need
> +	 * to be part of the prepare_pipes mask. We don't (yet) support global
> +	 * modeset across multiple crtcs, so modeset_pipes will only have one
> +	 * bit set at most. */
> +	list_for_each_entry(connector, &dev->mode_config.connector_list,
> +			    base.head) {
> +		if (connector->base.encoder == &connector->new_encoder->base)
> +			continue;
> +
> +		if (connector->base.encoder) {
> +			tmp_crtc = connector->base.encoder->crtc;
> +
> +			*prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
> +		}
> +
> +		if (connector->new_encoder)
> +			*prepare_pipes |=
> +				1 << connector->new_encoder->new_crtc->pipe;
> +	}
> +
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
> +			    base.head) {
> +		if (encoder->base.crtc == &encoder->new_crtc->base)
> +			continue;
> +
> +		if (encoder->base.crtc) {
> +			tmp_crtc = encoder->base.crtc;
> +
> +			*prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
> +		}
> +
> +		if (encoder->new_crtc)
> +			*prepare_pipes |= 1 << encoder->new_crtc->pipe;
> +	}
> +
> +	/* Check for any pipes that will be fully 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)
> +			continue;
> +
> +		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
> +				    base.head) {
> +			if (encoder->new_crtc == intel_crtc)
> +				used = true;
> +		}
> +
> +		if (!used)
> +			*disable_pipes |= 1 << intel_crtc->pipe;
> +	}
> +
> +
> +	/* set_mode is also used to update properties on life display pipes. */
> +	intel_crtc = to_intel_crtc(crtc);
> +	if (!*disable_pipes && crtc->enabled)
> +		*prepare_pipes |= 1 << intel_crtc->pipe;
> +
> +	/* We only support modeset on one single crtc, hence we need to do that
> +	 * only for the passed in crtc iff we change anything else than just
> +	 * disable crtcs. */
> +	if (*prepare_pipes)
> +		*modeset_pipes |= 1 << intel_crtc->pipe;
> +
> +	/* ... and mask these out. */
> +	*modeset_pipes &= ~(*disable_pipes);
> +	*prepare_pipes &= ~(*disable_pipes);
> +}
> +
>  bool intel_set_mode(struct drm_crtc *crtc,
>  		    struct drm_display_mode *mode,
>  		    int x, int y, struct drm_framebuffer *fb)
> @@ -6715,8 +6800,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
>  	struct drm_encoder_helper_funcs *encoder_funcs;
>  	struct drm_encoder *encoder;
> +	unsigned disable_pipe, prepare_pipes, modeset_pipes;
>  	bool ret = true;
>  
> +	intel_modeset_affected_pipes(crtc, &modeset_pipes,
> +				     &prepare_pipes, &disable_pipe);
> +
>  	intel_modeset_commit_output_state(dev);
>  
>  	crtc->enabled = drm_helper_crtc_in_use(crtc);

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: compute masks of crtcs affected in set_mode
  2012-08-29 10:34   ` [PATCH] " Daniel Vetter
@ 2012-09-05 18:09     ` Jesse Barnes
  2012-09-05 19:38       ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:09 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Wed, 29 Aug 2012 12:34:04 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> This is definetely a bit more generic than currently required, but
> if we keep track of all crtcs that need to be disabled/enable (because
> they loose an encoder or something similar), crtcs that get completely
> disabled and those that we need to do an actual mode change on nicely
> prepares us for global modeset operations on multiple crtcs.
> 
> The only big thing missing here would be a global resource allocation
> step (for e.g. pch plls), which would equally frob these bitmasks if
> e.g. a crtc only needs a new pll.
> 
> These masks aren't yet put to use in this patch, this will follow in the
> next one.
> 
> v2-v5: Fix up the computations for good (hopefully).
> 
> v6: Fixup a confusion reported by Damien Lespiau: I've conserved the
> (imo braindead) behaviour of the crtc helper to disable _any_
> disconnected outputs if we do a modeset, even when that newly disabled
> connector isn't connected to the crtc being changed by the modeset.
> 
> The effect of that is that we could disable an arbitrary number of
> unrelated crtcs, which I haven't taken into account when writing this
> code. Fix this up.

Might not need to clean it up here though, since the only time that
should matter is during the first mode set after a power on or resume
when a superfluous CRTC might be enabled.  And with the new hw state
readout, we can fix that up.

You choose though.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 51/58] drm/i915: implement new set_mode code flow
  2012-08-19 19:13 ` [PATCH 51/58] drm/i915: implement new set_mode code flow Daniel Vetter
@ 2012-09-05 18:14   ` Jesse Barnes
  2012-09-05 19:43     ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:14 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:08 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> ... using the pipe masks from the previous patch.
> 
> Well, not quite:
> - We still need to call the disable_unused_functions helper, until
>   we've moved the call to commit_output_state further down and
>   adjusted intel_crtc_disable a bit. The next patch will do that.
> - Because we don't support (yet) mode changes on more than one crtc at
>   a time, some of the modeset_pipes checks are a bit hackish - but
>   that only needs fixing once we incorporate global modeset support.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 99 +++++++++++++++++++++++-------------
>  1 file changed, 63 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 4334400..3d99522 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6791,6 +6791,12 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
>  	*prepare_pipes &= ~(*disable_pipes);
>  }
>  
> +#define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
> +	list_for_each_entry((intel_crtc), \
> +			    &(dev)->mode_config.crtc_list, \
> +			    base.head) \
> +		if (mask & (1 <<(intel_crtc)->pipe)) \
> +
>  bool intel_set_mode(struct drm_crtc *crtc,
>  		    struct drm_display_mode *mode,
>  		    int x, int y, struct drm_framebuffer *fb)
> @@ -6800,73 +6806,92 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
>  	struct drm_encoder_helper_funcs *encoder_funcs;
>  	struct drm_encoder *encoder;
> -	unsigned disable_pipe, prepare_pipes, modeset_pipes;
> +	struct intel_crtc *intel_crtc;
> +	unsigned disable_pipes, prepare_pipes, modeset_pipes;
>  	bool ret = true;
>  
>  	intel_modeset_affected_pipes(crtc, &modeset_pipes,
> -				     &prepare_pipes, &disable_pipe);
> +				     &prepare_pipes, &disable_pipes);
> +
> +	DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
> +		      modeset_pipes, prepare_pipes, disable_pipes);
>  
>  	intel_modeset_commit_output_state(dev);
>  
>  	crtc->enabled = drm_helper_crtc_in_use(crtc);
> -	if (!crtc->enabled) {
> -		drm_helper_disable_unused_functions(dev);
> -		return true;
> -	}
>  
> +	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
> +		drm_helper_disable_unused_functions(dev);
>  
>  	saved_hwmode = crtc->hwmode;
>  	saved_mode = crtc->mode;
>  
> -	adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
> -	if (IS_ERR(adjusted_mode)) {
> -		return false;
> -	}
> +	/* Hack: Because we don't (yet) support global modeset on multiple
> +	 * crtcs, we don't keep track of the new mode for more than one crtc.
> +	 * Hence simply check whether any bit is set in modeset_pipes in all the
> +	 * pieces of code that are not yet converted to deal with mutliple crtcs
> +	 * changing their mode at the same time. */
> +	adjusted_mode = NULL;
> +	if (modeset_pipes) {
> +		adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
> +		if (IS_ERR(adjusted_mode)) {
> +			return false;
> +		}
>  
> -	intel_crtc_prepare_encoders(dev);
> +		intel_crtc_prepare_encoders(dev);
> +	}
>  
> -	dev_priv->display.crtc_disable(crtc);
> +	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
> +		dev_priv->display.crtc_disable(&intel_crtc->base);
>  
> -	crtc->mode = *mode;
> +	if (modeset_pipes) {
> +		crtc->mode = *mode;
> +		crtc->x = x;
> +		crtc->y = y;
> +	}
>  
>  	/* Set up the DPLL and any encoders state that needs to adjust or depend
>  	 * on the DPLL.
>  	 */
> -	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, fb);
> -	if (!ret)
> -	    goto done;
> +	for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
> +		ret = !intel_crtc_mode_set(&intel_crtc->base,
> +					   mode, adjusted_mode,
> +					   x, y, fb);
> +		if (!ret)
> +		    goto done;
>  
> -	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
> +		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
>  
> -		if (encoder->crtc != crtc)
> -			continue;
> +			if (encoder->crtc != &intel_crtc->base)
> +				continue;
>  
> -		DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
> -			encoder->base.id, drm_get_encoder_name(encoder),
> -			mode->base.id, mode->name);
> -		encoder_funcs = encoder->helper_private;
> -		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
> +			DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
> +				encoder->base.id, drm_get_encoder_name(encoder),
> +				mode->base.id, mode->name);
> +			encoder_funcs = encoder->helper_private;
> +			encoder_funcs->mode_set(encoder, mode, adjusted_mode);
> +		}
>  	}
>  
> -	crtc->x = x;
> -	crtc->y = y;
> -
>  	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
> -	dev_priv->display.crtc_enable(crtc);
> +	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
> +		dev_priv->display.crtc_enable(&intel_crtc->base);
>  
> -	/* Store real post-adjustment hardware mode. */
> -	crtc->hwmode = *adjusted_mode;
> +	if (modeset_pipes) {
> +		/* Store real post-adjustment hardware mode. */
> +		crtc->hwmode = *adjusted_mode;
>  
> -	/* Calculate and store various constants which
> -	 * are later needed by vblank and swap-completion
> -	 * timestamping. They are derived from true hwmode.
> -	 */
> -	drm_calc_timestamping_constants(crtc);
> +		/* Calculate and store various constants which
> +		 * are later needed by vblank and swap-completion
> +		 * timestamping. They are derived from true hwmode.
> +		 */
> +		drm_calc_timestamping_constants(crtc);
> +	}
>  
>  	/* FIXME: add subpixel order */
>  done:
>  	drm_mode_destroy(dev, adjusted_mode);
> -	if (!ret) {
> +	if (!ret && crtc->enabled) {
>  		crtc->hwmode = saved_hwmode;
>  		crtc->mode = saved_mode;
>  	}
> @@ -6874,6 +6899,8 @@ done:
>  	return ret;
>  }
>  
> +#undef for_each_intel_crtc_masked
> +
>  static void intel_set_config_free(struct intel_set_config *config)
>  {
>  	if (config) {

An ugly intermediate step... also did you check whether moving the
crtc->x/y assignment up is safe?  We're passing it around, but some
places might check for crtc->x/y looking for old values (or did that
already change in the previous patch... too many patches).

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 52/58] drm/i915: push commit_output_state past crtc disabling
  2012-08-19 19:13 ` [PATCH 52/58] drm/i915: push commit_output_state past crtc disabling Daniel Vetter
@ 2012-09-05 18:17   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:17 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:09 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> This requires a few changes
> - We still need a noop function for crtc->disable, becuase the fb
>   helper is a bit too intimate with the crtc helper.
> - We need to clear crtc->fb ourselves in intel_crtc_disable now that
>   we no longer rely on the helper's disable_unused_functions to do
>   that.
> - We need to split out the sare update code, becuase the crtc code
>   can't call update_dpms any more, it needs to disable the crtc
>   unconditionally. This is because we now keep onto the encoder ->
>   crtc mapping of the (still) active output pipe configuration.
> - To check that we really disable a crtc that still has encoders,
>   insert a WARN_ON(!enabled) in the crtc disable function.
> - Lastly, we need to walk over all crtcs to update their enabled state
>   after having called commit_output_state - for all disabled crtc the
>   crtc helper code has done that for us previously.
> 
> v2: Update connector dpms and encoder->connectors_active after
> disabling the crtc, too.
> 
> v3: Noop-out intel_encoder_disable. Similarly to the crtc disable
> callback used by the crtc helper code we can't simply remove all these
> encoder callbacks: The fb helper (which we still use) has a rather
> incetious relationship with the crtc helper code ...
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 81 +++++++++++++++++++++++-------------
>  1 file changed, 53 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3d99522..48d763d 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3462,26 +3462,13 @@ static void i9xx_crtc_off(struct drm_crtc *crtc)
>  {
>  }
>  
> -/**
> - * Sets the power management mode of the pipe and plane.
> - */
> -void intel_crtc_update_dpms(struct drm_crtc *crtc)
> +static void intel_crtc_update_sarea(struct drm_crtc *crtc,
> +				    bool enabled)
>  {
>  	struct drm_device *dev = crtc->dev;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct drm_i915_master_private *master_priv;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> -	struct intel_encoder *intel_encoder;
>  	int pipe = intel_crtc->pipe;
> -	bool enabled, enable = false;
> -
> -	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
> -		enable |= intel_encoder->connectors_active;
> -
> -	if (enable)
> -		dev_priv->display.crtc_enable(crtc);
> -	else
> -		dev_priv->display.crtc_disable(crtc);
>  
>  	if (!dev->primary->master)
>  		return;
> @@ -3490,8 +3477,6 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc)
>  	if (!master_priv->sarea_priv)
>  		return;
>  
> -	enabled = crtc->enabled && enable;
> -
>  	switch (pipe) {
>  	case 0:
>  		master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0;
> @@ -3507,14 +3492,42 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc)
>  	}
>  }
>  
> +/**
> + * Sets the power management mode of the pipe and plane.
> + */
> +void intel_crtc_update_dpms(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_encoder *intel_encoder;
> +	bool enable = false;
> +
> +	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
> +		enable |= intel_encoder->connectors_active;
> +
> +	if (enable)
> +		dev_priv->display.crtc_enable(crtc);
> +	else
> +		dev_priv->display.crtc_disable(crtc);
> +
> +	intel_crtc_update_sarea(crtc, enable);
> +}
> +
> +static void intel_crtc_noop(struct drm_crtc *crtc)
> +{
> +}
> +
>  static void intel_crtc_disable(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
> +	struct drm_connector *connector;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> -	/* crtc->disable is only called when we have no encoders, hence this
> -	 * will disable the pipe. */
> -	intel_crtc_update_dpms(crtc);
> +	/* crtc should still be enabled when we disable it. */
> +	WARN_ON(!crtc->enabled);
> +
> +	dev_priv->display.crtc_disable(crtc);
> +	intel_crtc_update_sarea(crtc, false);
>  	dev_priv->display.off(crtc);
>  
>  	assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
> @@ -3524,14 +3537,24 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
>  		mutex_lock(&dev->struct_mutex);
>  		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
>  		mutex_unlock(&dev->struct_mutex);
> +		crtc->fb = NULL;
> +	}
> +
> +	/* Update computed state. */
> +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +		if (!connector->encoder || !connector->encoder->crtc)
> +			continue;
> +
> +		if (connector->encoder->crtc != crtc)
> +			continue;
> +
> +		connector->dpms = DRM_MODE_DPMS_OFF;
> +		to_intel_encoder(connector->encoder)->connectors_active = false;
>  	}
>  }
>  
>  void intel_encoder_disable(struct drm_encoder *encoder)
>  {
> -	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
> -
> -	intel_encoder->disable(intel_encoder);
>  }
>  
>  void intel_encoder_destroy(struct drm_encoder *encoder)
> @@ -6560,7 +6583,7 @@ free_work:
>  static struct drm_crtc_helper_funcs intel_helper_funcs = {
>  	.mode_set_base_atomic = intel_pipe_set_base_atomic,
>  	.load_lut = intel_crtc_load_lut,
> -	.disable = intel_crtc_disable,
> +	.disable = intel_crtc_noop,
>  };
>  
>  bool intel_encoder_check_non_cloned(struct intel_encoder *encoder)
> @@ -6816,12 +6839,14 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  	DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
>  		      modeset_pipes, prepare_pipes, disable_pipes);
>  
> -	intel_modeset_commit_output_state(dev);
> +	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
> +		intel_crtc_disable(&intel_crtc->base);
>  
> -	crtc->enabled = drm_helper_crtc_in_use(crtc);
> +	intel_modeset_commit_output_state(dev);
>  
> -	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
> -		drm_helper_disable_unused_functions(dev);
> +	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
> +			    base.head)
> +		intel_crtc->base.enabled = drm_helper_crtc_in_use(crtc);
>  
>  	saved_hwmode = crtc->hwmode;
>  	saved_mode = crtc->mode;

Starting to look much better.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 53/58] drm/i915: s/intel_encoder_disable/intel_encoder_noop
  2012-08-19 19:13 ` [PATCH 53/58] drm/i915: s/intel_encoder_disable/intel_encoder_noop Daniel Vetter
@ 2012-09-05 18:17   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:17 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:10 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_crt.c     | 2 +-
>  drivers/gpu/drm/i915/intel_display.c | 2 +-
>  drivers/gpu/drm/i915/intel_dp.c      | 2 +-
>  drivers/gpu/drm/i915/intel_drv.h     | 2 +-
>  drivers/gpu/drm/i915/intel_dvo.c     | 2 +-
>  drivers/gpu/drm/i915/intel_hdmi.c    | 4 ++--
>  drivers/gpu/drm/i915/intel_lvds.c    | 2 +-
>  drivers/gpu/drm/i915/intel_sdvo.c    | 2 +-
>  drivers/gpu/drm/i915/intel_tv.c      | 2 +-
>  9 files changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index 2855eb7..611564b 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -641,7 +641,7 @@ static void intel_crt_reset(struct drm_connector *connector)
>  static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
>  	.mode_fixup = intel_crt_mode_fixup,
>  	.mode_set = intel_crt_mode_set,
> -	.disable = intel_encoder_disable,
> +	.disable = intel_encoder_noop,
>  };
>  
>  static const struct drm_connector_funcs intel_crt_connector_funcs = {
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 48d763d..a716893 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3553,7 +3553,7 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
>  	}
>  }
>  
> -void intel_encoder_disable(struct drm_encoder *encoder)
> +void intel_encoder_noop(struct drm_encoder *encoder)
>  {
>  }
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index b07d4b4..3b1c407 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2393,7 +2393,7 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
>  	.mode_fixup = intel_dp_mode_fixup,
>  	.mode_set = intel_dp_mode_set,
> -	.disable = intel_encoder_disable,
> +	.disable = intel_encoder_noop,
>  };
>  
>  static const struct drm_connector_funcs intel_dp_connector_funcs = {
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 4aaf75c..1282bf0 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -452,7 +452,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_non_cloned(struct intel_encoder *encoder);
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index 17dc8be..aa1bf57 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -346,7 +346,7 @@ static void intel_dvo_destroy(struct drm_connector *connector)
>  static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
>  	.mode_fixup = intel_dvo_mode_fixup,
>  	.mode_set = intel_dvo_mode_set,
> -	.disable = intel_encoder_disable,
> +	.disable = intel_encoder_noop,
>  };
>  
>  static const struct drm_connector_funcs intel_dvo_connector_funcs = {
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index e7d5078..7acf2d9 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -907,13 +907,13 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
>  static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
>  	.mode_fixup = intel_hdmi_mode_fixup,
>  	.mode_set = intel_ddi_mode_set,
> -	.disable = intel_encoder_disable,
> +	.disable = intel_encoder_noop,
>  };
>  
>  static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
>  	.mode_fixup = intel_hdmi_mode_fixup,
>  	.mode_set = intel_hdmi_mode_set,
> -	.disable = intel_encoder_disable,
> +	.disable = intel_encoder_noop,
>  };
>  
>  static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index 7f730af..38ba2e8 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -590,7 +590,7 @@ static int intel_lvds_set_property(struct drm_connector *connector,
>  static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
>  	.mode_fixup = intel_lvds_mode_fixup,
>  	.mode_set = intel_lvds_mode_set,
> -	.disable = intel_encoder_disable,
> +	.disable = intel_encoder_noop,
>  };
>  
>  static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index 198bb89..6f53871 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -1936,7 +1936,7 @@ done:
>  static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
>  	.mode_fixup = intel_sdvo_mode_fixup,
>  	.mode_set = intel_sdvo_mode_set,
> -	.disable = intel_encoder_disable
> +	.disable = intel_encoder_noop,
>  };
>  
>  static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
> diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
> index 4def811..c9b2fb0 100644
> --- a/drivers/gpu/drm/i915/intel_tv.c
> +++ b/drivers/gpu/drm/i915/intel_tv.c
> @@ -1492,7 +1492,7 @@ out:
>  static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
>  	.mode_fixup = intel_tv_mode_fixup,
>  	.mode_set = intel_tv_mode_set,
> -	.disable = intel_encoder_disable,
> +	.disable = intel_encoder_noop,
>  };
>  
>  static const struct drm_connector_funcs intel_tv_connector_funcs = {

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 54/58] drm/i915: WARN if the pipe won't turn off
  2012-08-19 19:13 ` [PATCH 54/58] drm/i915: WARN if the pipe won't turn off Daniel Vetter
@ 2012-09-05 18:18   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:18 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:11 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> This seems to be the symptom of a few neat bugs, hence be more
> obnoxious when this fails.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index a716893..da45d39 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1006,7 +1006,7 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
>  		/* Wait for the Pipe State to go off */
>  		if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0,
>  			     100))
> -			DRM_DEBUG_KMS("pipe_off wait timed out\n");
> +			WARN(1, "pipe_off wait timed out\n");
>  	} else {
>  		u32 last_line, line_mask;
>  		int reg = PIPEDSL(pipe);
> @@ -1024,7 +1024,7 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
>  		} while (((I915_READ(reg) & line_mask) != last_line) &&
>  			 time_after(timeout, jiffies));
>  		if (time_after(jiffies, timeout))
> -			DRM_DEBUG_KMS("pipe_off wait timed out\n");
> +			WARN(1, "pipe_off wait timed out\n");
>  	}
>  }
>  

I hope we can actually fix all the issues this will report... :)

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 55/58] drm/i915: switch the load detect code to the staged modeset config
  2012-08-19 19:13 ` [PATCH 55/58] drm/i915: switch the load detect code to the staged modeset config Daniel Vetter
@ 2012-09-05 18:19   ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:19 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:12 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Now that set_mode also disables crtcs and expects it's new
> configuration in the staged output links we need to adjust the load
> detect code a bit.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index da45d39..5a72a27 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5796,8 +5796,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
>  		return false;
>  	}
>  
> -	encoder->crtc = crtc;
> -	connector->encoder = encoder;
> +	intel_encoder->new_crtc = to_intel_crtc(crtc);
> +	to_intel_connector(connector)->new_encoder = intel_encoder;
>  
>  	intel_crtc = to_intel_crtc(crtc);
>  	old->dpms_mode = connector->dpms;
> @@ -5849,16 +5849,17 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
>  	struct intel_encoder *intel_encoder =
>  		intel_attached_encoder(connector);
>  	struct drm_encoder *encoder = &intel_encoder->base;
> -	struct drm_device *dev = encoder->dev;
>  
>  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
>  		      connector->base.id, drm_get_connector_name(connector),
>  		      encoder->base.id, drm_get_encoder_name(encoder));
>  
>  	if (old->load_detect_temp) {
> -		connector->encoder = NULL;
> -		encoder->crtc = NULL;
> -		drm_helper_disable_unused_functions(dev);
> +		struct drm_crtc *crtc = encoder->crtc;
> +
> +		to_intel_connector(connector)->new_encoder = NULL;
> +		intel_encoder->new_crtc = NULL;
> +		intel_set_mode(crtc, NULL, 0, 0, NULL);
>  
>  		if (old->release_fb)
>  			old->release_fb->funcs->destroy(old->release_fb);

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing
  2012-09-04 19:32     ` Daniel Vetter
@ 2012-09-05 18:28       ` Jesse Barnes
  2012-09-05 19:48         ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:28 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Tue,  4 Sep 2012 21:32:28 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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 <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 108 +++++++++++++++++++++++------------
>  drivers/gpu/drm/i915/intel_drv.h     |   3 -
>  2 files changed, 70 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 2c2b4873..c3ab86b 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3221,10 +3221,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  
>  	WARN_ON(!crtc->enabled);
>  
> -	/* XXX: For compatability with the crtc helper code, call the encoder's
> -	 * enable function unconditionally for now. */
>  	if (intel_crtc->active)
> -		goto encoders;
> +		return;
>  
>  	intel_crtc->active = true;
>  	intel_update_watermarks(dev);
> @@ -3272,7 +3270,6 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  
>  	intel_crtc_update_cursor(crtc, true);
>  
> -encoders:
>  	for_each_encoder_on_crtc(dev, crtc, encoder)
>  		encoder->enable(encoder);
>  
> @@ -3290,14 +3287,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
>  	int plane = intel_crtc->plane;
>  	u32 reg, temp;
>  
> -	/* XXX: For compatability with the crtc helper code, call the encoder's
> -	 * disable function unconditionally for now. */
> -	for_each_encoder_on_crtc(dev, crtc, encoder)
> -		encoder->disable(encoder);
>  
>  	if (!intel_crtc->active)
>  		return;
>  
> +	for_each_encoder_on_crtc(dev, crtc, encoder)
> +		encoder->disable(encoder);
> +
>  	intel_crtc_wait_for_pending_flips(crtc);
>  	drm_vblank_off(dev, pipe);
>  	intel_crtc_update_cursor(crtc, false);
> @@ -3399,10 +3395,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
>  
>  	WARN_ON(!crtc->enabled);
>  
> -	/* XXX: For compatability with the crtc helper code, call the encoder's
> -	 * enable function unconditionally for now. */
>  	if (intel_crtc->active)
> -		goto encoders;
> +		return;
>  
>  	intel_crtc->active = true;
>  	intel_update_watermarks(dev);
> @@ -3418,7 +3412,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
>  	intel_crtc_dpms_overlay(intel_crtc, true);
>  	intel_crtc_update_cursor(crtc, true);
>  
> -encoders:
>  	for_each_encoder_on_crtc(dev, crtc, encoder)
>  		encoder->enable(encoder);
>  }
> @@ -3432,14 +3425,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
>  	int pipe = intel_crtc->pipe;
>  	int plane = intel_crtc->plane;
>  
> -	/* XXX: For compatability with the crtc helper code, call the encoder's
> -	 * disable function unconditionally for now. */
> -	for_each_encoder_on_crtc(dev, crtc, encoder)
> -		encoder->disable(encoder);
>  
>  	if (!intel_crtc->active)
>  		return;
>  
> +	for_each_encoder_on_crtc(dev, crtc, encoder)
> +		encoder->disable(encoder);
> +
>  	/* Give the overlay scaler a chance to disable if it's on this pipe */
>  	intel_crtc_wait_for_pending_flips(crtc);
>  	drm_vblank_off(dev, pipe);
> @@ -6631,18 +6623,6 @@ static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
>  	return false;
>  }
>  
> -static void
> -intel_crtc_prepare_encoders(struct drm_device *dev)
> -{
> -	struct intel_encoder *encoder;
> -
> -	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
> -		/* Disable unused encoders */
> -		if (encoder->base.crtc == NULL)
> -			encoder->disable(encoder);
> -	}
> -}
> -
>  /**
>   * intel_modeset_update_staged_output_state
>   *
> @@ -6822,6 +6802,60 @@ intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
>  	*prepare_pipes &= ~(*disable_pipes);
>  }
>  
> +static bool intel_crtc_in_use(struct drm_crtc *crtc)
> +{
> +	struct drm_encoder *encoder;
> +	struct drm_device *dev = crtc->dev;
> +
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
> +		if (encoder->crtc == crtc)
> +			return true;
> +
> +	return false;
> +}
> +
> +static void
> +intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
> +{
> +	struct intel_encoder *intel_encoder;
> +	struct intel_crtc *intel_crtc;
> +	struct drm_connector *connector;
> +
> +	list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list,
> +			    base.head) {
> +		if (!intel_encoder->base.crtc)
> +			continue;
> +
> +		intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
> +
> +		if (prepare_pipes & (1 << intel_crtc->pipe))
> +			intel_encoder->connectors_active = false;
> +	}
> +
> +	intel_modeset_commit_output_state(dev);
> +
> +	/* Update computed 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);
> +	}
> +
> +	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +		if (!connector->encoder || !connector->encoder->crtc)
> +			continue;
> +
> +		intel_crtc = to_intel_crtc(connector->encoder->crtc);
> +
> +		if (prepare_pipes & (1 << intel_crtc->pipe)) {
> +			connector->dpms = DRM_MODE_DPMS_ON;
> +
> +			intel_encoder = to_intel_encoder(connector->encoder);
> +			intel_encoder->connectors_active = true;
> +		}
> +	}
> +
> +}
> +
>  #define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
>  	list_for_each_entry((intel_crtc), \
>  			    &(dev)->mode_config.crtc_list, \
> @@ -6850,12 +6884,6 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
>  		intel_crtc_disable(&intel_crtc->base);
>  
> -	intel_modeset_commit_output_state(dev);
> -
> -	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
> -			    base.head)
> -		intel_crtc->base.enabled = drm_helper_crtc_in_use(crtc);
> -
>  	saved_hwmode = crtc->hwmode;
>  	saved_mode = crtc->mode;
>  
> @@ -6870,12 +6898,12 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  		if (IS_ERR(adjusted_mode)) {
>  			return false;
>  		}
> -
> -		intel_crtc_prepare_encoders(dev);
>  	}
>  
> -	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
> -		dev_priv->display.crtc_disable(&intel_crtc->base);
> +	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
> +		if (intel_crtc->base.enabled)
> +			dev_priv->display.crtc_disable(&intel_crtc->base);
> +	}
>  
>  	if (modeset_pipes) {
>  		crtc->mode = *mode;
> @@ -6883,6 +6911,10 @@ bool intel_set_mode(struct drm_crtc *crtc,
>  		crtc->y = y;
>  	}
>  
> +	/* Only after disabling all output pipelines that will be changed can we
> +	 * update the the output configuration. */
> +	intel_modeset_update_state(dev, prepare_pipes);
> +
>  	/* Set up the DPLL and any encoders state that needs to adjust or depend
>  	 * on the DPLL.
>  	 */
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 1282bf0..3e6feae 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? */

The variables have me confused a little... I would have expected
update_state to take modeset_pipes rather than prepare_pipes.  Could
you use either?  Or will that not catch cases where we updated a pipe
that was already on?

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 57/58] drm/i915: disable all crtcs at suspend time
  2012-08-19 19:13 ` [PATCH 57/58] drm/i915: disable all crtcs at suspend time Daniel Vetter
  2012-08-29 21:13   ` [PATCH] drm/i915: no longer call drm_helper_resume_force_mode Daniel Vetter
@ 2012-09-05 18:29   ` Jesse Barnes
  1 sibling, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:29 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:13:14 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> 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.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> Conflicts:
> 	drivers/gpu/drm/i915/intel_drv.h
> ---
>  drivers/gpu/drm/i915/i915_drv.c      |  3 +++
>  drivers/gpu/drm/i915/intel_display.c | 10 ++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |  1 +
>  3 files changed, 14 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 4abac6d..fe7512a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -470,6 +470,9 @@ static int i915_drm_freeze(struct drm_device *dev)
>  				"GEM idle failed, resume might fail\n");
>  			return error;
>  		}
> +
> +		intel_modeset_disable(dev);
> +
>  		drm_irq_uninstall(dev);
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 10e3f9c..95a9f04 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3545,6 +3545,16 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
>  	}
>  }
>  
> +void intel_modeset_disable(struct drm_device *dev)
> +{
> +	struct drm_crtc *crtc;
> +
> +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> +		if (crtc->enabled)
> +			intel_crtc_disable(crtc);
> +	}
> +}
> +
>  void intel_encoder_noop(struct drm_encoder *encoder)
>  {
>  }
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 1282bf0..71c1517 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -450,6 +450,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);

Looks safe enough.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: no longer call drm_helper_resume_force_mode
  2012-08-29 21:13   ` [PATCH] drm/i915: no longer call drm_helper_resume_force_mode Daniel Vetter
@ 2012-09-05 18:31     ` Jesse Barnes
  2012-09-05 19:56       ` Daniel Vetter
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:31 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Wed, 29 Aug 2012 23:13:29 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Since this only calls crtc helper functions, of which a shocking
> amount are NULL.
> 
> Now the curious thing is how the new modeset code worked with this
> function call still present:
> 
> Thanks to the hw state readout and the suspend fixes to properly
> quiescent the register state, nothing is actually enabled at resume
> (if the bios doesn't set up anything). Which means resume_force_mode
> doesn't actually do anything and hence nothing blows up at resume
> time.
> 
> The other reason things do work is that the fbcon layer has it's own
> resume notifier callback, which restores the mode. And thanks to the
> force vt switch at suspend/resume, that then forces X to restore it's
> own mode.
> 
> Hence everything still worked (as long as the bios doesn't enable
> anything). And we can just kill the call to resume_force_mode.
> 
> The upside of both this patch and the preceeding patch to quiescent
> the modeset state is that our resume path is much simpler:
> - We now longer restore bogus register values (which most often would
>   enable the backlight a bit and a few ports), causing flickering.
> - We now longer call resume_force_mode to restore a mode that the
>   fbcon layer would overwrite right away anyway.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/i915_drv.c | 5 -----
>  1 file changed, 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index fe7512a..cd6697c 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -549,11 +549,6 @@ static int i915_drm_thaw(struct drm_device *dev)
>  		intel_modeset_setup_hw_state(dev);
>  		drm_mode_config_reset(dev);
>  		drm_irq_install(dev);
> -
> -		/* Resume the modeset for every activated CRTC */
> -		mutex_lock(&dev->mode_config.mutex);
> -		drm_helper_resume_force_mode(dev);
> -		mutex_unlock(&dev->mode_config.mutex);
>  	}
>  
>  	intel_opregion_init(dev);

Wouldn't the fb layer's modeset end up being a no-op if the suspended
mode was the same as the fb mode (often the case)?  Or at the very
least just a flip rather than a full mode set.

Though we do need to deal with non-fb, non-X resumes as well.  kmscon
and wayland will expect to be restored at resume time even if CONFIG_VT
and the fb layer aren't compiled into the kernel.

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 1/2] drm/i915: add tons of modeset state checks
  2012-08-31 18:12     ` [PATCH 1/2] " Daniel Vetter
  2012-08-31 18:12       ` [PATCH 2/2] drm/i915: improve modeset state checking after dpms calls Daniel Vetter
@ 2012-09-05 18:33       ` Jesse Barnes
  1 sibling, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:33 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Fri, 31 Aug 2012 20:12:54 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> ... let's see whether this catches anything earlier and I can track
> down a few bugs.
> 
> v2: Add more checks and also add DRM_DEBUG_KMS output so that it's
> clear which connector/encoder/crtc is being checked atm. Which proved
> rather useful for debugging ...
> 
> v3: Add a WARN in the common encoder dpms function, now that also
> modeset changes properly update the dpms state ...
> 
> v4: Properly add a short explanation for each WARN, to avoid the need
> to correlate dmesg lines with source lines accurately. Suggested by
> Chris Wilson.
> 
> v5: Also dump (expected, found) for state checks (or wherever it's not
> apparent from the test what exactly mismatches with expectations).
> Again suggested by Chris Wilson.
> 
> v6: Due to an issue reported by Paulo Zanoni I've noticed that the
> encoder checking is by far not as strict as it could and should be.
> Improve this.
> 
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 104 ++++++++++++++++++++++++++++++++++-
>  1 file changed, 103 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 5c672ed..e703413 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3637,7 +3637,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
>  	if (encoder->base.crtc)
>  		intel_encoder_dpms(encoder, mode);
>  	else
> -		encoder->connectors_active = false;
> +		WARN_ON(encoder->connectors_active != false);
>  
>  	intel_connector_check_state(to_intel_connector(connector));
>  }
> @@ -6872,6 +6872,104 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
>  			    base.head) \
>  		if (mask & (1 <<(intel_crtc)->pipe)) \
>  
> +static void
> +intel_modeset_check_state(struct drm_device *dev)
> +{
> +	struct intel_crtc *crtc;
> +	struct intel_encoder *encoder;
> +	struct intel_connector *connector;
> +
> +	list_for_each_entry(connector, &dev->mode_config.connector_list,
> +			    base.head) {
> +		/* This also checks the encoder/connector hw state with the
> +		 * ->get_hw_state callbacks. */
> +		intel_connector_check_state(connector);
> +
> +		WARN(&connector->new_encoder->base != connector->base.encoder,
> +		     "connector's staged encoder doesn't match current encoder\n");
> +	}
> +
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
> +			    base.head) {
> +		bool enabled = false;
> +		bool active = false;
> +		enum pipe pipe, tracked_pipe;
> +
> +		DRM_DEBUG_KMS("[ENCODER:%d:%s]\n",
> +			      encoder->base.base.id,
> +			      drm_get_encoder_name(&encoder->base));
> +
> +		WARN(&encoder->new_crtc->base != encoder->base.crtc,
> +		     "encoder's stage crtc doesn't match current crtc\n");
> +		WARN(encoder->connectors_active && !encoder->base.crtc,
> +		     "encoder's active_connectors set, but no crtc\n");
> +
> +		list_for_each_entry(connector, &dev->mode_config.connector_list,
> +				    base.head) {
> +			if (connector->base.encoder != &encoder->base)
> +				continue;
> +			enabled = true;
> +			if (connector->base.dpms != DRM_MODE_DPMS_OFF)
> +				active = true;
> +		}
> +		WARN(!!encoder->base.crtc != enabled,
> +		     "encoder's enabled state mismatch "
> +		     "(expected %i, found %i)\n",
> +		     !!encoder->base.crtc, enabled);
> +		WARN(active && !encoder->base.crtc,
> +		     "active encoder with no crtc\n");
> +
> +		WARN(encoder->connectors_active != active,
> +		     "encoder's computed active state doesn't match tracked active state "
> +		     "(expected %i, found %i)\n", active, encoder->connectors_active);
> +
> +		active = encoder->get_hw_state(encoder, &pipe);
> +		WARN(active != encoder->connectors_active,
> +		     "encoder's hw state doesn't match sw tracking "
> +		     "(expected %i, found %i)\n",
> +		     encoder->connectors_active, active);
> +
> +		if (!encoder->base.crtc)
> +			continue;
> +
> +		tracked_pipe = to_intel_crtc(encoder->base.crtc)->pipe;
> +		WARN(active && pipe != tracked_pipe,
> +		     "active encoder's pipe doesn't match"
> +		     "(expected %i, found %i)\n",
> +		     tracked_pipe, pipe);
> +
> +	}
> +
> +	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
> +			    base.head) {
> +		bool enabled = false;
> +		bool active = false;
> +
> +		DRM_DEBUG_KMS("[CRTC:%d]\n",
> +			      crtc->base.base.id);
> +
> +		WARN(crtc->active && !crtc->base.enabled,
> +		     "active crtc, but not enabled in sw tracking\n");
> +
> +		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
> +				    base.head) {
> +			if (encoder->base.crtc != &crtc->base)
> +				continue;
> +			enabled = true;
> +			if (encoder->connectors_active)
> +				active = true;
> +		}
> +		WARN(active != crtc->active,
> +		     "crtc's computed active state doesn't match tracked active state "
> +		     "(expected %i, found %i)\n", active, crtc->active);
> +		WARN(enabled != crtc->base.enabled,
> +		     "crtc's computed enabled state doesn't match tracked enabled state "
> +		     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
> +
> +		assert_pipe(dev->dev_private, crtc->pipe, crtc->active);
> +	}
> +}
> +
>  bool intel_set_mode(struct drm_crtc *crtc,
>  		    struct drm_display_mode *mode,
>  		    int x, int y, struct drm_framebuffer *fb)
> @@ -6969,6 +7067,8 @@ done:
>  	if (!ret && crtc->enabled) {
>  		crtc->hwmode = saved_hwmode;
>  		crtc->mode = saved_mode;
> +	} else {
> +		intel_modeset_check_state(dev);
>  	}
>  
>  	return ret;
> @@ -8166,6 +8266,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev)
>  	}
>  
>  	intel_modeset_update_staged_output_state(dev);
> +
> +	intel_modeset_check_state(dev);
>  }
>  
>  void intel_modeset_gem_init(struct drm_device *dev)

Nice, should help us catch lots of issues.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 2/2] drm/i915: improve modeset state checking after dpms calls
  2012-08-31 18:12       ` [PATCH 2/2] drm/i915: improve modeset state checking after dpms calls Daniel Vetter
@ 2012-09-05 18:34         ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 18:34 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Fri, 31 Aug 2012 20:12:55 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Now that we have solid modeset state tracking and checking code in
> place, we can do the Full Monty also after dpms calls.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/intel_crt.c     | 2 +-
>  drivers/gpu/drm/i915/intel_display.c | 6 +++---
>  drivers/gpu/drm/i915/intel_dp.c      | 2 +-
>  drivers/gpu/drm/i915/intel_drv.h     | 3 ++-
>  drivers/gpu/drm/i915/intel_dvo.c     | 2 +-
>  drivers/gpu/drm/i915/intel_sdvo.c    | 2 +-
>  6 files changed, 9 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index cca266f..b9f08f6 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -177,7 +177,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
>  		intel_crtc_update_dpms(crtc);
>  	}
>  
> -	intel_connector_check_state(to_intel_connector(connector));
> +	intel_modeset_check_state(connector->dev);
>  }
>  
>  static int intel_crt_mode_valid(struct drm_connector *connector,
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index e703413..77191d8 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3585,7 +3585,7 @@ void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
>  
>  /* Cross check the actual hw state with our own modeset state tracking (and it's
>   * internal consistency). */
> -void intel_connector_check_state(struct intel_connector *connector)
> +static void intel_connector_check_state(struct intel_connector *connector)
>  {
>  	if (connector->get_hw_state(connector)) {
>  		struct intel_encoder *encoder = connector->encoder;
> @@ -3639,7 +3639,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
>  	else
>  		WARN_ON(encoder->connectors_active != false);
>  
> -	intel_connector_check_state(to_intel_connector(connector));
> +	intel_modeset_check_state(connector->dev);
>  }
>  
>  /* Simple connector->get_hw_state implementation for encoders that support only
> @@ -6872,7 +6872,7 @@ intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
>  			    base.head) \
>  		if (mask & (1 <<(intel_crtc)->pipe)) \
>  
> -static void
> +void
>  intel_modeset_check_state(struct drm_device *dev)
>  {
>  	struct intel_crtc *crtc;
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 3b1c407..d391e67 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1362,7 +1362,7 @@ intel_dp_dpms(struct drm_connector *connector, int mode)
>  		intel_encoder_dpms(&intel_dp->base, mode);
>  	}
>  
> -	intel_connector_check_state(to_intel_connector(connector));
> +	intel_modeset_check_state(connector->dev);
>  }
>  
>  /*
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 71c1517..1225bc5 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -459,7 +459,8 @@ extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode);
>  extern bool intel_encoder_check_non_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)
>  {
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index aa1bf57..4f1fdcc 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -189,7 +189,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode)
>  		intel_crtc_update_dpms(crtc);
>  	}
>  
> -	intel_connector_check_state(to_intel_connector(connector));
> +	intel_modeset_check_state(connector->dev);
>  }
>  
>  static int intel_dvo_mode_valid(struct drm_connector *connector,
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index 6f53871..07d3921 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -1275,7 +1275,7 @@ static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
>  		intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
>  	}
>  
> -	intel_connector_check_state(to_intel_connector(connector));
> +	intel_modeset_check_state(connector->dev);
>  }
>  
>  static int intel_sdvo_mode_valid(struct drm_connector *connector,

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* [PATCH] drm/i915: push crtc->fb update into pipe_set_base
  2012-09-05 19:48         ` Daniel Vetter
@ 2012-09-05 18:56           ` Daniel Vetter
  2012-09-05 19:50           ` [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing Jesse Barnes
  1 sibling, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 18:56 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_display.c | 104 ++++++++++++-----------------------
 drivers/gpu/drm/i915/intel_drv.h     |   1 -
 2 files changed, 34 insertions(+), 71 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5031e0c..9ce8c59 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2201,16 +2201,17 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
 
 static int
 intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
-		    struct drm_framebuffer *old_fb)
+		    struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_framebuffer *old_fb;
 	int ret;
 
 	/* no fb bound */
-	if (!crtc->fb) {
+	if (!fb) {
 		DRM_ERROR("No FB bound\n");
 		return 0;
 	}
@@ -2224,7 +2225,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 
 	mutex_lock(&dev->struct_mutex);
 	ret = intel_pin_and_fence_fb_obj(dev,
-					 to_intel_framebuffer(crtc->fb)->obj,
+					 to_intel_framebuffer(fb)->obj,
 					 NULL);
 	if (ret != 0) {
 		mutex_unlock(&dev->struct_mutex);
@@ -2232,17 +2233,20 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		return ret;
 	}
 
-	if (old_fb)
-		intel_finish_fb(old_fb);
+	if (crtc->fb)
+		intel_finish_fb(crtc->fb);
 
-	ret = dev_priv->display.update_plane(crtc, crtc->fb, x, y);
+	ret = dev_priv->display.update_plane(crtc, fb, x, y);
 	if (ret) {
-		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
+		intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj);
 		mutex_unlock(&dev->struct_mutex);
 		DRM_ERROR("failed to update base address\n");
 		return ret;
 	}
 
+	old_fb = crtc->fb;
+	crtc->fb = fb;
+
 	if (old_fb) {
 		intel_wait_for_vblank(dev, intel_crtc->pipe);
 		intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
@@ -3777,6 +3781,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
  * true if they don't match).
  */
 static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
+					 struct drm_framebuffer *fb,
 					 unsigned int *pipe_bpp,
 					 struct drm_display_mode *mode)
 {
@@ -3846,7 +3851,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
 	 * also stays within the max display bpc discovered above.
 	 */
 
-	switch (crtc->fb->depth) {
+	switch (fb->depth) {
 	case 8:
 		bpc = 8; /* since we go through a colormap */
 		break;
@@ -4265,7 +4270,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 			      struct drm_display_mode *mode,
 			      struct drm_display_mode *adjusted_mode,
 			      int x, int y,
-			      struct drm_framebuffer *old_fb)
+			      struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4455,7 +4460,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), dspcntr);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, old_fb);
+	ret = intel_pipe_set_base(crtc, x, y, fb);
 
 	intel_update_watermarks(dev);
 
@@ -4613,7 +4618,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode,
 				  int x, int y,
-				  struct drm_framebuffer *old_fb)
+				  struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4733,7 +4738,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	/* determine panel color depth */
 	temp = I915_READ(PIPECONF(pipe));
 	temp &= ~PIPE_BPC_MASK;
-	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
+	dither = intel_choose_pipe_bpp_dither(crtc, fb, &pipe_bpp, mode);
 	switch (pipe_bpp) {
 	case 18:
 		temp |= PIPE_6BPC;
@@ -5002,7 +5007,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), dspcntr);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, old_fb);
+	ret = intel_pipe_set_base(crtc, x, y, fb);
 
 	intel_update_watermarks(dev);
 
@@ -5015,7 +5020,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode,
 			       int x, int y,
-			       struct drm_framebuffer *old_fb)
+			       struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5026,7 +5031,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	drm_vblank_pre_modeset(dev, pipe);
 
 	ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
-					      x, y, old_fb);
+					      x, y, fb);
 	drm_vblank_post_modeset(dev, pipe);
 
 	return ret;
@@ -5718,7 +5723,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_crtc *crtc = NULL;
 	struct drm_device *dev = encoder->dev;
-	struct drm_framebuffer *old_fb;
+	struct drm_framebuffer *fb;
 	int i = -1;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
@@ -5779,8 +5784,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 	if (!mode)
 		mode = &load_detect_mode;
 
-	old_fb = crtc->fb;
-
 	/* We need a framebuffer large enough to accommodate all accesses
 	 * that the plane may generate whilst we perform load detection.
 	 * We can not rely on the fbcon either being present (we get called
@@ -5788,19 +5791,19 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 	 * not even exist) or that it is large enough to satisfy the
 	 * requested mode.
 	 */
-	crtc->fb = mode_fits_in_fbdev(dev, mode);
-	if (crtc->fb == NULL) {
+	fb = mode_fits_in_fbdev(dev, mode);
+	if (fb == NULL) {
 		DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
-		crtc->fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
-		old->release_fb = crtc->fb;
+		fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
+		old->release_fb = fb;
 	} else
 		DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
-	if (IS_ERR(crtc->fb)) {
+	if (IS_ERR(fb)) {
 		DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
 		goto fail;
 	}
 
-	if (!intel_set_mode(crtc, mode, 0, 0, old_fb)) {
+	if (!intel_set_mode(crtc, mode, 0, 0, fb)) {
 		DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
 		if (old->release_fb)
 			old->release_fb->funcs->destroy(old->release_fb);
@@ -5814,7 +5817,6 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
 fail:
 	connector->encoder = NULL;
 	encoder->crtc = NULL;
-	crtc->fb = old_fb;
 	return false;
 }
 
@@ -6666,13 +6668,12 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
 
 bool intel_set_mode(struct drm_crtc *crtc,
 		    struct drm_display_mode *mode,
-		    int x, int y, struct drm_framebuffer *old_fb)
+		    int x, int y, struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
 	struct drm_encoder_helper_funcs *encoder_funcs;
-	int saved_x, saved_y;
 	struct drm_encoder *encoder;
 	bool ret = true;
 
@@ -6686,15 +6687,11 @@ bool intel_set_mode(struct drm_crtc *crtc,
 
 	saved_hwmode = crtc->hwmode;
 	saved_mode = crtc->mode;
-	saved_x = crtc->x;
-	saved_y = crtc->y;
 
 	/* Update crtc values up front so the driver can rely on them for mode
 	 * setting.
 	 */
 	crtc->mode = *mode;
-	crtc->x = x;
-	crtc->y = y;
 
 	/* Pass our mode to the connectors and the CRTC to give them a chance to
 	 * adjust it according to limitations or connector properties, and also
@@ -6725,7 +6722,7 @@ bool intel_set_mode(struct drm_crtc *crtc,
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
-	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+	ret = !intel_crtc_mode_set(crtc, mode, adjusted_mode, x, y, fb);
 	if (!ret)
 	    goto done;
 
@@ -6741,6 +6738,9 @@ bool intel_set_mode(struct drm_crtc *crtc,
 		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 	}
 
+	crtc->x = x;
+	crtc->y = y;
+
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
 	dev_priv->display.crtc_enable(crtc);
 
@@ -6759,8 +6759,6 @@ done:
 	if (!ret) {
 		crtc->hwmode = saved_hwmode;
 		crtc->mode = saved_mode;
-		crtc->x = saved_x;
-		crtc->y = saved_y;
 	}
 
 	return ret;
@@ -6773,25 +6771,16 @@ static void intel_set_config_free(struct intel_set_config *config)
 
 	kfree(config->save_connector_encoders);
 	kfree(config->save_encoder_crtcs);
-	kfree(config->save_crtcs);
 	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;
 
-	/* Allocate space for the backup of all (non-pointer) crtc, encoder and
-	 * connector data. */
-	config->save_crtcs = kcalloc(dev->mode_config.num_crtc,
-				     sizeof(struct drm_crtc), GFP_KERNEL);
-	if (!config->save_crtcs)
-		return -ENOMEM;
-
 	config->save_encoder_crtcs =
 		kcalloc(dev->mode_config.num_encoder,
 			sizeof(struct drm_crtc *), GFP_KERNEL);
@@ -6809,11 +6798,6 @@ static int intel_set_config_save_state(struct drm_device *dev,
 	 * restored, not the drivers personal bookkeeping.
 	 */
 	count = 0;
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		config->save_crtcs[count++] = *crtc;
-	}
-
-	count = 0;
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		config->save_encoder_crtcs[count++] = encoder->crtc;
 	}
@@ -6829,17 +6813,11 @@ 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 drm_crtc *crtc;
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
 	int count;
 
 	count = 0;
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		*crtc = config->save_crtcs[count++];
-	}
-
-	count = 0;
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 		encoder->new_crtc =
 			to_intel_crtc(config->save_encoder_crtcs[count++]);
@@ -6994,7 +6972,6 @@ next_encoder:
 static int intel_crtc_set_config(struct drm_mode_set *set)
 {
 	struct drm_device *dev;
-	struct drm_framebuffer *old_fb = NULL;
 	struct drm_mode_set save_set;
 	struct intel_set_config *config;
 	int ret;
@@ -7057,13 +7034,10 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 			DRM_DEBUG_KMS("attempting to set mode from"
 					" userspace\n");
 			drm_mode_debug_printmodeline(set->mode);
-			old_fb = set->crtc->fb;
-			set->crtc->fb = set->fb;
 			if (!intel_set_mode(set->crtc, set->mode,
-					    set->x, set->y, old_fb)) {
+					    set->x, set->y, set->fb)) {
 				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
 					  set->crtc->base.id);
-				set->crtc->fb = old_fb;
 				ret = -EINVAL;
 				goto fail;
 			}
@@ -7076,18 +7050,8 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 		}
 		drm_helper_disable_unused_functions(dev);
 	} else if (config->fb_changed) {
-		set->crtc->x = set->x;
-		set->crtc->y = set->y;
-
-		old_fb = set->crtc->fb;
-		if (set->crtc->fb != set->fb)
-			set->crtc->fb = set->fb;
 		ret = intel_pipe_set_base(set->crtc,
-					  set->x, set->y, old_fb);
-		if (ret != 0) {
-			set->crtc->fb = old_fb;
-			goto fail;
-		}
+					  set->x, set->y, set->fb);
 	}
 
 	intel_set_config_free(config);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ae807af..1aa0b9c 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;
-- 
1.7.11.2

^ permalink raw reply related	[flat|nested] 173+ messages in thread

* Re: [PATCH 31/58] drm/i915: check connector hw/sw state
  2012-09-05 16:26   ` Jesse Barnes
@ 2012-09-05 19:10     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:10 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 6:26 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Sun, 19 Aug 2012 21:12:48 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
>
>> 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).
>
> Nice.  Only comment is that we may want to call it assert_state() to
> match our other assertions.  But no biggie.

All the other assertions (mostly) check whether we get the modeset
_sequence_ right, i.e. whether A is in the right state once we get
around to frob B. This stuff here mostly checks whether our own state
tracking somewhat resembles the actual hw state after the entire dance
is completed. This is especially important to give the fastboot stuff
better coverage: We use the same functions to read the intial modeset
state from the as we use to check the modeset state after any state
changes.

So I think the concepts are sufficiently different to get away with
different names ;-)
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 34/58] drm/i915: ensure the force pipe A quirk is actually followed
  2012-09-05 16:32   ` Jesse Barnes
@ 2012-09-05 19:12     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:12 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 6:32 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Sun, 19 Aug 2012 21:12:51 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
>
>> Many BIOSen forget to turn on the pipe A after resume (because they
>> actually don't turn on anything), so we have to do that ourselves when
>> sanitizing the hw state.
>>
>> I've discovered this due to the recent addition of a pipe WARN that
>> takes the force quirk into account.
>>
>> v2: Actually try to enable the pipe with a proper configuration instead
>> of simpyl switching it on with whatever random state the bios left it
>> in after resume.
>>
>> v3: Fixup rebase conflict - the load_detect functions have lost their
>> encoder argument.
>>
>> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>> ---
>>  drivers/gpu/drm/i915/intel_display.c | 36 ++++++++++++++++++++++++++++++++++++
>>  1 file changed, 36 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index 2cfb397..ab4fa7f 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -7602,6 +7602,33 @@ intel_connector_break_all_links(struct intel_connector *connector)
>>       connector->encoder->base.crtc = NULL;
>>  }
>>
>> +static void intel_enable_pipe_a(struct drm_device *dev)
>> +{
>> +     struct intel_connector *connector;
>> +     struct drm_connector *crt = NULL;
>> +     struct intel_load_detect_pipe load_detect_temp;
>> +
>> +     /* We can't just switch on the pipe A, we need to set things up with a
>> +      * proper mode and output configuration. As a gross hack, enable pipe A
>> +      * by enabling the load detect pipe once. */
>> +     list_for_each_entry(connector,
>> +                         &dev->mode_config.connector_list,
>> +                         base.head) {
>> +             if (connector->encoder->type == INTEL_OUTPUT_ANALOG) {
>> +                     crt = &connector->base;
>> +                     break;
>> +             }
>> +     }
>> +
>> +     if (!crt)
>> +             return;
>> +
>> +     if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp))
>> +             intel_release_load_detect_pipe(crt, &load_detect_temp);
>
> Should we shout if this fails?  Other than that:

We'll definitely shout on the next modeset (on pipe B) if pipe A is
still off. And the code also shouted rather loudly while we I've tried
to get this to work properly. So judging from experience I think we're
covered ...
-Daniel

> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
>
> --
> Jesse Barnes, Intel Open Source Technology Center



-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 39/58] drm/i915: implement crtc helper semantics relied upon by the fb helper
  2012-09-05 16:45   ` Jesse Barnes
@ 2012-09-05 19:15     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:15 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 6:45 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Sun, 19 Aug 2012 21:12:56 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
>
>> Yikes!
>>
>> But yeah, we have to do this until someone volunteers to clean up the
>> fb helper and rid it of its incetious relationship with the crtc
>> helper code.
>>
>> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>> ---
>>  drivers/gpu/drm/i915/intel_display.c | 6 ++++++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>> index 3cedc89..4b2b17f 100644
>> --- a/drivers/gpu/drm/i915/intel_display.c
>> +++ b/drivers/gpu/drm/i915/intel_display.c
>> @@ -6933,6 +6933,12 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>>       if (!set->mode)
>>               set->fb = NULL;
>>
>> +     /* The fb helper likes to play gross jokes with ->mode_set_config.
>> +      * Unfortunately the crtc helper doesn't do much at all for this case,
>> +      * so we have to cope with this madness until the fb helper is fixed up. */
>> +     if (set->fb && set->num_connectors == 0)
>> +             return 0;
>> +
>>       if (set->fb) {
>>               DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
>>                               set->crtc->base.id, set->fb->base.id,
>
> I wonder if this belongs earlier in the series?  But either way:

This one here should be right - we still implement the disable path
like the crtc helper, so we automatically implement the semantics the
fb helper expects. Only later patches need that.

But you're right that some of the later bugfixes that I've added might
slightly break bisect - I've tried hard to put them at the right spot,
but maybe I've mislaid one ... Especially fixups like these to
implement brain-dead crtc helper semantics are tricky to reason about
:(
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 41/58] drm/i915: convert pointless error checks in set_config to BUGs
  2012-09-05 16:50   ` Jesse Barnes
@ 2012-09-05 19:19     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:19 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 6:50 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
>> @@ -6919,16 +6917,9 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
>>       int ret;
>>       int i;
>>
>> -     DRM_DEBUG_KMS("\n");
>> -
>> -     if (!set)
>> -             return -EINVAL;
>> -
>> -     if (!set->crtc)
>> -             return -EINVAL;
>> -
>> -     if (!set->crtc->helper_private)
>> -             return -EINVAL;
>> +     BUG_ON(!set);
>> +     BUG_ON(!set->crtc);
>> +     BUG_ON(!set->crtc->helper_private);
>>
>>       if (!set->mode)
>>               set->fb = NULL;
>
> The BUG_ONs are probably superfluous too, but this is an improvement.

Actually I want to add even more ;-) One of the follow-up cleanups I'd
like to do is fix all the crazy assumptions in the fb helper (I guess
we'll keep on using that one). And to make sure that no-one violates
these accidentally, I'd like to check them in our code with BUG_ONs
(so that people don't accidentally break i915.ko when they frob the fb
helper or other parts of shared code we still use).

So the BUG_ONs are just interface documentation and enforcement.
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 42/58] drm/i915: don't save all the encoder/crtc state in set_config
  2012-09-05 16:52   ` Jesse Barnes
@ 2012-09-05 19:21     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:21 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 6:52 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> Sneaky that you moved to kcalloc too :)

Commit message is now less sneaky, thanks for spotting this.
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 35/58] drm/i915: introduce struct intel_set_config
  2012-09-05 16:34   ` Jesse Barnes
@ 2012-09-05 19:27     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:27 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 6:34 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
>         if (!config)
>                 return;
> ?
>
> My eyes always hurt a little when I see if blocks that take up the
> whole function. :)  Just a nit pick though.

Yeah, looks better. Bikeshed applied locally since it resulted in some
conflicts later on.
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 47/58] drm/i915: extract adjusted mode computation
  2012-09-05 18:00   ` Jesse Barnes
@ 2012-09-05 19:30     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:30 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 8:00 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> Fancy, using ERR_PTR even. :)

Consider this a tell-tale of the shape of things to come ;-) I.e. I
plan to extend this adjusted_mode computation to a full up-front
resource allocation step to decide about pipe bpp, dithering,
bandwidth allocation, pll allocation and all these fancy things. And
Chris wanted better error codes, so I've just started somewhere - in
the middle of the callchain, so doesn't really do anything yet, but
...
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: compute masks of crtcs affected in set_mode
  2012-09-05 18:09     ` Jesse Barnes
@ 2012-09-05 19:38       ` Daniel Vetter
  2012-09-05 19:45         ` Jesse Barnes
  0 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:38 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 8:09 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Wed, 29 Aug 2012 12:34:04 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
>
>> This is definetely a bit more generic than currently required, but
>> if we keep track of all crtcs that need to be disabled/enable (because
>> they loose an encoder or something similar), crtcs that get completely
>> disabled and those that we need to do an actual mode change on nicely
>> prepares us for global modeset operations on multiple crtcs.
>>
>> The only big thing missing here would be a global resource allocation
>> step (for e.g. pch plls), which would equally frob these bitmasks if
>> e.g. a crtc only needs a new pll.
>>
>> These masks aren't yet put to use in this patch, this will follow in the
>> next one.
>>
>> v2-v5: Fix up the computations for good (hopefully).
>>
>> v6: Fixup a confusion reported by Damien Lespiau: I've conserved the
>> (imo braindead) behaviour of the crtc helper to disable _any_
>> disconnected outputs if we do a modeset, even when that newly disabled
>> connector isn't connected to the crtc being changed by the modeset.
>>
>> The effect of that is that we could disable an arbitrary number of
>> unrelated crtcs, which I haven't taken into account when writing this
>> code. Fix this up.
>
> Might not need to clean it up here though, since the only time that
> should matter is during the first mode set after a power on or resume
> when a superfluous CRTC might be enabled.  And with the new hw state
> readout, we can fix that up.
>
> You choose though.

If your comment is just about the v6 fixup, that's definitely need
here. The failure mode is that we unplug a connector, then the window
systems disables _all_ connectors since it wants to reassign them (or
change the fb or whatever, atomic modeset would fix this better). On
the first modeset we then disable crtc 0, but crtc 1 gets disabled,
too (since the connector is now disconnected). Since I didn't consider
things, the state tracking would get out of synced with reality and
not enable crtc 0 again on the new framebuffer (worked though when
retrying).

If the comment is just about changing the behaviour, that's definitely
planned, but as a follow-up cleanup - it changes the abi behaviour, so
we need to have it in a separate patch for revertability.

Or do you mean something totally different?
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 51/58] drm/i915: implement new set_mode code flow
  2012-09-05 18:14   ` Jesse Barnes
@ 2012-09-05 19:43     ` Daniel Vetter
  2012-09-05 19:49       ` Jesse Barnes
  0 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:43 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 8:14 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> An ugly intermediate step... also did you check whether moving the
> crtc->x/y assignment up is safe?  We're passing it around, but some
> places might check for crtc->x/y looking for old values (or did that
> already change in the previous patch... too many patches).

Yeah, I've hunted around in the codebase and found nothing for these.
I also wanted to give crtc->mode the same treatment, but that is
definitely used all over the place. Obviously double-checking this by
the reviewer would be great ;-)

Wrt this being an ugly intermediate step: The disable/modeset stuff
was scary enough that I wanted to do that in discrete patches, hence
this slightly ugly prep step.
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: compute masks of crtcs affected in set_mode
  2012-09-05 19:38       ` Daniel Vetter
@ 2012-09-05 19:45         ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 19:45 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Wed, 5 Sep 2012 21:38:27 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> On Wed, Sep 5, 2012 at 8:09 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > On Wed, 29 Aug 2012 12:34:04 +0200
> > Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> >
> >> This is definetely a bit more generic than currently required, but
> >> if we keep track of all crtcs that need to be disabled/enable (because
> >> they loose an encoder or something similar), crtcs that get completely
> >> disabled and those that we need to do an actual mode change on nicely
> >> prepares us for global modeset operations on multiple crtcs.
> >>
> >> The only big thing missing here would be a global resource allocation
> >> step (for e.g. pch plls), which would equally frob these bitmasks if
> >> e.g. a crtc only needs a new pll.
> >>
> >> These masks aren't yet put to use in this patch, this will follow in the
> >> next one.
> >>
> >> v2-v5: Fix up the computations for good (hopefully).
> >>
> >> v6: Fixup a confusion reported by Damien Lespiau: I've conserved the
> >> (imo braindead) behaviour of the crtc helper to disable _any_
> >> disconnected outputs if we do a modeset, even when that newly disabled
> >> connector isn't connected to the crtc being changed by the modeset.
> >>
> >> The effect of that is that we could disable an arbitrary number of
> >> unrelated crtcs, which I haven't taken into account when writing this
> >> code. Fix this up.
> >
> > Might not need to clean it up here though, since the only time that
> > should matter is during the first mode set after a power on or resume
> > when a superfluous CRTC might be enabled.  And with the new hw state
> > readout, we can fix that up.
> >
> > You choose though.
> 
> If your comment is just about the v6 fixup, that's definitely need
> here. The failure mode is that we unplug a connector, then the window
> systems disables _all_ connectors since it wants to reassign them (or
> change the fb or whatever, atomic modeset would fix this better). On
> the first modeset we then disable crtc 0, but crtc 1 gets disabled,
> too (since the connector is now disconnected). Since I didn't consider
> things, the state tracking would get out of synced with reality and
> not enable crtc 0 again on the new framebuffer (worked though when
> retrying).
> 
> If the comment is just about changing the behaviour, that's definitely
> planned, but as a follow-up cleanup - it changes the abi behaviour, so
> we need to have it in a separate patch for revertability.
> 
> Or do you mean something totally different?

No that covers it, thanks for both explanations.

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing
  2012-09-05 18:28       ` Jesse Barnes
@ 2012-09-05 19:48         ` Daniel Vetter
  2012-09-05 18:56           ` [PATCH] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
  2012-09-05 19:50           ` [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing Jesse Barnes
  0 siblings, 2 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:48 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 8:28 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
>
> The variables have me confused a little... I would have expected
> update_state to take modeset_pipes rather than prepare_pipes.  Could
> you use either?  Or will that not catch cases where we updated a pipe
> that was already on?

The abstract idea for these masks was the following: Any pipe that
changes anything goes into prepare_pipes. For any pipe that also
changes the mode, it goes in addition into the modeset_pipes mask, so
the later is a subset of prepare pipes. The idea here was to avoid the
modeset step where not necessary (e.g. when disabling the 2nd output
of a cloned crtc we only need to disable/enable, not change anything
with the mode or clocks). But after some in-depth discussion with
Paulo Zanoni I think we'll move large parts of the mode_set step into
the enable function (at least for hsw due to funky ordering
requirements), so I think this disdinction doesn't make sense.

The disable mask just contains those pipes that get fully disable (and
which then also get removed from the prepares/modset masks).

Hence I pass the prepares mask into update_states, not just the modeset mask.
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 51/58] drm/i915: implement new set_mode code flow
  2012-09-05 19:43     ` Daniel Vetter
@ 2012-09-05 19:49       ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 19:49 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Wed, 5 Sep 2012 21:43:30 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> On Wed, Sep 5, 2012 at 8:14 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > An ugly intermediate step... also did you check whether moving the
> > crtc->x/y assignment up is safe?  We're passing it around, but some
> > places might check for crtc->x/y looking for old values (or did that
> > already change in the previous patch... too many patches).
> 
> Yeah, I've hunted around in the codebase and found nothing for these.
> I also wanted to give crtc->mode the same treatment, but that is
> definitely used all over the place. Obviously double-checking this by
> the reviewer would be great ;-)
> 
> Wrt this being an ugly intermediate step: The disable/modeset stuff
> was scary enough that I wanted to do that in discrete patches, hence
> this slightly ugly prep step.

Yeah it's fine, was just making noise.  It has to get ugly while it's
in the cocoon turning into a butterfly. :)

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing
  2012-09-05 19:48         ` Daniel Vetter
  2012-09-05 18:56           ` [PATCH] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
@ 2012-09-05 19:50           ` Jesse Barnes
  2012-09-06 20:46             ` Jesse Barnes
  1 sibling, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 19:50 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Wed, 5 Sep 2012 21:48:52 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> On Wed, Sep 5, 2012 at 8:28 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> >
> > The variables have me confused a little... I would have expected
> > update_state to take modeset_pipes rather than prepare_pipes.  Could
> > you use either?  Or will that not catch cases where we updated a pipe
> > that was already on?
> 
> The abstract idea for these masks was the following: Any pipe that
> changes anything goes into prepare_pipes. For any pipe that also
> changes the mode, it goes in addition into the modeset_pipes mask, so
> the later is a subset of prepare pipes. The idea here was to avoid the
> modeset step where not necessary (e.g. when disabling the 2nd output
> of a cloned crtc we only need to disable/enable, not change anything
> with the mode or clocks). But after some in-depth discussion with
> Paulo Zanoni I think we'll move large parts of the mode_set step into
> the enable function (at least for hsw due to funky ordering
> requirements), so I think this disdinction doesn't make sense.
> 
> The disable mask just contains those pipes that get fully disable (and
> which then also get removed from the prepares/modset masks).
> 
> Hence I pass the prepares mask into update_states, not just the modeset mask.

Ok, that makes some sense.  Hopefully we can preserve the full mode set
vs simple update behavior even after the refactoring for HSW.

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: no longer call drm_helper_resume_force_mode
  2012-09-05 18:31     ` Jesse Barnes
@ 2012-09-05 19:56       ` Daniel Vetter
  2012-09-05 20:04         ` Jesse Barnes
  0 siblings, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:56 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 8:31 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Wed, 29 Aug 2012 23:13:29 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
>
>> Since this only calls crtc helper functions, of which a shocking
>> amount are NULL.
>>
>> Now the curious thing is how the new modeset code worked with this
>> function call still present:
>>
>> Thanks to the hw state readout and the suspend fixes to properly
>> quiescent the register state, nothing is actually enabled at resume
>> (if the bios doesn't set up anything). Which means resume_force_mode
>> doesn't actually do anything and hence nothing blows up at resume
>> time.
>>
>> The other reason things do work is that the fbcon layer has it's own
>> resume notifier callback, which restores the mode. And thanks to the
>> force vt switch at suspend/resume, that then forces X to restore it's
>> own mode.
>>
>> Hence everything still worked (as long as the bios doesn't enable
>> anything). And we can just kill the call to resume_force_mode.
>>
>> The upside of both this patch and the preceeding patch to quiescent
>> the modeset state is that our resume path is much simpler:
>> - We now longer restore bogus register values (which most often would
>>   enable the backlight a bit and a few ports), causing flickering.
>> - We now longer call resume_force_mode to restore a mode that the
>>   fbcon layer would overwrite right away anyway.
>>
>> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>> ---
>>  drivers/gpu/drm/i915/i915_drv.c | 5 -----
>>  1 file changed, 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
>> index fe7512a..cd6697c 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.c
>> +++ b/drivers/gpu/drm/i915/i915_drv.c
>> @@ -549,11 +549,6 @@ static int i915_drm_thaw(struct drm_device *dev)
>>               intel_modeset_setup_hw_state(dev);
>>               drm_mode_config_reset(dev);
>>               drm_irq_install(dev);
>> -
>> -             /* Resume the modeset for every activated CRTC */
>> -             mutex_lock(&dev->mode_config.mutex);
>> -             drm_helper_resume_force_mode(dev);
>> -             mutex_unlock(&dev->mode_config.mutex);
>>       }
>>
>>       intel_opregion_init(dev);
>
> Wouldn't the fb layer's modeset end up being a no-op if the suspended
> mode was the same as the fb mode (often the case)?  Or at the very
> least just a flip rather than a full mode set.

I guess most of the flicker was because the register restoring
restored a bunch of crap (since the old modeset state wasn't properly
cleared before suspending).

> Though we do need to deal with non-fb, non-X resumes as well.  kmscon
> and wayland will expect to be restored at resume time even if CONFIG_VT
> and the fb layer aren't compiled into the kernel.

Tbh I was rather surprised that when I've noticed this little issue
here the restore still worked - until I've noticed by looking at the
logs that both the fbcon and the X server restore their modes.

I'm not sure what exactly we should do here, since even with the
current code the concept of a controlling node isn't really defined in
the kms interface (fbcon uses a bunch of funky checks to ensure it
doesn't clobber the output state of someone else). But for now (with
fbcon pretty much being non-optional) things keep on working, and
afaict actually work a bit better overall.
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: push crtc->fb update into pipe_set_base
  2012-09-05 17:55     ` Jesse Barnes
@ 2012-09-05 19:59       ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-05 19:59 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Wed, Sep 5, 2012 at 7:55 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> Ok obviously missed the leak.

Oops, just noticed that I'm still saving the crtc state. Will fix this.
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: no longer call drm_helper_resume_force_mode
  2012-09-05 19:56       ` Daniel Vetter
@ 2012-09-05 20:04         ` Jesse Barnes
  2012-09-06 20:47           ` Jesse Barnes
  0 siblings, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 20:04 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Wed, 5 Sep 2012 21:56:08 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> On Wed, Sep 5, 2012 at 8:31 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > On Wed, 29 Aug 2012 23:13:29 +0200
> > Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> >
> >> Since this only calls crtc helper functions, of which a shocking
> >> amount are NULL.
> >>
> >> Now the curious thing is how the new modeset code worked with this
> >> function call still present:
> >>
> >> Thanks to the hw state readout and the suspend fixes to properly
> >> quiescent the register state, nothing is actually enabled at resume
> >> (if the bios doesn't set up anything). Which means resume_force_mode
> >> doesn't actually do anything and hence nothing blows up at resume
> >> time.
> >>
> >> The other reason things do work is that the fbcon layer has it's own
> >> resume notifier callback, which restores the mode. And thanks to the
> >> force vt switch at suspend/resume, that then forces X to restore it's
> >> own mode.
> >>
> >> Hence everything still worked (as long as the bios doesn't enable
> >> anything). And we can just kill the call to resume_force_mode.
> >>
> >> The upside of both this patch and the preceeding patch to quiescent
> >> the modeset state is that our resume path is much simpler:
> >> - We now longer restore bogus register values (which most often would
> >>   enable the backlight a bit and a few ports), causing flickering.
> >> - We now longer call resume_force_mode to restore a mode that the
> >>   fbcon layer would overwrite right away anyway.
> >>
> >> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> >> ---
> >>  drivers/gpu/drm/i915/i915_drv.c | 5 -----
> >>  1 file changed, 5 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> >> index fe7512a..cd6697c 100644
> >> --- a/drivers/gpu/drm/i915/i915_drv.c
> >> +++ b/drivers/gpu/drm/i915/i915_drv.c
> >> @@ -549,11 +549,6 @@ static int i915_drm_thaw(struct drm_device *dev)
> >>               intel_modeset_setup_hw_state(dev);
> >>               drm_mode_config_reset(dev);
> >>               drm_irq_install(dev);
> >> -
> >> -             /* Resume the modeset for every activated CRTC */
> >> -             mutex_lock(&dev->mode_config.mutex);
> >> -             drm_helper_resume_force_mode(dev);
> >> -             mutex_unlock(&dev->mode_config.mutex);
> >>       }
> >>
> >>       intel_opregion_init(dev);
> >
> > Wouldn't the fb layer's modeset end up being a no-op if the suspended
> > mode was the same as the fb mode (often the case)?  Or at the very
> > least just a flip rather than a full mode set.
> 
> I guess most of the flicker was because the register restoring
> restored a bunch of crap (since the old modeset state wasn't properly
> cleared before suspending).
> 
> > Though we do need to deal with non-fb, non-X resumes as well.  kmscon
> > and wayland will expect to be restored at resume time even if CONFIG_VT
> > and the fb layer aren't compiled into the kernel.
> 
> Tbh I was rather surprised that when I've noticed this little issue
> here the restore still worked - until I've noticed by looking at the
> logs that both the fbcon and the X server restore their modes.
> 
> I'm not sure what exactly we should do here, since even with the
> current code the concept of a controlling node isn't really defined in
> the kms interface (fbcon uses a bunch of funky checks to ensure it
> doesn't clobber the output state of someone else). But for now (with
> fbcon pretty much being non-optional) things keep on working, and
> afaict actually work a bit better overall.

It's probably ok for now, but at some point we'll want some code that
restores the suspend mode if fbcon isn't enabled...

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (63 preceding siblings ...)
  2012-09-03 17:50 ` Paulo Zanoni
@ 2012-09-05 23:23 ` Jesse Barnes
  2012-09-06  6:55   ` Daniel Vetter
  2012-09-07  1:08   ` Jesse Barnes
  2012-09-06 21:00 ` Daniel Vetter
  65 siblings, 2 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-05 23:23 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

On Sun, 19 Aug 2012 21:12:17 +0200
Daniel Vetter <daniel.vetter@ffwll.ch> wrote:

> Hi all,
> 
> Changes since last time around:
> - The prep patches are all merged now.
> - I've left out the actual DP fixes/cleanups, I think we should merge those in a
>   separte step.
> - A few bugfixes (thanks to Paulo, Jani and Chris).
> - I've also applied a few bikesheds for naming that Paulo suggested (but I'm not
>   sure whether I've sent those out already in a previous patchbomb).
> 
> Essentially this is just the core rework, which addes the new get_hw_state code,
> refactors all the encoders to use the new functions and finally reworks the
> modeset logic to disable/enable entire pipes, always (and with a deterministic
> order).
> 
> For merging to -next, I plan to pull in everything with a real merge commit. For
> that reason I've put up a modeset-rework-base branch onto my private fdo repo[1].
> That way I can put a short documentation for the new modeset design into the
> merge commit (stichted together from the previous patchbomb cover letters),
> documenting my folly assumptions for eternity.
> 
> I'll also plan to put tags for the entire series in the merge commit, so if you
> have tested this on a few machines, read through and agree with the new designs,
> please reply with your tested-by/acked-by/reviewed-by tags.
> 
> Flames, comments and test reports highly welcome.

Ok I've tested on Ironlake, Cantiga, Crestline, and Pineview so far and
things look good.  I ran testdisplay both with and without VGA
attached (the ILK has a eDP panel), and tried S3 and S4 both with and
without VGA both in the console and in X.

There was one issue on Pineview where the VGA seemed to get
"forgotten", but I haven't isolated it yet.  I canceled testdisplay
part way through and that seemed to confuse fbcon about what was there.

I also see an issue with 1280x800 modes across all platforms, but that
may just be the monitor, I need to test more.

I'm testing Montara (that's 855 for you youngsters) now, but it's slow
so not all my builds have completed there yet.

Overall though:
Tested-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-09-05 23:23 ` Jesse Barnes
@ 2012-09-06  6:55   ` Daniel Vetter
  2012-09-06  7:23     ` Daniel Vetter
  2012-09-07  1:08   ` Jesse Barnes
  1 sibling, 1 reply; 173+ messages in thread
From: Daniel Vetter @ 2012-09-06  6:55 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Daniel Vetter, Intel Graphics Development

On Wed, Sep 05, 2012 at 04:23:55PM -0700, Jesse Barnes wrote:
> On Sun, 19 Aug 2012 21:12:17 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> 
> > Hi all,
> > 
> > Changes since last time around:
> > - The prep patches are all merged now.
> > - I've left out the actual DP fixes/cleanups, I think we should merge those in a
> >   separte step.
> > - A few bugfixes (thanks to Paulo, Jani and Chris).
> > - I've also applied a few bikesheds for naming that Paulo suggested (but I'm not
> >   sure whether I've sent those out already in a previous patchbomb).
> > 
> > Essentially this is just the core rework, which addes the new get_hw_state code,
> > refactors all the encoders to use the new functions and finally reworks the
> > modeset logic to disable/enable entire pipes, always (and with a deterministic
> > order).
> > 
> > For merging to -next, I plan to pull in everything with a real merge commit. For
> > that reason I've put up a modeset-rework-base branch onto my private fdo repo[1].
> > That way I can put a short documentation for the new modeset design into the
> > merge commit (stichted together from the previous patchbomb cover letters),
> > documenting my folly assumptions for eternity.
> > 
> > I'll also plan to put tags for the entire series in the merge commit, so if you
> > have tested this on a few machines, read through and agree with the new designs,
> > please reply with your tested-by/acked-by/reviewed-by tags.
> > 
> > Flames, comments and test reports highly welcome.
> 
> Ok I've tested on Ironlake, Cantiga, Crestline, and Pineview so far and
> things look good.  I ran testdisplay both with and without VGA
> attached (the ILK has a eDP panel), and tried S3 and S4 both with and
> without VGA both in the console and in X.
> 
> There was one issue on Pineview where the VGA seemed to get
> "forgotten", but I haven't isolated it yet.  I canceled testdisplay
> part way through and that seemed to confuse fbcon about what was there.

QA reported a similar issue where fbcon refuses to light up the display
after testdisplay completed a while back:

https://bugs.freedesktop.org/show_bug.cgi?id=42194

> I also see an issue with 1280x800 modes across all platforms, but that
> may just be the monitor, I need to test more.
> 
> I'm testing Montara (that's 855 for you youngsters) now, but it's slow
> so not all my builds have completed there yet.
> 
> Overall though:
> Tested-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Cool, thanks a lot for review&testing. I'll do the merge now (need to slap
all your r-b's onto patches first).
-Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-09-06  6:55   ` Daniel Vetter
@ 2012-09-06  7:23     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-06  7:23 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Daniel Vetter, Intel Graphics Development

On Thu, Sep 06, 2012 at 08:55:40AM +0200, Daniel Vetter wrote:
> On Wed, Sep 05, 2012 at 04:23:55PM -0700, Jesse Barnes wrote:
> > On Sun, 19 Aug 2012 21:12:17 +0200
> > Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> > 
> > > Hi all,
> > > 
> > > Changes since last time around:
> > > - The prep patches are all merged now.
> > > - I've left out the actual DP fixes/cleanups, I think we should merge those in a
> > >   separte step.
> > > - A few bugfixes (thanks to Paulo, Jani and Chris).
> > > - I've also applied a few bikesheds for naming that Paulo suggested (but I'm not
> > >   sure whether I've sent those out already in a previous patchbomb).
> > > 
> > > Essentially this is just the core rework, which addes the new get_hw_state code,
> > > refactors all the encoders to use the new functions and finally reworks the
> > > modeset logic to disable/enable entire pipes, always (and with a deterministic
> > > order).
> > > 
> > > For merging to -next, I plan to pull in everything with a real merge commit. For
> > > that reason I've put up a modeset-rework-base branch onto my private fdo repo[1].
> > > That way I can put a short documentation for the new modeset design into the
> > > merge commit (stichted together from the previous patchbomb cover letters),
> > > documenting my folly assumptions for eternity.
> > > 
> > > I'll also plan to put tags for the entire series in the merge commit, so if you
> > > have tested this on a few machines, read through and agree with the new designs,
> > > please reply with your tested-by/acked-by/reviewed-by tags.
> > > 
> > > Flames, comments and test reports highly welcome.
> > 
> > Ok I've tested on Ironlake, Cantiga, Crestline, and Pineview so far and
> > things look good.  I ran testdisplay both with and without VGA
> > attached (the ILK has a eDP panel), and tried S3 and S4 both with and
> > without VGA both in the console and in X.
> > 
> > There was one issue on Pineview where the VGA seemed to get
> > "forgotten", but I haven't isolated it yet.  I canceled testdisplay
> > part way through and that seemed to confuse fbcon about what was there.
> 
> QA reported a similar issue where fbcon refuses to light up the display
> after testdisplay completed a while back:
> 
> https://bugs.freedesktop.org/show_bug.cgi?id=42194
> 
> > I also see an issue with 1280x800 modes across all platforms, but that
> > may just be the monitor, I need to test more.
> > 
> > I'm testing Montara (that's 855 for you youngsters) now, but it's slow
> > so not all my builds have completed there yet.
> > 
> > Overall though:
> > Tested-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 
> Cool, thanks a lot for review&testing. I'll do the merge now (need to slap
> all your r-b's onto patches first).

Actually I'm still lacking an r-b on two patches ... I'll annoy you again
later today.
-Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 48/58] drm/i915: use staged outuput config in tv->mode_fixup
  2012-09-05 18:02   ` Jesse Barnes
@ 2012-09-06  7:30     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-06  7:30 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Daniel Vetter, Intel Graphics Development

On Wed, Sep 05, 2012 at 11:02:15AM -0700, Jesse Barnes wrote:
> On Sun, 19 Aug 2012 21:13:05 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> 
> > 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 ...
> > 
> > Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_drv.h     |  1 +
> >  drivers/gpu/drm/i915/intel_tv.c      |  7 ++-----
> >  3 files changed, 25 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index c7bd573..c59569e 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -6563,6 +6563,28 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = {
> >  	.disable = intel_crtc_disable,
> >  };
> >  
> > +bool intel_encoder_check_non_cloned(struct intel_encoder *encoder)
> > +{
> > +	struct intel_encoder *other_encoder;
> > +	struct drm_crtc *crtc = &encoder->new_crtc->base;
> > +
> > +	if (WARN_ON(!crtc))
> > +		return true;
> > +
> > +	list_for_each_entry(other_encoder,
> > +			    &crtc->dev->mode_config.encoder_list,
> > +			    base.head) {
> > +
> > +		if (&other_encoder->new_crtc->base != crtc ||
> > +		    encoder == other_encoder)
> > +			continue;
> > +		else
> > +			return false;
> > +	}
> > +
> > +	return true;
> > +}
> 
> encoder_is_cloned() would make the callers more readable and avoid the
> double negative...

Ok, got a bit bored and applied this bikeshed here, too. Won't bother with
resending though.
-Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing
  2012-09-05 19:50           ` [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing Jesse Barnes
@ 2012-09-06 20:46             ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-06 20:46 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Daniel Vetter, Intel Graphics Development

On Wed, 5 Sep 2012 12:50:26 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> On Wed, 5 Sep 2012 21:48:52 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> 
> > On Wed, Sep 5, 2012 at 8:28 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > >
> > > The variables have me confused a little... I would have expected
> > > update_state to take modeset_pipes rather than prepare_pipes.  Could
> > > you use either?  Or will that not catch cases where we updated a pipe
> > > that was already on?
> > 
> > The abstract idea for these masks was the following: Any pipe that
> > changes anything goes into prepare_pipes. For any pipe that also
> > changes the mode, it goes in addition into the modeset_pipes mask, so
> > the later is a subset of prepare pipes. The idea here was to avoid the
> > modeset step where not necessary (e.g. when disabling the 2nd output
> > of a cloned crtc we only need to disable/enable, not change anything
> > with the mode or clocks). But after some in-depth discussion with
> > Paulo Zanoni I think we'll move large parts of the mode_set step into
> > the enable function (at least for hsw due to funky ordering
> > requirements), so I think this disdinction doesn't make sense.
> > 
> > The disable mask just contains those pipes that get fully disable (and
> > which then also get removed from the prepares/modset masks).
> > 
> > Hence I pass the prepares mask into update_states, not just the modeset mask.
> 
> Ok, that makes some sense.  Hopefully we can preserve the full mode set
> vs simple update behavior even after the refactoring for HSW.
> 

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH] drm/i915: no longer call drm_helper_resume_force_mode
  2012-09-05 20:04         ` Jesse Barnes
@ 2012-09-06 20:47           ` Jesse Barnes
  0 siblings, 0 replies; 173+ messages in thread
From: Jesse Barnes @ 2012-09-06 20:47 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Daniel Vetter, Intel Graphics Development

On Wed, 5 Sep 2012 13:04:54 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> On Wed, 5 Sep 2012 21:56:08 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> 
> > On Wed, Sep 5, 2012 at 8:31 PM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > > On Wed, 29 Aug 2012 23:13:29 +0200
> > > Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> > >
> > >> Since this only calls crtc helper functions, of which a shocking
> > >> amount are NULL.
> > >>
> > >> Now the curious thing is how the new modeset code worked with this
> > >> function call still present:
> > >>
> > >> Thanks to the hw state readout and the suspend fixes to properly
> > >> quiescent the register state, nothing is actually enabled at resume
> > >> (if the bios doesn't set up anything). Which means resume_force_mode
> > >> doesn't actually do anything and hence nothing blows up at resume
> > >> time.
> > >>
> > >> The other reason things do work is that the fbcon layer has it's own
> > >> resume notifier callback, which restores the mode. And thanks to the
> > >> force vt switch at suspend/resume, that then forces X to restore it's
> > >> own mode.
> > >>
> > >> Hence everything still worked (as long as the bios doesn't enable
> > >> anything). And we can just kill the call to resume_force_mode.
> > >>
> > >> The upside of both this patch and the preceeding patch to quiescent
> > >> the modeset state is that our resume path is much simpler:
> > >> - We now longer restore bogus register values (which most often would
> > >>   enable the backlight a bit and a few ports), causing flickering.
> > >> - We now longer call resume_force_mode to restore a mode that the
> > >>   fbcon layer would overwrite right away anyway.
> > >>
> > >> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > >> ---
> > >>  drivers/gpu/drm/i915/i915_drv.c | 5 -----
> > >>  1 file changed, 5 deletions(-)
> > >>
> > >> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > >> index fe7512a..cd6697c 100644
> > >> --- a/drivers/gpu/drm/i915/i915_drv.c
> > >> +++ b/drivers/gpu/drm/i915/i915_drv.c
> > >> @@ -549,11 +549,6 @@ static int i915_drm_thaw(struct drm_device *dev)
> > >>               intel_modeset_setup_hw_state(dev);
> > >>               drm_mode_config_reset(dev);
> > >>               drm_irq_install(dev);
> > >> -
> > >> -             /* Resume the modeset for every activated CRTC */
> > >> -             mutex_lock(&dev->mode_config.mutex);
> > >> -             drm_helper_resume_force_mode(dev);
> > >> -             mutex_unlock(&dev->mode_config.mutex);
> > >>       }
> > >>
> > >>       intel_opregion_init(dev);
> > >
> > > Wouldn't the fb layer's modeset end up being a no-op if the suspended
> > > mode was the same as the fb mode (often the case)?  Or at the very
> > > least just a flip rather than a full mode set.
> > 
> > I guess most of the flicker was because the register restoring
> > restored a bunch of crap (since the old modeset state wasn't properly
> > cleared before suspending).
> > 
> > > Though we do need to deal with non-fb, non-X resumes as well.  kmscon
> > > and wayland will expect to be restored at resume time even if CONFIG_VT
> > > and the fb layer aren't compiled into the kernel.
> > 
> > Tbh I was rather surprised that when I've noticed this little issue
> > here the restore still worked - until I've noticed by looking at the
> > logs that both the fbcon and the X server restore their modes.
> > 
> > I'm not sure what exactly we should do here, since even with the
> > current code the concept of a controlling node isn't really defined in
> > the kms interface (fbcon uses a bunch of funky checks to ensure it
> > doesn't clobber the output state of someone else). But for now (with
> > fbcon pretty much being non-optional) things keep on working, and
> > afaict actually work a bit better overall.
> 
> It's probably ok for now, but at some point we'll want some code that
> restores the suspend mode if fbcon isn't enabled...
> 

So acked/reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

But note that if someone complains we'll need to add this back...

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
                   ` (64 preceding siblings ...)
  2012-09-05 23:23 ` Jesse Barnes
@ 2012-09-06 21:00 ` Daniel Vetter
  65 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-06 21:00 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

On Sun, Aug 19, 2012 at 09:12:17PM +0200, Daniel Vetter wrote:
> Hi all,
> 
> Changes since last time around:
> - The prep patches are all merged now.
> - I've left out the actual DP fixes/cleanups, I think we should merge those in a
>   separte step.
> - A few bugfixes (thanks to Paulo, Jani and Chris).
> - I've also applied a few bikesheds for naming that Paulo suggested (but I'm not
>   sure whether I've sent those out already in a previous patchbomb).
> 
> Essentially this is just the core rework, which addes the new get_hw_state code,
> refactors all the encoders to use the new functions and finally reworks the
> modeset logic to disable/enable entire pipes, always (and with a deterministic
> order).
> 
> For merging to -next, I plan to pull in everything with a real merge commit. For
> that reason I've put up a modeset-rework-base branch onto my private fdo repo[1].
> That way I can put a short documentation for the new modeset design into the
> merge commit (stichted together from the previous patchbomb cover letters),
> documenting my folly assumptions for eternity.
> 
> I'll also plan to put tags for the entire series in the merge commit, so if you
> have tested this on a few machines, read through and agree with the new designs,
> please reply with your tested-by/acked-by/reviewed-by tags.
> 
> Flames, comments and test reports highly welcome.

Ok, I've just merged the entire pile. Thanks everyone for testing
feedback, comments and review.

Cheers, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-09-05 23:23 ` Jesse Barnes
  2012-09-06  6:55   ` Daniel Vetter
@ 2012-09-07  1:08   ` Jesse Barnes
  2012-09-07  8:55     ` Daniel Vetter
  1 sibling, 1 reply; 173+ messages in thread
From: Jesse Barnes @ 2012-09-07  1:08 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Daniel Vetter, Intel Graphics Development

On Wed, 5 Sep 2012 16:23:55 -0700
Jesse Barnes <jbarnes@virtuousgeek.org> wrote:

> On Sun, 19 Aug 2012 21:12:17 +0200
> Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> 
> > Hi all,
> > 
> > Changes since last time around:
> > - The prep patches are all merged now.
> > - I've left out the actual DP fixes/cleanups, I think we should merge those in a
> >   separte step.
> > - A few bugfixes (thanks to Paulo, Jani and Chris).
> > - I've also applied a few bikesheds for naming that Paulo suggested (but I'm not
> >   sure whether I've sent those out already in a previous patchbomb).
> > 
> > Essentially this is just the core rework, which addes the new get_hw_state code,
> > refactors all the encoders to use the new functions and finally reworks the
> > modeset logic to disable/enable entire pipes, always (and with a deterministic
> > order).
> > 
> > For merging to -next, I plan to pull in everything with a real merge commit. For
> > that reason I've put up a modeset-rework-base branch onto my private fdo repo[1].
> > That way I can put a short documentation for the new modeset design into the
> > merge commit (stichted together from the previous patchbomb cover letters),
> > documenting my folly assumptions for eternity.
> > 
> > I'll also plan to put tags for the entire series in the merge commit, so if you
> > have tested this on a few machines, read through and agree with the new designs,
> > please reply with your tested-by/acked-by/reviewed-by tags.
> > 
> > Flames, comments and test reports highly welcome.
> 
> Ok I've tested on Ironlake, Cantiga, Crestline, and Pineview so far and
> things look good.  I ran testdisplay both with and without VGA
> attached (the ILK has a eDP panel), and tried S3 and S4 both with and
> without VGA both in the console and in X.
> 
> There was one issue on Pineview where the VGA seemed to get
> "forgotten", but I haven't isolated it yet.  I canceled testdisplay
> part way through and that seemed to confuse fbcon about what was there.
> 
> I also see an issue with 1280x800 modes across all platforms, but that
> may just be the monitor, I need to test more.
> 
> I'm testing Montara (that's 855 for you youngsters) now, but it's slow
> so not all my builds have completed there yet.
> 
> Overall though:
> Tested-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 

Looks like I just found an issue with DPMS on fbcon on SNB though.
Leaving the system for awhile either results in corruption (part of the
fbcon on the screen) or just the screen left on.

This is on LVDS.

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 173+ messages in thread

* Re: [PATCH 00/58] modeset-rework, the basic conversion
  2012-09-07  1:08   ` Jesse Barnes
@ 2012-09-07  8:55     ` Daniel Vetter
  0 siblings, 0 replies; 173+ messages in thread
From: Daniel Vetter @ 2012-09-07  8:55 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

On Fri, Sep 7, 2012 at 3:08 AM, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> Looks like I just found an issue with DPMS on fbcon on SNB though.
> Leaving the system for awhile either results in corruption (part of the
> fbcon on the screen) or just the screen left on.

Indeed another case where the fb helper is too intimate with the crtc
helper and calls the crtc helper dpms functions directly, instead of
going through the official interface vtable. I've thought I've checked
all crtc helper callsites in the fb helper, but must have missed this
one :(

Patch on the way and I've re-checked, and the last user of crtc helper
functions (that we don't yet work around) should now really be gone.

Thanks, Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 173+ messages in thread

end of thread, other threads:[~2012-09-07  8:55 UTC | newest]

Thread overview: 173+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-19 19:12 [PATCH 00/58] modeset-rework, the basic conversion Daniel Vetter
2012-08-19 19:12 ` [PATCH 01/58] drm/i915: add crtc->enable/disable vfuncs insted of dpms Daniel Vetter
2012-08-29 17:51   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 02/58] drm/i915: rip out crtc prepare/commit indirection Daniel Vetter
2012-08-29 17:52   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 03/58] drm/i915: add direct encoder disable/enable infrastructure Daniel Vetter
2012-08-29 18:01   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 04/58] drm/i915/hdmi: convert to encoder->disable/enable Daniel Vetter
2012-09-04 19:24   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 05/58] drm/i915/tv: convert to encoder enable/disable Daniel Vetter
2012-09-04 19:25   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 06/58] drm/i915/lvds: convert to encoder disable/enable Daniel Vetter
2012-09-04 19:26   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 07/58] drm/i915/dp: " Daniel Vetter
2012-09-04 19:33   ` Jesse Barnes
2012-09-04 19:42     ` Daniel Vetter
2012-08-19 19:12 ` [PATCH 08/58] drm/i915/crt: " Daniel Vetter
2012-09-04 19:50   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 09/58] drm/i915/sdvo: " Daniel Vetter
2012-09-04 19:52   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 10/58] drm/i915/dvo: " Daniel Vetter
2012-09-04 19:53   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 11/58] drm/i915: convert dpms functions of dvo/sdvo/crt Daniel Vetter
2012-08-29  7:12   ` [PATCH] " Daniel Vetter
2012-09-04 20:10     ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 12/58] drm/i915: rip out encoder->disable/enable checks Daniel Vetter
2012-09-04 20:11   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 13/58] drm/i915: clean up encoder_prepare/commit Daniel Vetter
2012-09-04 20:12   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 14/58] drm/i915: copy&paste drm_crtc_helper_set_config Daniel Vetter
2012-09-04 20:13   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 15/58] drm/i915: call set_base directly Daniel Vetter
2012-09-04 20:15   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 16/58] drm/i915: inline intel_best_encoder Daniel Vetter
2012-09-04 20:18   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 17/58] drm/i915: copy&paste drm_crtc_helper_set_mode Daniel Vetter
2012-09-04 20:19   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 18/58] drm/i915: simplify intel_crtc_prepare_encoders Daniel Vetter
2012-09-04 20:20   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 19/58] drm/i915: rip out encoder->prepare/commit Daniel Vetter
2012-09-04 20:21   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 20/58] drm/i915: call crtc functions directly Daniel Vetter
2012-09-04 20:22   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 21/58] drm/i915: WARN when trying to enabled an unused crtc Daniel Vetter
2012-09-04 20:23   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 22/58] drm/i915: Add interfaces to read out encoder/connector hw state Daniel Vetter
2012-09-04 20:25   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 23/58] drm/i915/dp: implement get_hw_state Daniel Vetter
2012-09-04 20:26   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 24/58] drm/i915/hdmi: " Daniel Vetter
2012-09-04 20:28   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 25/58] drm/i915/tv: " Daniel Vetter
2012-09-04 20:28   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 26/58] drm/i915/lvds: " Daniel Vetter
2012-09-04 20:28   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 27/58] drm/i915/crt: " Daniel Vetter
2012-09-04 20:29   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 28/58] drm/i915/sdvo: " Daniel Vetter
2012-09-04 20:31   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 29/58] drm/i915/dvo: " Daniel Vetter
2012-09-04 20:32   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 30/58] drm/i915: read out the modeset hw state at load and resume time Daniel Vetter
2012-09-05 16:14   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 31/58] drm/i915: check connector hw/sw state Daniel Vetter
2012-09-05 16:26   ` Jesse Barnes
2012-09-05 19:10     ` Daniel Vetter
2012-08-19 19:12 ` [PATCH 32/58] drm/i915: rip out intel_crtc->dpms_mode Daniel Vetter
2012-09-05 16:27   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 33/58] drm/i915: rip out intel_dp->dpms_mode Daniel Vetter
2012-09-05 16:28   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 34/58] drm/i915: ensure the force pipe A quirk is actually followed Daniel Vetter
2012-09-05 16:32   ` Jesse Barnes
2012-09-05 19:12     ` Daniel Vetter
2012-08-19 19:12 ` [PATCH 35/58] drm/i915: introduce struct intel_set_config Daniel Vetter
2012-09-05 16:34   ` Jesse Barnes
2012-09-05 19:27     ` Daniel Vetter
2012-08-19 19:12 ` [PATCH 36/58] drm/i915: extract modeset config save/restore code Daniel Vetter
2012-09-05 16:36   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 37/58] drm/i915: extract intel_set_config_compute_mode_changes Daniel Vetter
2012-09-05 16:42   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 38/58] drm/i915: extract intel_set_config_update_output_state Daniel Vetter
2012-09-05 16:44   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 39/58] drm/i915: implement crtc helper semantics relied upon by the fb helper Daniel Vetter
2012-09-05 16:45   ` Jesse Barnes
2012-09-05 19:15     ` Daniel Vetter
2012-08-19 19:12 ` [PATCH 40/58] drm/i915: don't update the fb base if there is no fb Daniel Vetter
2012-09-05 16:47   ` Jesse Barnes
2012-08-19 19:12 ` [PATCH 41/58] drm/i915: convert pointless error checks in set_config to BUGs Daniel Vetter
2012-09-05 16:50   ` Jesse Barnes
2012-09-05 19:19     ` Daniel Vetter
2012-08-19 19:12 ` [PATCH 42/58] drm/i915: don't save all the encoder/crtc state in set_config Daniel Vetter
2012-09-05 16:52   ` Jesse Barnes
2012-09-05 19:21     ` Daniel Vetter
2012-08-19 19:13 ` [PATCH 43/58] drm/i915: stage modeset output changes Daniel Vetter
2012-09-05 17:51   ` Jesse Barnes
2012-08-19 19:13 ` [PATCH 44/58] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
2012-09-04 19:33   ` [PATCH] " Daniel Vetter
2012-09-05 17:55     ` Jesse Barnes
2012-09-05 19:59       ` Daniel Vetter
2012-09-05 17:54   ` [PATCH 44/58] " Jesse Barnes
2012-08-19 19:13 ` [PATCH 45/58] drm/i915: remove crtc disabling special case Daniel Vetter
2012-09-05 17:56   ` Jesse Barnes
2012-08-19 19:13 ` [PATCH 46/58] drm/i915: move output commit and crtc disabling into set_mode Daniel Vetter
2012-09-05 17:58   ` Jesse Barnes
2012-08-19 19:13 ` [PATCH 47/58] drm/i915: extract adjusted mode computation Daniel Vetter
2012-09-05 18:00   ` Jesse Barnes
2012-09-05 19:30     ` Daniel Vetter
2012-08-19 19:13 ` [PATCH 48/58] drm/i915: use staged outuput config in tv->mode_fixup Daniel Vetter
2012-09-05 18:02   ` Jesse Barnes
2012-09-06  7:30     ` Daniel Vetter
2012-08-19 19:13 ` [PATCH 49/58] drm/i915: use staged outuput config in lvds->mode_fixup Daniel Vetter
2012-09-05 18:02   ` Jesse Barnes
2012-08-19 19:13 ` [PATCH 50/58] drm/i915: compute masks of crtcs affected in set_mode Daniel Vetter
2012-08-29 10:34   ` [PATCH] " Daniel Vetter
2012-09-05 18:09     ` Jesse Barnes
2012-09-05 19:38       ` Daniel Vetter
2012-09-05 19:45         ` Jesse Barnes
2012-09-05 18:07   ` [PATCH 50/58] " Jesse Barnes
2012-08-19 19:13 ` [PATCH 51/58] drm/i915: implement new set_mode code flow Daniel Vetter
2012-09-05 18:14   ` Jesse Barnes
2012-09-05 19:43     ` Daniel Vetter
2012-09-05 19:49       ` Jesse Barnes
2012-08-19 19:13 ` [PATCH 52/58] drm/i915: push commit_output_state past crtc disabling Daniel Vetter
2012-09-05 18:17   ` Jesse Barnes
2012-08-19 19:13 ` [PATCH 53/58] drm/i915: s/intel_encoder_disable/intel_encoder_noop Daniel Vetter
2012-09-05 18:17   ` Jesse Barnes
2012-08-19 19:13 ` [PATCH 54/58] drm/i915: WARN if the pipe won't turn off Daniel Vetter
2012-09-05 18:18   ` Jesse Barnes
2012-08-19 19:13 ` [PATCH 55/58] drm/i915: switch the load detect code to the staged modeset config Daniel Vetter
2012-09-05 18:19   ` Jesse Barnes
2012-08-19 19:13 ` [PATCH 56/58] drm/i915: push commit_output_state past the crtc/encoder preparing Daniel Vetter
2012-08-31 18:12   ` [PATCH] " Daniel Vetter
2012-09-04 19:32     ` Daniel Vetter
2012-09-05 18:28       ` Jesse Barnes
2012-09-05 19:48         ` Daniel Vetter
2012-09-05 18:56           ` [PATCH] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
2012-09-05 19:50           ` [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing Jesse Barnes
2012-09-06 20:46             ` Jesse Barnes
2012-08-19 19:13 ` [PATCH 57/58] drm/i915: disable all crtcs at suspend time Daniel Vetter
2012-08-29 21:13   ` [PATCH] drm/i915: no longer call drm_helper_resume_force_mode Daniel Vetter
2012-09-05 18:31     ` Jesse Barnes
2012-09-05 19:56       ` Daniel Vetter
2012-09-05 20:04         ` Jesse Barnes
2012-09-06 20:47           ` Jesse Barnes
2012-09-05 18:29   ` [PATCH 57/58] drm/i915: disable all crtcs at suspend time Jesse Barnes
2012-08-19 19:13 ` [PATCH 58/58] drm/i915: add tons of modeset state checks Daniel Vetter
2012-08-20  8:24   ` [PATCH] " Daniel Vetter
2012-08-20 12:22   ` Daniel Vetter
2012-08-31 18:12     ` [PATCH 1/2] " Daniel Vetter
2012-08-31 18:12       ` [PATCH 2/2] drm/i915: improve modeset state checking after dpms calls Daniel Vetter
2012-09-05 18:34         ` Jesse Barnes
2012-09-05 18:33       ` [PATCH 1/2] drm/i915: add tons of modeset state checks Jesse Barnes
2012-08-20 13:17 ` [PATCH 00/58] modeset-rework, the basic conversion Jani Nikula
2012-08-21  3:27 ` Ben Widawsky
2012-08-21 17:48 ` Lespiau, Damien
2012-08-21 18:11   ` Daniel Vetter
2012-08-22 10:46     ` Lespiau, Damien
2012-08-22 11:03       ` Lespiau, Damien
2012-08-22 19:13         ` Lespiau, Damien
2012-08-22 21:21           ` Daniel Vetter
2012-08-23 12:26             ` Lespiau, Damien
2012-08-23 22:39               ` Daniel Vetter
2012-08-29 12:26                 ` Lespiau, Damien
2012-08-30 10:40                   ` Rodrigo Vivi
2012-08-21 19:48 ` Chris Wilson
2012-08-27  8:04 ` Vijay Purushothaman
2012-09-03 17:50 ` Paulo Zanoni
2012-09-05 23:23 ` Jesse Barnes
2012-09-06  6:55   ` Daniel Vetter
2012-09-06  7:23     ` Daniel Vetter
2012-09-07  1:08   ` Jesse Barnes
2012-09-07  8:55     ` Daniel Vetter
2012-09-06 21:00 ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.