[RFC] drm/i915: read current config at init time to avoid flicker

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

 



On Thu, 1 Mar 2012 12:37:47 -0800
Jesse Barnes <jbarnes at virtuousgeek.org> wrote:

> The intent here is to build enough of the configuration to allow
> set_config to avoid mode setting if possible.
> 
> Seems to speed up boot a bit on my Dell E6510; should help other eDP
> platforms as well.
> 
> One thing that's missing is creating an initial fb for whatever's
> display at driver load time.  This would involve poking around in the
> display regs to get the offset and making bo and fb objects for the
> current framebuffer.

Here's an updated version that works on LVDS too.

-- 
Jesse Barnes, Intel Open Source Technology Center


diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cdcf99b..70118834 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7637,6 +7637,66 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
 	.page_flip = intel_crtc_page_flip,
 };
 
+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->pipe);
+	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_display_mode *mode;
+
+	mode = intel_crtc_mode_get(dev, crtc);
+	crtc->mode = *mode;
+	kfree(mode);
+	crtc->enabled = drm_helper_crtc_in_use(crtc);
+}
+
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -7669,9 +7729,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)) {
 		if (pipe == 2 && IS_IVYBRIDGE(dev))
@@ -9091,6 +9150,7 @@ static void i915_disable_vga(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);
@@ -9142,6 +9202,9 @@ void intel_modeset_init(struct drm_device *dev)
 		gen6_update_ring_freq(dev_priv);
 	}
 
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		intel_crtc_get_config(crtc);
+
 	INIT_WORK(&dev_priv->idle_work, intel_idle_update);
 	setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
 		    (unsigned long)dev);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 39eccf9..3e24f0b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2360,6 +2360,26 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 	intel_attach_broadcast_rgb_property(connector);
 }
 
+static struct drm_crtc *intel_dp_get_crtc(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct intel_crtc *intel_crtc;
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	int pipe;
+
+	pipe = (I915_READ(intel_dp->output_reg) & DP_PIPE_MASK) >> 30;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		intel_crtc = to_intel_crtc(crtc);
+		if (intel_crtc->pipe == pipe)
+			return crtc;
+	}
+
+	return NULL;
+}
+
 void
 intel_dp_init(struct drm_device *dev, int output_reg)
 {
@@ -2419,6 +2439,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 	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);
@@ -2427,6 +2448,8 @@ 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 = intel_dp_get_crtc(&intel_encoder->base);
+
 	/* Set up the DDC bus. */
 	switch (output_reg) {
 		case DP_A:
@@ -2538,4 +2561,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_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index b103c3b..db73089 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -937,6 +937,7 @@ bool intel_lvds_init(struct drm_device *dev)
 	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
 	connector->interlace_allowed = false;
 	connector->doublescan_allowed = false;
+	connector->encoder = encoder;
 
 	/* create the scaling mode property */
 	drm_mode_create_scaling_mode_property(dev);
@@ -1021,6 +1022,8 @@ bool intel_lvds_init(struct drm_device *dev)
 	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
 	crtc = intel_get_crtc_for_pipe(dev, pipe);
 
+	encoder->crtc = crtc;
+
 	if (crtc && (lvds & LVDS_PORT_EN)) {
 		intel_lvds->fixed_mode = intel_crtc_mode_get(dev, crtc);
 		if (intel_lvds->fixed_mode) {
@@ -1076,6 +1079,8 @@ out:
 	dev_priv->int_lvds_connector = connector;
 	drm_sysfs_connector_add(connector);
 
+	connector->status = intel_lvds_detect(connector, 0);
+
 	intel_panel_setup_backlight(dev);
 
 	return true;

-- 
Jesse Barnes, Intel Open Source Technology Center


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