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