All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/81] modeset rework
@ 2012-07-11 14:27 Daniel Vetter
  2012-07-11 14:27 ` [PATCH 01/81] drm/i915: add crtc->enable/disable vfuncs insted of dpms Daniel Vetter
                   ` (81 more replies)
  0 siblings, 82 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Or: How to fix cpu edp in 81 simple steps. Admittedly this includes some minor
detours.

Yeah, I've managed to pull it through and finally put the last piece into place
that started this entire endeavour: cpu edp on my ivb works!

I'm too lazy to repeat all the high-level overview stuff from the cover-letter
of the rfc series. But I think it's nice to give a short overview of where in
our code we still rely on crtc helper infrastructure:

- We still use the ->mode_fixup callbacks from the crtc helper. We also still
  use the encoder->mode_set callbacks. Boht can easily be moved to callbacks in
  intel_encoder, but honestly I didn't see the point.
- The fb helper code has a ridiculously incetious relationship with the crtc
  helper code. Read through the commit messages to see which pitfalls I've
  stumbled into. I plan to eventually fix this up, but this series only contains
  the minimal changes to drm_fb_helper.c to move ahead - I need to sharpen my
  broadsword first again.
- We also still rely on the crtc helper for hotplug detection and connector
  status probing.

Also, after this we still have some large opportunities to clean things up:
- I think we should create struct intel_mode and use it as the adjusted mode
  everywhere to store little pieces like needs_tvclock, pipe dithering values or
  dp link parameters.  That would still be a layering violation, but at least we
  wouldn't need to recompute these kinds of things in intel_display.c.
  Especially the port bpc computation needed for selecting the pipe bpc and
  dithering settings in intel_display.c is rather gross.
- In a related rework I think we should implement ->mode_valid in terms of
  ->mode_fixup in a generic way - I've hunted too many bugs where ->mode_valid
  did the right thing, but ->mode_fixup didn't. Or vice versa, resulting in
  funny bugs for user-supplied modes.
- I think we should ditch the idea to rework the hdp handling in the common crtc
  helper code and just move things to i915.ko. Which would rid us of the
  ->detect crtc helper dependencies.
- lvds wire pair and pll enabling is all done. We should be able to move this to
  the crtc_enable callbacks.

I haven't thought about how we could merge this (presuming people don't scream
an tear it apart), but there are definitely patches in here which can be merged
right away. If you see one, review + a nod highly appreciated, I've lost the big
picture a bit recently ;-)

Compared to the first part, I haven't yet tested this on anything but snb/ivb -
but the newly addded consistency checks are _extremely_ good, things essentially
started to work correctly once I've squashed the last WARN. So I'm positive that
further testing of the newly added patches on all my other machines won't turn
up anything troubling.

For reviewing this patch-carpet-bomber I suggest you grab the rfc intro mail at

http://lists.freedesktop.org/archives/intel-gfx/2012-July/018635.html

Then read the last patch, which motivated pretty much everything else and work
backwards from there, at least for the high-level picture.

Comments, flames and test reports highly welcome.

Cheers, Daniel

Daniel Vetter (81):
  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: add missing gen2 pipe A quirk entries
  drm/i915: rip out the overlay pipe A workaround
  drm/i915: prepare load-detect pipe code for dpms changes
  drm/i915/hdmi: convert to encoder->disable/enable
  drm/i915/tv: convert to encoder enable/disable
  drm/i915/lvds: ditch ->prepare special case
  drm/i915/lvds: convert to encoder disable/enable
  drm/i915/dp: convert to encoder disable/enable
  drm/i915: create VLV_DSIPLAY_BASE #define
  drm/i915: group ADPA #defines together
  drm/i915: add inte_crt->adpa_reg
  drm/i915/crt: convert to encoder disable/enable
  drm/i915/sdvo: convert to encoder disable/enable
  drm/i915: simplify dvo dpms interface
  drm/i915/dvo: convert to encoder disable/enable
  drm/i915: simplify possible_clones computation
  drm/i915: add port parameter to intel_hdmi_init
  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/fb helper: don't call drm_crtc_helper_set_config
  drm: remove the list_head from drm_mode_set
  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: kill a few unused things in dev_priv
  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
  drm/i915: extract ironlake_fdi_pll_disable
  drm/i915: rip out intel_disable_pch_ports
  drm/i915: don't disable fdi links harder in ilk_crtc_enable
  drm/i915: don't call dpms funcs after set_mode
  drm/i915: update dpms property in set_mode
  drm/i915: add encoder->pre_enable/post_disable
  drm/i915: clean up the cpu edp pll special case
  drm/i915: robustify edp_pll_on/off
  drm/i915: rip out dp port enabling cludges^Wchecks
  drm/i915: disable the cpu edp port after the cpu pipe

 drivers/gpu/drm/drm_fb_helper.c      |    2 +-
 drivers/gpu/drm/i915/dvo.h           |   15 +-
 drivers/gpu/drm/i915/dvo_ch7017.c    |   21 +-
 drivers/gpu/drm/i915/dvo_ch7xxx.c    |   17 +-
 drivers/gpu/drm/i915/dvo_ivch.c      |   23 +-
 drivers/gpu/drm/i915/dvo_sil164.c    |   20 +-
 drivers/gpu/drm/i915/dvo_tfp410.c    |   18 +-
 drivers/gpu/drm/i915/i915_dma.c      |   22 +-
 drivers/gpu/drm/i915/i915_drv.c      |    6 +-
 drivers/gpu/drm/i915/i915_drv.h      |   17 +-
 drivers/gpu/drm/i915/i915_reg.h      |   52 +-
 drivers/gpu/drm/i915/intel_crt.c     |  157 +++-
 drivers/gpu/drm/i915/intel_ddi.c     |   59 +-
 drivers/gpu/drm/i915/intel_display.c | 1600 +++++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/intel_dp.c      |  218 +++--
 drivers/gpu/drm/i915/intel_drv.h     |   94 ++-
 drivers/gpu/drm/i915/intel_dvo.c     |  105 ++-
 drivers/gpu/drm/i915/intel_hdmi.c    |  203 +++--
 drivers/gpu/drm/i915/intel_lvds.c    |  104 +--
 drivers/gpu/drm/i915/intel_overlay.c |   58 +--
 drivers/gpu/drm/i915/intel_sdvo.c    |  178 +++-
 drivers/gpu/drm/i915/intel_tv.c      |   63 +-
 include/drm/drm_crtc.h               |    2 -
 23 files changed, 2196 insertions(+), 858 deletions(-)

-- 
1.7.7.6

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

* [PATCH 01/81] drm/i915: add crtc->enable/disable vfuncs insted of dpms
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 02/81] drm/i915: rip out crtc prepare/commit indirection Daniel Vetter
                   ` (80 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 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 627fe35..cafa4cc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -239,7 +239,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 80fe02d..135eed0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3330,30 +3330,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);
@@ -3433,23 +3409,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)
 {
 }
@@ -3471,7 +3430,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;
@@ -6978,13 +6950,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.7.6

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

* [PATCH 02/81] drm/i915: rip out crtc prepare/commit indirection
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
  2012-07-11 14:27 ` [PATCH 01/81] drm/i915: add crtc->enable/disable vfuncs insted of dpms Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-12 14:44   ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 03/81] drm/i915: add direct encoder disable/enable infrastructure Daniel Vetter
                   ` (79 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 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 files changed, 2 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 135eed0..b1caa1b81 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3488,34 +3488,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;
@@ -6636,13 +6608,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.7.6

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

* [PATCH 03/81] drm/i915: add direct encoder disable/enable infrastructure
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
  2012-07-11 14:27 ` [PATCH 01/81] drm/i915: add crtc->enable/disable vfuncs insted of dpms Daniel Vetter
  2012-07-11 14:27 ` [PATCH 02/81] drm/i915: rip out crtc prepare/commit indirection Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 04/81] drm/i915: add missing gen2 pipe A quirk entries Daniel Vetter
                   ` (78 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 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 b1caa1b81..5d4f6d2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3178,13 +3178,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);
@@ -3231,6 +3234,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)
@@ -3238,10 +3247,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;
 
@@ -3359,11 +3376,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);
@@ -3378,6 +3398,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)
@@ -3385,9 +3411,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 6f3bf22..4ac2373 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -153,6 +153,8 @@ struct intel_encoder {
 	int type;
 	bool needs_tv_clock;
 	void (*hot_plug)(struct intel_encoder *);
+	void (*enable)(struct intel_encoder *);
+	void (*disable)(struct intel_encoder *);
 	int crtc_mask;
 	int clone_mask;
 };
-- 
1.7.7.6

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

* [PATCH 04/81] drm/i915: add missing gen2 pipe A quirk entries
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (2 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 03/81] drm/i915: add direct encoder disable/enable infrastructure Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 05/81] drm/i915: rip out the overlay pipe A workaround Daniel Vetter
                   ` (77 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

For some odd reason we've missed i830 and a i855 variant. Also
kill the two now redundant i830 entries.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5d4f6d2..db76cc8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7081,21 +7081,17 @@ static struct intel_quirk intel_quirks[] = {
 	/* HP Mini needs pipe A force quirk (LP: #322104) */
 	{ 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
 
-	/* Thinkpad R31 needs pipe A force quirk */
-	{ 0x3577, 0x1014, 0x0505, quirk_pipea_force },
 	/* Toshiba Protege R-205, S-209 needs pipe A force quirk */
 	{ 0x2592, 0x1179, 0x0001, quirk_pipea_force },
 
-	/* ThinkPad X30 needs pipe A force quirk (LP: #304614) */
-	{ 0x3577,  0x1014, 0x0513, quirk_pipea_force },
-	/* ThinkPad X40 needs pipe A force quirk */
-
 	/* ThinkPad T60 needs pipe A force quirk (bug #16494) */
 	{ 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
 
 	/* 855 & before need to leave pipe A & dpll A up */
 	{ 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
 	{ 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
+	{ 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
+	{ 0x358e, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
 
 	/* Lenovo U160 cannot use SSC on LVDS */
 	{ 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable },
-- 
1.7.7.6

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

* [PATCH 05/81] drm/i915: rip out the overlay pipe A workaround
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (3 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 04/81] drm/i915: add missing gen2 pipe A quirk entries Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 06/81] drm/i915: prepare load-detect pipe code for dpms changes Daniel Vetter
                   ` (76 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Now that all affected i830M systems have the pipe A quirk set,
we don't need to do any special dances in the overlay code any
longer. And reading through the code I'm rather dubios that it
actually does what it claims to do ...

As a nice benefit this rips out a users of the crtc helper dpms
callback.

v2: As suggested by Chris Wilson, replace the code by an appropriate
WARN to ensure that the pipe A is indeed running.

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

diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 830d0dd..c0f4858 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -235,54 +235,6 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
 	return 0;
 }
 
