Some machines may have a broken VBT or no VBT at all, but we still want to use SSC there. So check for it and keep it enabled if we see it already on. Based on an earlier fix from Kristian.
v2: honor modparam if set too (Daniel) read out at init time and store for panel_use_ssc() use (Jesse)
Reported-by: Kristian Høgsberg hoegsberg@gmail.com Signed-off-by: Jesse Barnes jbarnes@virtuousgeek.org --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_display.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 70fbe90..c64f770 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1507,6 +1507,8 @@ typedef struct drm_i915_private { struct intel_opregion opregion; struct intel_vbt_data vbt;
+ bool bios_ssc; /* BIOS had SSC enabled at boot? */ + /* overlay */ struct intel_overlay *overlay;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2bccc68..4b3e1c0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4986,7 +4986,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) { if (i915.panel_use_ssc >= 0) return i915.panel_use_ssc != 0; - return dev_priv->vbt.lvds_use_ssc + return (dev_priv->vbt.lvds_use_ssc || dev_priv->bios_ssc) && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); }
@@ -11732,9 +11732,18 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
void intel_modeset_gem_init(struct drm_device *dev) { + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *c; struct intel_framebuffer *fb;
+ /* + * There may be no VBT; and if the BIOS enabled SSC we can + * just keep using it to avoid unnecessary flicker. + */ + if ((HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) && + (I915_READ(PCH_DREF_CONTROL) & DREF_SSC1_ENABLE)) + dev_priv->bios_ssc = true; + intel_modeset_init_hw(dev);
intel_setup_overlay(dev);
As of IVB, the memory controller does internal swizzling already, so we shouldn't need to enable these. Based on an earlier fix from Kristian.
v2: preserve swizzling if BIOS had it set (Daniel)
Reported-by: Kristian Høgsberg hoegsberg@gmail.com Signed-off-by: Jesse Barnes jbarnes@virtuousgeek.org --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 6 ++++++ drivers/gpu/drm/i915/i915_gem_tiling.c | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c64f770..29cd977 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1508,6 +1508,7 @@ typedef struct drm_i915_private { struct intel_vbt_data vbt;
bool bios_ssc; /* BIOS had SSC enabled at boot? */ + bool bios_swizzle;
/* overlay */ struct intel_overlay *overlay; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 92b0b41..87e34bc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4313,6 +4313,9 @@ void i915_gem_init_swizzling(struct drm_device *dev) dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_NONE) return;
+ if (INTEL_INFO(dev)->gen >= 7 && !dev_priv->bios_swizzle) + return; + I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) | DISP_TILE_SURFACE_SWIZZLING);
@@ -4454,6 +4457,9 @@ int i915_gem_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret;
+ if (I915_READ(DISP_ARB_CTL) & DISP_TILE_SURFACE_SWIZZLING) + dev_priv->bios_swizzle = true; + mutex_lock(&dev->struct_mutex);
if (IS_VALLEYVIEW(dev)) { diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index eb99358..c6447de 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -91,7 +91,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
- if (IS_VALLEYVIEW(dev)) { + if (INTEL_INFO(dev)->gen >= 7 && + !(I915_READ(TILECTL) & TILECTL_SWZCTL)) { swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE; } else if (INTEL_INFO(dev)->gen >= 6) {
On Fri, Mar 14, 2014 at 02:37:09PM -0700, Jesse Barnes wrote:
As of IVB, the memory controller does internal swizzling already, so we shouldn't need to enable these. Based on an earlier fix from Kristian.
v2: preserve swizzling if BIOS had it set (Daniel)
Reported-by: Kristian Høgsberg hoegsberg@gmail.com Signed-off-by: Jesse Barnes jbarnes@virtuousgeek.org
drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 6 ++++++ drivers/gpu/drm/i915/i915_gem_tiling.c | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c64f770..29cd977 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1508,6 +1508,7 @@ typedef struct drm_i915_private { struct intel_vbt_data vbt;
bool bios_ssc; /* BIOS had SSC enabled at boot? */
bool bios_swizzle;
/* overlay */ struct intel_overlay *overlay;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 92b0b41..87e34bc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4313,6 +4313,9 @@ void i915_gem_init_swizzling(struct drm_device *dev) dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_NONE) return;
- if (INTEL_INFO(dev)->gen >= 7 && !dev_priv->bios_swizzle)
return;
- I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) | DISP_TILE_SURFACE_SWIZZLING);
@@ -4454,6 +4457,9 @@ int i915_gem_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret;
if (I915_READ(DISP_ARB_CTL) & DISP_TILE_SURFACE_SWIZZLING)
dev_priv->bios_swizzle = true;
mutex_lock(&dev->struct_mutex);
if (IS_VALLEYVIEW(dev)) {
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index eb99358..c6447de 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -91,7 +91,8 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
- if (IS_VALLEYVIEW(dev)) {
- if (INTEL_INFO(dev)->gen >= 7 &&
!(I915_READ(TILECTL) & TILECTL_SWZCTL)) {
Not quite what I've had in mind. I think what we need to do instead is
- Walk all the inherited framebuffer configs and check whether any of them are tiled. If one is, then we need to preserve the BIOS swizzle setting, if not then we can pick whatever we want.
- If we decide to preserve the BIOS config, then we need to preserve both the swizzled and the unswizlled case, i.e. we need a nested if switch whichc either sets SWIZZE_NONE or the correct swizzle bits.
- We need to check the swizzle bits in DISP_ARB_CTL, not one of the other three - the DISP_ARB bit is the one relevant for the display controller, the other might be wrong or not set.
- This should be done for all gen6+ platforms, sicne those are the ones where swizzling is driver controlled.
Cheers, Daniel
swizzle_x = I915_BIT_6_SWIZZLE_NONE; swizzle_y = I915_BIT_6_SWIZZLE_NONE;
} else if (INTEL_INFO(dev)->gen >= 6) {
1.7.9.5
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
From: Kristian Høgsberg hoegsberg@gmail.com
The BIOS may set a native mode that doesn't quite match the preferred mode timings. It should be ok to use however if it uses the same size, so try to avoid a mode set in that case.
Signed-off-by: Kristian Høgsberg hoegsberg@gmail.com Signed-off-by: Jesse Barnes jbarnes@virtuousgeek.org --- drivers/gpu/drm/drm_modes.c | 8 ++++++++ drivers/gpu/drm/i915/intel_fbdev.c | 37 ++++++++++++++++++------------------ include/drm/drm_crtc.h | 2 ++ 3 files changed, 28 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index b073315..7d2dda4 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -894,6 +894,14 @@ bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, } EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
+bool drm_mode_same_size(const struct drm_display_mode *mode1, + const struct drm_display_mode *mode2) +{ + return mode1->vdisplay == mode2->vdisplay && + mode1->hdisplay == mode2->hdisplay; +} +EXPORT_SYMBOL(drm_mode_same_size); + /** * drm_mode_validate_size - make sure modes adhere to size constraints * @dev: DRM device diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index d6d78c8..f81e3db 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -369,31 +369,30 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper, /* go for command line mode first */ modes[i] = drm_pick_cmdline_mode(fb_conn, width, height);
- /* try for preferred next */ + /* try for preferred next or match current */ if (!modes[i]) { + struct drm_display_mode *preferred; + DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", fb_conn->connector->base.id); - modes[i] = drm_has_preferred_mode(fb_conn, width, - height); - } - - /* last resort: use current mode */ - if (!modes[i]) { - /* - * IMPORTANT: We want to use the adjusted mode (i.e. - * after the panel fitter upscaling) as the initial - * config, not the input mode, which is what crtc->mode - * usually contains. But since our current fastboot - * code puts a mode derived from the post-pfit timings - * into crtc->mode this works out correctly. We don't - * use hwmode anywhere right now, so use it for this - * since the fb helper layer wants a pointer to - * something we own. - */ + preferred = drm_has_preferred_mode(fb_conn, width, + height); intel_mode_from_pipe_config(&encoder->crtc->hwmode, &to_intel_crtc(encoder->crtc)->config); - modes[i] = &encoder->crtc->hwmode; + modes[i] = &encoder->crtc->hwmode; + + if (preferred && + !drm_mode_same_size(preferred, modes[i])) { + DRM_DEBUG_KMS("using preferred mode %s " + "instead of current mode %s " + "on connector %d\n", + preferred->name, + modes[i]->name, + fb_conn->connector->base.id); + modes[i] = preferred; + } } + crtcs[i] = new_crtc;
DRM_DEBUG_KMS("connector %s on crtc %d: %s\n", diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index f764654..d5ebe3b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1020,6 +1020,8 @@ extern bool drm_mode_equal(const struct drm_display_mode *mode1, const struct dr extern bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2); extern int drm_mode_width(const struct drm_display_mode *mode); extern int drm_mode_height(const struct drm_display_mode *mode); +extern bool drm_mode_same_size(const struct drm_display_mode *mode1, + const struct drm_display_mode *mode2);
/* for us by fb module */ extern struct drm_display_mode *drm_mode_create(struct drm_device *dev);
Let them eat cake.
Signed-off-by: Jesse Barnes jbarnes@virtuousgeek.org --- drivers/gpu/drm/i915/i915_params.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index a66ffb6..5f81047 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -41,7 +41,7 @@ struct i915_params i915 __read_mostly = { .preliminary_hw_support = IS_ENABLED(CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT), .disable_power_well = 1, .enable_ips = 1, - .fastboot = 0, + .fastboot = 42, .enable_pc8 = 1, .pc8_timeout = 5000, .prefault_disable = 0,
dri-devel@lists.freedesktop.org