[PATCH 27/43] drm/i915: read initial config from hardware

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jesse Barnes <jbarnes at virtuousgeek.org>

This allows subsequent mode sets to do less work if possible, reducing
flicker and speeding up boot time.

Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>
---
 drivers/gpu/drm/drm_fb_helper.c      |   11 ++--
 drivers/gpu/drm/i915/intel_display.c |  101 +++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/i915/intel_dp.c      |   20 +++++++
 drivers/gpu/drm/i915/intel_fb.c      |    4 +-
 include/drm/drm_fb_helper.h          |    2 +-
 5 files changed, 129 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 02f04d4..391fc41 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1232,6 +1232,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 	struct drm_display_mode **modes;
 	struct drm_encoder *encoder;
 	struct drm_mode_set *modeset;
+	bool success;
 	bool *enabled;
 	int width, height;
 	int i, ret;
@@ -1255,10 +1256,12 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 
 	drm_enable_connectors(fb_helper, enabled);
 
-	if (fb_helper->funcs->initial_config) {
-		fb_helper->funcs->initial_config(fb_helper, crtcs, modes,
-						 enabled, width, height);
-	} else {
+	success = false;
+	if (fb_helper->funcs->initial_config &&
+	    fb_helper->funcs->initial_config(fb_helper, crtcs, modes,
+					     enabled, width, height))
+		success = true;
+	if (!success) {
 		/* clean out all the encoder/crtc combos */
 		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
 				    head)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 97f294e..6afe082 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6282,6 +6282,98 @@ static void intel_pch_pll_init(struct drm_device *dev)
 	}
 }
 
+static int intel_crtc_get_bpp(struct drm_crtc *crtc)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipeconf;
+	int ret;
+
+	pipeconf = PIPECONF(intel_crtc->pipe);
+
+	switch (pipeconf & PIPE_BPC_MASK) {
+	case PIPE_6BPC:
+		ret = 18;
+		break;
+	case PIPE_8BPC:
+		ret = 24;
+		break;
+	case PIPE_10BPC:
+		ret = 30;
+		break;
+	case PIPE_12BPC:
+		ret = 36;
+		break;
+	default:
+		ret = 24;
+		break;
+	}
+
+	return ret;
+}
+
+static bool intel_crtc_get_status(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);
+	int dspcntr, pipeconf;
+
+	dspcntr = DSPCNTR(intel_crtc->plane);
+	pipeconf = PIPECONF(intel_crtc->pipe);
+
+	if ((I915_READ(dspcntr) & DISPLAY_PLANE_ENABLE) &&
+	    (I915_READ(pipeconf) & PIPECONF_ENABLE))
+		return true;
+
+	return false;
+}
+
+/*
+ * Get current mode, encoder, and connector info for this CRTC
+ */
+static void intel_crtc_get_config(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_display_mode *mode;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int bpp, w, h, size;
+	u32 val, pixformat;
+	bool tiled;
+
+	mode = intel_crtc_mode_get(dev, crtc);
+	crtc->mode = *mode;
+	kfree(mode);
+	crtc->enabled = drm_helper_crtc_in_use(crtc);
+
+	val = I915_READ(DSPCNTR(intel_crtc->plane));
+	pixformat = val & DISPPLANE_PIXFORMAT_MASK;
+	tiled = val & DISPPLANE_TILED;
+
+	switch (pixformat) {
+	case DISPPLANE_8BPP:
+		bpp = 1;
+		break;
+	case DISPPLANE_15_16BPP:
+	case DISPPLANE_16BPP:
+		bpp = 2;
+		break;
+	case DISPPLANE_32BPP_NO_ALPHA:
+	case DISPPLANE_32BPP:
+	case DISPPLANE_32BPP_30BIT_NO_ALPHA:
+		bpp = 4;
+		break;
+	default:
+		bpp = 4; /* assume worst case */
+	}
+
+	val = I915_READ(PIPESRC(intel_crtc->pipe));
+	w = val >> 16;
+	h = val & 0xffff;
+
+	size = w * h * bpp;
+}
+
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -6314,9 +6406,8 @@ 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 */
+	intel_crtc->active = intel_crtc_get_status(&intel_crtc->base);
+	intel_crtc->bpp = intel_crtc_get_bpp(&intel_crtc->base);
 
 	if (HAS_PCH_SPLIT(dev)) {
 		intel_helper_funcs.prepare = ironlake_crtc_prepare;
@@ -6841,6 +6932,7 @@ void intel_modeset_init_hw(struct drm_device *dev)
 void intel_modeset_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
 	int i, ret;
 
 	drm_mode_config_init(dev);
@@ -6889,6 +6981,9 @@ void intel_modeset_init(struct drm_device *dev)
 	i915_disable_vga(dev);
 	intel_setup_outputs(dev);
 
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		intel_crtc_get_config(crtc);
+
 	/* Just in case the BIOS is doing something questionable. */
 	intel_disable_fbc(dev);
 }
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9b2effc..924dc27 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2386,6 +2386,17 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 	intel_attach_broadcast_rgb_property(connector);
 }
 
+static int intel_dp_get_pipe(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe;
+
+	pipe = (I915_READ(intel_dp->output_reg) & DP_PIPE_MASK) >> 30;
+
+	return pipe;
+}
+
 void
 intel_dp_init(struct drm_device *dev, int output_reg)
 {
@@ -2446,6 +2457,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
 	connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
+	connector->encoder = &intel_encoder->base;
 
 	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
 			 DRM_MODE_ENCODER_TMDS);
@@ -2454,6 +2466,12 @@ 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->base.crtc = dev_priv->pipe_to_crtc_mapping[intel_dp_get_pipe(intel_dp)];
+
+	DRM_DEBUG_KMS("setting dp encoder %p crtc to %p (%d)\n",
+		      &intel_encoder->base, intel_encoder->base.crtc,
+		      intel_encoder->base.crtc->base.id);
+
 	/* Set up the DDC bus. */
 	switch (output_reg) {
 		case DP_A:
@@ -2572,4 +2590,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 		u32 temp = I915_READ(PEG_BAND_GAP_DATA);
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
+
+	connector->status = intel_dp_detect(connector, 0);
 }
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 0388677..83d3f7b 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -214,7 +214,7 @@ static struct drm_fb_helper_crtc *intel_fb_helper_crtc(struct drm_fb_helper *fb_
 	return NULL;
 }
 
-static void intel_fb_initial_config(struct drm_fb_helper *fb_helper,
+static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
 				    struct drm_fb_helper_crtc **crtcs,
 				    struct drm_display_mode **modes,
 				    bool *enabled, int width, int height)
@@ -247,6 +247,8 @@ static void intel_fb_initial_config(struct drm_fb_helper *fb_helper,
 			      encoder->crtc->base.id,
 			      modes[i] ? modes[i]->name : "off");
 	}
+
+	return true;
 }
 
 static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index dd98012..40b0c5c 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -56,7 +56,7 @@ struct drm_fb_helper_funcs {
 
 	int (*fb_probe)(struct drm_fb_helper *helper,
 			struct drm_fb_helper_surface_size *sizes);
-	void (*initial_config)(struct drm_fb_helper *fb_helper,
+	bool (*initial_config)(struct drm_fb_helper *fb_helper,
 			       struct drm_fb_helper_crtc **crtcs,
 			       struct drm_display_mode **modes,
 			       bool *enabled, int width, int height);
-- 
1.7.10



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux