* [RFC] drm/i915: read current config at init time to avoid flicker
@ 2012-03-01 20:37 Jesse Barnes
2012-03-01 22:18 ` Jesse Barnes
2012-03-02 0:08 ` Keith Packard
0 siblings, 2 replies; 7+ messages in thread
From: Jesse Barnes @ 2012-03-01 20:37 UTC (permalink / raw)
To: intel-gfx
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.
--
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..8f25e68 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,9 @@ 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;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
int i, ret;
drm_mode_config_init(dev);
@@ -9142,6 +9204,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);
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC] drm/i915: read current config at init time to avoid flicker
2012-03-01 20:37 [RFC] drm/i915: read current config at init time to avoid flicker Jesse Barnes
@ 2012-03-01 22:18 ` Jesse Barnes
2012-03-01 22:41 ` Chris Wilson
2012-03-02 0:08 ` Keith Packard
1 sibling, 1 reply; 7+ messages in thread
From: Jesse Barnes @ 2012-03-01 22:18 UTC (permalink / raw)
To: intel-gfx
On Thu, 1 Mar 2012 12:37:47 -0800
Jesse Barnes <jbarnes@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
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC] drm/i915: read current config at init time to avoid flicker
2012-03-01 22:18 ` Jesse Barnes
@ 2012-03-01 22:41 ` Chris Wilson
2012-03-01 22:51 ` Jesse Barnes
0 siblings, 1 reply; 7+ messages in thread
From: Chris Wilson @ 2012-03-01 22:41 UTC (permalink / raw)
To: Jesse Barnes, intel-gfx
On Thu, 1 Mar 2012 14:18:58 -0800, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> @@ -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);
intel_encoder->base.crtc = dev_priv->pipe_to_crtc_mapping[intel_dp_get_pipe(intel_dp)]
As the pipe-to-crtc mapping is already established by this point, and
indeed used in the LVDS chunk, you may as well use it here.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] drm/i915: read current config at init time to avoid flicker
2012-03-01 22:41 ` Chris Wilson
@ 2012-03-01 22:51 ` Jesse Barnes
0 siblings, 0 replies; 7+ messages in thread
From: Jesse Barnes @ 2012-03-01 22:51 UTC (permalink / raw)
To: Chris Wilson; +Cc: intel-gfx
On Thu, 01 Mar 2012 22:41:45 +0000
Chris Wilson <chris@chris-wilson.co.uk> wrote:
> On Thu, 1 Mar 2012 14:18:58 -0800, Jesse Barnes
> <jbarnes@virtuousgeek.org> wrote:
> > @@ -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);
> intel_encoder->base.crtc =
> dev_priv->pipe_to_crtc_mapping[intel_dp_get_pipe(intel_dp)]
>
> As the pipe-to-crtc mapping is already established by this point, and
> indeed used in the LVDS chunk, you may as well use it here.
Ah yeah good point, that saves a bit of code.
Unfortunately, the dp code will still shut off the panel in ->prepare.
To avoid that at boot time, we need a valid fb...
An easy approach might be to allocate a bo of the appropriate size at
CRTC init time, and create an fb for it like we do in the intel_fb.c
code. We can simply memcpy from the current base into the new bo, flip
to it, and have a valid crtc->fb from very early on...
Jesse
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] drm/i915: read current config at init time to avoid flicker
2012-03-01 20:37 [RFC] drm/i915: read current config at init time to avoid flicker Jesse Barnes
2012-03-01 22:18 ` Jesse Barnes
@ 2012-03-02 0:08 ` Keith Packard
2012-03-02 0:52 ` Jesse Barnes
1 sibling, 1 reply; 7+ messages in thread
From: Keith Packard @ 2012-03-02 0:08 UTC (permalink / raw)
To: Jesse Barnes, intel-gfx
<#part sign=pgpmime>
On Thu, 1 Mar 2012 12:37:47 -0800, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> The intent here is to build enough of the configuration to allow
> set_config to avoid mode setting if possible.
When I played with this, not setting the fb across this process tended
to do 'bad' things to the hardware -- the scanout would get unmapped
when the GTT was initialized...
--
keith.packard@intel.com
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] drm/i915: read current config at init time to avoid flicker
2012-03-02 0:08 ` Keith Packard
@ 2012-03-02 0:52 ` Jesse Barnes
2012-03-02 6:30 ` Keith Packard
0 siblings, 1 reply; 7+ messages in thread
From: Jesse Barnes @ 2012-03-02 0:52 UTC (permalink / raw)
To: Keith Packard; +Cc: intel-gfx
On Thu, 01 Mar 2012 16:08:03 -0800
Keith Packard <keithp@keithp.com> wrote:
> <#part sign=pgpmime>
> On Thu, 1 Mar 2012 12:37:47 -0800, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> > The intent here is to build enough of the configuration to allow
> > set_config to avoid mode setting if possible.
>
> When I played with this, not setting the fb across this process tended
> to do 'bad' things to the hardware -- the scanout would get unmapped
> when the GTT was initialized...
>
Yeah we shouldn't do that. That's why I'd like to allocate a bo, copy
the contents, and have a real fb associated with each active crtc.
That should avoid any problems with scanning out unmapped memory.
--
Jesse Barnes, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC] drm/i915: read current config at init time to avoid flicker
2012-03-02 0:52 ` Jesse Barnes
@ 2012-03-02 6:30 ` Keith Packard
0 siblings, 0 replies; 7+ messages in thread
From: Keith Packard @ 2012-03-02 6:30 UTC (permalink / raw)
To: Jesse Barnes; +Cc: intel-gfx
<#part sign=pgpmime>
On Thu, 1 Mar 2012 16:52:43 -0800, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> Yeah we shouldn't do that. That's why I'd like to allocate a bo, copy
> the contents, and have a real fb associated with each active crtc.
> That should avoid any problems with scanning out unmapped memory.
It's a bit tricky as we have to do this across GTT initialization. It
should be possible to duplicate the existing GTT mapping for the frame
buffer up high in GTT space, reset the frame buffer base to that, then
initialize the rest of the GTT, map the new frame buffer and then clean
up the GTT after the fbdev mode set. Ick.
--
keith.packard@intel.com
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-03-02 6:30 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-01 20:37 [RFC] drm/i915: read current config at init time to avoid flicker Jesse Barnes
2012-03-01 22:18 ` Jesse Barnes
2012-03-01 22:41 ` Chris Wilson
2012-03-01 22:51 ` Jesse Barnes
2012-03-02 0:08 ` Keith Packard
2012-03-02 0:52 ` Jesse Barnes
2012-03-02 6:30 ` Keith Packard
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.