-/* Workaround for i830 bug where pipe a must be enable to change control regs */
-static int
-i830_activate_pipe_a(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct intel_crtc *crtc;
-	struct drm_crtc_helper_funcs *crtc_funcs;
-	struct drm_display_mode vesa_640x480 = {
-		DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
-			 752, 800, 0, 480, 489, 492, 525, 0,
-			 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
-	}, *mode;
-
-	crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]);
-	if (crtc->dpms_mode == DRM_MODE_DPMS_ON)
-		return 0;
-
-	/* most i8xx have pipe a forced on, so don't trust dpms mode */
-	if (I915_READ(_PIPEACONF) & PIPECONF_ENABLE)
-		return 0;
-
-	crtc_funcs = crtc->base.helper_private;
-	if (crtc_funcs->dpms == NULL)
-		return 0;
-
-	DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n");
-
-	mode = drm_mode_duplicate(dev, &vesa_640x480);
-
-	if (!drm_crtc_helper_set_mode(&crtc->base, mode,
-				       crtc->base.x, crtc->base.y,
-				       crtc->base.fb))
-		return 0;
-
-	crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON);
-	return 1;
-}
-
-static void
-i830_deactivate_pipe_a(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
-	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-
-	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
 /* overlay needs to be disable in OCMD reg */
 static int intel_overlay_on(struct intel_overlay *overlay)
 {
@@ -290,17 +242,12 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
 	struct drm_i915_gem_request *request;
-	int pipe_a_quirk = 0;
 	int ret;
 
 	BUG_ON(overlay->active);
 	overlay->active = 1;
 
-	if (IS_I830(dev)) {
-		pipe_a_quirk = i830_activate_pipe_a(dev);
-		if (pipe_a_quirk < 0)
-			return pipe_a_quirk;
-	}
+	WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
 
 	request = kzalloc(sizeof(*request), GFP_KERNEL);
 	if (request == NULL) {
@@ -322,9 +269,6 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 
 	ret = intel_overlay_do_wait_request(overlay, request, NULL);
 out:
-	if (pipe_a_quirk)
-		i830_deactivate_pipe_a(dev);
-
 	return ret;
 }
 
-- 
1.7.7.6

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

* [PATCH 06/81] drm/i915: prepare load-detect pipe code for dpms changes
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (4 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 05/81] drm/i915: rip out the overlay pipe A workaround Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 07/81] drm/i915/hdmi: convert to encoder->disable/enable Daniel Vetter
                   ` (75 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

A few things need adjustement:
- Change the dpms state by calling the dpms connector function and
  not some crtc helper internal callbacks. Otherwise this will break
  once we switch to our own dpms handling.
- Instead of tracking and restoring intel_crtc->dpms_mode use the
  connector's dpms variable - the former relies on the dpms compuation
  rules used by the crtc helper. And it would break when the encoder
  is cloned and the other output has a different dpms state. But luckily
  no one is crazy enough for that.
- Properly clear the connector -> encoder -> crtc linking, even when
  failing (note that the crtc helper removes the encoder -> crtc link
  in disabled_unused_functions for us).

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index db76cc8..1ea3776 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5601,21 +5601,12 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 	if (encoder->crtc) {
 		crtc = encoder->crtc;
 
-		intel_crtc = to_intel_crtc(crtc);
-		old->dpms_mode = intel_crtc->dpms_mode;
+		old->dpms_mode = connector->dpms;
 		old->load_detect_temp = false;
 
 		/* Make sure the crtc and connector are running */
-		if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
-			struct drm_encoder_helper_funcs *encoder_funcs;
-			struct drm_crtc_helper_funcs *crtc_funcs;
-
-			crtc_funcs = crtc->helper_private;
-			crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-
-			encoder_funcs = encoder->helper_private;
-			encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
-		}
+		if (connector->dpms != DRM_MODE_DPMS_ON)
+			connector->funcs->dpms(connector, DRM_MODE_DPMS_ON);
 
 		return true;
 	}
@@ -5643,7 +5634,7 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 	connector->encoder = encoder;
 
 	intel_crtc = to_intel_crtc(crtc);
-	old->dpms_mode = intel_crtc->dpms_mode;
+	old->dpms_mode = connector->dpms;
 	old->load_detect_temp = true;
 	old->release_fb = NULL;
 
@@ -5668,22 +5659,25 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 		DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
 	if (IS_ERR(crtc->fb)) {
 		DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
-		crtc->fb = old_fb;
-		return false;
+		goto fail;
 	}
 
 	if (!drm_crtc_helper_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);
-		crtc->fb = old_fb;
-		return false;
+		goto fail;
 	}
 
 	/* let the connector get through one full cycle before testing */
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 
 	return true;
+fail:
+	connector->encoder = NULL;
+	encoder->crtc = NULL;
+	crtc->fb = old_fb;
+	return false;
 }
 
 void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
@@ -5692,9 +5686,6 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_device *dev = encoder->dev;
-	struct drm_crtc *crtc = encoder->crtc;
-	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
-	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
 		      connector->base.id, drm_get_connector_name(connector),
@@ -5702,6 +5693,7 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
 
 	if (old->load_detect_temp) {
 		connector->encoder = NULL;
+		encoder->crtc = NULL;
 		drm_helper_disable_unused_functions(dev);
 
 		if (old->release_fb)
@@ -5711,10 +5703,8 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
 	}
 
 	/* Switch crtc and encoder back off if necessary */
-	if (old->dpms_mode != DRM_MODE_DPMS_ON) {
-		encoder_funcs->dpms(encoder, old->dpms_mode);
-		crtc_funcs->dpms(crtc, old->dpms_mode);
-	}
+	if (old->dpms_mode != DRM_MODE_DPMS_ON)
+		connector->funcs->dpms(connector, old->dpms_mode);
 }
 
 /* Returns the clock of the currently programmed mode of the given pipe. */
-- 
1.7.7.6

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

* [PATCH 07/81] drm/i915/hdmi: convert to encoder->disable/enable
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (5 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 06/81] drm/i915: prepare load-detect pipe code for dpms changes Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 08/81] drm/i915/tv: convert to encoder enable/disable Daniel Vetter
                   ` (74 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_ddi.c     |   28 +++++---
 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(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 933c748..fd60f48 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -738,21 +738,16 @@ 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
@@ -761,3 +756,18 @@ void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
 	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 1ea3776..1a201b2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3542,6 +3542,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);
@@ -3550,6 +3561,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,
 				  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 4ac2373..16680e5 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -152,6 +152,7 @@ struct intel_encoder {
 	struct drm_encoder base;
 	int type;
 	bool needs_tv_clock;
+	bool connectors_active;
 	void (*hot_plug)(struct intel_encoder *);
 	void (*enable)(struct intel_encoder *);
 	void (*disable)(struct intel_encoder *);
@@ -395,7 +396,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)
 {
@@ -504,7 +509,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 5b2c88c..188399f 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,
@@ -987,10 +1023,18 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 		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.7.6

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

* [PATCH 08/81] drm/i915/tv: convert to encoder enable/disable
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (6 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 07/81] drm/i915/hdmi: convert to encoder->disable/enable Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 09/81] drm/i915/lvds: ditch ->prepare special case Daniel Vetter
                   ` (73 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 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 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 3b413c9..a0ec1eb 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 *
@@ -1480,15 +1480,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,
@@ -1618,6 +1618,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.7.6

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

* [PATCH 09/81] drm/i915/lvds: ditch ->prepare special case
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (7 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 08/81] drm/i915/tv: convert to encoder enable/disable Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-22 14:52   ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 10/81] drm/i915/lvds: convert to encoder disable/enable Daniel Vetter
                   ` (72 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Takashi Iwai, Daniel Vetter

LVDS is the first output where dpms on/off and prepare/commit don't
perfectly match. Now the idea behind this special case seems to be
that for simple resolution changes on the LVDS we don't need to stop
the pipe, because (at least on newer chips) we can adjust the panel
fitter on the fly.

There are a few problems with the current code though:
- We still stop and restart the pipe unconditionally, because the crtc
  helper code isn't flexible enough.
- We show some ugly flickering, especially when changing crtcs (this
  the crtc helper would actually take into account, but we don't
  implement the encoder->get_crtc callback required to make this work
  properly).

So it doesn't even work as advertised. I agree that it would be nice
to do resolution changes on LVDS (and also eDP) whithout blacking the
screen where the panel fitter allows to do that. But imo we should
implement this as a special case a few layers up in the mode set code,
akin to how we already detect simple framebuffer changes (and only
update the required registers with ->mode_set_base).

Until this is all in place, make our lives easier and just rip it out.

Also note that this seems to fix actual bugs with enabling the lvds
output, see:

http://lists.freedesktop.org/archives/intel-gfx/2012-July/018614.html

Cc: Takashi Iwai <tiwai@suse.de>
Cc: Giacomo Comes <comes@naic.edu>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_lvds.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 9b706a5..73d0079 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -409,13 +409,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
 {
 	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 
-	/*
-	 * Prior to Ironlake, we must disable the pipe if we want to adjust
-	 * the panel fitter. However at all other times we can just reset
-	 * the registers regardless.
-	 */
-	if (!HAS_PCH_SPLIT(encoder->dev) && intel_lvds->pfit_dirty)
-		intel_lvds_disable(intel_lvds);
+	intel_lvds_disable(intel_lvds);
 }
 
 static void intel_lvds_commit(struct drm_encoder *encoder)
-- 
1.7.7.6

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

* [PATCH 10/81] drm/i915/lvds: convert to encoder disable/enable
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (8 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 09/81] drm/i915/lvds: ditch ->prepare special case Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 11/81] drm/i915/dp: " Daniel Vetter
                   ` (71 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 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 files changed, 14 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 73d0079..f1d0a05 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.7.6

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

* [PATCH 11/81] drm/i915/dp: convert to encoder disable/enable
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (9 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 10/81] drm/i915/lvds: convert to encoder disable/enable Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 12/81] drm/i915: create VLV_DSIPLAY_BASE #define Daniel Vetter
                   ` (70 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 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 ...

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 95817c4..3190e9d 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1277,10 +1277,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. */
@@ -1291,64 +1290,64 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	intel_dp_link_down(intel_dp);
 	ironlake_edp_panel_vdd_off(intel_dp, false);
+
+	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);
 
-	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);
-		ironlake_edp_panel_off(intel_dp);
+	/* DP supports only 2 dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
 
-		intel_dp_sink_dpms(intel_dp, mode);
-		intel_dp_link_down(intel_dp);
-		ironlake_edp_panel_vdd_off(intel_dp, false);
+	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) {
+		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;
 }
 
 /*
@@ -2361,15 +2360,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,
@@ -2507,6 +2506,9 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	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 (output_reg) {
 		case DP_A:
-- 
1.7.7.6

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

* [PATCH 12/81] drm/i915: create VLV_DSIPLAY_BASE #define
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (10 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 11/81] drm/i915/dp: " Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-20 12:07   ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 13/81] drm/i915: group ADPA #defines together Daniel Vetter
                   ` (69 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Will be used more in the next patch.

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

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index e754cdf..116670e 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1032,7 +1032,7 @@ static bool IS_DISPLAYREG(u32 reg)
 	 * This should make it easier to transition modules over to the
 	 * new register block scheme, since we can do it incrementally.
 	 */
-	if (reg >= 0x180000)
+	if (reg >= VLV_DISPLAY_BASE)
 		return false;
 
 	if (reg >= RENDER_RING_BASE &&
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index cc82871..e982900 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -528,6 +528,8 @@
 #define   GFX_PSMI_GRANULARITY		(1<<10)
 #define   GFX_PPGTT_ENABLE		(1<<9)
 
+#define VLV_DISPLAY_BASE 0x180000
+
 #define SCPD0		0x0209c /* 915+ only */
 #define IER		0x020a0
 #define IIR		0x020a4
-- 
1.7.7.6

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

* [PATCH 13/81] drm/i915: group ADPA #defines together
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (11 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 12/81] drm/i915: create VLV_DSIPLAY_BASE #define Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-12 13:06   ` Paulo Zanoni
  2012-07-11 14:27 ` [PATCH 14/81] drm/i915: add inte_crt->adpa_reg Daniel Vetter
                   ` (68 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Splitting them up between pch and gmch variants just makes it harder
to find things. Especially since the hotplug bits are actually valid
on earlier chips, too.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_reg.h |   47 ++++++++++++++++++--------------------
 1 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e982900..c7e21bf 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1546,12 +1546,34 @@
 
 /* VGA port control */
 #define ADPA			0x61100
+#define PCH_ADPA                0xe1100
+
 #define   ADPA_DAC_ENABLE	(1<<31)
 #define   ADPA_DAC_DISABLE	0
 #define   ADPA_PIPE_SELECT_MASK	(1<<30)
 #define   ADPA_PIPE_A_SELECT	0
 #define   ADPA_PIPE_B_SELECT	(1<<30)
 #define   ADPA_PIPE_SELECT(pipe) ((pipe) << 30)
+/* CPT uses bits 29:31 for pch transcoder select */
+#define   ADPA_CRT_HOTPLUG_MASK  0x03ff0000 /* bit 25-16 */
+#define   ADPA_CRT_HOTPLUG_MONITOR_NONE  (0<<24)
+#define   ADPA_CRT_HOTPLUG_MONITOR_MASK  (3<<24)
+#define   ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24)
+#define   ADPA_CRT_HOTPLUG_MONITOR_MONO  (2<<24)
+#define   ADPA_CRT_HOTPLUG_ENABLE        (1<<23)
+#define   ADPA_CRT_HOTPLUG_PERIOD_64     (0<<22)
+#define   ADPA_CRT_HOTPLUG_PERIOD_128    (1<<22)
+#define   ADPA_CRT_HOTPLUG_WARMUP_5MS    (0<<21)
+#define   ADPA_CRT_HOTPLUG_WARMUP_10MS   (1<<21)
+#define   ADPA_CRT_HOTPLUG_SAMPLE_2S     (0<<20)
+#define   ADPA_CRT_HOTPLUG_SAMPLE_4S     (1<<20)
+#define   ADPA_CRT_HOTPLUG_VOLTAGE_40    (0<<18)
+#define   ADPA_CRT_HOTPLUG_VOLTAGE_50    (1<<18)
+#define   ADPA_CRT_HOTPLUG_VOLTAGE_60    (2<<18)
+#define   ADPA_CRT_HOTPLUG_VOLTAGE_70    (3<<18)
+#define   ADPA_CRT_HOTPLUG_VOLREF_325MV  (0<<17)
+#define   ADPA_CRT_HOTPLUG_VOLREF_475MV  (1<<17)
+#define   ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
 #define   ADPA_USE_VGA_HVPOLARITY (1<<15)
 #define   ADPA_SETS_HVPOLARITY	0
 #define   ADPA_VSYNC_CNTL_DISABLE (1<<11)
@@ -3886,31 +3908,6 @@
 #define FDI_PLL_CTL_1           0xfe000
 #define FDI_PLL_CTL_2           0xfe004
 
-/* CRT */
-#define PCH_ADPA                0xe1100
-#define  ADPA_TRANS_SELECT_MASK (1<<30)
-#define  ADPA_TRANS_A_SELECT    0
-#define  ADPA_TRANS_B_SELECT    (1<<30)
-#define  ADPA_CRT_HOTPLUG_MASK  0x03ff0000 /* bit 25-16 */
-#define  ADPA_CRT_HOTPLUG_MONITOR_NONE  (0<<24)
-#define  ADPA_CRT_HOTPLUG_MONITOR_MASK  (3<<24)
-#define  ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24)
-#define  ADPA_CRT_HOTPLUG_MONITOR_MONO  (2<<24)
-#define  ADPA_CRT_HOTPLUG_ENABLE        (1<<23)
-#define  ADPA_CRT_HOTPLUG_PERIOD_64     (0<<22)
-#define  ADPA_CRT_HOTPLUG_PERIOD_128    (1<<22)
-#define  ADPA_CRT_HOTPLUG_WARMUP_5MS    (0<<21)
-#define  ADPA_CRT_HOTPLUG_WARMUP_10MS   (1<<21)
-#define  ADPA_CRT_HOTPLUG_SAMPLE_2S     (0<<20)
-#define  ADPA_CRT_HOTPLUG_SAMPLE_4S     (1<<20)
-#define  ADPA_CRT_HOTPLUG_VOLTAGE_40    (0<<18)
-#define  ADPA_CRT_HOTPLUG_VOLTAGE_50    (1<<18)
-#define  ADPA_CRT_HOTPLUG_VOLTAGE_60    (2<<18)
-#define  ADPA_CRT_HOTPLUG_VOLTAGE_70    (3<<18)
-#define  ADPA_CRT_HOTPLUG_VOLREF_325MV  (0<<17)
-#define  ADPA_CRT_HOTPLUG_VOLREF_475MV  (1<<17)
-#define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
-
 /* or SDVOB */
 #define HDMIB   0xe1140
 #define  PORT_ENABLE    (1 << 31)
-- 
1.7.7.6

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

* [PATCH 14/81] drm/i915: add inte_crt->adpa_reg
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (12 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 13/81] drm/i915: group ADPA #defines together Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-20 11:56   ` Chris Wilson
  2012-07-20 12:09   ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 15/81] drm/i915/crt: convert to encoder disable/enable Daniel Vetter
                   ` (67 subsequent siblings)
  81 siblings, 2 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

With the base addresses shifting around, this is easier to handle.
Also move to the real reg offset on vlv.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_reg.h  |    1 +
 drivers/gpu/drm/i915/intel_crt.c |   23 ++++++++++++++++-------
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index c7e21bf..ae1f1b7 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1547,6 +1547,7 @@
 /* VGA port control */
 #define ADPA			0x61100
 #define PCH_ADPA                0xe1100
+#define VLV_ADPA		(VLV_DISPLAY_BASE + ADPA)
 
 #define   ADPA_DAC_ENABLE	(1<<31)
 #define   ADPA_DAC_DISABLE	0
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 61d55d3..8babc10 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -47,6 +47,7 @@
 struct intel_crt {
 	struct intel_encoder base;
 	bool force_hotplug_required;
+	u32 adpa_reg;
 };
 
 static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
@@ -55,6 +56,11 @@ static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
 			    struct intel_crt, base);
 }
 
+static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
+{
+	return container_of(encoder, struct intel_crt, base);
+}
+
 static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
@@ -145,19 +151,15 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
 
 	struct drm_device *dev = encoder->dev;
 	struct drm_crtc *crtc = encoder->crtc;
+	struct intel_crt *crt =
+		intel_encoder_to_crt(to_intel_encoder(encoder));
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int dpll_md_reg;
 	u32 adpa, dpll_md;
-	u32 adpa_reg;
 
 	dpll_md_reg = DPLL_MD(intel_crtc->pipe);
 
-	if (HAS_PCH_SPLIT(dev))
-		adpa_reg = PCH_ADPA;
-	else
-		adpa_reg = ADPA;
-
 	/*
 	 * Disable separate mode multiplier used when cloning SDVO to CRT
 	 * XXX this needs to be adjusted when we really are cloning
@@ -185,7 +187,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
 	if (!HAS_PCH_SPLIT(dev))
 		I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
 
-	I915_WRITE(adpa_reg, adpa);
+	I915_WRITE(crt->adpa_reg, adpa);
 }
 
 static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
@@ -682,6 +684,13 @@ void intel_crt_init(struct drm_device *dev)
 	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;
+	else
+		crt->adpa_reg = ADPA;
+
 	drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs);
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
-- 
1.7.7.6

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

* [PATCH 15/81] drm/i915/crt: convert to encoder disable/enable
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (13 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 14/81] drm/i915: add inte_crt->adpa_reg Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:27 ` [PATCH 16/81] drm/i915/sdvo: " Daniel Vetter
                   ` (66 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 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 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 8babc10..9525822 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;
@@ -582,18 +605,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 = {
@@ -691,6 +716,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.7.6

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

* [PATCH 16/81] drm/i915/sdvo: convert to encoder disable/enable
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (14 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 15/81] drm/i915/crt: convert to encoder disable/enable Daniel Vetter
@ 2012-07-11 14:27 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 17/81] drm/i915: simplify dvo dpms interface Daniel Vetter
                   ` (65 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:27 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 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 2f5106a..d630db8 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1139,6 +1139,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;
@@ -1844,9 +1894,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 = {
@@ -2573,6 +2624,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.7.6

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

* [PATCH 17/81] drm/i915: simplify dvo dpms interface
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (15 preceding siblings ...)
  2012-07-11 14:27 ` [PATCH 16/81] drm/i915/sdvo: " Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 18/81] drm/i915/dvo: convert to encoder disable/enable Daniel Vetter
                   ` (64 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

All dvo drivers only support 2 dpms states, and our dvo driver
even switches of the dvo port for anything else than DPMS_ON. Hence
ditch this complexity and simply use bool enable.

While reading through this code I've noticed that the mode_set
function of ch7017 is a bit peculiar - it disable the lvds again, even
though the crtc helper code should have done that ... This might be to
work around an issue at driver load, we pretty much ignore the hw
state when taking over.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/dvo.h        |    9 ++++-----
 drivers/gpu/drm/i915/dvo_ch7017.c |    8 ++++----
 drivers/gpu/drm/i915/dvo_ch7xxx.c |    4 ++--
 drivers/gpu/drm/i915/dvo_ivch.c   |    8 ++++----
 drivers/gpu/drm/i915/dvo_sil164.c |    4 ++--
 drivers/gpu/drm/i915/dvo_tfp410.c |    4 ++--
 drivers/gpu/drm/i915/intel_dvo.c  |    4 ++--
 7 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
index 8c2ad01..8efec6d 100644
--- a/drivers/gpu/drm/i915/dvo.h
+++ b/drivers/gpu/drm/i915/dvo.h
@@ -58,13 +58,12 @@ struct intel_dvo_dev_ops {
 	void (*create_resources)(struct intel_dvo_device *dvo);
 
 	/*
-	 * Turn on/off output or set intermediate power levels if available.
+	 * Turn on/off output.
 	 *
-	 * Unsupported intermediate modes drop to the lower power setting.
-	 * If the  mode is DPMSModeOff, the output must be disabled,
-	 * as the DPLL may be disabled afterwards.
+	 * Because none of our dvo drivers support an intermediate power levels,
+	 * we don't expose this in the interfac.
 	 */
-	void (*dpms)(struct intel_dvo_device *dvo, int mode);
+	void (*dpms)(struct intel_dvo_device *dvo, bool enable);
 
 	/*
 	 * Callback for testing a video mode for a given output.
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
index 1ca799a..71e7650 100644
--- a/drivers/gpu/drm/i915/dvo_ch7017.c
+++ b/drivers/gpu/drm/i915/dvo_ch7017.c
@@ -163,7 +163,7 @@ struct ch7017_priv {
 };
 
 static void ch7017_dump_regs(struct intel_dvo_device *dvo);
-static void ch7017_dpms(struct intel_dvo_device *dvo, int mode);
+static void ch7017_dpms(struct intel_dvo_device *dvo, bool enable);
 
 static bool ch7017_read(struct intel_dvo_device *dvo, u8 addr, u8 *val)
 {
@@ -309,7 +309,7 @@ static void ch7017_mode_set(struct intel_dvo_device *dvo,
 	lvds_power_down = CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED |
 			  (mode->hdisplay & 0x0700) >> 8;
 
-	ch7017_dpms(dvo, DRM_MODE_DPMS_OFF);
+	ch7017_dpms(dvo, false);
 	ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT,
 			horizontal_active_pixel_input);
 	ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT,
@@ -331,7 +331,7 @@ static void ch7017_mode_set(struct intel_dvo_device *dvo,
 }
 
 /* set the CH7017 power state */
-static void ch7017_dpms(struct intel_dvo_device *dvo, int mode)
+static void ch7017_dpms(struct intel_dvo_device *dvo, bool enable)
 {
 	uint8_t val;
 
@@ -345,7 +345,7 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode)
 			CH7017_DAC3_POWER_DOWN |
 			CH7017_TV_POWER_DOWN_EN);
 
-	if (mode == DRM_MODE_DPMS_ON) {
+	if (enable) {
 		/* Turn on the LVDS */
 		ch7017_write(dvo, CH7017_LVDS_POWER_DOWN,
 			     val & ~CH7017_LVDS_POWER_DOWN_EN);
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
index 4a03660..c1dea5b 100644
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -289,9 +289,9 @@ static void ch7xxx_mode_set(struct intel_dvo_device *dvo,
 }
 
 /* set the CH7xxx power state */
-static void ch7xxx_dpms(struct intel_dvo_device *dvo, int mode)
+static void ch7xxx_dpms(struct intel_dvo_device *dvo, bool enable)
 {
-	if (mode == DRM_MODE_DPMS_ON)
+	if (enable)
 		ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_DVIL | CH7xxx_PM_DVIP);
 	else
 		ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_FPD);
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
index 04f2893..fa8ff6b 100644
--- a/drivers/gpu/drm/i915/dvo_ivch.c
+++ b/drivers/gpu/drm/i915/dvo_ivch.c
@@ -288,7 +288,7 @@ static enum drm_mode_status ivch_mode_valid(struct intel_dvo_device *dvo,
 }
 
 /** Sets the power state of the panel connected to the ivch */
-static void ivch_dpms(struct intel_dvo_device *dvo, int mode)
+static void ivch_dpms(struct intel_dvo_device *dvo, bool enable)
 {
 	int i;
 	uint16_t vr01, vr30, backlight;
@@ -297,13 +297,13 @@ static void ivch_dpms(struct intel_dvo_device *dvo, int mode)
 	if (!ivch_read(dvo, VR01, &vr01))
 		return;
 
-	if (mode == DRM_MODE_DPMS_ON)
+	if (enable)
 		backlight = 1;
 	else
 		backlight = 0;
 	ivch_write(dvo, VR80, backlight);
 
-	if (mode == DRM_MODE_DPMS_ON)
+	if (enable)
 		vr01 |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
 	else
 		vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
@@ -315,7 +315,7 @@ static void ivch_dpms(struct intel_dvo_device *dvo, int mode)
 		if (!ivch_read(dvo, VR30, &vr30))
 			break;
 
-		if (((vr30 & VR30_PANEL_ON) != 0) == (mode == DRM_MODE_DPMS_ON))
+		if (((vr30 & VR30_PANEL_ON) != 0) == enable)
 			break;
 		udelay(1000);
 	}
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
index a0b13a6..cc24c1c 100644
--- a/drivers/gpu/drm/i915/dvo_sil164.c
+++ b/drivers/gpu/drm/i915/dvo_sil164.c
@@ -208,7 +208,7 @@ static void sil164_mode_set(struct intel_dvo_device *dvo,
 }
 
 /* set the SIL164 power state */
-static void sil164_dpms(struct intel_dvo_device *dvo, int mode)
+static void sil164_dpms(struct intel_dvo_device *dvo, bool enable)
 {
 	int ret;
 	unsigned char ch;
@@ -217,7 +217,7 @@ static void sil164_dpms(struct intel_dvo_device *dvo, int mode)
 	if (ret == false)
 		return;
 
-	if (mode == DRM_MODE_DPMS_ON)
+	if (enable)
 		ch |= SIL164_8_PD;
 	else
 		ch &= ~SIL164_8_PD;
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
index aa2cd3e..097b3e8 100644
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -234,14 +234,14 @@ static void tfp410_mode_set(struct intel_dvo_device *dvo,
 }
 
 /* set the tfp410 power state */
-static void tfp410_dpms(struct intel_dvo_device *dvo, int mode)
+static void tfp410_dpms(struct intel_dvo_device *dvo, bool enable)
 {
 	uint8_t ctl1;
 
 	if (!tfp410_readb(dvo, TFP410_CTL_1, &ctl1))
 		return;
 
-	if (mode == DRM_MODE_DPMS_ON)
+	if (enable)
 		ctl1 |= TFP410_CTL_1_PD;
 	else
 		ctl1 &= ~TFP410_CTL_1_PD;
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 60ba50b9..d72584a 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -107,9 +107,9 @@ static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
 	if (mode == DRM_MODE_DPMS_ON) {
 		I915_WRITE(dvo_reg, temp | DVO_ENABLE);
 		I915_READ(dvo_reg);
-		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, mode);
+		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
 	} else {
-		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, mode);
+		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
 		I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
 		I915_READ(dvo_reg);
 	}
-- 
1.7.7.6

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

* [PATCH 18/81] drm/i915/dvo: convert to encoder disable/enable
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (16 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 17/81] drm/i915: simplify dvo dpms interface Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 19/81] drm/i915: simplify possible_clones computation Daniel Vetter
                   ` (63 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index d72584a..756e977 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -97,6 +97,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;
@@ -269,9 +293,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 = {
@@ -364,6 +389,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.7.6

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

* [PATCH 19/81] drm/i915: simplify possible_clones computation
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (17 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 18/81] drm/i915/dvo: convert to encoder disable/enable Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-12 18:10   ` Paulo Zanoni
  2012-07-11 14:28 ` [PATCH 20/81] drm/i915: add port parameter to intel_hdmi_init Daniel Vetter
                   ` (62 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Intel hw only has one MUX for encoders, so outputs are either not
cloneable or all in the same group of cloneable outputs. This neatly
simplifies the code and allows us to ditch some ugly if cascades in
the dp and hdmi init code (well, we need these if cascades for other
stuff still, but that can be taken care of in follow-up patches).

Also explain why sdvo LVDS outputs cannot be cloned: Native LVDS (and
also eDP) can't be cloned, because the panel fitter is before the
ouput MUX (and for cpu eDP cloning isn't possible, anyway).

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

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 9525822..c3f6680 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -690,9 +690,7 @@ void intel_crt_init(struct drm_device *dev)
 	intel_connector_attach_encoder(intel_connector, &crt->base);
 
 	crt->base.type = INTEL_OUTPUT_ANALOG;
-	crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT |
-				1 << INTEL_ANALOG_CLONE_BIT |
-				1 << INTEL_SDVO_LVDS_CLONE_BIT);
+	crt->base.cloneable = true;
 	if (IS_HASWELL(dev))
 		crt->base.crtc_mask = (1 << 0);
 	else
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1a201b2..38891ff 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6716,15 +6716,23 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
 	return 0;
 }
 
-static int intel_encoder_clones(struct drm_device *dev, int type_mask)
+static int intel_encoder_clones(struct intel_encoder *encoder)
 {
-	struct intel_encoder *encoder;
+	struct drm_device *dev = encoder->base.dev;
+	struct intel_encoder *source_encoder;
 	int index_mask = 0;
 	int entry = 0;
 
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
-		if (type_mask & encoder->clone_mask)
+	list_for_each_entry(source_encoder,
+			    &dev->mode_config.encoder_list, base.head) {
+
+		if (encoder == source_encoder)
 			index_mask |= (1 << entry);
+
+		/* Intel hw has only one MUX where enocoders could be cloned. */
+		if (encoder->cloneable && source_encoder->cloneable)
+			index_mask |= (1 << entry);
+
 		entry++;
 	}
 
@@ -6883,7 +6891,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 		encoder->base.possible_crtcs = encoder->crtc_mask;
 		encoder->base.possible_clones =
-			intel_encoder_clones(dev, encoder->clone_mask);
+			intel_encoder_clones(encoder);
 	}
 
 	/* disable all the possible outputs/crtcs before entering KMS mode */
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3190e9d..95b1022 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2481,18 +2481,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 
-	if (output_reg == DP_B || output_reg == PCH_DP_B)
-		intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
-	else if (output_reg == DP_C || output_reg == PCH_DP_C)
-		intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
-	else if (output_reg == DP_D || output_reg == PCH_DP_D)
-		intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+	intel_encoder->cloneable = false;
 
-	if (is_edp(intel_dp)) {
-		intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
-		INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
-				  ironlake_panel_vdd_work);
-	}
+	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
+			  ironlake_panel_vdd_work);
 
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 16680e5..f8c1f04 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -89,25 +89,6 @@
 #define INTEL_OUTPUT_DISPLAYPORT 7
 #define INTEL_OUTPUT_EDP 8
 
-/* Intel Pipe Clone Bit */
-#define INTEL_HDMIB_CLONE_BIT 1
-#define INTEL_HDMIC_CLONE_BIT 2
-#define INTEL_HDMID_CLONE_BIT 3
-#define INTEL_HDMIE_CLONE_BIT 4
-#define INTEL_HDMIF_CLONE_BIT 5
-#define INTEL_SDVO_NON_TV_CLONE_BIT 6
-#define INTEL_SDVO_TV_CLONE_BIT 7
-#define INTEL_SDVO_LVDS_CLONE_BIT 8
-#define INTEL_ANALOG_CLONE_BIT 9
-#define INTEL_TV_CLONE_BIT 10
-#define INTEL_DP_B_CLONE_BIT 11
-#define INTEL_DP_C_CLONE_BIT 12
-#define INTEL_DP_D_CLONE_BIT 13
-#define INTEL_LVDS_CLONE_BIT 14
-#define INTEL_DVO_TMDS_CLONE_BIT 15
-#define INTEL_DVO_LVDS_CLONE_BIT 16
-#define INTEL_EDP_CLONE_BIT 17
-
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
 #define INTEL_DVO_CHIP_TMDS 2
@@ -153,11 +134,15 @@ struct intel_encoder {
 	int type;
 	bool needs_tv_clock;
 	bool connectors_active;
+	/*
+	 * Intel hw has only one MUX where encoders could be clone, hence a
+	 * simple flag is enough to compute the possible_clones mask.
+	 */
+	bool cloneable;
 	void (*hot_plug)(struct intel_encoder *);
 	void (*enable)(struct intel_encoder *);
 	void (*disable)(struct intel_encoder *);
 	int crtc_mask;
-	int clone_mask;
 };
 
 struct intel_connector {
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 756e977..86a3d2b 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -424,17 +424,14 @@ void intel_dvo_init(struct drm_device *dev)
 		intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
 		switch (dvo->type) {
 		case INTEL_DVO_CHIP_TMDS:
-			intel_encoder->clone_mask =
-				(1 << INTEL_DVO_TMDS_CLONE_BIT) |
-				(1 << INTEL_ANALOG_CLONE_BIT);
+			intel_encoder->cloneable = true;
 			drm_connector_init(dev, connector,
 					   &intel_dvo_connector_funcs,
 					   DRM_MODE_CONNECTOR_DVII);
 			encoder_type = DRM_MODE_ENCODER_TMDS;
 			break;
 		case INTEL_DVO_CHIP_LVDS:
-			intel_encoder->clone_mask =
-				(1 << INTEL_DVO_LVDS_CLONE_BIT);
+			intel_encoder->cloneable = false;
 			drm_connector_init(dev, connector,
 					   &intel_dvo_connector_funcs,
 					   DRM_MODE_CONNECTOR_LVDS);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 188399f..b01900d 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -959,42 +959,36 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 	connector->doublescan_allowed = 0;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
+	intel_encoder->cloneable = false;
+
 	/* Set up the DDC bus. */
 	if (sdvox_reg == SDVOB) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == SDVOC) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMIB) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMIC) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMID) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
 		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == DDI_BUF_CTL(PORT_B)) {
 		DRM_DEBUG_DRIVER("LPT: detected output on DDI B\n");
-		intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
 		intel_hdmi->ddi_port = PORT_B;
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == DDI_BUF_CTL(PORT_C)) {
 		DRM_DEBUG_DRIVER("LPT: detected output on DDI C\n");
-		intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
 		intel_hdmi->ddi_port = PORT_C;
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == DDI_BUF_CTL(PORT_D)) {
 		DRM_DEBUG_DRIVER("LPT: detected output on DDI D\n");
-		intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
 		intel_hdmi->ddi_port = PORT_D;
 		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index f1d0a05..1e879bf 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -943,7 +943,7 @@ bool intel_lvds_init(struct drm_device *dev)
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_LVDS;
 
-	intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
+	intel_encoder->cloneable = false;
 	if (HAS_PCH_SPLIT(dev))
 		intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 	else if (IS_GEN4(dev))
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index d630db8..5fe044c 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2129,8 +2129,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 		connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
 		intel_sdvo->is_hdmi = true;
 	}
-	intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
-				       (1 << INTEL_ANALOG_CLONE_BIT));
+	intel_sdvo->base.cloneable= true;
 
 	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 	if (intel_sdvo->is_hdmi)
@@ -2161,7 +2160,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
 
 	intel_sdvo->is_tv = true;
 	intel_sdvo->base.needs_tv_clock = true;
-	intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
+	intel_sdvo->base.cloneable = false;
 
 	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 
@@ -2204,8 +2203,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
 	}
 
-	intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
-				       (1 << INTEL_ANALOG_CLONE_BIT));
+	intel_sdvo->base.cloneable = true;
 
 	intel_sdvo_connector_init(intel_sdvo_connector,
 				  intel_sdvo);
@@ -2237,8 +2235,10 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
 	}
 
-	intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) |
-				       (1 << INTEL_SDVO_LVDS_CLONE_BIT));
+	/* SDVO LVDS is cloneable because the SDVO encoder does the upscaling,
+	 * as opposed to native LVDS, where we upscale with the panel-fitter
+	 * (and hence only the native LVDS resolution could be cloned). */
+	intel_sdvo->base.cloneable = true;
 
 	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index a0ec1eb..ef9e7a5 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1624,7 +1624,7 @@ intel_tv_init(struct drm_device *dev)
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_TVOUT;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
-	intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
+	intel_encoder->cloneable = false;
 	intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
 	intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
 	intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
-- 
1.7.7.6

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

* [PATCH 20/81] drm/i915: add port parameter to intel_hdmi_init
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (18 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 19/81] drm/i915: simplify possible_clones computation Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-12 18:19   ` [PATCH] " Daniel Vetter
  2012-07-11 14:28 ` [PATCH 21/81] drm/i915: convert dpms functions of dvo/sdvo/crt Daniel Vetter
                   ` (61 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Instead of having a giant if cascade to figure this out according to
the passed-in register. We could do quite a bit more cleaning up and
all by using the port at more places, but I think this should be part
of a bigger rework to introduce a struct intel_digital_port which
would keep track of all these things. I guess this will be part of
some haswell-DP-induced refactoring.

For now this rips out the big cascade, which is what annoyed me so
much.

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index fd60f48..5370d17 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -250,7 +250,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 	case PORT_B:
 	case PORT_C:
 	case PORT_D:
-		intel_hdmi_init(dev, DDI_BUF_CTL(port));
+		intel_hdmi_init(dev, DDI_BUF_CTL(port), port);
 		break;
 	default:
 		DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 38891ff..3769e5f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6807,16 +6807,16 @@ static void intel_setup_outputs(struct drm_device *dev)
 			/* PCH SDVOB multiplex with HDMIB */
 			found = intel_sdvo_init(dev, PCH_SDVOB, true);
 			if (!found)
-				intel_hdmi_init(dev, HDMIB);
+				intel_hdmi_init(dev, HDMIB, PORT_B);
 			if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
 				intel_dp_init(dev, PCH_DP_B);
 		}
 
 		if (I915_READ(HDMIC) & PORT_DETECTED)
-			intel_hdmi_init(dev, HDMIC);
+			intel_hdmi_init(dev, HDMIC, PORT_C);
 
 		if (!dpd_is_edp && I915_READ(HDMID) & PORT_DETECTED)
-			intel_hdmi_init(dev, HDMID);
+			intel_hdmi_init(dev, HDMID, PORT_D);
 
 		if (I915_READ(PCH_DP_C) & DP_DETECTED)
 			intel_dp_init(dev, PCH_DP_C);
@@ -6830,13 +6830,13 @@ static void intel_setup_outputs(struct drm_device *dev)
 			/* SDVOB multiplex with HDMIB */
 			found = intel_sdvo_init(dev, SDVOB, true);
 			if (!found)
-				intel_hdmi_init(dev, SDVOB);
+				intel_hdmi_init(dev, SDVOB, PORT_B);
 			if (!found && (I915_READ(DP_B) & DP_DETECTED))
 				intel_dp_init(dev, DP_B);
 		}
 
 		if (I915_READ(SDVOC) & PORT_DETECTED)
-			intel_hdmi_init(dev, SDVOC);
+			intel_hdmi_init(dev, SDVOC, PORT_C);
 
 		/* Shares lanes with HDMI on SDVOC */
 		if (I915_READ(DP_C) & DP_DETECTED)
@@ -6849,7 +6849,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 			found = intel_sdvo_init(dev, SDVOB, true);
 			if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
 				DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
-				intel_hdmi_init(dev, SDVOB);
+				intel_hdmi_init(dev, SDVOB, PORT_B);
 			}
 
 			if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
@@ -6869,7 +6869,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 
 			if (SUPPORTS_INTEGRATED_HDMI(dev)) {
 				DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
-				intel_hdmi_init(dev, SDVOC);
+				intel_hdmi_init(dev, SDVOC, PORT_C);
 			}
 			if (SUPPORTS_INTEGRATED_DP(dev)) {
 				DRM_DEBUG_KMS("probing DP_C\n");
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f8c1f04..488b897 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -336,7 +336,7 @@ extern void intel_attach_force_audio_property(struct drm_connector *connector);
 extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
 
 extern void intel_crt_init(struct drm_device *dev);
-extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
+extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port);
 extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
 extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
 extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index b01900d..1332367 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -925,7 +925,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
 	intel_attach_broadcast_rgb_property(connector);
 }
 
-void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
+void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_connector *connector;
@@ -961,40 +961,23 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 
 	intel_encoder->cloneable = false;
 
-	/* Set up the DDC bus. */
-	if (sdvox_reg == SDVOB) {
+	intel_hdmi->ddi_port = port;
+	switch (port) {
+	case PORT_B:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == SDVOC) {
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == HDMIB) {
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
-		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == HDMIC) {
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == HDMID) {
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
-		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == DDI_BUF_CTL(PORT_B)) {
-		DRM_DEBUG_DRIVER("LPT: detected output on DDI B\n");
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
-		intel_hdmi->ddi_port = PORT_B;
-		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == DDI_BUF_CTL(PORT_C)) {
-		DRM_DEBUG_DRIVER("LPT: detected output on DDI C\n");
+		break;
+	case PORT_C:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-		intel_hdmi->ddi_port = PORT_C;
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == DDI_BUF_CTL(PORT_D)) {
-		DRM_DEBUG_DRIVER("LPT: detected output on DDI D\n");
+		break;
+	case PORT_D:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
-		intel_hdmi->ddi_port = PORT_D;
 		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
-	} else {
-		/* If we got an unknown sdvox_reg, things are pretty much broken
-		 * in a way that we should let the kernel know about it */
+		break;
+	case PORT_A:
+		/* Internal port only for eDP. */
+	default:
 		BUG();
 	}
 
-- 
1.7.7.6

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

* [PATCH 21/81] drm/i915: convert dpms functions of dvo/sdvo/crt
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (19 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 20/81] drm/i915: add port parameter to intel_hdmi_init Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 22/81] drm/i915: rip out encoder->disable/enable checks Daniel Vetter
                   ` (60 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 c3f6680..3cca437 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,
@@ -603,27 +622,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,
@@ -664,7 +673,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))
@@ -703,11 +711,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;
@@ -717,7 +720,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 3769e5f..eb3b7ab 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3450,34 +3450,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;
@@ -3486,7 +3483,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:
@@ -3505,11 +3502,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);
@@ -3569,11 +3567,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 488b897..d6f3d25 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -379,6 +379,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 86a3d2b..8a188f4 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -121,21 +121,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);
 	}
 }
 
@@ -291,7 +309,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,
@@ -300,7 +317,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 5fe044c..284513b 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1189,51 +1189,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,
@@ -1892,7 +1885,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,
@@ -1901,7 +1893,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.7.6

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

* [PATCH 22/81] drm/i915: rip out encoder->disable/enable checks
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (20 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 21/81] drm/i915: convert dpms functions of dvo/sdvo/crt Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 23/81] drm/i915: clean up encoder_prepare/commit Daniel Vetter
                   ` (59 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index eb3b7ab..cf2546c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3236,10 +3236,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)
@@ -3254,10 +3252,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;
@@ -3400,10 +3396,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)
@@ -3417,10 +3411,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.7.6

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

* [PATCH 23/81] drm/i915: clean up encoder_prepare/commit
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (21 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 22/81] drm/i915: rip out encoder->disable/enable checks Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 24/81] drm/fb helper: don't call drm_crtc_helper_set_config Daniel Vetter
                   ` (58 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 cf2546c..5317f35 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3238,6 +3238,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)
@@ -3512,26 +3515,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 d6f3d25..85c7da0 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -380,8 +380,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.7.6

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

* [PATCH 24/81] drm/fb helper: don't call drm_crtc_helper_set_config
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (22 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 23/81] drm/i915: clean up encoder_prepare/commit Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-18 15:49   ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 25/81] drm: remove the list_head from drm_mode_set Daniel Vetter
                   ` (57 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter, dri-devel

Go through the interface vtable instead, because not everyone might be
using the crtc helper code.

Cc: dri-devel@lists.freedesktop.org
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/drm_fb_helper.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 5683b7f..bf97c0a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -228,7 +228,7 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
 	int i, ret;
 	for (i = 0; i < fb_helper->crtc_count; i++) {
 		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
-		ret = drm_crtc_helper_set_config(mode_set);
+		ret = mode_set->crtc->funcs->set_config(mode_set);
 		if (ret)
 			error = true;
 	}
-- 
1.7.7.6

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

* [PATCH 25/81] drm: remove the list_head from drm_mode_set
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (23 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 24/81] drm/fb helper: don't call drm_crtc_helper_set_config Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-20  1:23   ` Dave Airlie
  2012-07-11 14:28 ` [PATCH 26/81] drm/i915: copy&paste drm_crtc_helper_set_config Daniel Vetter
                   ` (56 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter, dri-devel

It's unused. At it confused me quite a bit until I've discovered that.

Cc: dri-devel@lists.freedesktop.org
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 include/drm/drm_crtc.h |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index bac55c2..a1a0386 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -676,8 +676,6 @@ struct drm_plane {
  * This is used to set modes.
  */
 struct drm_mode_set {
-	struct list_head head;
-
 	struct drm_framebuffer *fb;
 	struct drm_crtc *crtc;
 	struct drm_display_mode *mode;
-- 
1.7.7.6

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

* [PATCH 26/81] drm/i915: copy&paste drm_crtc_helper_set_config
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (24 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 25/81] drm: remove the list_head from drm_mode_set Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 27/81] drm/i915: call set_base directly Daniel Vetter
                   ` (55 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 313 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5317f35..7edb3a1 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.7.6

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

* [PATCH 27/81] drm/i915: call set_base directly
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (25 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 26/81] drm/i915: copy&paste drm_crtc_helper_set_config Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 28/81] drm/i915: inline intel_best_encoder Daniel Vetter
                   ` (54 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7edb3a1..28a5ba0 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.7.6

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

* [PATCH 28/81] drm/i915: inline intel_best_encoder
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (26 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 27/81] drm/i915: call set_base directly Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 29/81] drm/i915: copy&paste drm_crtc_helper_set_mode Daniel Vetter
                   ` (53 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 3 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 28a5ba0..451dbba 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.7.6

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

* [PATCH 29/81] drm/i915: copy&paste drm_crtc_helper_set_mode
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (27 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 28/81] drm/i915: inline intel_best_encoder Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 30/81] drm/i915: simplify intel_crtc_prepare_encoders Daniel Vetter
                   ` (52 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 451dbba..d687bff 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5684,7 +5684,7 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 		goto fail;
 	}
 
-	if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) {
+	if (!intel_crtc_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,158 @@ 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_crtc_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,7 +6969,7 @@ 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,
+			if (!intel_crtc_set_mode(set->crtc, set->mode,
 						      set->x, set->y,
 						      old_fb)) {
 				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
@@ -6873,8 +7025,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_crtc_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 95b1022..8d6b699 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2324,9 +2324,9 @@ 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_crtc_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 85c7da0..d130683 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -378,6 +378,10 @@ 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_crtc_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 1332367..4b99140 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -869,9 +869,9 @@ 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_crtc_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 1e879bf..5e528d4 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -560,8 +560,9 @@ 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_crtc_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 284513b..35c47db 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1876,8 +1876,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_crtc_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 ef9e7a5..25d20ef 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1473,8 +1473,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_crtc_set_mode(crtc, &crtc->mode,
+				    crtc->x, crtc->y, crtc->fb);
 out:
 	return ret;
 }
-- 
1.7.7.6

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

* [PATCH 30/81] drm/i915: simplify intel_crtc_prepare_encoders
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (28 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 29/81] drm/i915: copy&paste drm_crtc_helper_set_mode Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 31/81] drm/i915: rip out encoder->prepare/commit Daniel Vetter
                   ` (51 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 4 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d687bff..cec8b82 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.7.6

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

* [PATCH 31/81] drm/i915: rip out encoder->prepare/commit
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (29 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 30/81] drm/i915: simplify intel_crtc_prepare_encoders Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 32/81] drm/i915: call crtc functions directly Daniel Vetter
                   ` (50 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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, 0 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 3cca437..7ea986c 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -624,8 +624,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 cec8b82..3534e67 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3515,10 +3515,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);
@@ -6702,16 +6698,6 @@ bool intel_crtc_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);
@@ -6738,16 +6724,6 @@ bool intel_crtc_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 8d6b699..4cfe283 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2361,9 +2361,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 d130683..02aea23 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -384,7 +384,6 @@ extern bool intel_crtc_set_mode(struct drm_crtc *crtc,
 				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 8a188f4..34cbe8c 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -310,9 +310,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 4b99140..1782357 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -886,17 +886,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 5e528d4..e3dd7b3 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -571,9 +571,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 35c47db..92763d5 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1886,9 +1886,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 25d20ef..3136f56 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1481,9 +1481,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.7.6

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

* [PATCH 32/81] drm/i915: call crtc functions directly
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (30 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 31/81] drm/i915: rip out encoder->prepare/commit Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 33/81] drm/i915: WARN when trying to enabled an unused crtc Daniel Vetter
                   ` (49 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3534e67..b91e7ea 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,
@@ -6649,8 +6647,8 @@ bool intel_crtc_set_mode(struct drm_crtc *crtc,
 			 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;
@@ -6692,7 +6690,7 @@ bool intel_crtc_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;
 	}
@@ -6700,12 +6698,12 @@ bool intel_crtc_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;
 
@@ -6722,7 +6720,7 @@ bool intel_crtc_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;
@@ -7057,9 +7055,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);
 
 	intel_crtc->busy = false;
-- 
1.7.7.6

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

* [PATCH 33/81] drm/i915: WARN when trying to enabled an unused crtc
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (31 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 32/81] drm/i915: call crtc functions directly Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 34/81] drm/i915: Add interfaces to read out encoder/connector hw state Daniel Vetter
                   ` (48 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b91e7ea..744241e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3184,6 +3184,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)
@@ -3379,6 +3381,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 02aea23..c5b71bf 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -156,7 +156,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 busy; /* is scanout buffer being updated frequently? */
 	struct timer_list idle_timer;
-- 
1.7.7.6

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

* [PATCH 34/81] drm/i915: Add interfaces to read out encoder/connector hw state
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (32 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 33/81] drm/i915: WARN when trying to enabled an unused crtc Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 35/81] drm/i915/dp: implement get_hw_state Daniel Vetter
                   ` (47 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 744241e..42b306a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3572,6 +3572,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,
 				  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 c5b71bf..c06cfda 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -142,12 +142,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 {
@@ -396,6 +403,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.7.6

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

* [PATCH 35/81] drm/i915/dp: implement get_hw_state
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (33 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 34/81] drm/i915: Add interfaces to read out encoder/connector hw state Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 36/81] drm/i915/hdmi: " Daniel Vetter
                   ` (46 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ae1f1b7..5163090 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4016,6 +4016,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 4cfe283..ad328ab 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1277,6 +1277,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);
@@ -2498,6 +2546,8 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
 	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 (output_reg) {
-- 
1.7.7.6

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

* [PATCH 36/81] drm/i915/hdmi: implement get_hw_state
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (34 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 35/81] drm/i915/dp: implement get_hw_state Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 37/81] drm/i915/tv: " Daniel Vetter
                   ` (45 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 5370d17..7fdc5d9 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -738,6 +738,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 c06cfda..28cf6cc 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -514,6 +514,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 1782357..3ccf7fd 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;
@@ -999,14 +1020,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.7.6

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

* [PATCH 37/81] drm/i915/tv: implement get_hw_state
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (35 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 36/81] drm/i915/hdmi: " Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 38/81] drm/i915/lvds: " Daniel Vetter
                   ` (44 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 3136f56..aa9beaa 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)
 {
@@ -1618,6 +1633,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.7.6

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

* [PATCH 38/81] drm/i915/lvds: implement get_hw_state
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (36 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 37/81] drm/i915/tv: " Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 39/81] drm/i915/crt: " Daniel Vetter
                   ` (43 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index e3dd7b3..af78502 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.
  */
@@ -938,6 +964,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.7.6

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

* [PATCH 39/81] drm/i915/crt: implement get_hw_state
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (37 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 38/81] drm/i915/lvds: " Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 40/81] drm/i915/sdvo: " Daniel Vetter
                   ` (42 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 7ea986c..0a5b61a 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;
@@ -717,6 +738,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.7.6

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

* [PATCH 40/81] drm/i915/sdvo: implement get_hw_state
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (38 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 39/81] drm/i915/crt: " Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 41/81] drm/i915/dvo: " Daniel Vetter
                   ` (41 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 46 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 92763d5..65b52a1 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -625,6 +625,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)
 {
@@ -1139,6 +1147,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;
@@ -2063,6 +2107,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);
@@ -2616,6 +2661,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.7.6

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

* [PATCH 41/81] drm/i915/dvo: implement get_hw_state
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (39 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 40/81] drm/i915/sdvo: " Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 42/81] drm/i915: read out the modeset hw state at load and resume time Daniel Vetter
                   ` (40 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 5 dvo drivers.

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_sil164.c |   16 ++++++++++++++++
 drivers/gpu/drm/i915/dvo_tfp410.c |   14 ++++++++++++++
 drivers/gpu/drm/i915/intel_dvo.c  |   27 +++++++++++++++++++++++++++
 7 files changed, 104 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
index 8efec6d..0ccda16 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_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 34cbe8c..88dd005 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -97,6 +97,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;
@@ -406,6 +431,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.7.6

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

* [PATCH 42/81] drm/i915: read out the modeset hw state at load and resume time
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (40 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 41/81] drm/i915/dvo: " Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 43/81] drm/i915: check connector hw/sw state Daniel Vetter
                   ` (39 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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.

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 |  276 ++++++++++++++++++++++++++--------
 3 files changed, 212 insertions(+), 66 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 116670e..92011b1 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -514,6 +514,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 cafa4cc..b03ae0b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1520,6 +1520,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 42b306a..c3a7ef0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3577,7 +3577,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,
@@ -7008,7 +6949,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,
@@ -7066,8 +7006,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);
@@ -7280,9 +7218,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);
 }
@@ -7662,11 +7597,220 @@ void intel_modeset_init(struct drm_device *dev)
 		    (unsigned long)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;
+
+		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
+		 * ...  */
+		crtc->plane = !crtc->pipe;
+		dev_priv->display.crtc_disable(&crtc->base);
+		crtc->plane = crtc->pipe;
+
+		/* ... 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.7.6

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

* [PATCH 43/81] drm/i915: check connector hw/sw state
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (41 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 42/81] drm/i915: read out the modeset hw state at load and resume time Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 44/81] drm/i915: rip out intel_crtc->dpms_mode Daniel Vetter
                   ` (38 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 0a5b61a..14a2f24 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 c3a7ef0..4160b09 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3550,6 +3550,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)
@@ -3570,6 +3605,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 ad328ab..220f1d1 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1396,6 +1396,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 28cf6cc..38b120a 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -404,6 +404,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 88dd005..b9df54c 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -180,6 +180,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 65b52a1..d624355 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1271,6 +1271,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.7.6

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

* [PATCH 44/81] drm/i915: rip out intel_crtc->dpms_mode
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (42 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 43/81] drm/i915: check connector hw/sw state Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 45/81] drm/i915: rip out intel_dp->dpms_mode Daniel Vetter
                   ` (37 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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, 0 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 4160b09..649d327 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3458,18 +3458,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
@@ -5036,11 +5028,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;
 }
 
@@ -7649,10 +7636,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 38b120a..8effd1b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -162,7 +162,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.7.6

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

* [PATCH 45/81] drm/i915: rip out intel_dp->dpms_mode
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (43 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 44/81] drm/i915: rip out intel_crtc->dpms_mode Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-26 18:06   ` Paulo Zanoni
  2012-07-11 14:28 ` [PATCH 46/81] drm/i915: ensure the force pipe A quirk is actually followed Daniel Vetter
                   ` (36 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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.

Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_dp.c |   12 ++----------
 1 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 220f1d1..58e16f4 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -52,7 +52,6 @@ struct intel_dp {
 	bool has_audio;
 	enum hdmi_force_audio force_audio;
 	uint32_t color_range;
-	int dpms_mode;
 	uint8_t link_bw;
 	uint8_t lane_count;
 	uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
@@ -1338,8 +1337,6 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	intel_dp_link_down(intel_dp);
 	ironlake_edp_panel_vdd_off(intel_dp, false);
-
-	intel_dp->dpms_mode = DRM_MODE_DPMS_OFF;
 }
 
 static void intel_enable_dp(struct intel_encoder *encoder)
@@ -1359,8 +1356,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
@@ -1385,7 +1380,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);
@@ -1394,7 +1388,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));
@@ -2081,10 +2074,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 */
@@ -2502,7 +2495,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 		return;
 
 	intel_dp->output_reg = output_reg;
-	intel_dp->dpms_mode = -1;
 
 	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
-- 
1.7.7.6

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

* [PATCH 46/81] drm/i915: ensure the force pipe A quirk is actually followed
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (44 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 45/81] drm/i915: rip out intel_dp->dpms_mode Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 47/81] drm/i915: introduce struct intel_set_config Daniel Vetter
                   ` (35 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 649d327..08d3684 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7630,6 +7630,35 @@ 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(intel_attached_encoder(crt),
+				       crt, NULL, &load_detect_temp))
+		intel_release_load_detect_pipe(intel_attached_encoder(crt),
+					       crt, &load_detect_temp);
+
+
+}
+
 static void intel_sanitize_crtc(struct intel_crtc *crtc)
 {
 	struct drm_device *dev = crtc->base.dev;
@@ -7676,6 +7705,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.7.6

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

* [PATCH 47/81] drm/i915: introduce struct intel_set_config
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (45 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 46/81] drm/i915: ensure the force pipe A quirk is actually followed Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 48/81] drm/i915: extract modeset config save/restore code Daniel Vetter
                   ` (34 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 08d3684..3d79373 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6724,17 +6724,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;
 
@@ -6763,27 +6774,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
@@ -6791,17 +6802,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;
@@ -6938,26 +6949,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 */
@@ -6966,9 +6976,8 @@ fail:
 				 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 8effd1b..426c112 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -392,6 +392,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_crtc_set_mode(struct drm_crtc *crtc,
 				struct drm_display_mode *mode,
 				int x, int y,
-- 
1.7.7.6

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

* [PATCH 48/81] drm/i915: extract modeset config save/restore code
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (46 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 47/81] drm/i915: introduce struct intel_set_config Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 49/81] drm/i915: extract intel_set_config_compute_mode_changes Daniel Vetter
                   ` (33 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 76 insertions(+), 51 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3d79373..e4d654d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6734,11 +6734,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 */
@@ -6779,42 +6850,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;
@@ -6954,21 +6993,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.7.6

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

* [PATCH 49/81] drm/i915: extract intel_set_config_compute_mode_changes
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (47 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 48/81] drm/i915: extract modeset config save/restore code Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 50/81] drm/i915: extract intel_set_config_update_output_state Daniel Vetter
                   ` (32 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 e4d654d..d816c0a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6805,14 +6805,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;
@@ -6860,33 +6892,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;
@@ -6902,7 +6912,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.
 			 */
@@ -6930,12 +6940,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) {
@@ -6948,7 +6957,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"
@@ -6973,7 +6982,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;
 
@@ -6996,7 +7005,7 @@ fail:
 	intel_set_config_restore_state(dev, config);
 
 	/* Try to restore the config */
-	if (mode_changed &&
+	if (config->mode_changed &&
 	    !intel_crtc_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 426c112..a5fbacc 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -396,6 +396,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_crtc_set_mode(struct drm_crtc *crtc,
-- 
1.7.7.6

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

* [PATCH 50/81] drm/i915: extract intel_set_config_update_output_state
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (48 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 49/81] drm/i915: extract intel_set_config_compute_mode_changes Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 51/81] drm/i915: implement crtc helper semantics relied upon by the fb helper Daniel Vetter
                   ` (31 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 67 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d816c0a..fdc1713 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6839,64 +6839,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;
@@ -6957,6 +6908,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.7.6

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

* [PATCH 51/81] drm/i915: implement crtc helper semantics relied upon by the fb helper
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (49 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 50/81] drm/i915: extract intel_set_config_update_output_state Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 52/81] drm/i915: don't update the fb base if there is no fb Daniel Vetter
                   ` (30 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fdc1713..577b964 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6934,6 +6934,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.7.6

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

* [PATCH 52/81] drm/i915: don't update the fb base if there is no fb
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (50 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 51/81] drm/i915: implement crtc helper semantics relied upon by the fb helper Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 53/81] drm/i915: convert pointless error checks in set_config to BUGs Daniel Vetter
                   ` (29 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 577b964..f90860f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6828,7 +6828,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.7.6

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

* [PATCH 53/81] drm/i915: convert pointless error checks in set_config to BUGs
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (51 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 52/81] drm/i915: don't update the fb base if there is no fb Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 54/81] drm/i915: don't save all the encoder/crtc state in set_config Daniel Vetter
                   ` (28 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f90860f..2659ad5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5380,8 +5380,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");
@@ -6920,16 +6918,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.7.6

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

* [PATCH 54/81] drm/i915: don't save all the encoder/crtc state in set_config
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (52 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 53/81] drm/i915: convert pointless error checks in set_config to BUGs Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 55/81] drm/i915: stage modeset output changes Daniel Vetter
                   ` (27 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 2659ad5..e2563d0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6725,8 +6725,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);
@@ -6742,19 +6742,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.
@@ -6768,12 +6770,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;
@@ -6794,12 +6796,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 a5fbacc..1065c2d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -393,8 +393,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.7.6

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

* [PATCH 55/81] drm/i915: stage modeset output changes
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (53 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 54/81] drm/i915: don't save all the encoder/crtc state in set_config Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 56/81] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
                   ` (26 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e2563d0..c5bf814 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_crtc_set_mode(struct drm_crtc *crtc,
 			 struct drm_display_mode *mode,
 			 int x, int y,
@@ -6785,8 +6830,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;
@@ -6795,13 +6840,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++]);
 	}
 }
 
@@ -6840,73 +6887,102 @@ 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) {
+		/* If we disable the crtc, disable all its connectors. */
+		if (!set->fb && 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));
+		}
+
+		/* 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 (&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;
 }
@@ -6965,11 +7041,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"
@@ -7016,6 +7094,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_crtc_set_mode(save_set.crtc, save_set.mode, save_set.x,
@@ -7915,6 +7995,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 1065c2d..ff8760b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -131,6 +131,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;
 	bool connectors_active;
@@ -151,7 +157,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.7.6

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

* [PATCH 56/81] drm/i915: push crtc->fb update into pipe_set_base
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (54 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 55/81] drm/i915: stage modeset output changes Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 57/81] drm/i915: remove crtc disabling special case Daniel Vetter
                   ` (25 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 34 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c5bf814..19ef083 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2198,16 +2198,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;
 	}
@@ -2221,7 +2222,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);
@@ -2229,17 +2230,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);
@@ -3765,6 +3769,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)
 {
@@ -3845,7 +3850,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;
@@ -4264,7 +4269,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;
@@ -4454,7 +4459,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);
 
@@ -4612,7 +4617,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;
@@ -4732,7 +4737,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;
@@ -5001,7 +5006,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);
 
@@ -5014,7 +5019,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;
@@ -5025,7 +5030,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;
@@ -5635,7 +5640,7 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 	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",
@@ -5696,8 +5701,6 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 	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
@@ -5705,19 +5708,19 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 	 * 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_crtc_set_mode(crtc, mode, 0, 0, old_fb)) {
+	if (!intel_crtc_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);
@@ -5731,7 +5734,6 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 fail:
 	connector->encoder = NULL;
 	encoder->crtc = NULL;
-	crtc->fb = old_fb;
 	return false;
 }
 
@@ -6667,13 +6669,12 @@ static void intel_modeset_commit_output_state(struct drm_device *dev)
 bool intel_crtc_set_mode(struct drm_crtc *crtc,
 			 struct drm_display_mode *mode,
 			 int x, int y,
-			 struct drm_framebuffer *old_fb)
+			 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;
 
@@ -6687,15 +6688,11 @@ bool intel_crtc_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
@@ -6726,7 +6723,7 @@ bool intel_crtc_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;
 
@@ -6742,6 +6739,9 @@ bool intel_crtc_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);
 
@@ -6760,8 +6760,6 @@ done:
 	if (!ret) {
 		crtc->hwmode = saved_hwmode;
 		crtc->mode = saved_mode;
-		crtc->x = saved_x;
-		crtc->y = saved_y;
 	}
 
 	return ret;
@@ -6990,7 +6988,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;
@@ -7053,14 +7050,11 @@ 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_crtc_set_mode(set->crtc, set->mode,
 						      set->x, set->y,
-						      old_fb)) {
+						      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;
 			}
@@ -7073,18 +7067,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.7.6

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

* [PATCH 57/81] drm/i915: remove crtc disabling special case
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (55 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 56/81] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 58/81] drm/i915: move output commit and crtc disabling into set_mode Daniel Vetter
                   ` (24 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 0 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 19ef083..edd7efc 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)
 {
@@ -7012,7 +6988,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.7.6

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

* [PATCH 58/81] drm/i915: move output commit and crtc disabling into set_mode
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (56 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 57/81] drm/i915: remove crtc disabling special case Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 59/81] drm/i915: extract adjusted mode computation Daniel Vetter
                   ` (23 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 |   34 ++++++++++++++++++----------------
 1 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index edd7efc..af8855e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6654,9 +6654,13 @@ bool intel_crtc_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)
@@ -7018,21 +7022,22 @@ 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_crtc_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_crtc_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,
@@ -7040,7 +7045,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);
@@ -7053,8 +7057,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_crtc_set_mode(save_set.crtc, save_set.mode, save_set.x,
-- 
1.7.7.6

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

* [PATCH 59/81] drm/i915: extract adjusted mode computation
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (57 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 58/81] drm/i915: move output commit and crtc disabling into set_mode Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 60/81] drm/i915: use staged outuput config in tv->mode_fixup Daniel Vetter
                   ` (22 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index af8855e..7e75a37 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_crtc_set_mode(struct drm_crtc *crtc,
 			 struct drm_display_mode *mode,
 			 int x, int y,
@@ -6662,44 +6704,21 @@ bool intel_crtc_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.7.6

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

* [PATCH 60/81] drm/i915: use staged outuput config in tv->mode_fixup
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (58 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 59/81] drm/i915: extract adjusted mode computation Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 61/81] drm/i915: use staged outuput config in lvds->mode_fixup Daniel Vetter
                   ` (21 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 7e75a37..a226b38 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 ff8760b..bad45da 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -426,6 +426,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 aa9beaa..b8afc83 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -909,17 +909,14 @@ static bool
 intel_tv_mode_fixup(struct drm_encoder *encoder, 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.7.6

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

* [PATCH 61/81] drm/i915: use staged outuput config in lvds->mode_fixup
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (59 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 60/81] drm/i915: use staged outuput config in tv->mode_fixup Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 62/81] drm/i915: compute masks of crtcs affected in set_mode Daniel Vetter
                   ` (20 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index af78502..37c7ab1 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.7.6

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

* [PATCH 62/81] drm/i915: compute masks of crtcs affected in set_mode
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (60 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 61/81] drm/i915: use staged outuput config in lvds->mode_fixup Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 63/81] drm/i915: implement new set_mode code flow Daniel Vetter
                   ` (19 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a226b38..b69afbc 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_crtc_set_mode(struct drm_crtc *crtc,
 			 struct drm_display_mode *mode,
 			 int x, int y,
@@ -6716,8 +6801,12 @@ bool intel_crtc_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.7.6

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

* [PATCH 63/81] drm/i915: implement new set_mode code flow
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (61 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 62/81] drm/i915: compute masks of crtcs affected in set_mode Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 64/81] drm/i915: push commit_output_state past crtc disabling Daniel Vetter
                   ` (18 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 63 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b69afbc..d946f73 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_crtc_set_mode(struct drm_crtc *crtc,
 			 struct drm_display_mode *mode,
 			 int x, int y,
@@ -6801,73 +6807,92 @@ bool intel_crtc_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;
 	}
@@ -6875,6 +6900,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.7.6

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

* [PATCH 64/81] drm/i915: push commit_output_state past crtc disabling
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (62 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 63/81] drm/i915: implement new set_mode code flow Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 65/81] drm/i915: s/intel_encoder_disable/intel_encoder_noop Daniel Vetter
                   ` (17 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 53 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d946f73..4b87804 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3450,26 +3450,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;
@@ -3478,8 +3465,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;
@@ -3495,14 +3480,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);
@@ -3512,14 +3525,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)
@@ -6817,12 +6840,14 @@ bool intel_crtc_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.7.6

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

* [PATCH 65/81] drm/i915: s/intel_encoder_disable/intel_encoder_noop
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (63 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 64/81] drm/i915: push commit_output_state past crtc disabling Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 66/81] drm/i915: kill a few unused things in dev_priv Daniel Vetter
                   ` (16 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 14a2f24..e83f5ff 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -648,7 +648,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 4b87804..b479755 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3541,7 +3541,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 58e16f4..8f0bb2b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2405,7 +2405,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 bad45da..e457109 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -423,7 +423,7 @@ extern bool intel_crtc_set_mode(struct drm_crtc *crtc,
 				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 b9df54c..20b8481 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -338,7 +338,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 3ccf7fd..c43cc42 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -908,13 +908,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 37c7ab1..ffec618 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -591,7 +591,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 d624355..838120b 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1933,7 +1933,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 b8afc83..bc4c7a6 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1494,7 +1494,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.7.6

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

* [PATCH 66/81] drm/i915: kill a few unused things in dev_priv
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (64 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 65/81] drm/i915: s/intel_encoder_disable/intel_encoder_noop Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 67/81] drm/i915: WARN if the pipe won't turn off Daniel Vetter
                   ` (15 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

... and move a few others only used by i915_dma.c into the dri1
dungeon.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_dma.c |   22 +++++++++++-----------
 drivers/gpu/drm/i915/i915_drv.h |   13 ++++++-------
 2 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index f64ef4b..a4d9967 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -235,10 +235,10 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
 		}
 	}
 
-	dev_priv->cpp = init->cpp;
-	dev_priv->back_offset = init->back_offset;
-	dev_priv->front_offset = init->front_offset;
-	dev_priv->current_page = 0;
+	dev_priv->dri1.cpp = init->cpp;
+	dev_priv->dri1.back_offset = init->back_offset;
+	dev_priv->dri1.front_offset = init->front_offset;
+	dev_priv->dri1.current_page = 0;
 	if (master_priv->sarea_priv)
 		master_priv->sarea_priv->pf_current_page = 0;
 
@@ -575,7 +575,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
 
 	DRM_DEBUG_DRIVER("%s: page=%d pfCurrentPage=%d\n",
 			  __func__,
-			 dev_priv->current_page,
+			 dev_priv->dri1.current_page,
 			 master_priv->sarea_priv->pf_current_page);
 
 	i915_kernel_lost_context(dev);
@@ -589,12 +589,12 @@ static int i915_dispatch_flip(struct drm_device * dev)
 
 	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
 	OUT_RING(0);
-	if (dev_priv->current_page == 0) {
-		OUT_RING(dev_priv->back_offset);
-		dev_priv->current_page = 1;
+	if (dev_priv->dri1.current_page == 0) {
+		OUT_RING(dev_priv->dri1.back_offset);
+		dev_priv->dri1.current_page = 1;
 	} else {
-		OUT_RING(dev_priv->front_offset);
-		dev_priv->current_page = 0;
+		OUT_RING(dev_priv->dri1.front_offset);
+		dev_priv->dri1.current_page = 0;
 	}
 	OUT_RING(0);
 
@@ -613,7 +613,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
 		ADVANCE_LP_RING();
 	}
 
-	master_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+	master_priv->sarea_priv->pf_current_page = dev_priv->dri1.current_page;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b03ae0b..1b5dc791 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -403,12 +403,6 @@ typedef struct drm_i915_private {
 
 	struct resource mch_res;
 
-	unsigned int cpp;
-	int back_offset;
-	int front_offset;
-	int current_page;
-	int page_flipping;
-
 	atomic_t irq_received;
 
 	/* protects the irq masks */
@@ -426,7 +420,6 @@ typedef struct drm_i915_private {
 	u32 hotplug_supported_mask;
 	struct work_struct hotplug_work;
 
-	unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
 	int num_pipe;
 	int num_pch_pll;
 
@@ -776,6 +769,12 @@ typedef struct drm_i915_private {
 	struct {
 		unsigned allow_batchbuffer : 1;
 		u32 __iomem *gfx_hws_cpu_addr;
+
+		unsigned int cpp;
+		int back_offset;
+		int front_offset;
+		int current_page;
+		int page_flipping;
 	} dri1;
 
 	/* Kernel Modesetting */
-- 
1.7.7.6

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

* [PATCH 67/81] drm/i915: WARN if the pipe won't turn off
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (65 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 66/81] drm/i915: kill a few unused things in dev_priv Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 68/81] drm/i915: switch the load detect code to the staged modeset config Daniel Vetter
                   ` (14 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index b479755..03f3cd3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1005,7 +1005,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);
@@ -1023,7 +1023,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.7.6

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

* [PATCH 68/81] drm/i915: switch the load detect code to the staged modeset config
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (66 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 67/81] drm/i915: WARN if the pipe won't turn off Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 69/81] drm/i915: push commit_output_state past the crtc/encoder preparing Daniel Vetter
                   ` (13 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 03f3cd3..2815dc9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5713,8 +5713,8 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 		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;
@@ -5765,16 +5765,17 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
 				    struct intel_load_detect_pipe *old)
 {
 	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_crtc_set_mode(crtc, NULL, 0, 0, NULL);
 
 		if (old->release_fb)
 			old->release_fb->funcs->destroy(old->release_fb);
-- 
1.7.7.6

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

* [PATCH 69/81] drm/i915: push commit_output_state past the crtc/encoder preparing
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (67 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 68/81] drm/i915: switch the load detect code to the staged modeset config Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 16:02   ` [PATCH] " Daniel Vetter
  2012-07-11 14:28 ` [PATCH 70/81] drm/i915: disable all crtcs at suspend time Daniel Vetter
                   ` (12 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2815dc9..45db3e7 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3190,10 +3190,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);
@@ -3241,7 +3239,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);
 
@@ -3259,14 +3256,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);
@@ -3387,10 +3383,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);
@@ -3406,7 +3400,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);
 }
@@ -3420,14 +3413,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, \
@@ -6832,6 +6824,7 @@ bool intel_crtc_set_mode(struct drm_crtc *crtc,
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct drm_encoder *encoder;
 	struct intel_crtc *intel_crtc;
+	struct drm_connector *connector;
 	unsigned disable_pipes, prepare_pipes, modeset_pipes;
 	bool ret = true;
 
@@ -6844,12 +6837,6 @@ bool intel_crtc_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;
 
@@ -6864,12 +6851,12 @@ bool intel_crtc_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;
@@ -6877,6 +6864,31 @@ bool intel_crtc_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(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;
+
+		printk("adjusting dpms for connector %i to %i\n", connector->base.id,
+		       connector->dpms);
+	}
+
 	/* Set up the DPLL and any encoders state that needs to adjust or depend
 	 * on the DPLL.
 	 */
-- 
1.7.7.6

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

* [PATCH 70/81] drm/i915: disable all crtcs at suspend time
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (68 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 69/81] drm/i915: push commit_output_state past the crtc/encoder preparing Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 71/81] drm/i915: add tons of modeset state checks Daniel Vetter
                   ` (11 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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>
---
 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(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 92011b1..daa0ccc 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -441,6 +441,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 45db3e7..0975ec3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3533,6 +3533,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 e457109..f95919b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -421,6 +421,7 @@ extern bool intel_crtc_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.7.6

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

* [PATCH 71/81] drm/i915: add tons of modeset state checks
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (69 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 70/81] drm/i915: disable all crtcs at suspend time Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 17:46   ` [PATCH] " Daniel Vetter
  2012-07-11 14:28 ` [PATCH 72/81] drm/i915: extract ironlake_fdi_pll_disable Daniel Vetter
                   ` (10 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 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 ...

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0975ec3..1bade92 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -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_crtc_set_mode(struct drm_crtc *crtc,
 			 struct drm_display_mode *mode,
 			 int x, int y,
@@ -6945,6 +7014,8 @@ done:
 		crtc->mode = saved_mode;
 	}
 
+	intel_modeset_check_state(dev);
+
 	return ret;
 }
 
@@ -8163,6 +8234,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.7.6

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

* [PATCH 72/81] drm/i915: extract ironlake_fdi_pll_disable
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (70 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 71/81] drm/i915: add tons of modeset state checks Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 73/81] drm/i915: rip out intel_disable_pch_ports Daniel Vetter
                   ` (9 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Simply to make the ilk+ crtc disable path clearer and more symmetric
with the enable function.

Also switch to intel_crtc for the enable function.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1bade92..36bdac1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2710,11 +2710,10 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
 	DRM_DEBUG_KMS("FDI train done.\n");
 }
 
-static void ironlake_fdi_pll_enable(struct drm_crtc *crtc)
+static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
 {
-	struct drm_device *dev = crtc->dev;
+	struct drm_device *dev = intel_crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 	u32 reg, temp;
 
@@ -2755,6 +2754,35 @@ static void ironlake_fdi_pll_enable(struct drm_crtc *crtc)
 	}
 }
 
+static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe = intel_crtc->pipe;
+	u32 reg, temp;
+
+	/* Switch from PCDclk to Rawclk */
+	reg = FDI_RX_CTL(pipe);
+	temp = I915_READ(reg);
+	I915_WRITE(reg, temp & ~FDI_PCDCLK);
+
+	/* Disable CPU FDI TX PLL */
+	reg = FDI_TX_CTL(pipe);
+	temp = I915_READ(reg);
+	I915_WRITE(reg, temp & ~FDI_TX_PLL_ENABLE);
+
+	POSTING_READ(reg);
+	udelay(100);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = I915_READ(reg);
+	I915_WRITE(reg, temp & ~FDI_RX_PLL_ENABLE);
+
+	/* Wait for the clocks to turn off. */
+	POSTING_READ(reg);
+	udelay(100);
+}
+
 static void cpt_phase_pointer_disable(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3205,7 +3233,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	is_pch_port = intel_crtc_driving_pch(crtc);
 
 	if (is_pch_port)
-		ironlake_fdi_pll_enable(crtc);
+		ironlake_fdi_pll_enable(intel_crtc);
 	else
 		ironlake_fdi_disable(crtc);
 
@@ -3319,26 +3347,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	/* disable PCH DPLL */
 	intel_disable_pch_pll(intel_crtc);
 
-	/* Switch from PCDclk to Rawclk */
-	reg = FDI_RX_CTL(pipe);
-	temp = I915_READ(reg);
-	I915_WRITE(reg, temp & ~FDI_PCDCLK);
-
-	/* Disable CPU FDI TX PLL */
-	reg = FDI_TX_CTL(pipe);
-	temp = I915_READ(reg);
-	I915_WRITE(reg, temp & ~FDI_TX_PLL_ENABLE);
-
-	POSTING_READ(reg);
-	udelay(100);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = I915_READ(reg);
-	I915_WRITE(reg, temp & ~FDI_RX_PLL_ENABLE);
-
-	/* Wait for the clocks to turn off. */
-	POSTING_READ(reg);
-	udelay(100);
+	ironlake_fdi_pll_disable(intel_crtc);
 
 	intel_crtc->active = false;
 	intel_update_watermarks(dev);
-- 
1.7.7.6

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

* [PATCH 73/81] drm/i915: rip out intel_disable_pch_ports
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (71 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 72/81] drm/i915: extract ironlake_fdi_pll_disable Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 74/81] drm/i915: don't disable fdi links harder in ilk_crtc_enable Daniel Vetter
                   ` (8 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Even with the old crtc helper code we should have disabled all
encoders on that pipe by now, and with the new code this would
definitely paper over a bug. We already have the necessary checks
in place in intel_disable_transcoder, so if we accidentally leave
a pch port on, this will be caught.

Hence just rip this all out.

Note that up to the patch in this giant modeset series that removes
the LVDS special case to avoid disabling LVDS in the encoder->prepare
callback ("drm/i915/lvds: ditch ->prepare special case"), this was not
the case for all outputs.

Also note that in

commit 1b3c7a47f993bf9ab6c4c7cc3bbf5588052b58f4
Author: Zhenyu Wang <zhenyuw@linux.intel.com>
Date:   Wed Nov 25 13:09:38 2009 +0800

    drm/i915: Fix LVDS stability issue on Ironlake

this was already discovered independently and worked around. How I
bloody hate this entire mess of cludges piled on top of other cludges.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 36bdac1..38a73bf 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1857,59 +1857,6 @@ static void intel_disable_plane(struct drm_i915_private *dev_priv,
 	intel_wait_for_vblank(dev_priv->dev, pipe);
 }
 
-static void disable_pch_dp(struct drm_i915_private *dev_priv,
-			   enum pipe pipe, int reg, u32 port_sel)
-{
-	u32 val = I915_READ(reg);
-	if (dp_pipe_enabled(dev_priv, pipe, port_sel, val)) {
-		DRM_DEBUG_KMS("Disabling pch dp %x on pipe %d\n", reg, pipe);
-		I915_WRITE(reg, val & ~DP_PORT_EN);
-	}
-}
-
-static void disable_pch_hdmi(struct drm_i915_private *dev_priv,
-			     enum pipe pipe, int reg)
-{
-	u32 val = I915_READ(reg);
-	if (hdmi_pipe_enabled(dev_priv, val, pipe)) {
-		DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n",
-			      reg, pipe);
-		I915_WRITE(reg, val & ~PORT_ENABLE);
-	}
-}
-
-/* Disable any ports connected to this transcoder */
-static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
-				    enum pipe pipe)
-{
-	u32 reg, val;
-
-	val = I915_READ(PCH_PP_CONTROL);
-	I915_WRITE(PCH_PP_CONTROL, val | PANEL_UNLOCK_REGS);
-
-	disable_pch_dp(dev_priv, pipe, PCH_DP_B, TRANS_DP_PORT_SEL_B);
-	disable_pch_dp(dev_priv, pipe, PCH_DP_C, TRANS_DP_PORT_SEL_C);
-	disable_pch_dp(dev_priv, pipe, PCH_DP_D, TRANS_DP_PORT_SEL_D);
-
-	reg = PCH_ADPA;
-	val = I915_READ(reg);
-	if (adpa_pipe_enabled(dev_priv, val, pipe))
-		I915_WRITE(reg, val & ~ADPA_DAC_ENABLE);
-
-	reg = PCH_LVDS;
-	val = I915_READ(reg);
-	if (lvds_pipe_enabled(dev_priv, val, pipe)) {
-		DRM_DEBUG_KMS("disable lvds on pipe %d val 0x%08x\n", pipe, val);
-		I915_WRITE(reg, val & ~LVDS_PORT_EN);
-		POSTING_READ(reg);
-		udelay(100);
-	}
-
-	disable_pch_hdmi(dev_priv, pipe, HDMIB);
-	disable_pch_hdmi(dev_priv, pipe, HDMIC);
-	disable_pch_hdmi(dev_priv, pipe, HDMID);
-}
-
 int
 intel_pin_and_fence_fb_obj(struct drm_device *dev,
 			   struct drm_i915_gem_object *obj,
@@ -3308,13 +3255,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
 	ironlake_fdi_disable(crtc);
 
-	/* This is a horrible layering violation; we should be doing this in
-	 * the connector/encoder ->prepare instead, but we don't always have
-	 * enough information there about the config to know whether it will
-	 * actually be necessary or just cause undesired flicker.
-	 */
-	intel_disable_pch_ports(dev_priv, pipe);
-
 	intel_disable_transcoder(dev_priv, pipe);
 
 	if (HAS_PCH_CPT(dev)) {
-- 
1.7.7.6

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

* [PATCH 74/81] drm/i915: don't disable fdi links harder in ilk_crtc_enable
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (72 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 73/81] drm/i915: rip out intel_disable_pch_ports Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 75/81] drm/i915: don't call dpms funcs after set_mode Daniel Vetter
                   ` (7 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Because they should have been disabled when shutting down the display
pipe previously. To ensure that this is the case, add a few assserts
instead of unconditionally disabling the fdi link.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 38a73bf..03133e4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3179,10 +3179,12 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
 	is_pch_port = intel_crtc_driving_pch(crtc);
 
-	if (is_pch_port)
+	if (is_pch_port) {
 		ironlake_fdi_pll_enable(intel_crtc);
-	else
-		ironlake_fdi_disable(crtc);
+	} else {
+		assert_fdi_tx_disabled(dev_priv, pipe);
+		assert_fdi_rx_disabled(dev_priv, pipe);
+	}
 
 	/* Enable panel fitting for LVDS */
 	if (dev_priv->pch_pf_size &&
-- 
1.7.7.6

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

* [PATCH 75/81] drm/i915: don't call dpms funcs after set_mode
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (73 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 74/81] drm/i915: don't disable fdi links harder in ilk_crtc_enable Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:28 ` [PATCH 76/81] drm/i915: update dpms property in set_mode Daniel Vetter
                   ` (6 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

... because our current set_mode implementation doesn't bother to adjust
for the dpms state, we just forcefully update it. So stop pretending that
we're better than we're are and rip out this extranous call.

Note that this totally confuses userspace, because the exposed connector
property isn't actually updated ...

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 03133e4..c8f7f54 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7198,7 +7198,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 	struct drm_mode_set save_set;
 	struct intel_set_config *config;
 	int ret;
-	int i;
 
 	BUG_ON(!set);
 	BUG_ON(!set->crtc);
@@ -7263,15 +7262,6 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
 			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,
-					      drm_get_connector_name(set->connectors[i]));
-				set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
-			}
-		}
 	} else if (config->fb_changed) {
 		ret = intel_pipe_set_base(set->crtc,
 					  set->x, set->y, set->fb);
-- 
1.7.7.6

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

* [PATCH 76/81] drm/i915: update dpms property in set_mode
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (74 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 75/81] drm/i915: don't call dpms funcs after set_mode Daniel Vetter
@ 2012-07-11 14:28 ` Daniel Vetter
  2012-07-11 14:29 ` [PATCH 77/81] drm/i915: add encoder->pre_enable/post_disable Daniel Vetter
                   ` (5 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:28 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Hopefully this makes userspace slightly less confused about us
frobbing the dpms state behind its back. Yeah, it would be better
to be more careful with not changing the dpms state, but that is
quite more invasive.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c8f7f54..91d8560 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6910,8 +6910,15 @@ bool intel_crtc_set_mode(struct drm_crtc *crtc,
 
 		intel_crtc = to_intel_crtc(connector->encoder->crtc);
 
-		if (prepare_pipes & (1 << intel_crtc->pipe))
+		if (prepare_pipes & (1 << intel_crtc->pipe)) {
+			struct drm_property *dpms_property =
+				dev->mode_config.dpms_property;
+
 			connector->dpms = DRM_MODE_DPMS_ON;
+			drm_connector_property_set_value(connector,
+							 dpms_property,
+							 DRM_MODE_DPMS_ON);
+		}
 
 		to_intel_encoder(connector->encoder)->connectors_active = true;
 
-- 
1.7.7.6

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

* [PATCH 77/81] drm/i915: add encoder->pre_enable/post_disable
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (75 preceding siblings ...)
  2012-07-11 14:28 ` [PATCH 76/81] drm/i915: update dpms property in set_mode Daniel Vetter
@ 2012-07-11 14:29 ` Daniel Vetter
  2012-07-11 14:29 ` [PATCH 78/81] drm/i915: clean up the cpu edp pll special case Daniel Vetter
                   ` (4 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:29 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

The cpu eDP encoder has some horrible hacks to set up the DP pll at
the right time. To be able to move them to the right place, add some
more encoder callbacks so that this can happen at the right time.

LVDS has some similar funky hacks, but that would require more work
(we need to move around the pll setup a bit). Hence for now only
wiring these new callbacks up for ilk+ - we only have cpu eDP on these
platforms.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 91d8560..79c5974 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3186,6 +3186,10 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 		assert_fdi_rx_disabled(dev_priv, pipe);
 	}
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		if (encoder->pre_enable)
+			encoder->pre_enable(encoder);
+
 	/* Enable panel fitting for LVDS */
 	if (dev_priv->pch_pf_size &&
 	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) {
@@ -3255,6 +3259,10 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	I915_WRITE(PF_CTL(pipe), 0);
 	I915_WRITE(PF_WIN_SZ(pipe), 0);
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		if (encoder->post_disable)
+			encoder->post_disable(encoder);
+
 	ironlake_fdi_disable(crtc);
 
 	intel_disable_transcoder(dev_priv, pipe);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f95919b..f5426a2 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -147,7 +147,9 @@ struct intel_encoder {
 	bool cloneable;
 	void (*hot_plug)(struct intel_encoder *);
 	void (*enable)(struct intel_encoder *);
+	void (*pre_enable)(struct intel_encoder *);
 	void (*disable)(struct intel_encoder *);
+	void (*post_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. */
-- 
1.7.7.6

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

* [PATCH 78/81] drm/i915: clean up the cpu edp pll special case
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (76 preceding siblings ...)
  2012-07-11 14:29 ` [PATCH 77/81] drm/i915: add encoder->pre_enable/post_disable Daniel Vetter
@ 2012-07-11 14:29 ` Daniel Vetter
  2012-07-11 14:29 ` [PATCH 79/81] drm/i915: robustify edp_pll_on/off Daniel Vetter
                   ` (3 subsequent siblings)
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:29 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

By using the new pre_enabel/post_disable functions.

To ensure that we only frob the cpu edp pll while the pipe is off add
the relevant asserts. Thanks to the new output state staging, this is
now really easy.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 8f0bb2b..6d3f3df 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -838,9 +838,6 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	}
 }
 
-static void ironlake_edp_pll_on(struct drm_encoder *encoder);
-static void ironlake_edp_pll_off(struct drm_encoder *encoder);
-
 static void
 intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		  struct drm_display_mode *adjusted_mode)
@@ -851,14 +848,6 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 	struct drm_crtc *crtc = intel_dp->base.base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-	/* Turn on the eDP PLL if needed */
-	if (is_edp(intel_dp)) {
-		if (!is_pch_edp(intel_dp))
-			ironlake_edp_pll_on(encoder);
-		else
-			ironlake_edp_pll_off(encoder);
-	}
-
 	/*
 	 * There are four kinds of DP registers:
 	 *
@@ -1219,12 +1208,16 @@ static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
 	msleep(intel_dp->backlight_off_delay);
 }
 
-static void ironlake_edp_pll_on(struct drm_encoder *encoder)
+static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_crtc *crtc = intel_dp->base.base.crtc;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpa_ctl;
 
+	assert_pipe_disabled(dev_priv,
+			     to_intel_crtc(crtc)->pipe);
+
 	DRM_DEBUG_KMS("\n");
 	dpa_ctl = I915_READ(DP_A);
 	dpa_ctl |= DP_PLL_ENABLE;
@@ -1233,12 +1226,16 @@ static void ironlake_edp_pll_on(struct drm_encoder *encoder)
 	udelay(200);
 }
 
-static void ironlake_edp_pll_off(struct drm_encoder *encoder)
+static void ironlake_edp_pll_off(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_crtc *crtc = intel_dp->base.base.crtc;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 dpa_ctl;
 
+	assert_pipe_disabled(dev_priv,
+			     to_intel_crtc(crtc)->pipe);
+
 	dpa_ctl = I915_READ(DP_A);
 	dpa_ctl &= ~DP_PLL_ENABLE;
 	I915_WRITE(DP_A, dpa_ctl);
@@ -1339,6 +1336,14 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 	ironlake_edp_panel_vdd_off(intel_dp, false);
 }
 
+static void intel_post_disable_dp(struct intel_encoder *encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+
+	if (is_cpu_edp(intel_dp))
+		ironlake_edp_pll_off(intel_dp);
+}
+
 static void intel_enable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -1358,39 +1363,12 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	ironlake_edp_backlight_on(intel_dp);
 }
 
-static void
-intel_dp_dpms(struct drm_connector *connector, int mode)
+static void intel_pre_enable_dp(struct intel_encoder *encoder)
 {
-	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) {
-		intel_encoder_dpms(&intel_dp->base, mode);
-
-		if (is_cpu_edp(intel_dp))
-			ironlake_edp_pll_off(&intel_dp->base.base);
-	} else {
-		if (is_cpu_edp(intel_dp))
-			ironlake_edp_pll_on(&intel_dp->base.base);
-
-		intel_encoder_dpms(&intel_dp->base, mode);
-	}
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
-	intel_connector_check_state(to_intel_connector(connector));
+	if (is_cpu_edp(intel_dp))
+		ironlake_edp_pll_on(intel_dp);
 }
 
 /*
@@ -2409,7 +2387,7 @@ static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
 };
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
-	.dpms = intel_dp_dpms,
+	.dpms = intel_connector_dpms,
 	.detect = intel_dp_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_dp_set_property,
@@ -2539,7 +2517,9 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	drm_sysfs_connector_add(connector);
 
 	intel_encoder->enable = intel_enable_dp;
+	intel_encoder->pre_enable = intel_pre_enable_dp;
 	intel_encoder->disable = intel_disable_dp;
+	intel_encoder->post_disable = intel_post_disable_dp;
 	intel_encoder->get_hw_state = intel_dp_get_hw_state;
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
-- 
1.7.7.6

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

* [PATCH 79/81] drm/i915: robustify edp_pll_on/off
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (77 preceding siblings ...)
  2012-07-11 14:29 ` [PATCH 78/81] drm/i915: clean up the cpu edp pll special case Daniel Vetter
@ 2012-07-11 14:29 ` Daniel Vetter
  2012-07-11 17:47   ` [PATCH] " Daniel Vetter
  2012-07-11 14:29 ` [PATCH 80/81] drm/i915: rip out dp port enabling cludges^Wchecks Daniel Vetter
                   ` (2 subsequent siblings)
  81 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:29 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

With the previous patch to clean up where exactly these two functions
are getting called, this patch can tackle the enable/disable code
itself:

- WARN if the port enable bit is in the wrong state or if the edp pll
  bit is in the wrong state, just for paranoia's sake.
- Don't disable the edp pll harder in the modeset functions just for
  fun.
- Don't set the edp pll enable flag in intel_dp->DP in modeset, do
  that while changing the actual hw state. We do the same with the
  actual port enable bit, so this is a bit more consistent.
- Track the current DP register value when setting things up and add
  some comments how intel_dp->DP is used in the disable code.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6d3f3df..68fe1dd 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -919,7 +919,6 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		intel_dp->DP |= intel_crtc->pipe << 29;
 
 		/* don't miss out required setting for eDP */
-		intel_dp->DP |= DP_PLL_ENABLE;
 		if (adjusted_mode->clock < 200000)
 			intel_dp->DP |= DP_PLL_FREQ_160MHZ;
 		else
@@ -941,7 +940,6 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 
 		if (is_cpu_edp(intel_dp)) {
 			/* don't miss out required setting for eDP */
-			intel_dp->DP |= DP_PLL_ENABLE;
 			if (adjusted_mode->clock < 200000)
 				intel_dp->DP |= DP_PLL_FREQ_160MHZ;
 			else
@@ -1220,8 +1218,11 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("\n");
 	dpa_ctl = I915_READ(DP_A);
-	dpa_ctl |= DP_PLL_ENABLE;
-	I915_WRITE(DP_A, dpa_ctl);
+	WARN(dpa_ctl & DP_PLL_ENABLE, "dp pll on, should be off\n");
+	WARN(dpa_ctl & DP_PORT_EN, "dp port still on, should be off\n");
+
+	intel_dp->DP |= DP_PLL_ENABLE;
+	I915_WRITE(DP_A, intel_dp->DP);
 	POSTING_READ(DP_A);
 	udelay(200);
 }
@@ -1237,6 +1238,13 @@ static void ironlake_edp_pll_off(struct intel_dp *intel_dp)
 			     to_intel_crtc(crtc)->pipe);
 
 	dpa_ctl = I915_READ(DP_A);
+	WARN((dpa_ctl & DP_PLL_ENABLE) == 0,
+	     "dp pll off, should be on\n");
+	WARN(dpa_ctl & DP_PORT_EN, "dp port still on, should be off\n");
+
+	/* We can't rely on the value tracked for the DP register in
+	 * intel_dp->DP because link_down must not change that (otherwise link
+	 * re-training will fail. */
 	dpa_ctl &= ~DP_PLL_ENABLE;
 	I915_WRITE(DP_A, dpa_ctl);
 	POSTING_READ(DP_A);
@@ -1919,13 +1927,6 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("\n");
 
-	if (is_edp(intel_dp)) {
-		DP &= ~DP_PLL_ENABLE;
-		I915_WRITE(intel_dp->output_reg, DP);
-		POSTING_READ(intel_dp->output_reg);
-		udelay(100);
-	}
-
 	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
 		DP &= ~DP_LINK_TRAIN_MASK_CPT;
 		I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
@@ -2473,6 +2474,8 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 		return;
 
 	intel_dp->output_reg = output_reg;
+	/* Preserve the current hw state. */
+	intel_dp->DP = I915_READ(intel_dp->output_reg);
 
 	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
-- 
1.7.7.6

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

* [PATCH 80/81] drm/i915: rip out dp port enabling cludges^Wchecks
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (78 preceding siblings ...)
  2012-07-11 14:29 ` [PATCH 79/81] drm/i915: robustify edp_pll_on/off Daniel Vetter
@ 2012-07-11 14:29 ` Daniel Vetter
  2012-07-11 14:38 ` [PATCH 81/81] drm/i915: disable the cpu edp port after the cpu pipe Daniel Vetter
  2012-07-15 13:13 ` [PATCH 00/81] modeset rework Chris Wilson
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:29 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

These have been added because dp links are fiddle things and don't
like it when we try to re-train an enabled output (or disable a
disable output harder). And because the crtc helper code is
ridiculously bad add tracking the modeset state.

But with the new code in place it is simply a bug to disable a disable
encoder or to enable an enabled encoder again. Hence convert these to
WARNs (and bail out for safety), but flatten all conditionals in the
code itself.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 68fe1dd..90b03e9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1359,15 +1359,15 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 
+	if (WARN_ON(dp_reg & DP_PORT_EN))
+		return;
+
 	ironlake_edp_panel_vdd_on(intel_dp);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
-	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);
+	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);
 	ironlake_edp_backlight_on(intel_dp);
 }
 
@@ -1922,7 +1922,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t DP = intel_dp->DP;
 
-	if ((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
+	if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0))
 		return;
 
 	DRM_DEBUG_KMS("\n");
-- 
1.7.7.6

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

* [PATCH 81/81] drm/i915: disable the cpu edp port after the cpu pipe
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (79 preceding siblings ...)
  2012-07-11 14:29 ` [PATCH 80/81] drm/i915: rip out dp port enabling cludges^Wchecks Daniel Vetter
@ 2012-07-11 14:38 ` Daniel Vetter
  2012-07-15 13:13 ` [PATCH 00/81] modeset rework Chris Wilson
  81 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 14:38 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

See bspec, Vol3 Part2, Section 1.1.3 "Display Mode Set Sequence". This
applies to all platforms where we currently support eDP on, i.e. ilk,
snb & ivb.

Without this change we fail to light up the eDP port on previously
unused crtcs (likely because something is stuck on the old pipe), and
we also fail to properly disable the old pipe (i.e. bit 30 in the
PIPECONF register is stuck as set until the next reboot).

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=44001
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/i915/intel_dp.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 90b03e9..51053fb 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1340,16 +1340,23 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 	ironlake_edp_panel_off(intel_dp);
 
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
-	intel_dp_link_down(intel_dp);
-	ironlake_edp_panel_vdd_off(intel_dp, false);
+
+	/* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */
+	if (!is_cpu_edp(intel_dp)) {
+		intel_dp_link_down(intel_dp);
+		ironlake_edp_panel_vdd_off(intel_dp, false);
+	}
 }
 
 static void intel_post_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
-	if (is_cpu_edp(intel_dp))
+	if (is_cpu_edp(intel_dp)) {
+		intel_dp_link_down(intel_dp);
+		ironlake_edp_panel_vdd_off(intel_dp, false);
 		ironlake_edp_pll_off(intel_dp);
+	}
 }
 
 static void intel_enable_dp(struct intel_encoder *encoder)
-- 
1.7.7.6

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

* [PATCH] drm/i915: push commit_output_state past the crtc/encoder preparing
  2012-07-11 14:28 ` [PATCH 69/81] drm/i915: push commit_output_state past the crtc/encoder preparing Daniel Vetter
@ 2012-07-11 16:02   ` Daniel Vetter
  0 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 16:02 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.

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

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2815dc9..38c3eed 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3190,10 +3190,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);
@@ -3241,7 +3239,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);
 
@@ -3259,14 +3256,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);
@@ -3387,10 +3383,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);
@@ -3406,7 +3400,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);
 }
@@ -3420,14 +3413,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, \
@@ -6832,6 +6824,7 @@ bool intel_crtc_set_mode(struct drm_crtc *crtc,
 	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct drm_encoder *encoder;
 	struct intel_crtc *intel_crtc;
+	struct drm_connector *connector;
 	unsigned disable_pipes, prepare_pipes, modeset_pipes;
 	bool ret = true;
 
@@ -6844,12 +6837,6 @@ bool intel_crtc_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;
 
@@ -6864,12 +6851,12 @@ bool intel_crtc_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;
@@ -6877,6 +6864,28 @@ bool intel_crtc_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(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.7.6

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

* [PATCH] drm/i915: add tons of modeset state checks
  2012-07-11 14:28 ` [PATCH 71/81] drm/i915: add tons of modeset state checks Daniel Vetter
@ 2012-07-11 17:46   ` Daniel Vetter
  0 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 17:46 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 files changed, 74 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f5e8b10..779994d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3625,7 +3625,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_crtc_set_mode(struct drm_crtc *crtc,
 			 struct drm_display_mode *mode,
 			 int x, int y,
@@ -6942,6 +7011,8 @@ done:
 		crtc->mode = saved_mode;
 	}
 
+	intel_modeset_check_state(dev);
+
 	return ret;
 }
 
@@ -8160,6 +8231,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.7.6

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

* [PATCH] drm/i915: robustify edp_pll_on/off
  2012-07-11 14:29 ` [PATCH 79/81] drm/i915: robustify edp_pll_on/off Daniel Vetter
@ 2012-07-11 17:47   ` Daniel Vetter
  0 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-11 17:47 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

With the previous patch to clean up where exactly these two functions
are getting called, this patch can tackle the enable/disable code
itself:

- WARN if the port enable bit is in the wrong state or if the edp pll
  bit is in the wrong state, just for paranoia's sake.
- Don't disable the edp pll harder in the modeset functions just for
  fun.
- Don't set the edp pll enable flag in intel_dp->DP in modeset, do
  that while changing the actual hw state. We do the same with the
  actual port enable bit, so this is a bit more consistent.
- Track the current DP register value when setting things up and add
  some comments how intel_dp->DP is used in the disable code.

v2: Be more careful with resetting intel_dp->DP - otherwise dpms
off->on will fail spectacularly, becuase we enable the eDP port when
we should only enable the eDP pll.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6d3f3df..a306841 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -919,7 +919,6 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		intel_dp->DP |= intel_crtc->pipe << 29;
 
 		/* don't miss out required setting for eDP */
-		intel_dp->DP |= DP_PLL_ENABLE;
 		if (adjusted_mode->clock < 200000)
 			intel_dp->DP |= DP_PLL_FREQ_160MHZ;
 		else
@@ -941,7 +940,6 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 
 		if (is_cpu_edp(intel_dp)) {
 			/* don't miss out required setting for eDP */
-			intel_dp->DP |= DP_PLL_ENABLE;
 			if (adjusted_mode->clock < 200000)
 				intel_dp->DP |= DP_PLL_FREQ_160MHZ;
 			else
@@ -1220,8 +1218,15 @@ static void ironlake_edp_pll_on(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("\n");
 	dpa_ctl = I915_READ(DP_A);
-	dpa_ctl |= DP_PLL_ENABLE;
-	I915_WRITE(DP_A, dpa_ctl);
+	WARN(dpa_ctl & DP_PLL_ENABLE, "dp pll on, should be off\n");
+	WARN(dpa_ctl & DP_PORT_EN, "dp port still on, should be off\n");
+
+	/* We don't adjust intel_dp->DP while tearing down the link, to
+	 * facilitate link retraining (e.g. after hotplug). Hence clear all
+	 * enable bits here to ensure that we don't enable too much. */
+	intel_dp->DP &= ~(DP_PORT_EN | DP_AUDIO_OUTPUT_ENABLE);
+	intel_dp->DP |= DP_PLL_ENABLE;
+	I915_WRITE(DP_A, intel_dp->DP);
 	POSTING_READ(DP_A);
 	udelay(200);
 }
@@ -1237,6 +1242,13 @@ static void ironlake_edp_pll_off(struct intel_dp *intel_dp)
 			     to_intel_crtc(crtc)->pipe);
 
 	dpa_ctl = I915_READ(DP_A);
+	WARN((dpa_ctl & DP_PLL_ENABLE) == 0,
+	     "dp pll off, should be on\n");
+	WARN(dpa_ctl & DP_PORT_EN, "dp port still on, should be off\n");
+
+	/* We can't rely on the value tracked for the DP register in
+	 * intel_dp->DP because link_down must not change that (otherwise link
+	 * re-training will fail. */
 	dpa_ctl &= ~DP_PLL_ENABLE;
 	I915_WRITE(DP_A, dpa_ctl);
 	POSTING_READ(DP_A);
@@ -1919,13 +1931,6 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("\n");
 
-	if (is_edp(intel_dp)) {
-		DP &= ~DP_PLL_ENABLE;
-		I915_WRITE(intel_dp->output_reg, DP);
-		POSTING_READ(intel_dp->output_reg);
-		udelay(100);
-	}
-
 	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
 		DP &= ~DP_LINK_TRAIN_MASK_CPT;
 		I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
@@ -2473,6 +2478,8 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 		return;
 
 	intel_dp->output_reg = output_reg;
+	/* Preserve the current hw state. */
+	intel_dp->DP = I915_READ(intel_dp->output_reg);
 
 	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
-- 
1.7.7.6

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

* Re: [PATCH 13/81] drm/i915: group ADPA #defines together
  2012-07-11 14:27 ` [PATCH 13/81] drm/i915: group ADPA #defines together Daniel Vetter
@ 2012-07-12 13:06   ` Paulo Zanoni
  0 siblings, 0 replies; 107+ messages in thread
From: Paulo Zanoni @ 2012-07-12 13:06 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

Looks like this one can go first.

2012/7/11 Daniel Vetter <daniel.vetter@ffwll.ch>:
> Splitting them up between pch and gmch variants just makes it harder
> to find things. Especially since the hotplug bits are actually valid
> on earlier chips, too.
>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/i915/i915_reg.h |   47 ++++++++++++++++++--------------------
>  1 files changed, 22 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index e982900..c7e21bf 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1546,12 +1546,34 @@
>
>  /* VGA port control */
>  #define ADPA                   0x61100
> +#define PCH_ADPA                0xe1100
> +
>  #define   ADPA_DAC_ENABLE      (1<<31)
>  #define   ADPA_DAC_DISABLE     0
>  #define   ADPA_PIPE_SELECT_MASK        (1<<30)
>  #define   ADPA_PIPE_A_SELECT   0
>  #define   ADPA_PIPE_B_SELECT   (1<<30)
>  #define   ADPA_PIPE_SELECT(pipe) ((pipe) << 30)
> +/* CPT uses bits 29:31 for pch transcoder select */

It's actually 30:29.

With that fixed:
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> +#define   ADPA_CRT_HOTPLUG_MASK  0x03ff0000 /* bit 25-16 */
> +#define   ADPA_CRT_HOTPLUG_MONITOR_NONE  (0<<24)
> +#define   ADPA_CRT_HOTPLUG_MONITOR_MASK  (3<<24)
> +#define   ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24)
> +#define   ADPA_CRT_HOTPLUG_MONITOR_MONO  (2<<24)
> +#define   ADPA_CRT_HOTPLUG_ENABLE        (1<<23)
> +#define   ADPA_CRT_HOTPLUG_PERIOD_64     (0<<22)
> +#define   ADPA_CRT_HOTPLUG_PERIOD_128    (1<<22)
> +#define   ADPA_CRT_HOTPLUG_WARMUP_5MS    (0<<21)
> +#define   ADPA_CRT_HOTPLUG_WARMUP_10MS   (1<<21)
> +#define   ADPA_CRT_HOTPLUG_SAMPLE_2S     (0<<20)
> +#define   ADPA_CRT_HOTPLUG_SAMPLE_4S     (1<<20)
> +#define   ADPA_CRT_HOTPLUG_VOLTAGE_40    (0<<18)
> +#define   ADPA_CRT_HOTPLUG_VOLTAGE_50    (1<<18)
> +#define   ADPA_CRT_HOTPLUG_VOLTAGE_60    (2<<18)
> +#define   ADPA_CRT_HOTPLUG_VOLTAGE_70    (3<<18)
> +#define   ADPA_CRT_HOTPLUG_VOLREF_325MV  (0<<17)
> +#define   ADPA_CRT_HOTPLUG_VOLREF_475MV  (1<<17)
> +#define   ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
>  #define   ADPA_USE_VGA_HVPOLARITY (1<<15)
>  #define   ADPA_SETS_HVPOLARITY 0
>  #define   ADPA_VSYNC_CNTL_DISABLE (1<<11)
> @@ -3886,31 +3908,6 @@
>  #define FDI_PLL_CTL_1           0xfe000
>  #define FDI_PLL_CTL_2           0xfe004
>
> -/* CRT */
> -#define PCH_ADPA                0xe1100
> -#define  ADPA_TRANS_SELECT_MASK (1<<30)
> -#define  ADPA_TRANS_A_SELECT    0
> -#define  ADPA_TRANS_B_SELECT    (1<<30)
> -#define  ADPA_CRT_HOTPLUG_MASK  0x03ff0000 /* bit 25-16 */
> -#define  ADPA_CRT_HOTPLUG_MONITOR_NONE  (0<<24)
> -#define  ADPA_CRT_HOTPLUG_MONITOR_MASK  (3<<24)
> -#define  ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24)
> -#define  ADPA_CRT_HOTPLUG_MONITOR_MONO  (2<<24)
> -#define  ADPA_CRT_HOTPLUG_ENABLE        (1<<23)
> -#define  ADPA_CRT_HOTPLUG_PERIOD_64     (0<<22)
> -#define  ADPA_CRT_HOTPLUG_PERIOD_128    (1<<22)
> -#define  ADPA_CRT_HOTPLUG_WARMUP_5MS    (0<<21)
> -#define  ADPA_CRT_HOTPLUG_WARMUP_10MS   (1<<21)
> -#define  ADPA_CRT_HOTPLUG_SAMPLE_2S     (0<<20)
> -#define  ADPA_CRT_HOTPLUG_SAMPLE_4S     (1<<20)
> -#define  ADPA_CRT_HOTPLUG_VOLTAGE_40    (0<<18)
> -#define  ADPA_CRT_HOTPLUG_VOLTAGE_50    (1<<18)
> -#define  ADPA_CRT_HOTPLUG_VOLTAGE_60    (2<<18)
> -#define  ADPA_CRT_HOTPLUG_VOLTAGE_70    (3<<18)
> -#define  ADPA_CRT_HOTPLUG_VOLREF_325MV  (0<<17)
> -#define  ADPA_CRT_HOTPLUG_VOLREF_475MV  (1<<17)
> -#define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
> -
>  /* or SDVOB */
>  #define HDMIB   0xe1140
>  #define  PORT_ENABLE    (1 << 31)
> --
> 1.7.7.6
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

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

* Re: [PATCH 02/81] drm/i915: rip out crtc prepare/commit indirection
  2012-07-11 14:27 ` [PATCH 02/81] drm/i915: rip out crtc prepare/commit indirection Daniel Vetter
@ 2012-07-12 14:44   ` Daniel Vetter
  0 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-12 14:44 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

On Wed, Jul 11, 2012 at 04:27:45PM +0200, Daniel Vetter 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 files changed, 2 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 135eed0..b1caa1b81 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3488,34 +3488,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;
> @@ -6636,13 +6608,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.7.6
> 

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

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

* [PATCH] drm/i915: simplify possible_clones computation
  2012-07-12 18:47     ` Daniel Vetter
@ 2012-07-12 18:08       ` Daniel Vetter
  2012-07-12 19:48         ` Paulo Zanoni
  0 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-12 18:08 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Intel hw only has one MUX for encoders, so outputs are either not
cloneable or all in the same group of cloneable outputs. This neatly
simplifies the code and allows us to ditch some ugly if cascades in
the dp and hdmi init code (well, we need these if cascades for other
stuff still, but that can be taken care of in follow-up patches).

Note that this changes two things:
- dvo can now be cloned with sdvo, but dvo is gen2 whereas sdvo is
  gen3+, so no problem. Note that the old code had a bug and didn't
  allow cloning crt with dvo (but only the other way round).
- sdvo-lvds can now be cloned with sdvo-non-tv. Spec says this won't
  work, but the only reason I've found is that you can't use the
  panel-fitter (used for lvds upscaling) with anything else. But we
  don't use the panel fitter for sdvo-lvds. Imo this part of Bspec is
  a) rather confusing b) mostly as a guideline to implementors (i.e.
  explicitly stating what is already implicit from the spec, without
  always going into the details of why). So I think we can ignore this
  - worst case we'll get a bug report from a user with with sdvo-lvds
  and sdvo-tmds and have to add that special case back in.

Because sdvo lvds is a bit special explain in comments why sdvo LVDS
outputs can be cloned, but native LVDS and eDP can't be cloned - we
use the panel fitter for the later, but not for sdvo.

Note that this also uncoditionally initializes the panel_vdd work used
by eDP. Trying to be clever doesn't buy us anything (but strange bugs)
and this way we can kill the is_edp check.

v2: Incorporate review from Paulo
- Add in a missing space.
- Pimp comment message to address his concerns.

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

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 9525822..c3f6680 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -690,9 +690,7 @@ void intel_crt_init(struct drm_device *dev)
 	intel_connector_attach_encoder(intel_connector, &crt->base);
 
 	crt->base.type = INTEL_OUTPUT_ANALOG;
-	crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT |
-				1 << INTEL_ANALOG_CLONE_BIT |
-				1 << INTEL_SDVO_LVDS_CLONE_BIT);
+	crt->base.cloneable = true;
 	if (IS_HASWELL(dev))
 		crt->base.crtc_mask = (1 << 0);
 	else
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1a201b2..38891ff 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6716,15 +6716,23 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
 	return 0;
 }
 
-static int intel_encoder_clones(struct drm_device *dev, int type_mask)
+static int intel_encoder_clones(struct intel_encoder *encoder)
 {
-	struct intel_encoder *encoder;
+	struct drm_device *dev = encoder->base.dev;
+	struct intel_encoder *source_encoder;
 	int index_mask = 0;
 	int entry = 0;
 
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
-		if (type_mask & encoder->clone_mask)
+	list_for_each_entry(source_encoder,
+			    &dev->mode_config.encoder_list, base.head) {
+
+		if (encoder == source_encoder)
 			index_mask |= (1 << entry);
+
+		/* Intel hw has only one MUX where enocoders could be cloned. */
+		if (encoder->cloneable && source_encoder->cloneable)
+			index_mask |= (1 << entry);
+
 		entry++;
 	}
 
@@ -6883,7 +6891,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 		encoder->base.possible_crtcs = encoder->crtc_mask;
 		encoder->base.possible_clones =
-			intel_encoder_clones(dev, encoder->clone_mask);
+			intel_encoder_clones(encoder);
 	}
 
 	/* disable all the possible outputs/crtcs before entering KMS mode */
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 3190e9d..95b1022 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2481,18 +2481,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 
-	if (output_reg == DP_B || output_reg == PCH_DP_B)
-		intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
-	else if (output_reg == DP_C || output_reg == PCH_DP_C)
-		intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
-	else if (output_reg == DP_D || output_reg == PCH_DP_D)
-		intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+	intel_encoder->cloneable = false;
 
-	if (is_edp(intel_dp)) {
-		intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
-		INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
-				  ironlake_panel_vdd_work);
-	}
+	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
+			  ironlake_panel_vdd_work);
 
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 16680e5..f8c1f04 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -89,25 +89,6 @@
 #define INTEL_OUTPUT_DISPLAYPORT 7
 #define INTEL_OUTPUT_EDP 8
 
-/* Intel Pipe Clone Bit */
-#define INTEL_HDMIB_CLONE_BIT 1
-#define INTEL_HDMIC_CLONE_BIT 2
-#define INTEL_HDMID_CLONE_BIT 3
-#define INTEL_HDMIE_CLONE_BIT 4
-#define INTEL_HDMIF_CLONE_BIT 5
-#define INTEL_SDVO_NON_TV_CLONE_BIT 6
-#define INTEL_SDVO_TV_CLONE_BIT 7
-#define INTEL_SDVO_LVDS_CLONE_BIT 8
-#define INTEL_ANALOG_CLONE_BIT 9
-#define INTEL_TV_CLONE_BIT 10
-#define INTEL_DP_B_CLONE_BIT 11
-#define INTEL_DP_C_CLONE_BIT 12
-#define INTEL_DP_D_CLONE_BIT 13
-#define INTEL_LVDS_CLONE_BIT 14
-#define INTEL_DVO_TMDS_CLONE_BIT 15
-#define INTEL_DVO_LVDS_CLONE_BIT 16
-#define INTEL_EDP_CLONE_BIT 17
-
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
 #define INTEL_DVO_CHIP_TMDS 2
@@ -153,11 +134,15 @@ struct intel_encoder {
 	int type;
 	bool needs_tv_clock;
 	bool connectors_active;
+	/*
+	 * Intel hw has only one MUX where encoders could be clone, hence a
+	 * simple flag is enough to compute the possible_clones mask.
+	 */
+	bool cloneable;
 	void (*hot_plug)(struct intel_encoder *);
 	void (*enable)(struct intel_encoder *);
 	void (*disable)(struct intel_encoder *);
 	int crtc_mask;
-	int clone_mask;
 };
 
 struct intel_connector {
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 756e977..86a3d2b 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -424,17 +424,14 @@ void intel_dvo_init(struct drm_device *dev)
 		intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
 		switch (dvo->type) {
 		case INTEL_DVO_CHIP_TMDS:
-			intel_encoder->clone_mask =
-				(1 << INTEL_DVO_TMDS_CLONE_BIT) |
-				(1 << INTEL_ANALOG_CLONE_BIT);
+			intel_encoder->cloneable = true;
 			drm_connector_init(dev, connector,
 					   &intel_dvo_connector_funcs,
 					   DRM_MODE_CONNECTOR_DVII);
 			encoder_type = DRM_MODE_ENCODER_TMDS;
 			break;
 		case INTEL_DVO_CHIP_LVDS:
-			intel_encoder->clone_mask =
-				(1 << INTEL_DVO_LVDS_CLONE_BIT);
+			intel_encoder->cloneable = false;
 			drm_connector_init(dev, connector,
 					   &intel_dvo_connector_funcs,
 					   DRM_MODE_CONNECTOR_LVDS);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 188399f..b01900d 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -959,42 +959,36 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 	connector->doublescan_allowed = 0;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
+	intel_encoder->cloneable = false;
+
 	/* Set up the DDC bus. */
 	if (sdvox_reg == SDVOB) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == SDVOC) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMIB) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMIC) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == HDMID) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
 		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == DDI_BUF_CTL(PORT_B)) {
 		DRM_DEBUG_DRIVER("LPT: detected output on DDI B\n");
-		intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
 		intel_hdmi->ddi_port = PORT_B;
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == DDI_BUF_CTL(PORT_C)) {
 		DRM_DEBUG_DRIVER("LPT: detected output on DDI C\n");
-		intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
 		intel_hdmi->ddi_port = PORT_C;
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
 	} else if (sdvox_reg == DDI_BUF_CTL(PORT_D)) {
 		DRM_DEBUG_DRIVER("LPT: detected output on DDI D\n");
-		intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
 		intel_hdmi->ddi_port = PORT_D;
 		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index f1d0a05..1e879bf 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -943,7 +943,7 @@ bool intel_lvds_init(struct drm_device *dev)
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_LVDS;
 
-	intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
+	intel_encoder->cloneable = false;
 	if (HAS_PCH_SPLIT(dev))
 		intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 	else if (IS_GEN4(dev))
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index d630db8..467d92a 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2129,8 +2129,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 		connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
 		intel_sdvo->is_hdmi = true;
 	}
-	intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
-				       (1 << INTEL_ANALOG_CLONE_BIT));
+	intel_sdvo->base.cloneable = true;
 
 	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 	if (intel_sdvo->is_hdmi)
@@ -2161,7 +2160,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
 
 	intel_sdvo->is_tv = true;
 	intel_sdvo->base.needs_tv_clock = true;
-	intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
+	intel_sdvo->base.cloneable = false;
 
 	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 
@@ -2204,8 +2203,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
 	}
 
-	intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
-				       (1 << INTEL_ANALOG_CLONE_BIT));
+	intel_sdvo->base.cloneable = true;
 
 	intel_sdvo_connector_init(intel_sdvo_connector,
 				  intel_sdvo);
@@ -2237,8 +2235,10 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
 	}
 
-	intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) |
-				       (1 << INTEL_SDVO_LVDS_CLONE_BIT));
+	/* SDVO LVDS is cloneable because the SDVO encoder does the upscaling,
+	 * as opposed to native LVDS, where we upscale with the panel-fitter
+	 * (and hence only the native LVDS resolution could be cloned). */
+	intel_sdvo->base.cloneable = true;
 
 	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index a0ec1eb..ef9e7a5 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1624,7 +1624,7 @@ intel_tv_init(struct drm_device *dev)
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_TVOUT;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
-	intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
+	intel_encoder->cloneable = false;
 	intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
 	intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
 	intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
-- 
1.7.7.6

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

* Re: [PATCH 19/81] drm/i915: simplify possible_clones computation
  2012-07-11 14:28 ` [PATCH 19/81] drm/i915: simplify possible_clones computation Daniel Vetter
@ 2012-07-12 18:10   ` Paulo Zanoni
  2012-07-12 18:47     ` Daniel Vetter
  0 siblings, 1 reply; 107+ messages in thread
From: Paulo Zanoni @ 2012-07-12 18:10 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

Hi

I like your idea.

2012/7/11 Daniel Vetter <daniel.vetter@ffwll.ch>:
> Intel hw only has one MUX for encoders, so outputs are either not
> cloneable or all in the same group of cloneable outputs.

I don't agree with this sentence... Our documentation contains
sections called "Simultaneous Display Capabilities on a Single Display
Pipe/Transcoder" describing the details and what/how/who/when cloning
is possible.

So in our code, before your patch, these were valid:
- CRT could be cloned with CRT, SDVO-non-tv, SDVO-lvds
- DVO-tmds could be cloned with CRT, DVO-tmds  (notice that even
though DVO-tmds can be cloned with CRT, CRT can't be cloned with
DVO-tmds! bug!)
- SDVO-non-tv could be cloned with CRT and SDVO-non-tv
- SDVO-lvds could be cloned with CRT, SDVO-lvds

After your patch, all these can be cloned with each other:
- CRT, DVO-tmds, SDVO-non-tv, SDVO-lvds

Things that were previously not possible and now are possible:

- SDVO-non-tv with SDVO-lvds
- DVO-tmds with SDVO-non-tv (does hardware with both DVO and SDVO exist?)
- DVO-tmds with SDVO-lvds (same question)

Maybe we should find a way to move all this code to inside
intel_encoder_clones directly? Or keep your patch just like it is, but
add a check inside intel_encoder_clones preventing SDVO-non-tv with
SDVO-lvds?


> This neatly
> simplifies the code and allows us to ditch some ugly if cascades in
> the dp and hdmi init code (well, we need these if cascades for other
> stuff still, but that can be taken care of in follow-up patches).
>
> Also explain why sdvo LVDS outputs cannot be cloned: Native LVDS (and

I think you mean "sdvo LVDS can be cloned".



> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 3190e9d..95b1022 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2481,18 +2481,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
>
>         connector->polled = DRM_CONNECTOR_POLL_HPD;
>
> -       if (output_reg == DP_B || output_reg == PCH_DP_B)
> -               intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
> -       else if (output_reg == DP_C || output_reg == PCH_DP_C)
> -               intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
> -       else if (output_reg == DP_D || output_reg == PCH_DP_D)
> -               intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
> +       intel_encoder->cloneable = false;
>
> -       if (is_edp(intel_dp)) {
> -               intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
> -               INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
> -                                 ironlake_panel_vdd_work);
> -       }
> +       INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
> +                         ironlake_panel_vdd_work);


You removed the "if" statement... Is this correct? Even if it is
correct, move to a separate patch?


> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index d630db8..5fe044c 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -2129,8 +2129,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
>                 connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
>                 intel_sdvo->is_hdmi = true;
>         }
> -       intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
> -                                      (1 << INTEL_ANALOG_CLONE_BIT));
> +       intel_sdvo->base.cloneable= true;


Please add a white space between "cloneable" and "=".


Cheers,
Paulo

-- 
Paulo Zanoni

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

* [PATCH] drm/i915: add port parameter to intel_hdmi_init
  2012-07-11 14:28 ` [PATCH 20/81] drm/i915: add port parameter to intel_hdmi_init Daniel Vetter
@ 2012-07-12 18:19   ` Daniel Vetter
  2012-07-12 19:49     ` Paulo Zanoni
  0 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-12 18:19 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Instead of having a giant if cascade to figure this out according to
the passed-in register. We could do quite a bit more cleaning up and
all by using the port at more places, but I think this should be part
of a bigger rework to introduce a struct intel_digital_port which
would keep track of all these things. I guess this will be part of
some haswell-DP-induced refactoring.

For now this rips out the big cascade, which is what annoyed me so
much.

v2: Add port variable name back for the func decl (I've tried to trick
myself below the 80 char limit).

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

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index fd60f48..5370d17 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -250,7 +250,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 	case PORT_B:
 	case PORT_C:
 	case PORT_D:
-		intel_hdmi_init(dev, DDI_BUF_CTL(port));
+		intel_hdmi_init(dev, DDI_BUF_CTL(port), port);
 		break;
 	default:
 		DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 38891ff..3769e5f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6807,16 +6807,16 @@ static void intel_setup_outputs(struct drm_device *dev)
 			/* PCH SDVOB multiplex with HDMIB */
 			found = intel_sdvo_init(dev, PCH_SDVOB, true);
 			if (!found)
-				intel_hdmi_init(dev, HDMIB);
+				intel_hdmi_init(dev, HDMIB, PORT_B);
 			if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
 				intel_dp_init(dev, PCH_DP_B);
 		}
 
 		if (I915_READ(HDMIC) & PORT_DETECTED)
-			intel_hdmi_init(dev, HDMIC);
+			intel_hdmi_init(dev, HDMIC, PORT_C);
 
 		if (!dpd_is_edp && I915_READ(HDMID) & PORT_DETECTED)
-			intel_hdmi_init(dev, HDMID);
+			intel_hdmi_init(dev, HDMID, PORT_D);
 
 		if (I915_READ(PCH_DP_C) & DP_DETECTED)
 			intel_dp_init(dev, PCH_DP_C);
@@ -6830,13 +6830,13 @@ static void intel_setup_outputs(struct drm_device *dev)
 			/* SDVOB multiplex with HDMIB */
 			found = intel_sdvo_init(dev, SDVOB, true);
 			if (!found)
-				intel_hdmi_init(dev, SDVOB);
+				intel_hdmi_init(dev, SDVOB, PORT_B);
 			if (!found && (I915_READ(DP_B) & DP_DETECTED))
 				intel_dp_init(dev, DP_B);
 		}
 
 		if (I915_READ(SDVOC) & PORT_DETECTED)
-			intel_hdmi_init(dev, SDVOC);
+			intel_hdmi_init(dev, SDVOC, PORT_C);
 
 		/* Shares lanes with HDMI on SDVOC */
 		if (I915_READ(DP_C) & DP_DETECTED)
@@ -6849,7 +6849,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 			found = intel_sdvo_init(dev, SDVOB, true);
 			if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
 				DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
-				intel_hdmi_init(dev, SDVOB);
+				intel_hdmi_init(dev, SDVOB, PORT_B);
 			}
 
 			if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
@@ -6869,7 +6869,7 @@ static void intel_setup_outputs(struct drm_device *dev)
 
 			if (SUPPORTS_INTEGRATED_HDMI(dev)) {
 				DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
-				intel_hdmi_init(dev, SDVOC);
+				intel_hdmi_init(dev, SDVOC, PORT_C);
 			}
 			if (SUPPORTS_INTEGRATED_DP(dev)) {
 				DRM_DEBUG_KMS("probing DP_C\n");
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f8c1f04..ff78679 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -336,7 +336,8 @@ extern void intel_attach_force_audio_property(struct drm_connector *connector);
 extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
 
 extern void intel_crt_init(struct drm_device *dev);
-extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
+extern void intel_hdmi_init(struct drm_device *dev,
+			    int sdvox_reg, enum port port);
 extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
 extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
 extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index b01900d..1332367 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -925,7 +925,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
 	intel_attach_broadcast_rgb_property(connector);
 }
 
-void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
+void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_connector *connector;
@@ -961,40 +961,23 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 
 	intel_encoder->cloneable = false;
 
-	/* Set up the DDC bus. */
-	if (sdvox_reg == SDVOB) {
+	intel_hdmi->ddi_port = port;
+	switch (port) {
+	case PORT_B:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == SDVOC) {
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == HDMIB) {
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
-		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == HDMIC) {
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == HDMID) {
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
-		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == DDI_BUF_CTL(PORT_B)) {
-		DRM_DEBUG_DRIVER("LPT: detected output on DDI B\n");
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
-		intel_hdmi->ddi_port = PORT_B;
-		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == DDI_BUF_CTL(PORT_C)) {
-		DRM_DEBUG_DRIVER("LPT: detected output on DDI C\n");
+		break;
+	case PORT_C:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-		intel_hdmi->ddi_port = PORT_C;
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == DDI_BUF_CTL(PORT_D)) {
-		DRM_DEBUG_DRIVER("LPT: detected output on DDI D\n");
+		break;
+	case PORT_D:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
-		intel_hdmi->ddi_port = PORT_D;
 		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
-	} else {
-		/* If we got an unknown sdvox_reg, things are pretty much broken
-		 * in a way that we should let the kernel know about it */
+		break;
+	case PORT_A:
+		/* Internal port only for eDP. */
+	default:
 		BUG();
 	}
 
-- 
1.7.7.6

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

* Re: [PATCH 19/81] drm/i915: simplify possible_clones computation
  2012-07-12 18:10   ` Paulo Zanoni
@ 2012-07-12 18:47     ` Daniel Vetter
  2012-07-12 18:08       ` [PATCH] " Daniel Vetter
  0 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-12 18:47 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Daniel Vetter, Intel Graphics Development

On Thu, Jul 12, 2012 at 03:10:21PM -0300, Paulo Zanoni wrote:
> Hi
> 
> I like your idea.
> 
> 2012/7/11 Daniel Vetter <daniel.vetter@ffwll.ch>:
> > Intel hw only has one MUX for encoders, so outputs are either not
> > cloneable or all in the same group of cloneable outputs.
> 
> I don't agree with this sentence... Our documentation contains
> sections called "Simultaneous Display Capabilities on a Single Display
> Pipe/Transcoder" describing the details and what/how/who/when cloning
> is possible.
> 
> So in our code, before your patch, these were valid:
> - CRT could be cloned with CRT, SDVO-non-tv, SDVO-lvds
> - DVO-tmds could be cloned with CRT, DVO-tmds  (notice that even
> though DVO-tmds can be cloned with CRT, CRT can't be cloned with
> DVO-tmds! bug!)
> - SDVO-non-tv could be cloned with CRT and SDVO-non-tv
> - SDVO-lvds could be cloned with CRT, SDVO-lvds
> 
> After your patch, all these can be cloned with each other:
> - CRT, DVO-tmds, SDVO-non-tv, SDVO-lvds
> 
> Things that were previously not possible and now are possible:
> 
> - SDVO-non-tv with SDVO-lvds
> - DVO-tmds with SDVO-non-tv (does hardware with both DVO and SDVO exist?)
> - DVO-tmds with SDVO-lvds (same question)

dvo is gen2 only, sdvo is gen3+. For the SDVO-non-tv cloned with SDVO-lvds
I couldn't come up with any reason why cloning SDVO-lvds with SDVO-non-tv
wouldn't work ... After checking the docs the only case I've found as
justification why that would not work is that you can't use the panel
fitter together with anything else. Which explains why lvds can't be
cloned, but not why sdvo-lvds can't be cloned because we simply don't use
the panel fitter there (we use the lvds encoder to do the upscaling ...).

Imo this is a case where the spec is just guidance for implementers and in
the specific case of sdvo-lvds doesn't make much sense - I suspect that
the windows code also uses the panel fitter in some cases for sdvo-lvds
... or they're talking about enabling multiple outputs on the same sdvo
encoder, which again we don't support.

I think we can ignore this special case until someone whith sdvo-tmds +
sdvo-lvds files a bug report about broken clonig ...

All extend the commit message with this discussion.

> Maybe we should find a way to move all this code to inside
> intel_encoder_clones directly? Or keep your patch just like it is, but
> add a check inside intel_encoder_clones preventing SDVO-non-tv with
> SDVO-lvds?
> 
> 
> > This neatly
> > simplifies the code and allows us to ditch some ugly if cascades in
> > the dp and hdmi init code (well, we need these if cascades for other
> > stuff still, but that can be taken care of in follow-up patches).
> >
> > Also explain why sdvo LVDS outputs cannot be cloned: Native LVDS (and
> 
> I think you mean "sdvo LVDS can be cloned".

Yeah, will fix.
> 
> 
> 
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 3190e9d..95b1022 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -2481,18 +2481,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
> >
> >         connector->polled = DRM_CONNECTOR_POLL_HPD;
> >
> > -       if (output_reg == DP_B || output_reg == PCH_DP_B)
> > -               intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
> > -       else if (output_reg == DP_C || output_reg == PCH_DP_C)
> > -               intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
> > -       else if (output_reg == DP_D || output_reg == PCH_DP_D)
> > -               intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
> > +       intel_encoder->cloneable = false;
> >
> > -       if (is_edp(intel_dp)) {
> > -               intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
> > -               INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
> > -                                 ironlake_panel_vdd_work);
> > -       }
> > +       INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
> > +                         ironlake_panel_vdd_work);
> 
> 
> You removed the "if" statement... Is this correct? Even if it is
> correct, move to a separate patch?

I've figured 81 patches are enough already, and generally initializing
work items unconditionally is a good thing - we've recently broken resume
due to such an initialization bug.

> > diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> > index d630db8..5fe044c 100644
> > --- a/drivers/gpu/drm/i915/intel_sdvo.c
> > +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> > @@ -2129,8 +2129,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
> >                 connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
> >                 intel_sdvo->is_hdmi = true;
> >         }
> > -       intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
> > -                                      (1 << INTEL_ANALOG_CLONE_BIT));
> > +       intel_sdvo->base.cloneable= true;
> 
> 
> Please add a white space between "cloneable" and "=".

Will fix.

Thanks, Daniel
> 
> 
> Cheers,
> Paulo
> 
> -- 
> Paulo Zanoni

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

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

* Re: [PATCH] drm/i915: simplify possible_clones computation
  2012-07-12 18:08       ` [PATCH] " Daniel Vetter
@ 2012-07-12 19:48         ` Paulo Zanoni
  0 siblings, 0 replies; 107+ messages in thread
From: Paulo Zanoni @ 2012-07-12 19:48 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

2012/7/12 Daniel Vetter <daniel.vetter@ffwll.ch>:
> Intel hw only has one MUX for encoders, so outputs are either not
> cloneable or all in the same group of cloneable outputs. This neatly
> simplifies the code and allows us to ditch some ugly if cascades in
> the dp and hdmi init code (well, we need these if cascades for other
> stuff still, but that can be taken care of in follow-up patches).
>
> Note that this changes two things:
> - dvo can now be cloned with sdvo, but dvo is gen2 whereas sdvo is
>   gen3+, so no problem. Note that the old code had a bug and didn't
>   allow cloning crt with dvo (but only the other way round).
> - sdvo-lvds can now be cloned with sdvo-non-tv. Spec says this won't
>   work, but the only reason I've found is that you can't use the
>   panel-fitter (used for lvds upscaling) with anything else. But we
>   don't use the panel fitter for sdvo-lvds. Imo this part of Bspec is
>   a) rather confusing b) mostly as a guideline to implementors (i.e.
>   explicitly stating what is already implicit from the spec, without
>   always going into the details of why). So I think we can ignore this
>   - worst case we'll get a bug report from a user with with sdvo-lvds
>   and sdvo-tmds and have to add that special case back in.
>
> Because sdvo lvds is a bit special explain in comments why sdvo LVDS
> outputs can be cloned, but native LVDS and eDP can't be cloned - we
> use the panel fitter for the later, but not for sdvo.
>
> Note that this also uncoditionally initializes the panel_vdd work used
> by eDP. Trying to be clever doesn't buy us anything (but strange bugs)
> and this way we can kill the is_edp check.
>
> v2: Incorporate review from Paulo
> - Add in a missing space.
> - Pimp comment message to address his concerns.
>
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

If you try to commit this to dinq you'll get a conflict on
intel_drv.h. This is easy to fix, so you can keep the R-B after that
:)

> ---
>  drivers/gpu/drm/i915/intel_crt.c     |    4 +---
>  drivers/gpu/drm/i915/intel_display.c |   18 +++++++++++++-----
>  drivers/gpu/drm/i915/intel_dp.c      |   14 +++-----------
>  drivers/gpu/drm/i915/intel_drv.h     |   25 +++++--------------------
>  drivers/gpu/drm/i915/intel_dvo.c     |    7 ++-----
>  drivers/gpu/drm/i915/intel_hdmi.c    |   10 ++--------
>  drivers/gpu/drm/i915/intel_lvds.c    |    2 +-
>  drivers/gpu/drm/i915/intel_sdvo.c    |   14 +++++++-------
>  drivers/gpu/drm/i915/intel_tv.c      |    2 +-
>  9 files changed, 35 insertions(+), 61 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index 9525822..c3f6680 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -690,9 +690,7 @@ void intel_crt_init(struct drm_device *dev)
>         intel_connector_attach_encoder(intel_connector, &crt->base);
>
>         crt->base.type = INTEL_OUTPUT_ANALOG;
> -       crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT |
> -                               1 << INTEL_ANALOG_CLONE_BIT |
> -                               1 << INTEL_SDVO_LVDS_CLONE_BIT);
> +       crt->base.cloneable = true;
>         if (IS_HASWELL(dev))
>                 crt->base.crtc_mask = (1 << 0);
>         else
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 1a201b2..38891ff 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6716,15 +6716,23 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
>         return 0;
>  }
>
> -static int intel_encoder_clones(struct drm_device *dev, int type_mask)
> +static int intel_encoder_clones(struct intel_encoder *encoder)
>  {
> -       struct intel_encoder *encoder;
> +       struct drm_device *dev = encoder->base.dev;
> +       struct intel_encoder *source_encoder;
>         int index_mask = 0;
>         int entry = 0;
>
> -       list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
> -               if (type_mask & encoder->clone_mask)
> +       list_for_each_entry(source_encoder,
> +                           &dev->mode_config.encoder_list, base.head) {
> +
> +               if (encoder == source_encoder)
>                         index_mask |= (1 << entry);
> +
> +               /* Intel hw has only one MUX where enocoders could be cloned. */
> +               if (encoder->cloneable && source_encoder->cloneable)
> +                       index_mask |= (1 << entry);
> +
>                 entry++;
>         }
>
> @@ -6883,7 +6891,7 @@ static void intel_setup_outputs(struct drm_device *dev)
>         list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
>                 encoder->base.possible_crtcs = encoder->crtc_mask;
>                 encoder->base.possible_clones =
> -                       intel_encoder_clones(dev, encoder->clone_mask);
> +                       intel_encoder_clones(encoder);
>         }
>
>         /* disable all the possible outputs/crtcs before entering KMS mode */
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 3190e9d..95b1022 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2481,18 +2481,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
>
>         connector->polled = DRM_CONNECTOR_POLL_HPD;
>
> -       if (output_reg == DP_B || output_reg == PCH_DP_B)
> -               intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
> -       else if (output_reg == DP_C || output_reg == PCH_DP_C)
> -               intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
> -       else if (output_reg == DP_D || output_reg == PCH_DP_D)
> -               intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
> +       intel_encoder->cloneable = false;
>
> -       if (is_edp(intel_dp)) {
> -               intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
> -               INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
> -                                 ironlake_panel_vdd_work);
> -       }
> +       INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
> +                         ironlake_panel_vdd_work);
>
>         intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 16680e5..f8c1f04 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -89,25 +89,6 @@
>  #define INTEL_OUTPUT_DISPLAYPORT 7
>  #define INTEL_OUTPUT_EDP 8
>
> -/* Intel Pipe Clone Bit */
> -#define INTEL_HDMIB_CLONE_BIT 1
> -#define INTEL_HDMIC_CLONE_BIT 2
> -#define INTEL_HDMID_CLONE_BIT 3
> -#define INTEL_HDMIE_CLONE_BIT 4
> -#define INTEL_HDMIF_CLONE_BIT 5
> -#define INTEL_SDVO_NON_TV_CLONE_BIT 6
> -#define INTEL_SDVO_TV_CLONE_BIT 7
> -#define INTEL_SDVO_LVDS_CLONE_BIT 8
> -#define INTEL_ANALOG_CLONE_BIT 9
> -#define INTEL_TV_CLONE_BIT 10
> -#define INTEL_DP_B_CLONE_BIT 11
> -#define INTEL_DP_C_CLONE_BIT 12
> -#define INTEL_DP_D_CLONE_BIT 13
> -#define INTEL_LVDS_CLONE_BIT 14
> -#define INTEL_DVO_TMDS_CLONE_BIT 15
> -#define INTEL_DVO_LVDS_CLONE_BIT 16
> -#define INTEL_EDP_CLONE_BIT 17
> -
>  #define INTEL_DVO_CHIP_NONE 0
>  #define INTEL_DVO_CHIP_LVDS 1
>  #define INTEL_DVO_CHIP_TMDS 2
> @@ -153,11 +134,15 @@ struct intel_encoder {
>         int type;
>         bool needs_tv_clock;
>         bool connectors_active;
> +       /*
> +        * Intel hw has only one MUX where encoders could be clone, hence a
> +        * simple flag is enough to compute the possible_clones mask.
> +        */
> +       bool cloneable;
>         void (*hot_plug)(struct intel_encoder *);
>         void (*enable)(struct intel_encoder *);
>         void (*disable)(struct intel_encoder *);
>         int crtc_mask;
> -       int clone_mask;
>  };
>
>  struct intel_connector {
> diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
> index 756e977..86a3d2b 100644
> --- a/drivers/gpu/drm/i915/intel_dvo.c
> +++ b/drivers/gpu/drm/i915/intel_dvo.c
> @@ -424,17 +424,14 @@ void intel_dvo_init(struct drm_device *dev)
>                 intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
>                 switch (dvo->type) {
>                 case INTEL_DVO_CHIP_TMDS:
> -                       intel_encoder->clone_mask =
> -                               (1 << INTEL_DVO_TMDS_CLONE_BIT) |
> -                               (1 << INTEL_ANALOG_CLONE_BIT);
> +                       intel_encoder->cloneable = true;
>                         drm_connector_init(dev, connector,
>                                            &intel_dvo_connector_funcs,
>                                            DRM_MODE_CONNECTOR_DVII);
>                         encoder_type = DRM_MODE_ENCODER_TMDS;
>                         break;
>                 case INTEL_DVO_CHIP_LVDS:
> -                       intel_encoder->clone_mask =
> -                               (1 << INTEL_DVO_LVDS_CLONE_BIT);
> +                       intel_encoder->cloneable = false;
>                         drm_connector_init(dev, connector,
>                                            &intel_dvo_connector_funcs,
>                                            DRM_MODE_CONNECTOR_LVDS);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 188399f..b01900d 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -959,42 +959,36 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
>         connector->doublescan_allowed = 0;
>         intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
>
> +       intel_encoder->cloneable = false;
> +
>         /* Set up the DDC bus. */
>         if (sdvox_reg == SDVOB) {
> -               intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
>                 dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
>         } else if (sdvox_reg == SDVOC) {
> -               intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
>                 dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
>         } else if (sdvox_reg == HDMIB) {
> -               intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
>                 dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
>         } else if (sdvox_reg == HDMIC) {
> -               intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
>                 dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
>         } else if (sdvox_reg == HDMID) {
> -               intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
>                 dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
>         } else if (sdvox_reg == DDI_BUF_CTL(PORT_B)) {
>                 DRM_DEBUG_DRIVER("LPT: detected output on DDI B\n");
> -               intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
>                 intel_hdmi->ddi_port = PORT_B;
>                 dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
>         } else if (sdvox_reg == DDI_BUF_CTL(PORT_C)) {
>                 DRM_DEBUG_DRIVER("LPT: detected output on DDI C\n");
> -               intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
>                 intel_hdmi->ddi_port = PORT_C;
>                 dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
>         } else if (sdvox_reg == DDI_BUF_CTL(PORT_D)) {
>                 DRM_DEBUG_DRIVER("LPT: detected output on DDI D\n");
> -               intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
>                 intel_hdmi->ddi_port = PORT_D;
>                 dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
> diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
> index f1d0a05..1e879bf 100644
> --- a/drivers/gpu/drm/i915/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/intel_lvds.c
> @@ -943,7 +943,7 @@ bool intel_lvds_init(struct drm_device *dev)
>         intel_connector_attach_encoder(intel_connector, intel_encoder);
>         intel_encoder->type = INTEL_OUTPUT_LVDS;
>
> -       intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
> +       intel_encoder->cloneable = false;
>         if (HAS_PCH_SPLIT(dev))
>                 intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
>         else if (IS_GEN4(dev))
> diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
> index d630db8..467d92a 100644
> --- a/drivers/gpu/drm/i915/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/intel_sdvo.c
> @@ -2129,8 +2129,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
>                 connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
>                 intel_sdvo->is_hdmi = true;
>         }
> -       intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
> -                                      (1 << INTEL_ANALOG_CLONE_BIT));
> +       intel_sdvo->base.cloneable = true;
>
>         intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
>         if (intel_sdvo->is_hdmi)
> @@ -2161,7 +2160,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
>
>         intel_sdvo->is_tv = true;
>         intel_sdvo->base.needs_tv_clock = true;
> -       intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
> +       intel_sdvo->base.cloneable = false;
>
>         intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
>
> @@ -2204,8 +2203,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
>                 intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
>         }
>
> -       intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
> -                                      (1 << INTEL_ANALOG_CLONE_BIT));
> +       intel_sdvo->base.cloneable = true;
>
>         intel_sdvo_connector_init(intel_sdvo_connector,
>                                   intel_sdvo);
> @@ -2237,8 +2235,10 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
>                 intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
>         }
>
> -       intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) |
> -                                      (1 << INTEL_SDVO_LVDS_CLONE_BIT));
> +       /* SDVO LVDS is cloneable because the SDVO encoder does the upscaling,
> +        * as opposed to native LVDS, where we upscale with the panel-fitter
> +        * (and hence only the native LVDS resolution could be cloned). */
> +       intel_sdvo->base.cloneable = true;
>
>         intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
>         if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
> diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
> index a0ec1eb..ef9e7a5 100644
> --- a/drivers/gpu/drm/i915/intel_tv.c
> +++ b/drivers/gpu/drm/i915/intel_tv.c
> @@ -1624,7 +1624,7 @@ intel_tv_init(struct drm_device *dev)
>         intel_connector_attach_encoder(intel_connector, intel_encoder);
>         intel_encoder->type = INTEL_OUTPUT_TVOUT;
>         intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
> -       intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
> +       intel_encoder->cloneable = false;
>         intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
>         intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
>         intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
> --
> 1.7.7.6
>



-- 
Paulo Zanoni

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

* Re: [PATCH] drm/i915: add port parameter to intel_hdmi_init
  2012-07-12 18:19   ` [PATCH] " Daniel Vetter
@ 2012-07-12 19:49     ` Paulo Zanoni
  2012-07-17  8:43       ` Daniel Vetter
  0 siblings, 1 reply; 107+ messages in thread
From: Paulo Zanoni @ 2012-07-12 19:49 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

2012/7/12 Daniel Vetter <daniel.vetter@ffwll.ch>:
> Instead of having a giant if cascade to figure this out according to
> the passed-in register. We could do quite a bit more cleaning up and
> all by using the port at more places, but I think this should be part
> of a bigger rework to introduce a struct intel_digital_port which
> would keep track of all these things. I guess this will be part of
> some haswell-DP-induced refactoring.
>
> For now this rips out the big cascade, which is what annoyed me so
> much.
>
> v2: Add port variable name back for the func decl (I've tried to trick
> myself below the 80 char limit).
>
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_ddi.c     |    2 +-
>  drivers/gpu/drm/i915/intel_display.c |   14 +++++-----
>  drivers/gpu/drm/i915/intel_drv.h     |    3 +-
>  drivers/gpu/drm/i915/intel_hdmi.c    |   41 ++++++++++------------------------
>  4 files changed, 22 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index fd60f48..5370d17 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -250,7 +250,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
>         case PORT_B:
>         case PORT_C:
>         case PORT_D:
> -               intel_hdmi_init(dev, DDI_BUF_CTL(port));
> +               intel_hdmi_init(dev, DDI_BUF_CTL(port), port);
>                 break;
>         default:
>                 DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 38891ff..3769e5f 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -6807,16 +6807,16 @@ static void intel_setup_outputs(struct drm_device *dev)
>                         /* PCH SDVOB multiplex with HDMIB */
>                         found = intel_sdvo_init(dev, PCH_SDVOB, true);
>                         if (!found)
> -                               intel_hdmi_init(dev, HDMIB);
> +                               intel_hdmi_init(dev, HDMIB, PORT_B);
>                         if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
>                                 intel_dp_init(dev, PCH_DP_B);
>                 }
>
>                 if (I915_READ(HDMIC) & PORT_DETECTED)
> -                       intel_hdmi_init(dev, HDMIC);
> +                       intel_hdmi_init(dev, HDMIC, PORT_C);
>
>                 if (!dpd_is_edp && I915_READ(HDMID) & PORT_DETECTED)
> -                       intel_hdmi_init(dev, HDMID);
> +                       intel_hdmi_init(dev, HDMID, PORT_D);
>
>                 if (I915_READ(PCH_DP_C) & DP_DETECTED)
>                         intel_dp_init(dev, PCH_DP_C);
> @@ -6830,13 +6830,13 @@ static void intel_setup_outputs(struct drm_device *dev)
>                         /* SDVOB multiplex with HDMIB */
>                         found = intel_sdvo_init(dev, SDVOB, true);
>                         if (!found)
> -                               intel_hdmi_init(dev, SDVOB);
> +                               intel_hdmi_init(dev, SDVOB, PORT_B);
>                         if (!found && (I915_READ(DP_B) & DP_DETECTED))
>                                 intel_dp_init(dev, DP_B);
>                 }
>
>                 if (I915_READ(SDVOC) & PORT_DETECTED)
> -                       intel_hdmi_init(dev, SDVOC);
> +                       intel_hdmi_init(dev, SDVOC, PORT_C);
>
>                 /* Shares lanes with HDMI on SDVOC */
>                 if (I915_READ(DP_C) & DP_DETECTED)
> @@ -6849,7 +6849,7 @@ static void intel_setup_outputs(struct drm_device *dev)
>                         found = intel_sdvo_init(dev, SDVOB, true);
>                         if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
>                                 DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
> -                               intel_hdmi_init(dev, SDVOB);
> +                               intel_hdmi_init(dev, SDVOB, PORT_B);
>                         }
>
>                         if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
> @@ -6869,7 +6869,7 @@ static void intel_setup_outputs(struct drm_device *dev)
>
>                         if (SUPPORTS_INTEGRATED_HDMI(dev)) {
>                                 DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
> -                               intel_hdmi_init(dev, SDVOC);
> +                               intel_hdmi_init(dev, SDVOC, PORT_C);
>                         }
>                         if (SUPPORTS_INTEGRATED_DP(dev)) {
>                                 DRM_DEBUG_KMS("probing DP_C\n");
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index f8c1f04..ff78679 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -336,7 +336,8 @@ extern void intel_attach_force_audio_property(struct drm_connector *connector);
>  extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
>
>  extern void intel_crt_init(struct drm_device *dev);
> -extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
> +extern void intel_hdmi_init(struct drm_device *dev,
> +                           int sdvox_reg, enum port port);
>  extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
>  extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
>  extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index b01900d..1332367 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -925,7 +925,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
>         intel_attach_broadcast_rgb_property(connector);
>  }
>
> -void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
> +void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
>  {
>         struct drm_i915_private *dev_priv = dev->dev_private;
>         struct drm_connector *connector;
> @@ -961,40 +961,23 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
>
>         intel_encoder->cloneable = false;
>
> -       /* Set up the DDC bus. */
> -       if (sdvox_reg == SDVOB) {
> +       intel_hdmi->ddi_port = port;
> +       switch (port) {
> +       case PORT_B:
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
>                 dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
> -       } else if (sdvox_reg == SDVOC) {
> -               intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
> -               dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
> -       } else if (sdvox_reg == HDMIB) {
> -               intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
> -               dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
> -       } else if (sdvox_reg == HDMIC) {
> -               intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
> -               dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
> -       } else if (sdvox_reg == HDMID) {
> -               intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
> -               dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
> -       } else if (sdvox_reg == DDI_BUF_CTL(PORT_B)) {
> -               DRM_DEBUG_DRIVER("LPT: detected output on DDI B\n");
> -               intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
> -               intel_hdmi->ddi_port = PORT_B;
> -               dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
> -       } else if (sdvox_reg == DDI_BUF_CTL(PORT_C)) {
> -               DRM_DEBUG_DRIVER("LPT: detected output on DDI C\n");
> +               break;
> +       case PORT_C:
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
> -               intel_hdmi->ddi_port = PORT_C;
>                 dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
> -       } else if (sdvox_reg == DDI_BUF_CTL(PORT_D)) {
> -               DRM_DEBUG_DRIVER("LPT: detected output on DDI D\n");
> +               break;
> +       case PORT_D:
>                 intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
> -               intel_hdmi->ddi_port = PORT_D;
>                 dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
> -       } else {
> -               /* If we got an unknown sdvox_reg, things are pretty much broken
> -                * in a way that we should let the kernel know about it */
> +               break;
> +       case PORT_A:
> +               /* Internal port only for eDP. */
> +       default:
>                 BUG();
>         }
>
> --
> 1.7.7.6
>



-- 
Paulo Zanoni

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

* Re: [PATCH 00/81] modeset rework
  2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
                   ` (80 preceding siblings ...)
  2012-07-11 14:38 ` [PATCH 81/81] drm/i915: disable the cpu edp port after the cpu pipe Daniel Vetter
@ 2012-07-15 13:13 ` Chris Wilson
  2012-07-15 14:57   ` Daniel Vetter
  81 siblings, 1 reply; 107+ messages in thread
From: Chris Wilson @ 2012-07-15 13:13 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

On Wed, 11 Jul 2012 16:27:43 +0200, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> Or: How to fix cpu edp in 81 simple steps. Admittedly this includes some minor
> detours.

Let me quickly jump in with my demands:

That modeset should detect failure and propagate that back to the user.

The modesetting code has outgrown its origins of setting a couple of
registers and be done, as we are now in the domain of fiddly link
training and end-point negotations. So it is fragile, can conceivably
fail and so the errors need to be reported rather than blindly assume
the output is now working.

So all of these nice new WARNs I'm seeing need to return error codes as
well.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 00/81] modeset rework
  2012-07-15 13:13 ` [PATCH 00/81] modeset rework Chris Wilson
@ 2012-07-15 14:57   ` Daniel Vetter
  0 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-15 14:57 UTC (permalink / raw)
  To: Chris Wilson; +Cc: Daniel Vetter, Intel Graphics Development

On Sun, Jul 15, 2012 at 02:13:41PM +0100, Chris Wilson wrote:
> On Wed, 11 Jul 2012 16:27:43 +0200, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> > Or: How to fix cpu edp in 81 simple steps. Admittedly this includes some minor
> > detours.
> 
> Let me quickly jump in with my demands:
> 
> That modeset should detect failure and propagate that back to the user.
> 
> The modesetting code has outgrown its origins of setting a couple of
> registers and be done, as we are now in the domain of fiddly link
> training and end-point negotations. So it is fragile, can conceivably
> fail and so the errors need to be reported rather than blindly assume
> the output is now working.
> 
> So all of these nice new WARNs I'm seeing need to return error codes as
> well.

Tbh failure propagation hasn't been front-and-center when I've done this
rework, but I've certainly noticed that we currenlty suck at this. Hence
nothing too coherent, but just a few thoughts:

- I think the WARNs should stay as-is. With the new code I only call them
  once the modeset has completely, or at least once our code thinks it has
  completed. Imo it's a really good tool to catch state-tracking goof-ups
  or modeset sequence ordering issues, not more. I.e. all the WARNs I've
  hit cleared indicated an issue in the code itself, and usually where the
  harbingers of this pesky permanent-black-screen-till-reboot issue.

- The current error code handling inherited from the crtc helpers is
  rather lacking, i.e. I wondered whether I should smash a quick patch on
  top of this series to make set_base interruptible. And then noticed that
  we only return a bool in set_base (and many other such places). So even
  improving this for some simple&know cases will be quite some work.

- I think we should also differentiate between the different reasons why a
  modeset can fail: From modes that the output doesn't support, failure in
  pinning the fb because the gpu died, global resource allocation issues
  (e.g. lack of pll, fdi links, ...) to the hw actually doing something
  wrong. Current set_mode ioctl is restricted to -ERRNO, but I wonder
  whether we should add something more flexible for the global modeset
  code (similar to how we already have tons of reasons to reject a mode in
  the ->mode_valid functions).

- For global resource allocation and reservation (get_pch, pin_and_fence
  ...) I think we should move this kind of stuff out of the crtc/encoder
  callbacks into a prepare step (maybe merged together with the
  ->mode_fixup step). That way the actual modeset code should only fail if
  the hw is in a non-cooperative mood. This is also a necessary step to
  implement Jesse's idea of a modeset configuration checker. If we'd add
  some drm modeset specific error codes the mode configuration selection
  tool could even show nice tooltips on greyed-out-modes, explaning why
  the mode doesn't work (e.g. "not enough memory bandwidth", "not enough
  plls", or some generic "not enough resources" error ...). Yeah, I can
  have dreams ...

- After all that, we'd be left with with the true hw issues like link
  training failures or stuck pipes. Judging by bug reports and own
  experience, once we're in such a state, we're stuck in such a state and
  re-doing the modeset doesn't help too much. We already try to restore
  the old mode, but if that also fails I'm not too sure what userspace
  should do with the resulting -EIO.

At least for the short-term I think that our modeset code will profits the
most if we exploit the simplified state machine of the new code and cut
down on the statespace we're handling in the code. Like this patch series
already does for DP. Also, all these WARNs should help in improving our
modeset experience indirectly, through more bug reports and their fixes
;-)

Long term I agree that we need robuster error handling, but I think
handling of hw error should be about the last item: Ime we tend to keep on
flailing once we start, and I expect the pay-off in code quality and
robustness of the previous items to be better. In any case, this is all
stuff that should sit on top of this modeset rework.

Cc'ing Ville, maybe he has some further ideas from his global modeset
work.

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

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

* Re: [PATCH] drm/i915: add port parameter to intel_hdmi_init
  2012-07-12 19:49     ` Paulo Zanoni
@ 2012-07-17  8:43       ` Daniel Vetter
  0 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-17  8:43 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Daniel Vetter, Intel Graphics Development

On Thu, Jul 12, 2012 at 04:49:34PM -0300, Paulo Zanoni wrote:
> 2012/7/12 Daniel Vetter <daniel.vetter@ffwll.ch>:
> > Instead of having a giant if cascade to figure this out according to
> > the passed-in register. We could do quite a bit more cleaning up and
> > all by using the port at more places, but I think this should be part
> > of a bigger rework to introduce a struct intel_digital_port which
> > would keep track of all these things. I guess this will be part of
> > some haswell-DP-induced refactoring.
> >
> > For now this rips out the big cascade, which is what annoyed me so
> > much.
> >
> > v2: Add port variable name back for the func decl (I've tried to trick
> > myself below the 80 char limit).
> >
> > Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>

I've merged the three patches you've reviewed already to dinq (with the
comment in patch 13 fixed up), thanks for the review.
-Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

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

* Re: [PATCH 24/81] drm/fb helper: don't call drm_crtc_helper_set_config
  2012-07-11 14:28 ` [PATCH 24/81] drm/fb helper: don't call drm_crtc_helper_set_config Daniel Vetter
@ 2012-07-18 15:49   ` Daniel Vetter
  2012-07-18 15:50     ` Daniel Vetter
  0 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-18 15:49 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter, dri-devel

Hi Dave,

Can you please pick this one up for -next? There are a few other issues
where the fb helper is a bit too intimate with the crtc helper (i.e. it
depends upon callbacks and behaviour only provided when using the crtc
helpers). But this one here is the only one I can't work around in i915.ko
and hence would block merging the modeset rewrite for 3.7.

I've put a todo down to untangle the fb helper a bit better from the crtc
helper, but that's for a later patch series.

Yours, Daneil

PS: Can you also pick up the other drm patch in this series? That unused
list_head confused me quite a bit until I've noticed that it's ... unused.

On Wed, Jul 11, 2012 at 04:28:07PM +0200, Daniel Vetter wrote:
> Go through the interface vtable instead, because not everyone might be
> using the crtc helper code.
> 
> Cc: dri-devel@lists.freedesktop.org
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
>  drivers/gpu/drm/drm_fb_helper.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 5683b7f..bf97c0a 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -228,7 +228,7 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
>  	int i, ret;
>  	for (i = 0; i < fb_helper->crtc_count; i++) {
>  		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
> -		ret = drm_crtc_helper_set_config(mode_set);
> +		ret = mode_set->crtc->funcs->set_config(mode_set);
>  		if (ret)
>  			error = true;
>  	}
> -- 
> 1.7.7.6
> 

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

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

* Re: [PATCH 24/81] drm/fb helper: don't call drm_crtc_helper_set_config
  2012-07-18 15:49   ` Daniel Vetter
@ 2012-07-18 15:50     ` Daniel Vetter
  2012-07-20  1:17       ` Dave Airlie
  0 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-18 15:50 UTC (permalink / raw)
  To: Intel Graphics Development, Dave Airlie; +Cc: Daniel Vetter, dri-devel

Actually including Dave on the recipient list might work bettter ;-)

On Wed, Jul 18, 2012 at 05:49:22PM +0200, Daniel Vetter wrote:
> Hi Dave,
> 
> Can you please pick this one up for -next? There are a few other issues
> where the fb helper is a bit too intimate with the crtc helper (i.e. it
> depends upon callbacks and behaviour only provided when using the crtc
> helpers). But this one here is the only one I can't work around in i915.ko
> and hence would block merging the modeset rewrite for 3.7.
> 
> I've put a todo down to untangle the fb helper a bit better from the crtc
> helper, but that's for a later patch series.
> 
> Yours, Daneil
> 
> PS: Can you also pick up the other drm patch in this series? That unused
> list_head confused me quite a bit until I've noticed that it's ... unused.
> 
> On Wed, Jul 11, 2012 at 04:28:07PM +0200, Daniel Vetter wrote:
> > Go through the interface vtable instead, because not everyone might be
> > using the crtc helper code.
> > 
> > Cc: dri-devel@lists.freedesktop.org
> > Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > ---
> >  drivers/gpu/drm/drm_fb_helper.c |    2 +-
> >  1 files changed, 1 insertions(+), 1 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> > index 5683b7f..bf97c0a 100644
> > --- a/drivers/gpu/drm/drm_fb_helper.c
> > +++ b/drivers/gpu/drm/drm_fb_helper.c
> > @@ -228,7 +228,7 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
> >  	int i, ret;
> >  	for (i = 0; i < fb_helper->crtc_count; i++) {
> >  		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
> > -		ret = drm_crtc_helper_set_config(mode_set);
> > +		ret = mode_set->crtc->funcs->set_config(mode_set);
> >  		if (ret)
> >  			error = true;
> >  	}
> > -- 
> > 1.7.7.6
> > 
> 
> -- 
> Daniel Vetter
> Mail: daniel@ffwll.ch
> Mobile: +41 (0)79 365 57 48

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

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

* Re: [PATCH 24/81] drm/fb helper: don't call drm_crtc_helper_set_config
  2012-07-18 15:50     ` Daniel Vetter
@ 2012-07-20  1:17       ` Dave Airlie
  0 siblings, 0 replies; 107+ messages in thread
From: Dave Airlie @ 2012-07-20  1:17 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, Intel Graphics Development, dri-devel

On Thu, Jul 19, 2012 at 1:50 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> Actually including Dave on the recipient list might work bettter ;-)
>
> On Wed, Jul 18, 2012 at 05:49:22PM +0200, Daniel Vetter wrote:
>> Hi Dave,
>>
>> Can you please pick this one up for -next? There are a few other issues
>> where the fb helper is a bit too intimate with the crtc helper (i.e. it
>> depends upon callbacks and behaviour only provided when using the crtc
>> helpers). But this one here is the only one I can't work around in i915.ko
>> and hence would block merging the modeset rewrite for 3.7.
>>
>> I've put a todo down to untangle the fb helper a bit better from the crtc
>> helper, but that's for a later patch series.
>>
>> Yours, Daneil
>>
>> PS: Can you also pick up the other drm patch in this series? That unused
>> list_head confused me quite a bit until I've noticed that it's ... unused.
>>
Merged.

Thanks.
Dave.

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

* Re: [PATCH 25/81] drm: remove the list_head from drm_mode_set
  2012-07-11 14:28 ` [PATCH 25/81] drm: remove the list_head from drm_mode_set Daniel Vetter
@ 2012-07-20  1:23   ` Dave Airlie
  0 siblings, 0 replies; 107+ messages in thread
From: Dave Airlie @ 2012-07-20  1:23 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development, dri-devel

On Thu, Jul 12, 2012 at 12:28 AM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> It's unused. At it confused me quite a bit until I've discovered that.

Applied thanks,
Dave.

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

* Re: [PATCH 14/81] drm/i915: add inte_crt->adpa_reg
  2012-07-11 14:27 ` [PATCH 14/81] drm/i915: add inte_crt->adpa_reg Daniel Vetter
@ 2012-07-20 11:56   ` Chris Wilson
  2012-07-20 12:09   ` Daniel Vetter
  1 sibling, 0 replies; 107+ messages in thread
From: Chris Wilson @ 2012-07-20 11:56 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

Just fixup the patch title: s/inte_crt/intel_crtl/

On Wed, 11 Jul 2012 16:27:57 +0200, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> With the base addresses shifting around, this is easier to handle.
> Also move to the real reg offset on vlv.

+1
 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Acked-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

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

* Re: [PATCH 12/81] drm/i915: create VLV_DSIPLAY_BASE #define
  2012-07-11 14:27 ` [PATCH 12/81] drm/i915: create VLV_DSIPLAY_BASE #define Daniel Vetter
@ 2012-07-20 12:07   ` Daniel Vetter
  0 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-20 12:07 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

On Wed, Jul 11, 2012 at 04:27:55PM +0200, Daniel Vetter wrote:
> Will be used more in the next patch.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Jesse's not around to ack this and Paulo punted. So I've just merged this.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_drv.c |    2 +-
>  drivers/gpu/drm/i915/i915_reg.h |    2 ++
>  2 files changed, 3 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index e754cdf..116670e 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1032,7 +1032,7 @@ static bool IS_DISPLAYREG(u32 reg)
>  	 * This should make it easier to transition modules over to the
>  	 * new register block scheme, since we can do it incrementally.
>  	 */
> -	if (reg >= 0x180000)
> +	if (reg >= VLV_DISPLAY_BASE)
>  		return false;
>  
>  	if (reg >= RENDER_RING_BASE &&
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index cc82871..e982900 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -528,6 +528,8 @@
>  #define   GFX_PSMI_GRANULARITY		(1<<10)
>  #define   GFX_PPGTT_ENABLE		(1<<9)
>  
> +#define VLV_DISPLAY_BASE 0x180000
> +
>  #define SCPD0		0x0209c /* 915+ only */
>  #define IER		0x020a0
>  #define IIR		0x020a4
> -- 
> 1.7.7.6
> 

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

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

* Re: [PATCH 14/81] drm/i915: add inte_crt->adpa_reg
  2012-07-11 14:27 ` [PATCH 14/81] drm/i915: add inte_crt->adpa_reg Daniel Vetter
  2012-07-20 11:56   ` Chris Wilson
@ 2012-07-20 12:09   ` Daniel Vetter
  1 sibling, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-20 12:09 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Daniel Vetter

On Wed, Jul 11, 2012 at 04:27:57PM +0200, Daniel Vetter wrote:
> With the base addresses shifting around, this is easier to handle.
> Also move to the real reg offset on vlv.
> 
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
I've merged this for -next with Chris' irc-ack.
-Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

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

* Re: [PATCH 09/81] drm/i915/lvds: ditch ->prepare special case
  2012-07-11 14:27 ` [PATCH 09/81] drm/i915/lvds: ditch ->prepare special case Daniel Vetter
@ 2012-07-22 14:52   ` Daniel Vetter
  2012-07-22 16:32     ` Takashi Iwai
  0 siblings, 1 reply; 107+ messages in thread
From: Daniel Vetter @ 2012-07-22 14:52 UTC (permalink / raw)
  To: Intel Graphics Development; +Cc: Takashi Iwai, Daniel Vetter

On Wed, Jul 11, 2012 at 04:27:52PM +0200, Daniel Vetter wrote:
> LVDS is the first output where dpms on/off and prepare/commit don't
> perfectly match. Now the idea behind this special case seems to be
> that for simple resolution changes on the LVDS we don't need to stop
> the pipe, because (at least on newer chips) we can adjust the panel
> fitter on the fly.
> 
> There are a few problems with the current code though:
> - We still stop and restart the pipe unconditionally, because the crtc
>   helper code isn't flexible enough.
> - We show some ugly flickering, especially when changing crtcs (this
>   the crtc helper would actually take into account, but we don't
>   implement the encoder->get_crtc callback required to make this work
>   properly).
> 
> So it doesn't even work as advertised. I agree that it would be nice
> to do resolution changes on LVDS (and also eDP) whithout blacking the
> screen where the panel fitter allows to do that. But imo we should
> implement this as a special case a few layers up in the mode set code,
> akin to how we already detect simple framebuffer changes (and only
> update the required registers with ->mode_set_base).
> 
> Until this is all in place, make our lives easier and just rip it out.
> 
> Also note that this seems to fix actual bugs with enabling the lvds
> output, see:
> 
> http://lists.freedesktop.org/archives/intel-gfx/2012-July/018614.html
> 
> Cc: Takashi Iwai <tiwai@suse.de>
> Cc: Giacomo Comes <comes@naic.edu>
> Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

I've merged this with Chris' irc-ack (under the condition that the
modeset-rework leads to reinstated lvds fastpath that actually works
eventually). I've stalled a bit for tested-bys from Takashi, but he seems
to be awol atm.
-Daniel
-- 
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48

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

* Re: [PATCH 09/81] drm/i915/lvds: ditch ->prepare special case
  2012-07-22 14:52   ` Daniel Vetter
@ 2012-07-22 16:32     ` Takashi Iwai
  2012-07-22 19:20       ` Daniel Vetter
  0 siblings, 1 reply; 107+ messages in thread
From: Takashi Iwai @ 2012-07-22 16:32 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, Intel Graphics Development

At Sun, 22 Jul 2012 16:52:54 +0200,
Daniel Vetter wrote:
> 
> On Wed, Jul 11, 2012 at 04:27:52PM +0200, Daniel Vetter wrote:
> > LVDS is the first output where dpms on/off and prepare/commit don't
> > perfectly match. Now the idea behind this special case seems to be
> > that for simple resolution changes on the LVDS we don't need to stop
> > the pipe, because (at least on newer chips) we can adjust the panel
> > fitter on the fly.
> > 
> > There are a few problems with the current code though:
> > - We still stop and restart the pipe unconditionally, because the crtc
> >   helper code isn't flexible enough.
> > - We show some ugly flickering, especially when changing crtcs (this
> >   the crtc helper would actually take into account, but we don't
> >   implement the encoder->get_crtc callback required to make this work
> >   properly).
> > 
> > So it doesn't even work as advertised. I agree that it would be nice
> > to do resolution changes on LVDS (and also eDP) whithout blacking the
> > screen where the panel fitter allows to do that. But imo we should
> > implement this as a special case a few layers up in the mode set code,
> > akin to how we already detect simple framebuffer changes (and only
> > update the required registers with ->mode_set_base).
> > 
> > Until this is all in place, make our lives easier and just rip it out.
> > 
> > Also note that this seems to fix actual bugs with enabling the lvds
> > output, see:
> > 
> > http://lists.freedesktop.org/archives/intel-gfx/2012-July/018614.html
> > 
> > Cc: Takashi Iwai <tiwai@suse.de>
> > Cc: Giacomo Comes <comes@naic.edu>
> > Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> 
> I've merged this with Chris' irc-ack (under the condition that the
> modeset-rework leads to reinstated lvds fastpath that actually works
> eventually). I've stalled a bit for tested-bys from Takashi, but he seems
> to be awol atm.

Sorry, I was too busy for other tasks after vacation.
Tested on a few machines and it worked as expected.

Tested-by: Takashi Iwai <tiwai@suse.de>


Takashi

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

* Re: [PATCH 09/81] drm/i915/lvds: ditch ->prepare special case
  2012-07-22 16:32     ` Takashi Iwai
@ 2012-07-22 19:20       ` Daniel Vetter
  0 siblings, 0 replies; 107+ messages in thread
From: Daniel Vetter @ 2012-07-22 19:20 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Intel Graphics Development

On Sun, Jul 22, 2012 at 6:32 PM, Takashi Iwai <tiwai@suse.de> wrote:
> At Sun, 22 Jul 2012 16:52:54 +0200,
> Daniel Vetter wrote:
>>
>> On Wed, Jul 11, 2012 at 04:27:52PM +0200, Daniel Vetter wrote:
>> > LVDS is the first output where dpms on/off and prepare/commit don't
>> > perfectly match. Now the idea behind this special case seems to be
>> > that for simple resolution changes on the LVDS we don't need to stop
>> > the pipe, because (at least on newer chips) we can adjust the panel
>> > fitter on the fly.
>> >
>> > There are a few problems with the current code though:
>> > - We still stop and restart the pipe unconditionally, because the crtc
>> >   helper code isn't flexible enough.
>> > - We show some ugly flickering, especially when changing crtcs (this
>> >   the crtc helper would actually take into account, but we don't
>> >   implement the encoder->get_crtc callback required to make this work
>> >   properly).
>> >
>> > So it doesn't even work as advertised. I agree that it would be nice
>> > to do resolution changes on LVDS (and also eDP) whithout blacking the
>> > screen where the panel fitter allows to do that. But imo we should
>> > implement this as a special case a few layers up in the mode set code,
>> > akin to how we already detect simple framebuffer changes (and only
>> > update the required registers with ->mode_set_base).
>> >
>> > Until this is all in place, make our lives easier and just rip it out.
>> >
>> > Also note that this seems to fix actual bugs with enabling the lvds
>> > output, see:
>> >
>> > http://lists.freedesktop.org/archives/intel-gfx/2012-July/018614.html
>> >
>> > Cc: Takashi Iwai <tiwai@suse.de>
>> > Cc: Giacomo Comes <comes@naic.edu>
>> > Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
>>
>> I've merged this with Chris' irc-ack (under the condition that the
>> modeset-rework leads to reinstated lvds fastpath that actually works
>> eventually). I've stalled a bit for tested-bys from Takashi, but he seems
>> to be awol atm.
>
> Sorry, I was too busy for other tasks after vacation.
> Tested on a few machines and it worked as expected.
>
> Tested-by: Takashi Iwai <tiwai@suse.de>

No problem ;-) and thanks for putting the patches through it's paces
on a few bothersome machines. Tested-by added to the patch.
-Daniel
-- 
Daniel Vetter
daniel.vetter@ffwll.ch - +41 (0) 79 364 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 45/81] drm/i915: rip out intel_dp->dpms_mode
  2012-07-11 14:28 ` [PATCH 45/81] drm/i915: rip out intel_dp->dpms_mode Daniel Vetter
@ 2012-07-26 18:06   ` Paulo Zanoni
  0 siblings, 0 replies; 107+ messages in thread
From: Paulo Zanoni @ 2012-07-26 18:06 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Intel Graphics Development

Hi

2012/7/11 Daniel Vetter <daniel.vetter@ffwll.ch>:
> @@ -2502,7 +2495,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)
>                 return;
>
>         intel_dp->output_reg = output_reg;
> -       intel_dp->dpms_mode = -1;

In your current modeset-rework branch, you're also removing the
"intel_dp->port = port" line. Look:
http://cgit.freedesktop.org/~danvet/drm/commit/drivers/gpu/drm/i915/intel_dp.c?h=modeset-rework&id=d777693a7eefd4f92a57d49e4a6051f60282f72b

This is probably an accident caused by rebasing.

-- 
Paulo Zanoni

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

end of thread, other threads:[~2012-07-26 18:06 UTC | newest]

Thread overview: 107+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-11 14:27 [PATCH 00/81] modeset rework Daniel Vetter
2012-07-11 14:27 ` [PATCH 01/81] drm/i915: add crtc->enable/disable vfuncs insted of dpms Daniel Vetter
2012-07-11 14:27 ` [PATCH 02/81] drm/i915: rip out crtc prepare/commit indirection Daniel Vetter
2012-07-12 14:44   ` Daniel Vetter
2012-07-11 14:27 ` [PATCH 03/81] drm/i915: add direct encoder disable/enable infrastructure Daniel Vetter
2012-07-11 14:27 ` [PATCH 04/81] drm/i915: add missing gen2 pipe A quirk entries Daniel Vetter
2012-07-11 14:27 ` [PATCH 05/81] drm/i915: rip out the overlay pipe A workaround Daniel Vetter
2012-07-11 14:27 ` [PATCH 06/81] drm/i915: prepare load-detect pipe code for dpms changes Daniel Vetter
2012-07-11 14:27 ` [PATCH 07/81] drm/i915/hdmi: convert to encoder->disable/enable Daniel Vetter
2012-07-11 14:27 ` [PATCH 08/81] drm/i915/tv: convert to encoder enable/disable Daniel Vetter
2012-07-11 14:27 ` [PATCH 09/81] drm/i915/lvds: ditch ->prepare special case Daniel Vetter
2012-07-22 14:52   ` Daniel Vetter
2012-07-22 16:32     ` Takashi Iwai
2012-07-22 19:20       ` Daniel Vetter
2012-07-11 14:27 ` [PATCH 10/81] drm/i915/lvds: convert to encoder disable/enable Daniel Vetter
2012-07-11 14:27 ` [PATCH 11/81] drm/i915/dp: " Daniel Vetter
2012-07-11 14:27 ` [PATCH 12/81] drm/i915: create VLV_DSIPLAY_BASE #define Daniel Vetter
2012-07-20 12:07   ` Daniel Vetter
2012-07-11 14:27 ` [PATCH 13/81] drm/i915: group ADPA #defines together Daniel Vetter
2012-07-12 13:06   ` Paulo Zanoni
2012-07-11 14:27 ` [PATCH 14/81] drm/i915: add inte_crt->adpa_reg Daniel Vetter
2012-07-20 11:56   ` Chris Wilson
2012-07-20 12:09   ` Daniel Vetter
2012-07-11 14:27 ` [PATCH 15/81] drm/i915/crt: convert to encoder disable/enable Daniel Vetter
2012-07-11 14:27 ` [PATCH 16/81] drm/i915/sdvo: " Daniel Vetter
2012-07-11 14:28 ` [PATCH 17/81] drm/i915: simplify dvo dpms interface Daniel Vetter
2012-07-11 14:28 ` [PATCH 18/81] drm/i915/dvo: convert to encoder disable/enable Daniel Vetter
2012-07-11 14:28 ` [PATCH 19/81] drm/i915: simplify possible_clones computation Daniel Vetter
2012-07-12 18:10   ` Paulo Zanoni
2012-07-12 18:47     ` Daniel Vetter
2012-07-12 18:08       ` [PATCH] " Daniel Vetter
2012-07-12 19:48         ` Paulo Zanoni
2012-07-11 14:28 ` [PATCH 20/81] drm/i915: add port parameter to intel_hdmi_init Daniel Vetter
2012-07-12 18:19   ` [PATCH] " Daniel Vetter
2012-07-12 19:49     ` Paulo Zanoni
2012-07-17  8:43       ` Daniel Vetter
2012-07-11 14:28 ` [PATCH 21/81] drm/i915: convert dpms functions of dvo/sdvo/crt Daniel Vetter
2012-07-11 14:28 ` [PATCH 22/81] drm/i915: rip out encoder->disable/enable checks Daniel Vetter
2012-07-11 14:28 ` [PATCH 23/81] drm/i915: clean up encoder_prepare/commit Daniel Vetter
2012-07-11 14:28 ` [PATCH 24/81] drm/fb helper: don't call drm_crtc_helper_set_config Daniel Vetter
2012-07-18 15:49   ` Daniel Vetter
2012-07-18 15:50     ` Daniel Vetter
2012-07-20  1:17       ` Dave Airlie
2012-07-11 14:28 ` [PATCH 25/81] drm: remove the list_head from drm_mode_set Daniel Vetter
2012-07-20  1:23   ` Dave Airlie
2012-07-11 14:28 ` [PATCH 26/81] drm/i915: copy&paste drm_crtc_helper_set_config Daniel Vetter
2012-07-11 14:28 ` [PATCH 27/81] drm/i915: call set_base directly Daniel Vetter
2012-07-11 14:28 ` [PATCH 28/81] drm/i915: inline intel_best_encoder Daniel Vetter
2012-07-11 14:28 ` [PATCH 29/81] drm/i915: copy&paste drm_crtc_helper_set_mode Daniel Vetter
2012-07-11 14:28 ` [PATCH 30/81] drm/i915: simplify intel_crtc_prepare_encoders Daniel Vetter
2012-07-11 14:28 ` [PATCH 31/81] drm/i915: rip out encoder->prepare/commit Daniel Vetter
2012-07-11 14:28 ` [PATCH 32/81] drm/i915: call crtc functions directly Daniel Vetter
2012-07-11 14:28 ` [PATCH 33/81] drm/i915: WARN when trying to enabled an unused crtc Daniel Vetter
2012-07-11 14:28 ` [PATCH 34/81] drm/i915: Add interfaces to read out encoder/connector hw state Daniel Vetter
2012-07-11 14:28 ` [PATCH 35/81] drm/i915/dp: implement get_hw_state Daniel Vetter
2012-07-11 14:28 ` [PATCH 36/81] drm/i915/hdmi: " Daniel Vetter
2012-07-11 14:28 ` [PATCH 37/81] drm/i915/tv: " Daniel Vetter
2012-07-11 14:28 ` [PATCH 38/81] drm/i915/lvds: " Daniel Vetter
2012-07-11 14:28 ` [PATCH 39/81] drm/i915/crt: " Daniel Vetter
2012-07-11 14:28 ` [PATCH 40/81] drm/i915/sdvo: " Daniel Vetter
2012-07-11 14:28 ` [PATCH 41/81] drm/i915/dvo: " Daniel Vetter
2012-07-11 14:28 ` [PATCH 42/81] drm/i915: read out the modeset hw state at load and resume time Daniel Vetter
2012-07-11 14:28 ` [PATCH 43/81] drm/i915: check connector hw/sw state Daniel Vetter
2012-07-11 14:28 ` [PATCH 44/81] drm/i915: rip out intel_crtc->dpms_mode Daniel Vetter
2012-07-11 14:28 ` [PATCH 45/81] drm/i915: rip out intel_dp->dpms_mode Daniel Vetter
2012-07-26 18:06   ` Paulo Zanoni
2012-07-11 14:28 ` [PATCH 46/81] drm/i915: ensure the force pipe A quirk is actually followed Daniel Vetter
2012-07-11 14:28 ` [PATCH 47/81] drm/i915: introduce struct intel_set_config Daniel Vetter
2012-07-11 14:28 ` [PATCH 48/81] drm/i915: extract modeset config save/restore code Daniel Vetter
2012-07-11 14:28 ` [PATCH 49/81] drm/i915: extract intel_set_config_compute_mode_changes Daniel Vetter
2012-07-11 14:28 ` [PATCH 50/81] drm/i915: extract intel_set_config_update_output_state Daniel Vetter
2012-07-11 14:28 ` [PATCH 51/81] drm/i915: implement crtc helper semantics relied upon by the fb helper Daniel Vetter
2012-07-11 14:28 ` [PATCH 52/81] drm/i915: don't update the fb base if there is no fb Daniel Vetter
2012-07-11 14:28 ` [PATCH 53/81] drm/i915: convert pointless error checks in set_config to BUGs Daniel Vetter
2012-07-11 14:28 ` [PATCH 54/81] drm/i915: don't save all the encoder/crtc state in set_config Daniel Vetter
2012-07-11 14:28 ` [PATCH 55/81] drm/i915: stage modeset output changes Daniel Vetter
2012-07-11 14:28 ` [PATCH 56/81] drm/i915: push crtc->fb update into pipe_set_base Daniel Vetter
2012-07-11 14:28 ` [PATCH 57/81] drm/i915: remove crtc disabling special case Daniel Vetter
2012-07-11 14:28 ` [PATCH 58/81] drm/i915: move output commit and crtc disabling into set_mode Daniel Vetter
2012-07-11 14:28 ` [PATCH 59/81] drm/i915: extract adjusted mode computation Daniel Vetter
2012-07-11 14:28 ` [PATCH 60/81] drm/i915: use staged outuput config in tv->mode_fixup Daniel Vetter
2012-07-11 14:28 ` [PATCH 61/81] drm/i915: use staged outuput config in lvds->mode_fixup Daniel Vetter
2012-07-11 14:28 ` [PATCH 62/81] drm/i915: compute masks of crtcs affected in set_mode Daniel Vetter
2012-07-11 14:28 ` [PATCH 63/81] drm/i915: implement new set_mode code flow Daniel Vetter
2012-07-11 14:28 ` [PATCH 64/81] drm/i915: push commit_output_state past crtc disabling Daniel Vetter
2012-07-11 14:28 ` [PATCH 65/81] drm/i915: s/intel_encoder_disable/intel_encoder_noop Daniel Vetter
2012-07-11 14:28 ` [PATCH 66/81] drm/i915: kill a few unused things in dev_priv Daniel Vetter
2012-07-11 14:28 ` [PATCH 67/81] drm/i915: WARN if the pipe won't turn off Daniel Vetter
2012-07-11 14:28 ` [PATCH 68/81] drm/i915: switch the load detect code to the staged modeset config Daniel Vetter
2012-07-11 14:28 ` [PATCH 69/81] drm/i915: push commit_output_state past the crtc/encoder preparing Daniel Vetter
2012-07-11 16:02   ` [PATCH] " Daniel Vetter
2012-07-11 14:28 ` [PATCH 70/81] drm/i915: disable all crtcs at suspend time Daniel Vetter
2012-07-11 14:28 ` [PATCH 71/81] drm/i915: add tons of modeset state checks Daniel Vetter
2012-07-11 17:46   ` [PATCH] " Daniel Vetter
2012-07-11 14:28 ` [PATCH 72/81] drm/i915: extract ironlake_fdi_pll_disable Daniel Vetter
2012-07-11 14:28 ` [PATCH 73/81] drm/i915: rip out intel_disable_pch_ports Daniel Vetter
2012-07-11 14:28 ` [PATCH 74/81] drm/i915: don't disable fdi links harder in ilk_crtc_enable Daniel Vetter
2012-07-11 14:28 ` [PATCH 75/81] drm/i915: don't call dpms funcs after set_mode Daniel Vetter
2012-07-11 14:28 ` [PATCH 76/81] drm/i915: update dpms property in set_mode Daniel Vetter
2012-07-11 14:29 ` [PATCH 77/81] drm/i915: add encoder->pre_enable/post_disable Daniel Vetter
2012-07-11 14:29 ` [PATCH 78/81] drm/i915: clean up the cpu edp pll special case Daniel Vetter
2012-07-11 14:29 ` [PATCH 79/81] drm/i915: robustify edp_pll_on/off Daniel Vetter
2012-07-11 17:47   ` [PATCH] " Daniel Vetter
2012-07-11 14:29 ` [PATCH 80/81] drm/i915: rip out dp port enabling cludges^Wchecks Daniel Vetter
2012-07-11 14:38 ` [PATCH 81/81] drm/i915: disable the cpu edp port after the cpu pipe Daniel Vetter
2012-07-15 13:13 ` [PATCH 00/81] modeset rework Chris Wilson
2012-07-15 14:57   ` 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.