From 44522d852f1979ec0e6807eb4dc58bd7ecc8af08 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:44:02 +0200 Subject: [PATCH 01/80] drm/i915: Set csc coefficients in update_pipe_size. This might not have been set during boot, and when we preserve the initial mode this can result in a black screen. Cc: Daniel Stone Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 62573d5595fa..19049198364a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3274,6 +3274,9 @@ static void intel_update_pipe_size(struct intel_crtc *crtc) if (!i915.fastboot) return; + if (HAS_DDI(dev)) + intel_set_pipe_csc(&crtc->base); + /* * Update pipe size and adjust fitter if needed: the reason for this is * that in compute_mode_changes we check the native mode (not the pfit From d551599181769571f4f68dd93e5d8b15868889af Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:44:03 +0200 Subject: [PATCH 02/80] drm/i915: Remove references to crtc->active from intel_fbdev.c It should really use the atomic state. Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_fbdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 96476d7d7ed2..0c9291da1d2e 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -550,7 +550,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, intel_fb_obj(crtc->primary->state->fb); intel_crtc = to_intel_crtc(crtc); - if (!intel_crtc->active || !obj) { + if (!crtc->state->active || !obj) { DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n", pipe_name(intel_crtc->pipe)); continue; @@ -575,7 +575,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, intel_crtc = to_intel_crtc(crtc); - if (!intel_crtc->active) { + if (!crtc->state->active) { DRM_DEBUG_KMS("pipe %c not active, skipping\n", pipe_name(intel_crtc->pipe)); continue; @@ -638,7 +638,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, for_each_crtc(dev, crtc) { intel_crtc = to_intel_crtc(crtc); - if (!intel_crtc->active) + if (!crtc->state->active) continue; WARN(!crtc->primary->fb, From f4502c25ebd04691f284fdafff4a5613299c36dc Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:44:04 +0200 Subject: [PATCH 03/80] drm/i915: Always try to inherit the initial fb. The initial state is read out correctly and the state is atomic, so it's safe to preserve the fb without any hacks if it's suitable. Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_fbdev.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 0c9291da1d2e..73a14e86a127 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -541,9 +541,6 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, struct intel_crtc *intel_crtc; unsigned int max_size = 0; - if (!i915.fastboot) - return false; - /* Find the largest fb */ for_each_crtc(dev, crtc) { struct drm_i915_gem_object *obj = From bfd16b2a23dc99f2af3f5c4f54aa153347f2dc3c Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:44:05 +0200 Subject: [PATCH 04/80] drm/i915: Make updating pipe without modeset atomic. Instead of doing a hack during primary plane commit the state is updated during atomic evasion. It handles differences in pipe size and the panel fitter. This is continuing on top of Daniel's work to make faster modesets atomic, and not yet enabled by default. Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes [danvet: - simplify/future-proof if ladder that Jesse spotted - resolve conflict in pipe_config_check and don't spuriously move the code.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_atomic.c | 2 + drivers/gpu/drm/i915/intel_display.c | 106 +++++++++++++++++---------- drivers/gpu/drm/i915/intel_drv.h | 2 + 3 files changed, 70 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 2c4b1c44296c..f1975f267710 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -93,6 +93,8 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base); + crtc_state->update_pipe = false; + return &crtc_state->base; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 19049198364a..1691ec23bb95 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -112,6 +112,9 @@ static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_cr struct intel_crtc_state *crtc_state); static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state, int num_connectors); +static void skylake_pfit_enable(struct intel_crtc *crtc); +static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force); +static void ironlake_pfit_enable(struct intel_crtc *crtc); static void intel_modeset_setup_hw_state(struct drm_device *dev); typedef struct { @@ -3265,14 +3268,20 @@ static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) return pending; } -static void intel_update_pipe_size(struct intel_crtc *crtc) +static void intel_update_pipe_config(struct intel_crtc *crtc, + struct intel_crtc_state *old_crtc_state) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - const struct drm_display_mode *adjusted_mode; + struct intel_crtc_state *pipe_config = + to_intel_crtc_state(crtc->base.state); - if (!i915.fastboot) - return; + /* drm_atomic_helper_update_legacy_modeset_state might not be called. */ + crtc->base.mode = crtc->base.state->mode; + + DRM_DEBUG_KMS("Updating pipe size %ix%i -> %ix%i\n", + old_crtc_state->pipe_src_w, old_crtc_state->pipe_src_h, + pipe_config->pipe_src_w, pipe_config->pipe_src_h); if (HAS_DDI(dev)) intel_set_pipe_csc(&crtc->base); @@ -3284,27 +3293,24 @@ static void intel_update_pipe_size(struct intel_crtc *crtc) * fastboot case, we'll flip, but if we don't update the pipesrc and * pfit state, we'll end up with a big fb scanned out into the wrong * sized surface. - * - * To fix this properly, we need to hoist the checks up into - * compute_mode_changes (or above), check the actual pfit state and - * whether the platform allows pfit disable with pipe active, and only - * then update the pipesrc and pfit state, even on the flip path. */ - adjusted_mode = &crtc->config->base.adjusted_mode; - I915_WRITE(PIPESRC(crtc->pipe), - ((adjusted_mode->crtc_hdisplay - 1) << 16) | - (adjusted_mode->crtc_vdisplay - 1)); - if (!crtc->config->pch_pfit.enabled && - (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || - intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { - I915_WRITE(PF_CTL(crtc->pipe), 0); - I915_WRITE(PF_WIN_POS(crtc->pipe), 0); - I915_WRITE(PF_WIN_SZ(crtc->pipe), 0); + ((pipe_config->pipe_src_w - 1) << 16) | + (pipe_config->pipe_src_h - 1)); + + /* on skylake this is done by detaching scalers */ + if (INTEL_INFO(dev)->gen >= 9) { + skl_detach_scalers(crtc); + + if (pipe_config->pch_pfit.enabled) + skylake_pfit_enable(crtc); + } else if (HAS_PCH_SPLIT(dev)) { + if (pipe_config->pch_pfit.enabled) + ironlake_pfit_enable(crtc); + else if (old_crtc_state->pch_pfit.enabled) + ironlake_pfit_disable(crtc, true); } - crtc->config->pipe_src_w = adjusted_mode->crtc_hdisplay; - crtc->config->pipe_src_h = adjusted_mode->crtc_vdisplay; } static void intel_fdi_normal_train(struct drm_crtc *crtc) @@ -4961,7 +4967,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) } } -static void ironlake_pfit_disable(struct intel_crtc *crtc) +static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -4969,7 +4975,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc) /* To avoid upsetting the power well on haswell only disable the pfit if * it's in use. The hw state code will make sure we get this right. */ - if (crtc->config->pch_pfit.enabled) { + if (force || crtc->config->pch_pfit.enabled) { I915_WRITE(PF_CTL(pipe), 0); I915_WRITE(PF_WIN_POS(pipe), 0); I915_WRITE(PF_WIN_SZ(pipe), 0); @@ -4996,7 +5002,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) intel_disable_pipe(intel_crtc); - ironlake_pfit_disable(intel_crtc); + ironlake_pfit_disable(intel_crtc, false); if (intel_crtc->config->has_pch_encoder) ironlake_fdi_disable(crtc); @@ -5059,7 +5065,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) if (INTEL_INFO(dev)->gen >= 9) skylake_scaler_disable(intel_crtc); else - ironlake_pfit_disable(intel_crtc); + ironlake_pfit_disable(intel_crtc, false); intel_ddi_disable_pipe_clock(intel_crtc); @@ -12218,7 +12224,6 @@ static bool intel_fuzzy_clock_check(int clock1, int clock2) base.head) \ if (mask & (1 <<(intel_crtc)->pipe)) - static bool intel_compare_m_n(unsigned int m, unsigned int n, unsigned int m2, unsigned int n2, @@ -12439,19 +12444,21 @@ intel_pipe_config_compare(struct drm_device *dev, DRM_MODE_FLAG_NVSYNC); } - PIPE_CONF_CHECK_I(pipe_src_w); - PIPE_CONF_CHECK_I(pipe_src_h); - PIPE_CONF_CHECK_X(gmch_pfit.control); /* pfit ratios are autocomputed by the hw on gen4+ */ if (INTEL_INFO(dev)->gen < 4) PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios); PIPE_CONF_CHECK_X(gmch_pfit.lvds_border_bits); - PIPE_CONF_CHECK_I(pch_pfit.enabled); - if (current_config->pch_pfit.enabled) { - PIPE_CONF_CHECK_X(pch_pfit.pos); - PIPE_CONF_CHECK_X(pch_pfit.size); + if (!adjust) { + PIPE_CONF_CHECK_I(pipe_src_w); + PIPE_CONF_CHECK_I(pipe_src_h); + + PIPE_CONF_CHECK_I(pch_pfit.enabled); + if (current_config->pch_pfit.enabled) { + PIPE_CONF_CHECK_X(pch_pfit.pos); + PIPE_CONF_CHECK_X(pch_pfit.size); + } } PIPE_CONF_CHECK_I(scaler_state.scaler_id); @@ -12616,7 +12623,8 @@ check_crtc_state(struct drm_device *dev, struct drm_atomic_state *old_state) struct intel_crtc_state *pipe_config, *sw_config; bool active; - if (!needs_modeset(crtc->state)) + if (!needs_modeset(crtc->state) && + !to_intel_crtc_state(crtc->state)->update_pipe) continue; __drm_atomic_helper_crtc_destroy_state(crtc, old_crtc_state); @@ -12912,7 +12920,6 @@ static int intel_modeset_all_pipes(struct drm_atomic_state *state) return ret; } - static int intel_modeset_checks(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; @@ -13003,6 +13010,7 @@ static int intel_atomic_check(struct drm_device *dev, to_intel_crtc_state(crtc->state), pipe_config, true)) { crtc_state->mode_changed = false; + to_intel_crtc_state(crtc_state)->update_pipe = true; } if (needs_modeset(crtc_state)) { @@ -13100,16 +13108,30 @@ static int intel_atomic_commit(struct drm_device *dev, for_each_crtc_in_state(state, crtc, crtc_state, i) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); bool modeset = needs_modeset(crtc->state); + bool update_pipe = !modeset && + to_intel_crtc_state(crtc->state)->update_pipe; + unsigned long put_domains = 0; if (modeset && crtc->state->active) { update_scanline_offset(to_intel_crtc(crtc)); dev_priv->display.crtc_enable(crtc); } + if (update_pipe) { + put_domains = modeset_get_crtc_power_domains(crtc); + + /* make sure intel_modeset_check_state runs */ + any_ms = true; + } + if (!modeset) intel_pre_plane_update(intel_crtc); drm_atomic_helper_commit_planes_on_crtc(crtc_state); + + if (put_domains) + modeset_put_power_domains(dev_priv, put_domains); + intel_post_plane_update(intel_crtc); } @@ -13426,10 +13448,6 @@ intel_commit_primary_plane(struct drm_plane *plane, if (!crtc->state->active) return; - if (state->visible) - /* FIXME: kill this fastboot hack */ - intel_update_pipe_size(intel_crtc); - dev_priv->display.update_primary_plane(crtc, fb, state->src.x1 >> 16, state->src.y1 >> 16); @@ -13450,6 +13468,9 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *old_intel_state = + to_intel_crtc_state(old_crtc_state); + bool modeset = needs_modeset(crtc->state); if (intel_crtc->atomic.update_wm_pre) intel_update_watermarks(crtc); @@ -13458,7 +13479,12 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, if (crtc->state->active) intel_pipe_update_start(intel_crtc); - if (!needs_modeset(crtc->state) && INTEL_INFO(dev)->gen >= 9) + if (modeset) + return; + + if (to_intel_crtc_state(crtc->state)->update_pipe) + intel_update_pipe_config(intel_crtc, old_intel_state); + else if (INTEL_INFO(dev)->gen >= 9) skl_detach_scalers(intel_crtc); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 129d99e33bc2..e9e5cfd2d9b8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -338,6 +338,8 @@ struct intel_crtc_state { #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ unsigned long quirks; + bool update_pipe; + /* Pipe source size (ie. panel fitter input size) * All planes will be positioned inside this space, * and get clipped at the edges. */ From 6764e9f8724f1231b4deac53b9a82286ac0830e7 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 27 Aug 2015 15:44:06 +0200 Subject: [PATCH 05/80] drm/i915: skip modeset if compatible for everyone. This is done as a separate commit, to make it easier to revert when things break. Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_params.c | 5 ----- drivers/gpu/drm/i915/intel_display.c | 3 +-- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index da0f2640d1d7..2994ce5f6476 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2644,7 +2644,6 @@ struct i915_params { int enable_cmd_parser; /* leave bools at the end to not create holes */ bool enable_hangcheck; - bool fastboot; bool prefault_disable; bool load_detect_test; bool reset; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 05053e2e9ff0..ca060d5549bb 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -40,7 +40,6 @@ 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, .prefault_disable = 0, .load_detect_test = 0, .reset = true, @@ -133,10 +132,6 @@ MODULE_PARM_DESC(disable_power_well, module_param_named(enable_ips, i915.enable_ips, int, 0600); MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)"); -module_param_named(fastboot, i915.fastboot, bool, 0600); -MODULE_PARM_DESC(fastboot, - "Try to skip unnecessary mode sets at boot time (default: false)"); - module_param_named_unsafe(prefault_disable, i915.prefault_disable, bool, 0600); MODULE_PARM_DESC(prefault_disable, "Disable page prefaulting for pread/pwrite/reloc (default:false). " diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1691ec23bb95..a001cbbb855b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13005,8 +13005,7 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) return ret; - if (i915.fastboot && - intel_pipe_config_compare(state->dev, + if (intel_pipe_config_compare(state->dev, to_intel_crtc_state(crtc->state), pipe_config, true)) { crtc_state->mode_changed = false; From ec72d5884c6a3cf4f27b52da51654a472b919545 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Fri, 4 Sep 2015 12:59:14 +0100 Subject: [PATCH 06/80] drm/i915: WaEnableForceRestoreInCtxtDescForVCS is for video engines only Also check for correct revision id in each Gen9 platform (SKL until B0 and BXT until A0). Cc: Nick Hoath Signed-off-by: Michel Thierry Reviewed-by: Arun Siluvery Tested-by: Daniele Ceraolo Spurio Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 28a712e7d2d0..d8b605fc4aa9 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -301,10 +301,10 @@ uint64_t intel_lr_context_descriptor(struct intel_context *ctx, /* desc |= GEN8_CTX_FORCE_RESTORE; */ /* WaEnableForceRestoreInCtxtDescForVCS:skl */ - if (IS_GEN9(dev) && - INTEL_REVID(dev) <= SKL_REVID_B0 && - (ring->id == BCS || ring->id == VCS || - ring->id == VECS || ring->id == VCS2)) + /* WaEnableForceRestoreInCtxtDescForVCS:bxt */ + if (((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || + (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) && + (ring->id == VCS || ring->id == VCS2)) desc |= GEN8_CTX_FORCE_RESTORE; return desc; From 5af05fefb5be51d42effc4f802b6d806fbda34eb Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Fri, 4 Sep 2015 12:59:15 +0100 Subject: [PATCH 07/80] drm/i915/lrc: Prevent preemption when lite-restore is disabled When WaEnableForceRestoreInCtxtDescForVCS is required, it is only safe to send new contexts if the last reported event is "active to idle". Otherwise the same context can fully preempt itself because lite-restore is disabled. Testcase: igt/gem_concurrent_blit Reported-by: Daniele Ceraolo Spurio Signed-off-by: Michel Thierry Reviewed-by: Arun Siluvery Tested-by: Daniele Ceraolo Spurio Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index d8b605fc4aa9..c3fca4be7a8c 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -277,10 +277,18 @@ u32 intel_execlists_ctx_id(struct drm_i915_gem_object *ctx_obj) return lrca >> 12; } +static bool disable_lite_restore_wa(struct intel_engine_cs *ring) +{ + struct drm_device *dev = ring->dev; + + return ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || + (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) && + (ring->id == VCS || ring->id == VCS2); +} + uint64_t intel_lr_context_descriptor(struct intel_context *ctx, struct intel_engine_cs *ring) { - struct drm_device *dev = ring->dev; struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; uint64_t desc; uint64_t lrca = i915_gem_obj_ggtt_offset(ctx_obj) + @@ -302,9 +310,7 @@ uint64_t intel_lr_context_descriptor(struct intel_context *ctx, /* WaEnableForceRestoreInCtxtDescForVCS:skl */ /* WaEnableForceRestoreInCtxtDescForVCS:bxt */ - if (((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || - (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) && - (ring->id == VCS || ring->id == VCS2)) + if (disable_lite_restore_wa(ring)) desc |= GEN8_CTX_FORCE_RESTORE; return desc; @@ -495,7 +501,7 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) u32 status_pointer; u8 read_pointer; u8 write_pointer; - u32 status; + u32 status = 0; u32 status_id; u32 submit_contexts = 0; @@ -533,8 +539,14 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) } } - if (submit_contexts != 0) + if (disable_lite_restore_wa(ring)) { + /* Prevent a ctx to preempt itself */ + if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) && + (submit_contexts != 0)) + execlists_context_unqueue(ring); + } else if (submit_contexts != 0) { execlists_context_unqueue(ring); + } spin_unlock(&ring->execlist_lock); From e2ec35a58b3c9cdadbb7d913e8262ad9ddcb00f7 Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Fri, 11 Sep 2015 16:58:32 +0530 Subject: [PATCH 08/80] drm/i915/bxt: Use intel_encoder->hpd_pin to check live status Using intel_encoder's hpd_pin to check the live status because of BXT A0/A1 WA for HPD pins and hpd_pin contains the updated pin for the corresponding port. Signed-off-by: Sonika Jindal Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 45ab25e479ae..b8c4fc5a92f1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4637,11 +4637,14 @@ static bool vlv_digital_port_connected(struct drm_i915_private *dev_priv, } static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, - struct intel_digital_port *port) + struct intel_digital_port *intel_dig_port) { + struct intel_encoder *intel_encoder = &intel_dig_port->base; + enum port port; u32 bit; - switch (port->port) { + intel_hpd_pin_to_port(intel_encoder->hpd_pin, &port); + switch (port) { case PORT_A: bit = BXT_DE_PORT_HP_DDIA; break; @@ -4652,7 +4655,7 @@ static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, bit = BXT_DE_PORT_HP_DDIC; break; default: - MISSING_CASE(port->port); + MISSING_CASE(port); return false; } From 8c761609ec3beca88819e28d4fcf333b579d29b4 Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Tue, 8 Sep 2015 10:31:48 +0100 Subject: [PATCH 09/80] drm/i915/gen9: Add WaDisableSamplerPowerBypassForSOPingPong Signed-off-by: Arun Siluvery Reviewed-by: Sagar Arun Kamble Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 20a75bb516ac..684e0693dae9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -983,6 +983,13 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE; WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp); + /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt */ + if (IS_SKYLAKE(dev) || + (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_B0)) { + WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, + GEN8_SAMPLER_POWER_BYPASS_DIS); + } + return 0; } From 5b88abacd4820c66bc347a6beeb3d6ad1144544b Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Tue, 8 Sep 2015 10:31:49 +0100 Subject: [PATCH 10/80] drm/i915/bxt: Add WaSetClckGatingDisableMedia Signed-off-by: Arun Siluvery Reviewed-by: Sagar Arun Kamble Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 65b5682b19ac..495ac17b04c7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6897,6 +6897,7 @@ enum skl_disp_power_wells { #define GEN7_DOP_CLOCK_GATE_ENABLE (1<<0) #define GEN8_DOP_CLOCK_GATE_CFCLK_ENABLE (1<<2) #define GEN8_DOP_CLOCK_GATE_GUC_ENABLE (1<<4) +#define GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE (1<<6) #define GEN8_GARBCNTL 0xB004 #define GEN9_GAPS_TSV_CREDIT_DISABLE (1<<7) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 64bc77ef6b2e..920872acf4db 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -134,6 +134,12 @@ static void bxt_init_clock_gating(struct drm_device *dev) */ I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); } + + /* WaSetClckGatingDisableMedia:bxt */ + if (INTEL_REVID(dev) == BXT_REVID_A0) { + I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & + ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); + } } static void i915_pineview_get_mem_freq(struct drm_device *dev) From b970b48685a7ae2953e659f7e657cde2949b12ae Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Tue, 8 Sep 2015 10:31:53 +0100 Subject: [PATCH 11/80] drm/i915/gen9: Add WaDisableMinuteIaClockGating Signed-off-by: Nick Hoath Signed-off-by: Arun Siluvery Reviewed-by: Sagar Arun Kamble Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_guc_loader.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 5eafd31fb4a6..e0601cc5a795 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -330,6 +330,13 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) /* Enable MIA caching. GuC clock gating is disabled. */ I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE); + /* WaDisableMinuteIaClockGating:skl,bxt */ + if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0) || + (IS_BROXTON(dev) && INTEL_REVID(dev) == BXT_REVID_A0)) { + I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) & + ~GUC_ENABLE_MIA_CLOCK_GATING)); + } + /* WaC6DisallowByGfxPause*/ I915_WRITE(GEN6_GFXPAUSE, 0x30FFF); From 6ff8ab0d0fab914755cb79b1e0469dd7123cc471 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Sep 2015 08:20:28 -0700 Subject: [PATCH 12/80] drm/i915: make CSR firmware messages less verbose Use WARN_ONCE in a bunch of places and demote a message that would continually spam us. Signed-off-by: Jesse Barnes Acked-by: Damien Lespiau Acked-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_csr.c | 12 ++++----- drivers/gpu/drm/i915/intel_runtime_pm.c | 36 ++++++++++++------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index ba1ae031e6fd..765dfcd15727 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -454,10 +454,10 @@ void intel_csr_ucode_fini(struct drm_device *dev) void assert_csr_loaded(struct drm_i915_private *dev_priv) { - WARN(intel_csr_load_status_get(dev_priv) != FW_LOADED, - "CSR is not loaded.\n"); - WARN(!I915_READ(CSR_PROGRAM_BASE), - "CSR program storage start is NULL\n"); - WARN(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n"); - WARN(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n"); + WARN_ONCE(intel_csr_load_status_get(dev_priv) != FW_LOADED, + "CSR is not loaded.\n"); + WARN_ONCE(!I915_READ(CSR_PROGRAM_BASE), + "CSR program storage start is NULL\n"); + WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n"); + WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n"); } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 3f682a1a08ce..85c35fdfac65 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -463,14 +463,14 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv) bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv, SKL_DISP_PW_2); - WARN(!IS_SKYLAKE(dev), "Platform doesn't support DC5.\n"); - WARN(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n"); - WARN(pg2_enabled, "PG2 not disabled to enable DC5.\n"); + WARN_ONCE(!IS_SKYLAKE(dev), "Platform doesn't support DC5.\n"); + WARN_ONCE(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n"); + WARN_ONCE(pg2_enabled, "PG2 not disabled to enable DC5.\n"); - WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5), - "DC5 already programmed to be enabled.\n"); - WARN(dev_priv->pm.suspended, - "DC5 cannot be enabled, if platform is runtime-suspended.\n"); + WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5), + "DC5 already programmed to be enabled.\n"); + WARN_ONCE(dev_priv->pm.suspended, + "DC5 cannot be enabled, if platform is runtime-suspended.\n"); assert_csr_loaded(dev_priv); } @@ -486,8 +486,8 @@ static void assert_can_disable_dc5(struct drm_i915_private *dev_priv) if (dev_priv->power_domains.initializing) return; - WARN(!pg2_enabled, "PG2 not enabled to disable DC5.\n"); - WARN(dev_priv->pm.suspended, + WARN_ONCE(!pg2_enabled, "PG2 not enabled to disable DC5.\n"); + WARN_ONCE(dev_priv->pm.suspended, "Disabling of DC5 while platform is runtime-suspended should never happen.\n"); } @@ -526,12 +526,12 @@ static void assert_can_enable_dc6(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; - WARN(!IS_SKYLAKE(dev), "Platform doesn't support DC6.\n"); - WARN(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n"); - WARN(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE, - "Backlight is not disabled.\n"); - WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), - "DC6 already programmed to be enabled.\n"); + WARN_ONCE(!IS_SKYLAKE(dev), "Platform doesn't support DC6.\n"); + WARN_ONCE(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n"); + WARN_ONCE(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE, + "Backlight is not disabled.\n"); + WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), + "DC6 already programmed to be enabled.\n"); assert_csr_loaded(dev_priv); } @@ -546,8 +546,8 @@ static void assert_can_disable_dc6(struct drm_i915_private *dev_priv) return; assert_csr_loaded(dev_priv); - WARN(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), - "DC6 already programmed to be disabled.\n"); + WARN_ONCE(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), + "DC6 already programmed to be disabled.\n"); } static void skl_enable_dc6(struct drm_i915_private *dev_priv) @@ -670,7 +670,7 @@ static void skl_set_power_well(struct drm_i915_private *dev_priv, wait_for((state = intel_csr_load_status_get(dev_priv)) != FW_UNINITIALIZED, 1000); if (state != FW_LOADED) - DRM_ERROR("CSR firmware not ready (%d)\n", + DRM_DEBUG("CSR firmware not ready (%d)\n", state); else if (SKL_ENABLE_DC6(dev)) From 87bcdd2e275d75e374434a4ad7da66bbb6da1d17 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Sep 2015 14:55:00 -0700 Subject: [PATCH 13/80] drm/i915: don't try to load GuC fw on pre-gen9 This avoids some bad register writes and generally feels more correct than unconditionally trying to redirect interrupts and such. References: https://bugs.freedesktop.org/show_bug.cgi?id=91777 Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 760cfba22e71..acb1f23c4dbf 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4687,19 +4687,22 @@ i915_gem_init_hw(struct drm_device *dev) } /* We can't enable contexts until all firmware is loaded */ - ret = intel_guc_ucode_load(dev); - if (ret) { - /* - * If we got an error and GuC submission is enabled, map - * the error to -EIO so the GPU will be declared wedged. - * OTOH, if we didn't intend to use the GuC anyway, just - * discard the error and carry on. - */ - DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret, - i915.enable_guc_submission ? "" : " (ignored)"); - ret = i915.enable_guc_submission ? -EIO : 0; - if (ret) - goto out; + if (HAS_GUC_UCODE(dev)) { + ret = intel_guc_ucode_load(dev); + if (ret) { + /* + * If we got an error and GuC submission is enabled, map + * the error to -EIO so the GPU will be declared wedged. + * OTOH, if we didn't intend to use the GuC anyway, just + * discard the error and carry on. + */ + DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret, + i915.enable_guc_submission ? "" : + " (ignored)"); + ret = i915.enable_guc_submission ? -EIO : 0; + if (ret) + goto out; + } } /* Now it is safe to go back round and do everything else: */ From e84fe80337dc85cca07d0417ea97edbec4789d8b Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Fri, 11 Sep 2015 12:53:46 +0100 Subject: [PATCH 14/80] drm/i915: Split alloc from init for lrc Extend init/init_hw split to context init. - Move context initialisation in to i915_gem_init_hw - Move one off initialisation for render ring to i915_gem_validate_context - Move default context initialisation to logical_ring_init Rename intel_lr_context_deferred_create to intel_lr_context_deferred_alloc, to reflect reduced functionality & alloc/init split. This patch is intended to split out the allocation of resources & initialisation to allow easier reuse of code for resume/gpu reset. v2: Removed function ptr wrapping of do_switch_context (Daniel Vetter) Left ->init_context int intel_lr_context_deferred_alloc (Daniel Vetter) Remove unnecessary init flag & ring type test. (Daniel Vetter) Improve commit message (Daniel Vetter) v3: On init/reinit, set the hw next sequence number to the sw next sequence number. This is set to 1 at driver load time. This prevents the seqno being reset on reinit (Chris Wilson) v4: Set seqno back to ~0 - 0x1000 at start-of-day, and increment by 0x100 on reset. This makes it obvious which bbs are which after a reset. (David Gordon & John Harrison) Rebase. v5: Rebase. Fixed rebase breakage. Put context pinning in separate function. Removed code churn. (Thomas Daniel) v6: Cleanup up issues introduced in v2 & v5 (Thomas Daniel) Issue: VIZ-4798 Signed-off-by: Nick Hoath Cc: Daniel Vetter Cc: Chris Wilson Cc: John Harrison Cc: David Gordon Cc: Thomas Daniel Reviewed-by: Thomas Daniel Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_gem.c | 22 ++- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/intel_lrc.c | 164 ++++++++++----------- drivers/gpu/drm/i915/intel_lrc.h | 4 +- 5 files changed, 99 insertions(+), 94 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2994ce5f6476..7ddf17b1cee7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -890,7 +890,6 @@ struct intel_context { } legacy_hw_ctx; /* Execlists */ - bool rcs_initialized; struct { struct drm_i915_gem_object *state; struct intel_ringbuffer *ringbuf; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index acb1f23c4dbf..cb0df7efe083 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4609,14 +4609,8 @@ int i915_gem_init_rings(struct drm_device *dev) goto cleanup_vebox_ring; } - ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000)); - if (ret) - goto cleanup_bsd2_ring; - return 0; -cleanup_bsd2_ring: - intel_cleanup_ring_buffer(&dev_priv->ring[VCS2]); cleanup_vebox_ring: intel_cleanup_ring_buffer(&dev_priv->ring[VECS]); cleanup_blt_ring: @@ -4705,6 +4699,14 @@ i915_gem_init_hw(struct drm_device *dev) } } + /* + * Increment the next seqno by 0x100 so we have a visible break + * on re-initialisation + */ + ret = i915_gem_set_seqno(dev, dev_priv->next_seqno+0x100); + if (ret) + goto out; + /* Now it is safe to go back round and do everything else: */ for_each_ring(ring, dev_priv, i) { struct drm_i915_gem_request *req; @@ -4906,6 +4908,14 @@ i915_gem_load(struct drm_device *dev) dev_priv->num_fence_regs = I915_READ(vgtif_reg(avail_rs.fence_num)); + /* + * Set initial sequence number for requests. + * Using this number allows the wraparound to happen early, + * catching any obvious problems. + */ + dev_priv->next_seqno = ((u32)~0 - 0x1100); + dev_priv->last_seqno = ((u32)~0 - 0x1101); + /* Initialize fence registers to zero */ INIT_LIST_HEAD(&dev_priv->mm.fence_list); i915_gem_restore_fences(dev); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 923a3c4bf0b7..98952b4b9e7f 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1009,7 +1009,7 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file, } if (i915.enable_execlists && !ctx->engine[ring->id].state) { - int ret = intel_lr_context_deferred_create(ctx, ring); + int ret = intel_lr_context_deferred_alloc(ctx, ring); if (ret) { DRM_DEBUG("Could not create LRC %u: %d\n", ctx_id, ret); return ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index c3fca4be7a8c..0a53c96c4d86 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -221,6 +221,9 @@ enum { #define CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT 0x17 static int intel_lr_context_pin(struct drm_i915_gem_request *rq); +static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, + struct drm_i915_gem_object *default_ctx_obj); + /** * intel_sanitize_enable_execlists() - sanitize i915.enable_execlists @@ -1020,39 +1023,54 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req) return 0; } -static int intel_lr_context_pin(struct drm_i915_gem_request *rq) +static int intel_lr_context_do_pin(struct intel_engine_cs *ring, + struct drm_i915_gem_object *ctx_obj, + struct intel_ringbuffer *ringbuf) { - struct drm_i915_private *dev_priv = rq->i915; - struct intel_engine_cs *ring = rq->ring; - struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; - struct intel_ringbuffer *ringbuf = rq->ringbuf; + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; int ret = 0; WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); - if (rq->ctx->engine[ring->id].pin_count++ == 0) { - ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, - PIN_OFFSET_BIAS | GUC_WOPCM_TOP); - if (ret) - goto reset_pin_count; + ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, + PIN_OFFSET_BIAS | GUC_WOPCM_TOP); + if (ret) + return ret; - ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf); - if (ret) - goto unpin_ctx_obj; + ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf); + if (ret) + goto unpin_ctx_obj; - ctx_obj->dirty = true; + ctx_obj->dirty = true; - /* Invalidate GuC TLB. */ - if (i915.enable_guc_submission) - I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); - } + /* Invalidate GuC TLB. */ + if (i915.enable_guc_submission) + I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); return ret; unpin_ctx_obj: i915_gem_object_ggtt_unpin(ctx_obj); + + return ret; +} + +static int intel_lr_context_pin(struct drm_i915_gem_request *rq) +{ + int ret = 0; + struct intel_engine_cs *ring = rq->ring; + struct drm_i915_gem_object *ctx_obj = rq->ctx->engine[ring->id].state; + struct intel_ringbuffer *ringbuf = rq->ringbuf; + + if (rq->ctx->engine[ring->id].pin_count++ == 0) { + ret = intel_lr_context_do_pin(ring, ctx_obj, ringbuf); + if (ret) + goto reset_pin_count; + } + return ret; + reset_pin_count: rq->ctx->engine[ring->id].pin_count = 0; - return ret; } @@ -1462,6 +1480,9 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring) struct drm_device *dev = ring->dev; struct drm_i915_private *dev_priv = dev->dev_private; + lrc_setup_hardware_status_page(ring, + ring->default_context->engine[ring->id].state); + I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff); @@ -1901,7 +1922,21 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rin if (ret) return ret; - ret = intel_lr_context_deferred_create(ring->default_context, ring); + ret = intel_lr_context_deferred_alloc(ring->default_context, ring); + if (ret) + return ret; + + /* As this is the default context, always pin it */ + ret = intel_lr_context_do_pin( + ring, + ring->default_context->engine[ring->id].state, + ring->default_context->engine[ring->id].ringbuf); + if (ret) { + DRM_ERROR( + "Failed to pin and map ringbuffer %s: %d\n", + ring->name, ret); + return ret; + } return ret; } @@ -2124,14 +2159,8 @@ int intel_logical_rings_init(struct drm_device *dev) goto cleanup_vebox_ring; } - ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000)); - if (ret) - goto cleanup_bsd2_ring; - return 0; -cleanup_bsd2_ring: - intel_logical_ring_cleanup(&dev_priv->ring[VCS2]); cleanup_vebox_ring: intel_logical_ring_cleanup(&dev_priv->ring[VECS]); cleanup_blt_ring: @@ -2401,7 +2430,7 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, } /** - * intel_lr_context_deferred_create() - create the LRC specific bits of a context + * intel_lr_context_deferred_alloc() - create the LRC specific bits of a context * @ctx: LR context to create. * @ring: engine to be used with the context. * @@ -2413,12 +2442,11 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, * * Return: non-zero on error. */ -int intel_lr_context_deferred_create(struct intel_context *ctx, + +int intel_lr_context_deferred_alloc(struct intel_context *ctx, struct intel_engine_cs *ring) { - const bool is_global_default_ctx = (ctx == ring->default_context); struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *ctx_obj; uint32_t context_size; struct intel_ringbuffer *ringbuf; @@ -2438,82 +2466,50 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, return -ENOMEM; } - if (is_global_default_ctx) { - ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, - PIN_OFFSET_BIAS | GUC_WOPCM_TOP); - if (ret) { - DRM_DEBUG_DRIVER("Pin LRC backing obj failed: %d\n", - ret); - drm_gem_object_unreference(&ctx_obj->base); - return ret; - } - - /* Invalidate GuC TLB. */ - if (i915.enable_guc_submission) - I915_WRITE(GEN8_GTCR, GEN8_GTCR_INVALIDATE); - } - ringbuf = intel_engine_create_ringbuffer(ring, 4 * PAGE_SIZE); if (IS_ERR(ringbuf)) { ret = PTR_ERR(ringbuf); - goto error_unpin_ctx; - } - - if (is_global_default_ctx) { - ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf); - if (ret) { - DRM_ERROR( - "Failed to pin and map ringbuffer %s: %d\n", - ring->name, ret); - goto error_ringbuf; - } + goto error_deref_obj; } ret = populate_lr_context(ctx, ctx_obj, ring, ringbuf); if (ret) { DRM_DEBUG_DRIVER("Failed to populate LRC: %d\n", ret); - goto error; + goto error_ringbuf; } ctx->engine[ring->id].ringbuf = ringbuf; ctx->engine[ring->id].state = ctx_obj; - if (ctx == ring->default_context) - lrc_setup_hardware_status_page(ring, ctx_obj); - else if (ring->id == RCS && !ctx->rcs_initialized) { - if (ring->init_context) { - struct drm_i915_gem_request *req; + if (ctx != ring->default_context && ring->init_context) { + struct drm_i915_gem_request *req; - ret = i915_gem_request_alloc(ring, ctx, &req); - if (ret) - return ret; - - ret = ring->init_context(req); - if (ret) { - DRM_ERROR("ring init context: %d\n", ret); - i915_gem_request_cancel(req); - ctx->engine[ring->id].ringbuf = NULL; - ctx->engine[ring->id].state = NULL; - goto error; - } - - i915_add_request_no_flush(req); + ret = i915_gem_request_alloc(ring, + ctx, &req); + if (ret) { + DRM_ERROR("ring create req: %d\n", + ret); + i915_gem_request_cancel(req); + goto error_ringbuf; } - ctx->rcs_initialized = true; + ret = ring->init_context(req); + if (ret) { + DRM_ERROR("ring init context: %d\n", + ret); + i915_gem_request_cancel(req); + goto error_ringbuf; + } + i915_add_request_no_flush(req); } - return 0; -error: - if (is_global_default_ctx) - intel_unpin_ringbuffer_obj(ringbuf); error_ringbuf: intel_ringbuffer_free(ringbuf); -error_unpin_ctx: - if (is_global_default_ctx) - i915_gem_object_ggtt_unpin(ctx_obj); +error_deref_obj: drm_gem_object_unreference(&ctx_obj->base); + ctx->engine[ring->id].ringbuf = NULL; + ctx->engine[ring->id].state = NULL; return ret; } diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 4cc54b371afd..69d99f0df400 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -75,8 +75,8 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf, #define LRC_STATE_PN (LRC_PPHWSP_PN + 1) void intel_lr_context_free(struct intel_context *ctx); -int intel_lr_context_deferred_create(struct intel_context *ctx, - struct intel_engine_cs *ring); +int intel_lr_context_deferred_alloc(struct intel_context *ctx, + struct intel_engine_cs *ring); void intel_lr_context_unpin(struct drm_i915_gem_request *req); void intel_lr_context_reset(struct drm_device *dev, struct intel_context *ctx); From 374887bae861be2e691381f704b3d6068a54457c Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sun, 13 Sep 2015 21:08:31 +0900 Subject: [PATCH 15/80] drm/i915: Fix warnings while make xmldocs caused by intel_lrc.c This patch fix following warnings while "make xmldocs". .//drivers/gpu/drm/i915/intel_lrc.c:780: warning: No description found for parameter 'req' .//drivers/gpu/drm/i915/intel_lrc.c:780: warning: Excess function parameter 'request' description in 'intel_logical_ring_begin' .//drivers/gpu/drm/i915/intel_lrc.c:780: warning: Excess function parameter 'ctx' description in 'intel_logical_ring_begin' Signed-off-by: Masanari Iida Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 0a53c96c4d86..fe06accb0797 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -802,8 +802,7 @@ static int logical_ring_prepare(struct drm_i915_gem_request *req, int bytes) /** * intel_logical_ring_begin() - prepare the logical ringbuffer to accept some commands * - * @request: The request to start some new work for - * @ctx: Logical ring context whose ringbuffer is being prepared. + * @req: The request to start some new work for * @num_dwords: number of DWORDs that we plan to write to the ringbuffer. * * The ringbuffer might not be ready to accept the commands right away (maybe it needs to From d7884d69a524b92d9770bcdc03df3c5a6120c2d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Sep 2015 21:14:29 +0300 Subject: [PATCH 16/80] drm/i915: Set stolen reserved to 0 for pre-g4x platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This stolen reserved stuff was introduced on g4x, so no need to waste stolen on older platforms. Unfortunately configdb is no more so I can't look up the right way to detect this stuff. I do have one hint as to where the register might be on ctg, but I don't have a ctg to test it, and on the elk I have here it doesn't contain sensible looking data. For ilk grits suggegsts it might be in the same place as on snb (the original PCI reg, not the mirror) but I can't be entirely sure about it The register shows a round zero on my ilk. So when there's no really good data for any of these platforms leave the current "assume 1MiB" approach in place. Cc: Paulo Zanoni Cc: Chris Wilson Signed-off-by: Ville Syrjälä Acked-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_stolen.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index f361c4a56995..bf26ecc3781b 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -281,7 +281,7 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv, int i915_gem_init_stolen(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long reserved_total, reserved_base, reserved_size; + unsigned long reserved_total, reserved_base = 0, reserved_size; unsigned long stolen_top; mutex_init(&dev_priv->mm.stolen_lock); @@ -306,6 +306,9 @@ int i915_gem_init_stolen(struct drm_device *dev) case 2: case 3: case 4: + if (!IS_G4X(dev)) + break; + /* fall through */ case 5: /* Assume the gen6 maximum for the older platforms. */ reserved_size = 1024 * 1024; From 6b6d5626750d72a22180a6e094cf95acd1d85c9b Mon Sep 17 00:00:00 2001 From: Robert Beckett Date: Tue, 8 Sep 2015 10:31:52 +0100 Subject: [PATCH 17/80] drm/i915/gen9: WA ST Unit Power Optimization Disable WaDisableSTUnitPowerOptimization:skl,bxt Signed-off-by: Robert Beckett Signed-off-by: Arun Siluvery Reviewed-by: Sagar Arun Kamble Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_ringbuffer.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 495ac17b04c7..dd3d235b27ac 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6943,6 +6943,9 @@ enum skl_disp_power_wells { #define HSW_ROW_CHICKEN3 0xe49c #define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6) +#define HALF_SLICE_CHICKEN2 0xe180 +#define GEN8_ST_PO_DISABLE (1<<13) + #define HALF_SLICE_CHICKEN3 0xe184 #define HSW_SAMPLE_C_PERFORMANCE (1<<9) #define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 684e0693dae9..16a4eada60a1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -990,6 +990,9 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) GEN8_SAMPLER_POWER_BYPASS_DIS); } + /* WaDisableSTUnitPowerOptimization:skl,bxt */ + WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); + return 0; } From d1b9d039de79a1cdd789d1547251d5ba0fad573b Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Mon, 14 Sep 2015 21:35:42 +0530 Subject: [PATCH 18/80] drm/i915: Fix fb object's frontbuffer-bits Shared frontbuffer bits are causing warnings when same FB is displayed in another plane without clearing the bits from previous plane. v2: Removing coversion of fb bits to 64 bit as it is not needed for now. (Daniel) Change-Id: Ic2df80747f314b82afd22f8326297c57d1e652c6 Signed-off-by: Sagar Arun Kamble Signed-off-by: Kumar, Mahesh [danvet: Drop INTEL_FRONTBUFFER_SPRITE_MASK since unused.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 15 ++++++++------- drivers/gpu/drm/i915/intel_sprite.c | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7ddf17b1cee7..677faa8be228 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2011,25 +2011,26 @@ struct drm_i915_gem_object_ops { /* * Frontbuffer tracking bits. Set in obj->frontbuffer_bits while a gem bo is - * considered to be the frontbuffer for the given plane interface-vise. This + * considered to be the frontbuffer for the given plane interface-wise. This * doesn't mean that the hw necessarily already scans it out, but that any * rendering (by the cpu or gpu) will land in the frontbuffer eventually. * * We have one bit per pipe and per scanout plane type. */ -#define INTEL_FRONTBUFFER_BITS_PER_PIPE 4 +#define INTEL_MAX_SPRITE_BITS_PER_PIPE 5 +#define INTEL_FRONTBUFFER_BITS_PER_PIPE 8 #define INTEL_FRONTBUFFER_BITS \ (INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES) #define INTEL_FRONTBUFFER_PRIMARY(pipe) \ (1 << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) #define INTEL_FRONTBUFFER_CURSOR(pipe) \ - (1 << (1 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) -#define INTEL_FRONTBUFFER_SPRITE(pipe) \ - (1 << (2 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) + (1 << (1 + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) +#define INTEL_FRONTBUFFER_SPRITE(pipe, plane) \ + (1 << (2 + plane + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) #define INTEL_FRONTBUFFER_OVERLAY(pipe) \ - (1 << (3 +(INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) + (1 << (2 + INTEL_MAX_SPRITE_BITS_PER_PIPE + (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))) #define INTEL_FRONTBUFFER_ALL_MASK(pipe) \ - (0xf << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) + (0xff << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe))) struct drm_i915_gem_object { struct drm_gem_object base; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 9553859ca151..4d27243656e3 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1123,7 +1123,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) intel_plane->pipe = pipe; intel_plane->plane = plane; - intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe); + intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane); intel_plane->check_plane = intel_check_sprite_plane; intel_plane->commit_plane = intel_commit_sprite_plane; possible_crtcs = (1 << pipe); From d9072a3e80bd0f2e95d6a452987899039ba808ed Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 15 Sep 2015 05:58:44 -0700 Subject: [PATCH 19/80] drm/i915: fix kernel-doc warnings in i915_gem.c Fix the following 'make htmldocs' warnings: .//drivers/gpu/drm/i915/i915_gem.c:1729: warning: No description found for parameter 'vma' .//drivers/gpu/drm/i915/i915_gem.c:1729: warning: No description found for parameter 'vmf' .//drivers/gpu/drm/i915/i915_gem.c:4962: warning: No description found for parameter 'old' .//drivers/gpu/drm/i915/i915_gem.c:4962: warning: No description found for parameter 'new' .//drivers/gpu/drm/i915/i915_gem.c:4962: warning: No description found for parameter 'frontbuffer_bits' Signed-off-by: Geliang Tang Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_gem.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cb0df7efe083..e1b6457b5404 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1713,8 +1713,8 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, /** * i915_gem_fault - fault a page into the GTT - * vma: VMA in question - * vmf: fault info + * @vma: VMA in question + * @vmf: fault info * * The fault handler is set up by drm_gem_mmap() when a object is GTT mapped * from userspace. The fault handler takes care of binding the object to @@ -4985,9 +4985,9 @@ int i915_gem_open(struct drm_device *dev, struct drm_file *file) /** * i915_gem_track_fb - update frontbuffer tracking - * old: current GEM buffer for the frontbuffer slots - * new: new GEM buffer for the frontbuffer slots - * frontbuffer_bits: bitmask of frontbuffer slots + * @old: current GEM buffer for the frontbuffer slots + * @new: new GEM buffer for the frontbuffer slots + * @frontbuffer_bits: bitmask of frontbuffer slots * * This updates the frontbuffer tracking bits @frontbuffer_bits by clearing them * from @old and setting them in @new. Both @old and @new can be NULL. From eb120ef6a3e18780e7464e7de70221d06dfe5845 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 15 Sep 2015 14:19:32 -0700 Subject: [PATCH 20/80] drm/i915: add more debug info for when atomic updates fail v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I used these additional fields to track down the issue I saw on HSW. v2: move debug fields into a substruct (Ville) v3: clean up debug code more (Ville) References: https://bugs.freedesktop.org/show_bug.cgi?id=91579 Signed-off-by: Jesse Barnes Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_drv.h | 8 ++++++-- drivers/gpu/drm/i915/intel_sprite.c | 25 +++++++++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e9e5cfd2d9b8..8760814e81f6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -565,8 +565,12 @@ struct intel_crtc { int scanline_offset; - unsigned start_vbl_count; - ktime_t start_vbl_time; + struct { + unsigned start_vbl_count; + ktime_t start_vbl_time; + int min_vbl, max_vbl; + int scanline_start; + } debug; struct intel_crtc_atomic_commit atomic; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 4d27243656e3..7de121d9bab2 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -95,7 +95,6 @@ void intel_pipe_update_start(struct intel_crtc *crtc) max = vblank_start - 1; local_irq_disable(); - crtc->start_vbl_count = 0; if (min <= 0 || max <= 0) return; @@ -134,11 +133,15 @@ void intel_pipe_update_start(struct intel_crtc *crtc) drm_crtc_vblank_put(&crtc->base); - crtc->start_vbl_time = ktime_get(); - crtc->start_vbl_count = dev->driver->get_vblank_counter(dev, pipe); + crtc->debug.min_vbl = min; + crtc->debug.max_vbl = max; + crtc->debug.scanline_start = scanline; + crtc->debug.start_vbl_time = ktime_get(); + crtc->debug.start_vbl_count = + dev->driver->get_vblank_counter(dev, pipe); trace_i915_pipe_update_vblank_evaded(crtc, min, max, - crtc->start_vbl_count); + crtc->debug.start_vbl_count); } /** @@ -154,6 +157,7 @@ void intel_pipe_update_end(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; enum pipe pipe = crtc->pipe; + int scanline_end = intel_get_crtc_scanline(crtc); u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe); ktime_t end_vbl_time = ktime_get(); @@ -161,10 +165,15 @@ void intel_pipe_update_end(struct intel_crtc *crtc) local_irq_enable(); - if (crtc->start_vbl_count && crtc->start_vbl_count != end_vbl_count) - DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us\n", - pipe_name(pipe), crtc->start_vbl_count, end_vbl_count, - ktime_us_delta(end_vbl_time, crtc->start_vbl_time)); + if (crtc->debug.start_vbl_count && + crtc->debug.start_vbl_count != end_vbl_count) { + DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n", + pipe_name(pipe), crtc->debug.start_vbl_count, + end_vbl_count, + ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), + crtc->debug.min_vbl, crtc->debug.max_vbl, + crtc->debug.scanline_start, scanline_end); + } } static void From d637ce3f6dcc0bec950ed4e03e53162500d6b28b Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 Sep 2015 08:08:32 -0700 Subject: [PATCH 21/80] drm/i915: cleanup pipe_update trace functions with new crtc debug info v3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the new debug info in the intel_crtc struct in these functions rather than passing them as args. v2: move min/max assignment back above first trace call (Ville) use scanline from crtc->debug rather than fetching a new one (Ville) v3: fix up trace_i915_pipe_update_end, needs end scanline (Ville) Requested-by: Ville Syrjälä Signed-off-by: Jesse Barnes Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_trace.h | 26 +++++++++++++------------- drivers/gpu/drm/i915/intel_sprite.c | 11 +++++------ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index e6b5c7470ba0..d0993bc814ea 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -17,8 +17,8 @@ /* pipe updates */ TRACE_EVENT(i915_pipe_update_start, - TP_PROTO(struct intel_crtc *crtc, u32 min, u32 max), - TP_ARGS(crtc, min, max), + TP_PROTO(struct intel_crtc *crtc), + TP_ARGS(crtc), TP_STRUCT__entry( __field(enum pipe, pipe) @@ -33,8 +33,8 @@ TRACE_EVENT(i915_pipe_update_start, __entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev, crtc->pipe); __entry->scanline = intel_get_crtc_scanline(crtc); - __entry->min = min; - __entry->max = max; + __entry->min = crtc->debug.min_vbl; + __entry->max = crtc->debug.max_vbl; ), TP_printk("pipe %c, frame=%u, scanline=%u, min=%u, max=%u", @@ -43,8 +43,8 @@ TRACE_EVENT(i915_pipe_update_start, ); TRACE_EVENT(i915_pipe_update_vblank_evaded, - TP_PROTO(struct intel_crtc *crtc, u32 min, u32 max, u32 frame), - TP_ARGS(crtc, min, max, frame), + TP_PROTO(struct intel_crtc *crtc), + TP_ARGS(crtc), TP_STRUCT__entry( __field(enum pipe, pipe) @@ -56,10 +56,10 @@ TRACE_EVENT(i915_pipe_update_vblank_evaded, TP_fast_assign( __entry->pipe = crtc->pipe; - __entry->frame = frame; - __entry->scanline = intel_get_crtc_scanline(crtc); - __entry->min = min; - __entry->max = max; + __entry->frame = crtc->debug.start_vbl_count; + __entry->scanline = crtc->debug.scanline_start; + __entry->min = crtc->debug.min_vbl; + __entry->max = crtc->debug.max_vbl; ), TP_printk("pipe %c, frame=%u, scanline=%u, min=%u, max=%u", @@ -68,8 +68,8 @@ TRACE_EVENT(i915_pipe_update_vblank_evaded, ); TRACE_EVENT(i915_pipe_update_end, - TP_PROTO(struct intel_crtc *crtc, u32 frame), - TP_ARGS(crtc, frame), + TP_PROTO(struct intel_crtc *crtc, u32 frame, int scanline_end), + TP_ARGS(crtc, frame, scanline_end), TP_STRUCT__entry( __field(enum pipe, pipe) @@ -80,7 +80,7 @@ TRACE_EVENT(i915_pipe_update_end, TP_fast_assign( __entry->pipe = crtc->pipe; __entry->frame = frame; - __entry->scanline = intel_get_crtc_scanline(crtc); + __entry->scanline = scanline_end; ), TP_printk("pipe %c, frame=%u, scanline=%u", diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 7de121d9bab2..79f7cc247ab7 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -102,7 +102,9 @@ void intel_pipe_update_start(struct intel_crtc *crtc) if (WARN_ON(drm_crtc_vblank_get(&crtc->base))) return; - trace_i915_pipe_update_start(crtc, min, max); + crtc->debug.min_vbl = min; + crtc->debug.max_vbl = max; + trace_i915_pipe_update_start(crtc); for (;;) { /* @@ -133,15 +135,12 @@ void intel_pipe_update_start(struct intel_crtc *crtc) drm_crtc_vblank_put(&crtc->base); - crtc->debug.min_vbl = min; - crtc->debug.max_vbl = max; crtc->debug.scanline_start = scanline; crtc->debug.start_vbl_time = ktime_get(); crtc->debug.start_vbl_count = dev->driver->get_vblank_counter(dev, pipe); - trace_i915_pipe_update_vblank_evaded(crtc, min, max, - crtc->debug.start_vbl_count); + trace_i915_pipe_update_vblank_evaded(crtc); } /** @@ -161,7 +160,7 @@ void intel_pipe_update_end(struct intel_crtc *crtc) u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe); ktime_t end_vbl_time = ktime_get(); - trace_i915_pipe_update_end(crtc, end_vbl_count); + trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end); local_irq_enable(); From 9aa6114253a9d01513796f6b44eda9838dc7bf3b Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 14 Sep 2015 19:24:18 -0700 Subject: [PATCH 22/80] drm/i915: Don't leak VBT mode data We allocate memory for LVDS modes while parsing the VBT at startup, but never free this memory when the driver is unloaded, causing a small leak. Signed-off-by: Matt Roper Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_dma.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 066a0efa75d7..c0695504dd8f 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1137,6 +1137,10 @@ int i915_driver_unload(struct drm_device *dev) dev_priv->vbt.child_dev = NULL; dev_priv->vbt.child_dev_num = 0; } + kfree(dev_priv->vbt.sdvo_lvds_vbt_mode); + dev_priv->vbt.sdvo_lvds_vbt_mode = NULL; + kfree(dev_priv->vbt.lfp_lvds_vbt_mode); + dev_priv->vbt.lfp_lvds_vbt_mode = NULL; vga_switcheroo_unregister_client(dev->pdev); vga_client_register(dev->pdev, NULL, NULL, NULL); From b5dada82ad624b69a2229c819d6a30b664a5606f Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Thu, 17 Sep 2015 14:20:32 +0100 Subject: [PATCH 23/80] drm/i915/bxt: Fix wrongly placed ')' in I915_READ() Not the first time! not the last time? There is a possibility to use gcc 5's -Wbool-compare to try and compare (reg) in those macros to a constant and gcc will warn that the comparison between a boolean expression and a constant is always either true or false. Maybe. Cc: Imre Deak Signed-off-by: Damien Lespiau Reviewed-by: Imre Deak Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_ddi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 4823184258a0..5b600bf1adcb 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2882,7 +2882,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, * here just read out lanes 0/1 and output a note if lanes 2/3 differ. */ hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); - if (I915_READ(BXT_PORT_PCS_DW12_LN23(port) != hw_state->pcsdw12)) + if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12) DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n", hw_state->pcsdw12, I915_READ(BXT_PORT_PCS_DW12_LN23(port))); From a78695d3ea045cd9977a8397c89171d762708f86 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 18 Sep 2015 15:54:50 +0300 Subject: [PATCH 24/80] drm/i915/skl: handle port E in cpt_digital_port_connected SKL port E handling was added in commit 26951caf55d73ceb1967b0bf12f6d0b96853508e Author: Xiong Zhang Date: Mon Aug 17 15:55:50 2015 +0800 drm/i915/skl: enable DDI-E hotplug but the whole function was moved in a another branch in commit b93433ccf64846820b9448f5ff5dd4348b58a8ed Author: Jani Nikula Date: Thu Aug 20 10:47:36 2015 +0300 drm/i915: move ibx_digital_port_connected to intel_dp.c and the addition was lost at some backmerge that I was unable to identify. Put it back in. Tested-by: Tomi Sarvela Reviewed-by: Mika Kuoppala Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b8c4fc5a92f1..9700f774dc6c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4582,6 +4582,9 @@ static bool cpt_digital_port_connected(struct drm_i915_private *dev_priv, case PORT_D: bit = SDE_PORTD_HOTPLUG_CPT; break; + case PORT_E: + bit = SDE_PORTE_HOTPLUG_SPT; + break; default: MISSING_CASE(port->port); return false; From 5389e916c3b64c3dd249018dfaf983e2e3a06c6f Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Fri, 4 Sep 2015 21:06:15 +0200 Subject: [PATCH 25/80] drm/i915: Spell vga_switcheroo consistently Currently everyone and their dog has their own favourite spelling for vga_switcheroo. This makes it hard to grep dmesg for log entries relating to vga_switcheroo. It also makes it hard to find related source files in the tree. vga_switcheroo.c uses pr_fmt "vga_switcheroo". Use that everywhere. Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_acpi.c | 2 +- drivers/gpu/drm/i915/intel_panel.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index d96eee1ae9c5..8b13b9d0373a 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c @@ -146,7 +146,7 @@ static bool intel_dsm_detect(void) if (vga_count == 2 && has_dsm) { acpi_get_name(intel_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); - DRM_DEBUG_DRIVER("VGA switcheroo: detected DSM switching method %s handle\n", + DRM_DEBUG_DRIVER("vga_switcheroo: detected DSM switching method %s handle\n", acpi_method_name); return true; } diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 2034438a0664..2c11b4eedfc6 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -821,7 +821,7 @@ void intel_panel_disable_backlight(struct intel_connector *connector) return; /* - * Do not disable backlight on the vgaswitcheroo path. When switching + * Do not disable backlight on the vga_switcheroo path. When switching * away from i915, the other client may depend on i915 to handle the * backlight. This will leave the backlight on unnecessarily when * another client is not activated. From 604ef7346862bb761a091932e99c14204ff4050a Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Mon, 21 Sep 2015 15:33:35 +0200 Subject: [PATCH 26/80] drm/i915: fix handling gen8_emit_flush_coherentl3_wa result The function can return negative value. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2038576 Signed-off-by: Andrzej Hajda Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index fe06accb0797..ff9a481ed997 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1254,9 +1254,10 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring, /* WaFlushCoherentL3CacheLinesAtContextSwitch:bdw */ if (IS_BROADWELL(ring->dev)) { - index = gen8_emit_flush_coherentl3_wa(ring, batch, index); - if (index < 0) - return index; + int rc = gen8_emit_flush_coherentl3_wa(ring, batch, index); + if (rc < 0) + return rc; + index = rc; } /* WaClearSlmSpaceAtContextSwitch:bdw,chv */ From 25e1793f6c642604b13e33bc81a9c8d48d652c86 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 8 Sep 2015 13:56:23 +0200 Subject: [PATCH 27/80] drm/i915: Mark debug mod options as _unsafe We don't want random people to touch these. Especially true since we've just screwed up SKL by holding it way too long under the preliminary flag because of some ABI issues. And now there's howtos all over the internets about how to set this. Same pretty much for anything else. Cc: Jani Nikula Signed-off-by: Daniel Vetter Reviewed-by: Jani Nikula [danvet: drop fastboot changes, that option is gone.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_params.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index ca060d5549bb..ca9b8f644ffe 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -61,7 +61,7 @@ MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (0=disable, " "1=on, -1=force vga console preference [default])"); -module_param_named(panel_ignore_lid, i915.panel_ignore_lid, int, 0600); +module_param_named_unsafe(panel_ignore_lid, i915.panel_ignore_lid, int, 0600); MODULE_PARM_DESC(panel_ignore_lid, "Override lid status (0=autodetect, 1=autodetect disabled [default], " "-1=force lid closed, -2=force lid open)"); @@ -84,17 +84,17 @@ MODULE_PARM_DESC(enable_fbc, "Enable frame buffer compression for power savings " "(default: -1 (use per-chip default))"); -module_param_named(lvds_channel_mode, i915.lvds_channel_mode, int, 0600); +module_param_named_unsafe(lvds_channel_mode, i915.lvds_channel_mode, int, 0600); MODULE_PARM_DESC(lvds_channel_mode, "Specify LVDS channel mode " "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)"); -module_param_named(lvds_use_ssc, i915.panel_use_ssc, int, 0600); +module_param_named_unsafe(lvds_use_ssc, i915.panel_use_ssc, int, 0600); MODULE_PARM_DESC(lvds_use_ssc, "Use Spread Spectrum Clock with panels [LVDS/eDP] " "(default: auto from VBT)"); -module_param_named(vbt_sdvo_panel_type, i915.vbt_sdvo_panel_type, int, 0600); +module_param_named_unsafe(vbt_sdvo_panel_type, i915.vbt_sdvo_panel_type, int, 0600); MODULE_PARM_DESC(vbt_sdvo_panel_type, "Override/Ignore selection of SDVO panel mode in the VBT " "(-2=ignore, -1=auto [default], index in VBT BIOS table)"); @@ -102,7 +102,7 @@ MODULE_PARM_DESC(vbt_sdvo_panel_type, module_param_named_unsafe(reset, i915.reset, bool, 0600); MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)"); -module_param_named(enable_hangcheck, i915.enable_hangcheck, bool, 0644); +module_param_named_unsafe(enable_hangcheck, i915.enable_hangcheck, bool, 0644); MODULE_PARM_DESC(enable_hangcheck, "Periodically check GPU activity for detecting hangs. " "WARNING: Disabling this can cause system wide hangs. " @@ -113,23 +113,23 @@ MODULE_PARM_DESC(enable_ppgtt, "Override PPGTT usage. " "(-1=auto [default], 0=disabled, 1=aliasing, 2=full)"); -module_param_named(enable_execlists, i915.enable_execlists, int, 0400); +module_param_named_unsafe(enable_execlists, i915.enable_execlists, int, 0400); MODULE_PARM_DESC(enable_execlists, "Override execlists usage. " "(-1=auto [default], 0=disabled, 1=enabled)"); -module_param_named(enable_psr, i915.enable_psr, int, 0600); +module_param_named_unsafe(enable_psr, i915.enable_psr, int, 0600); MODULE_PARM_DESC(enable_psr, "Enable PSR (default: false)"); -module_param_named(preliminary_hw_support, i915.preliminary_hw_support, int, 0600); +module_param_named_unsafe(preliminary_hw_support, i915.preliminary_hw_support, int, 0600); MODULE_PARM_DESC(preliminary_hw_support, "Enable preliminary hardware support."); -module_param_named(disable_power_well, i915.disable_power_well, int, 0600); +module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0600); MODULE_PARM_DESC(disable_power_well, "Disable the power well when possible (default: true)"); -module_param_named(enable_ips, i915.enable_ips, int, 0600); +module_param_named_unsafe(enable_ips, i915.enable_ips, int, 0600); MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)"); module_param_named_unsafe(prefault_disable, i915.prefault_disable, bool, 0600); @@ -142,7 +142,7 @@ MODULE_PARM_DESC(load_detect_test, "Force-enable the VGA load detect code for testing (default:false). " "For developers only."); -module_param_named(invert_brightness, i915.invert_brightness, int, 0600); +module_param_named_unsafe(invert_brightness, i915.invert_brightness, int, 0600); MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " "(-1 force normal, 0 machine defaults, 1 force inversion), please " @@ -153,14 +153,14 @@ MODULE_PARM_DESC(invert_brightness, module_param_named(disable_display, i915.disable_display, bool, 0600); MODULE_PARM_DESC(disable_display, "Disable display (default: false)"); -module_param_named(disable_vtd_wa, i915.disable_vtd_wa, bool, 0600); +module_param_named_unsafe(disable_vtd_wa, i915.disable_vtd_wa, bool, 0600); MODULE_PARM_DESC(disable_vtd_wa, "Disable all VT-d workarounds (default: false)"); -module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600); +module_param_named_unsafe(enable_cmd_parser, i915.enable_cmd_parser, int, 0600); MODULE_PARM_DESC(enable_cmd_parser, "Enable command parsing (1=enabled [default], 0=disabled)"); -module_param_named(use_mmio_flip, i915.use_mmio_flip, int, 0600); +module_param_named_unsafe(use_mmio_flip, i915.use_mmio_flip, int, 0600); MODULE_PARM_DESC(use_mmio_flip, "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)"); From adda50b8b32bd559906d82fa32caeaf6c9306f59 Mon Sep 17 00:00:00 2001 From: Bob Paauwe Date: Tue, 21 Jul 2015 10:42:53 -0700 Subject: [PATCH 28/80] drm/i915/skl: Don't clear all watermarks when updating. (v2) Clearing the watermarks for all pipes/planes when updating the watermarks for a single CRTC change seems like the wrong thing to do here. As is, this code will ony update any pipe/plane watermarks that need updating and leave the remaining set to zero. Later, the watermark checks in check_wm_state() will flag these zero'd out pipe/plane watermarks and throw errors. By clearing only the watermark values associated with the specific crtc the other watermark values may remain unchanged. v2: Make sure all the dirty flags are cleared. Damien Clear all values assoicated with crtc/pipe being updated. Damien Signed-off-by: Bob Paauwe Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 920872acf4db..bec4e0e3d549 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3689,6 +3689,26 @@ static void skl_update_other_pipe_wm(struct drm_device *dev, } } +static void skl_clear_wm(struct skl_wm_values *watermarks, enum pipe pipe) +{ + watermarks->wm_linetime[pipe] = 0; + memset(watermarks->plane[pipe], 0, + sizeof(uint32_t) * 8 * I915_MAX_PLANES); + memset(watermarks->cursor[pipe], 0, sizeof(uint32_t) * 8); + memset(watermarks->plane_trans[pipe], + 0, sizeof(uint32_t) * I915_MAX_PLANES); + watermarks->cursor_trans[pipe] = 0; + + /* Clear ddb entries for pipe */ + memset(&watermarks->ddb.pipe[pipe], 0, sizeof(struct skl_ddb_entry)); + memset(&watermarks->ddb.plane[pipe], 0, + sizeof(struct skl_ddb_entry) * I915_MAX_PLANES); + memset(&watermarks->ddb.y_plane[pipe], 0, + sizeof(struct skl_ddb_entry) * I915_MAX_PLANES); + memset(&watermarks->ddb.cursor[pipe], 0, sizeof(struct skl_ddb_entry)); + +} + static void skl_update_wm(struct drm_crtc *crtc) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); @@ -3699,7 +3719,11 @@ static void skl_update_wm(struct drm_crtc *crtc) struct skl_pipe_wm pipe_wm = {}; struct intel_wm_config config = {}; - memset(results, 0, sizeof(*results)); + + /* Clear all dirty flags */ + memset(results->dirty, 0, sizeof(bool) * I915_MAX_PIPES); + + skl_clear_wm(results, intel_crtc->pipe); skl_compute_wm_global_parameters(dev, &config); From 18c237c0f9fa2e1c66e1eb4c305aeff4f28f89bf Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Tue, 4 Aug 2015 22:02:41 +0530 Subject: [PATCH 29/80] drm/i915/bxt: Path added of dmc firmware ver1 for BXT. Broxton also has dmc to manage low-power display engine state. Path of the firmware added in intel_csr.c. Naming convention followed as _dmc_.bin v1: Initial version. v2: Commit description added based on review comment from Sunil. Cc: Damien Lespiau Cc: Rodrigo Vivi Cc: Sunil Kamath Signed-off-by: Animesh Manna Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_csr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 765dfcd15727..6d1aaff164af 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -42,8 +42,10 @@ */ #define I915_CSR_SKL "i915/skl_dmc_ver1.bin" +#define I915_CSR_BXT "i915/bxt_dmc_ver1.bin" MODULE_FIRMWARE(I915_CSR_SKL); +MODULE_FIRMWARE(I915_CSR_BXT); /* * SKL CSR registers for DC5 and DC6 @@ -409,6 +411,8 @@ void intel_csr_ucode_init(struct drm_device *dev) if (IS_SKYLAKE(dev)) csr->fw_path = I915_CSR_SKL; + else if (IS_BROXTON(dev_priv)) + csr->fw_path = I915_CSR_BXT; else { DRM_ERROR("Unexpected: no known CSR firmware for platform\n"); intel_csr_load_status_set(dev_priv, FW_FAILED); From cff765fb1383dff6787fa735fcc88aa122d3c00d Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Tue, 4 Aug 2015 22:02:43 +0530 Subject: [PATCH 30/80] drm/i915/bxt: Stepping info added for bxt. Added stepping info in intel_csr.c which is required to extract specific firmware from packaged dmc firmware. Stepping info is aligned with current bspec info. Cc: Vetter, Daniel Cc: Damien Lespiau Cc: Imre Deak Cc: Sunil Kamath Signed-off-by: Animesh Manna Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_csr.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 6d1aaff164af..780d5d5464d7 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -183,11 +183,19 @@ static const struct stepping_info skl_stepping_info[] = { {'G', '0'}, {'H', '0'}, {'I', '0'} }; +static struct stepping_info bxt_stepping_info[] = { + {'A', '0'}, {'A', '1'}, {'A', '2'}, + {'B', '0'}, {'B', '1'}, {'B', '2'} +}; + static char intel_get_stepping(struct drm_device *dev) { if (IS_SKYLAKE(dev) && (dev->pdev->revision < ARRAY_SIZE(skl_stepping_info))) return skl_stepping_info[dev->pdev->revision].stepping; + else if (IS_BROXTON(dev) && (dev->pdev->revision < + ARRAY_SIZE(bxt_stepping_info))) + return bxt_stepping_info[dev->pdev->revision].stepping; else return -ENODATA; } @@ -197,6 +205,9 @@ static char intel_get_substepping(struct drm_device *dev) if (IS_SKYLAKE(dev) && (dev->pdev->revision < ARRAY_SIZE(skl_stepping_info))) return skl_stepping_info[dev->pdev->revision].substepping; + else if (IS_BROXTON(dev) && (dev->pdev->revision < + ARRAY_SIZE(bxt_stepping_info))) + return bxt_stepping_info[dev->pdev->revision].substepping; else return -ENODATA; } From 7b403ffba8ed8636f3467a9008bd2e060792b2e4 Mon Sep 17 00:00:00 2001 From: Animesh Manna Date: Tue, 4 Aug 2015 22:02:42 +0530 Subject: [PATCH 31/80] drm/i915/bxt: Modified HAS_CSR, added support for BXT Modified HAS_CSR macro defination which earlier only supported for skl, now added support for BXT. v1: Initial version. v2: Instaed of skylake/broxton check added gen9 check alone based on review comment from Sunil. Cc: Vetter, Daniel Cc: Damien Lespiau Cc: Imre Deak Cc: Sunil Kamath Signed-off-by: Animesh Manna Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 677faa8be228..3795fdfcd1c3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2578,7 +2578,7 @@ struct drm_i915_cmd_table { #define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6) #define HAS_RC6p(dev) (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev)) -#define HAS_CSR(dev) (IS_SKYLAKE(dev)) +#define HAS_CSR(dev) (IS_GEN9(dev)) #define HAS_GUC_UCODE(dev) (IS_GEN9(dev)) #define HAS_GUC_SCHED(dev) (IS_GEN9(dev)) From 23eafea6a9d1faac0588a5275d0c755cb261346e Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sun, 23 Aug 2015 17:52:48 +0530 Subject: [PATCH 32/80] drm/i915/bxt: WaGsvDisableTurbo Disable Turbo on steppings prior to B0 on BXT due to hangs seen during GT CPD exit. Change-Id: I50c5c03f59f5ba092db19e17234951d89db42c6c Signed-off-by: Sagar Arun Kamble Reviewed by: Alex Dai . Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index bec4e0e3d549..f52431b1a058 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4487,6 +4487,10 @@ static void gen6_set_rps(struct drm_device *dev, u8 val) { struct drm_i915_private *dev_priv = dev->dev_private; + /* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */ + if (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) + return; + WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); WARN_ON(val > dev_priv->rps.max_freq); WARN_ON(val < dev_priv->rps.min_freq); @@ -4807,6 +4811,12 @@ static void gen9_enable_rps(struct drm_device *dev) gen6_init_rps_frequencies(dev); + /* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */ + if (IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) { + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); + return; + } + /* Program defaults and thresholds for RPS*/ I915_WRITE(GEN6_RC_VIDEO_FREQ, GEN9_FREQUENCY(dev_priv->rps.rp1_freq)); From 83e3337204b2385d20e149c8fe91bb2719978df2 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sun, 23 Aug 2015 17:52:47 +0530 Subject: [PATCH 33/80] drm/i915: Increase maximum polling time to 50ms for forcewake request/clear ack On BXT, We Observe timeout for forcewake request completion with 2ms polling period as given here: [drm:fw_domains_get] ERROR render: timed out waiting for forcewake ack request. Polling for 50ms is recommended to avoid these timeouts. Change-Id: Ie715b0069a3049606e9602bc5e97a6511890864d Signed-off-by: Sagar Arun Kamble Reviewed by: Alex Dai Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 440e2a5658af..14d0831c6156 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -27,7 +27,7 @@ #include -#define FORCEWAKE_ACK_TIMEOUT_MS 2 +#define FORCEWAKE_ACK_TIMEOUT_MS 50 #define __raw_i915_read8(dev_priv__, reg__) readb((dev_priv__)->regs + (reg__)) #define __raw_i915_write8(dev_priv__, reg__, val__) writeb(val__, (dev_priv__)->regs + (reg__)) From cfe01a5eba1ff5723f3a47895fb7e9d890edf157 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Tue, 1 Sep 2015 19:41:38 +0530 Subject: [PATCH 34/80] drm/i915/bxt: Enable BXT DSI PLL This patch adds new functions for BXT clock and PLL programming. They are: 1. configure_dsi_pll for BXT. This function does the basic math and generates the divider ratio based on requested pixclock, and program clock registers. 2. enable_dsi_pll function. This function programs the calculated clock values on the PLL. 3. intel_enable_dsi_pll Wrapper function to use same code for multiple platforms. It checks the platform and calls appropriate core pll enable function. v2: Fixed Jani's review comments. Macros are adjusted as per convention. v3: Removed a redundant change wrt code comment. Signed-off-by: Shashank Sharma Signed-off-by: Uma Shankar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 22 +++++++ drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_dsi.h | 2 +- drivers/gpu/drm/i915/intel_dsi_pll.c | 95 +++++++++++++++++++++++++++- 4 files changed, 118 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index dd3d235b27ac..4ef16aabc30a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7507,6 +7507,28 @@ enum skl_disp_power_wells { #define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */ +#define BXT_DSI_PLL_CTL 0x161000 +#define BXT_DSI_PLL_PVD_RATIO_SHIFT 16 +#define BXT_DSI_PLL_PVD_RATIO_MASK (3 << BXT_DSI_PLL_PVD_RATIO_SHIFT) +#define BXT_DSI_PLL_PVD_RATIO_1 (1 << BXT_DSI_PLL_PVD_RATIO_SHIFT) +#define BXT_DSIC_16X_BY2 (1 << 10) +#define BXT_DSIC_16X_BY3 (2 << 10) +#define BXT_DSIC_16X_BY4 (3 << 10) +#define BXT_DSIA_16X_BY2 (1 << 8) +#define BXT_DSIA_16X_BY3 (2 << 8) +#define BXT_DSIA_16X_BY4 (3 << 8) +#define BXT_DSI_FREQ_SEL_SHIFT 8 +#define BXT_DSI_FREQ_SEL_MASK (0xF << BXT_DSI_FREQ_SEL_SHIFT) + +#define BXT_DSI_PLL_RATIO_MAX 0x7D +#define BXT_DSI_PLL_RATIO_MIN 0x22 +#define BXT_DSI_PLL_RATIO_MASK 0xFF +#define BXT_REF_CLOCK_KHZ 19500 + +#define BXT_DSI_PLL_ENABLE 0x46080 +#define BXT_DSI_PLL_DO_ENABLE (1 << 31) +#define BXT_DSI_PLL_LOCKED (1 << 30) + #define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190) #define _MIPIC_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700) #define MIPI_PORT_CTRL(port) _MIPI_PORT(port, _MIPIA_PORT_CTRL, _MIPIC_PORT_CTRL) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 781c267ea97c..f2f819605e5c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -914,8 +914,8 @@ static void intel_dsi_pre_pll_enable(struct intel_encoder *encoder) DRM_DEBUG_KMS("\n"); intel_dsi_prepare(encoder); + intel_enable_dsi_pll(encoder); - vlv_enable_dsi_pll(encoder); } static enum drm_connector_status diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 42a68593e32a..7f16c686771b 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -124,7 +124,7 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) return container_of(encoder, struct intel_dsi, base.base); } -extern void vlv_enable_dsi_pll(struct intel_encoder *encoder); +extern void intel_enable_dsi_pll(struct intel_encoder *encoder); extern void vlv_disable_dsi_pll(struct intel_encoder *encoder); extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp); diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index c6a8975b128f..b07483beded0 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -246,7 +246,7 @@ static void vlv_configure_dsi_pll(struct intel_encoder *encoder) vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl); } -void vlv_enable_dsi_pll(struct intel_encoder *encoder) +static void vlv_enable_dsi_pll(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; u32 tmp; @@ -363,3 +363,96 @@ u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp) return pclk; } + +static bool bxt_configure_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + u8 dsi_ratio; + u32 dsi_clk; + u32 val; + + dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format, + intel_dsi->lane_count); + + /* + * From clock diagram, to get PLL ratio divider, divide double of DSI + * link rate (i.e., 2*8x=16x frequency value) by ref clock. Make sure to + * round 'up' the result + */ + dsi_ratio = DIV_ROUND_UP(dsi_clk * 2, BXT_REF_CLOCK_KHZ); + if (dsi_ratio < BXT_DSI_PLL_RATIO_MIN || + dsi_ratio > BXT_DSI_PLL_RATIO_MAX) { + DRM_ERROR("Cant get a suitable ratio from DSI PLL ratios\n"); + return false; + } + + /* + * Program DSI ratio and Select MIPIC and MIPIA PLL output as 8x + * Spec says both have to be programmed, even if one is not getting + * used. Configure MIPI_CLOCK_CTL dividers in modeset + */ + val = I915_READ(BXT_DSI_PLL_CTL); + val &= ~BXT_DSI_PLL_PVD_RATIO_MASK; + val &= ~BXT_DSI_FREQ_SEL_MASK; + val &= ~BXT_DSI_PLL_RATIO_MASK; + val |= (dsi_ratio | BXT_DSIA_16X_BY2 | BXT_DSIC_16X_BY2); + + /* As per recommendation from hardware team, + * Prog PVD ratio =1 if dsi ratio <= 50 + */ + if (dsi_ratio <= 50) { + val &= ~BXT_DSI_PLL_PVD_RATIO_MASK; + val |= BXT_DSI_PLL_PVD_RATIO_1; + } + + I915_WRITE(BXT_DSI_PLL_CTL, val); + POSTING_READ(BXT_DSI_PLL_CTL); + + return true; +} + +static void bxt_enable_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + u32 val; + + DRM_DEBUG_KMS("\n"); + + val = I915_READ(BXT_DSI_PLL_ENABLE); + + if (val & BXT_DSI_PLL_DO_ENABLE) { + WARN(1, "DSI PLL already enabled. Disabling it.\n"); + val &= ~BXT_DSI_PLL_DO_ENABLE; + I915_WRITE(BXT_DSI_PLL_ENABLE, val); + } + + /* Configure PLL vales */ + if (!bxt_configure_dsi_pll(encoder)) { + DRM_ERROR("Configure DSI PLL failed, abort PLL enable\n"); + return; + } + + /* Enable DSI PLL */ + val = I915_READ(BXT_DSI_PLL_ENABLE); + val |= BXT_DSI_PLL_DO_ENABLE; + I915_WRITE(BXT_DSI_PLL_ENABLE, val); + + /* Timeout and fail if PLL not locked */ + if (wait_for(I915_READ(BXT_DSI_PLL_ENABLE) & BXT_DSI_PLL_LOCKED, 1)) { + DRM_ERROR("Timed out waiting for DSI PLL to lock\n"); + return; + } + + DRM_DEBUG_KMS("DSI PLL locked\n"); +} + +void intel_enable_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + + if (IS_VALLEYVIEW(dev)) + vlv_enable_dsi_pll(encoder); + else if (IS_BROXTON(dev)) + bxt_enable_dsi_pll(encoder); +} From fe88fc6828f6471c9eebc511aa15984d055d11c1 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Tue, 1 Sep 2015 19:41:39 +0530 Subject: [PATCH 35/80] drm/i915/bxt: Disable DSI PLL for BXT This patch adds two new functions: - disable_dsi_pll. BXT DSI disable sequence and registers are different from previous platforms. - intel_disable_dsi_pll wrapper function to re-use the same code for multiple platforms. It checks platform type and calls appropriate core pll disable function. v2: Fixed Jani's review comments. v3: Rebased on latest drm-nightly branch. Signed-off-by: Shashank Sharma Signed-off-by: Uma Shankar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_dsi.h | 2 +- drivers/gpu/drm/i915/intel_dsi_pll.c | 32 +++++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index f2f819605e5c..50159a99d58a 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -557,7 +557,7 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) usleep_range(2000, 2500); } - vlv_disable_dsi_pll(encoder); + intel_disable_dsi_pll(encoder); } static void intel_dsi_post_disable(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 7f16c686771b..5cc46b4131f7 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -125,7 +125,7 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) } extern void intel_enable_dsi_pll(struct intel_encoder *encoder); -extern void vlv_disable_dsi_pll(struct intel_encoder *encoder); +extern void intel_disable_dsi_pll(struct intel_encoder *encoder); extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp); struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id); diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index b07483beded0..f335e6cd4431 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -276,7 +276,7 @@ static void vlv_enable_dsi_pll(struct intel_encoder *encoder) DRM_DEBUG_KMS("DSI PLL locked\n"); } -void vlv_disable_dsi_pll(struct intel_encoder *encoder) +static void vlv_disable_dsi_pll(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; u32 tmp; @@ -293,6 +293,26 @@ void vlv_disable_dsi_pll(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); } +static void bxt_disable_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; + u32 val; + + DRM_DEBUG_KMS("\n"); + + val = I915_READ(BXT_DSI_PLL_ENABLE); + val &= ~BXT_DSI_PLL_DO_ENABLE; + I915_WRITE(BXT_DSI_PLL_ENABLE, val); + + /* + * PLL lock should deassert within 200us. + * Wait up to 1ms before timing out. + */ + if (wait_for((I915_READ(BXT_DSI_PLL_ENABLE) + & BXT_DSI_PLL_LOCKED) == 0, 1)) + DRM_ERROR("Timeout waiting for PLL lock deassertion\n"); +} + static void assert_bpp_mismatch(int pixel_format, int pipe_bpp) { int bpp = dsi_pixel_format_bpp(pixel_format); @@ -456,3 +476,13 @@ void intel_enable_dsi_pll(struct intel_encoder *encoder) else if (IS_BROXTON(dev)) bxt_enable_dsi_pll(encoder); } + +void intel_disable_dsi_pll(struct intel_encoder *encoder) +{ + struct drm_device *dev = encoder->base.dev; + + if (IS_VALLEYVIEW(dev)) + vlv_disable_dsi_pll(encoder); + else if (IS_BROXTON(dev)) + bxt_disable_dsi_pll(encoder); +} From d2e08c0f34438af791482de8abf2c8e4e573b1d3 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Tue, 1 Sep 2015 19:41:40 +0530 Subject: [PATCH 36/80] drm/i915/bxt: DSI prepare changes for BXT This patch modifies dsi_prepare() function to support the same modeset prepare sequence for BXT also. Main changes are: 1. BXT port control register is different than VLV. 2. BXT modeset sequence needs vdisplay and hdisplay programmed for transcoder. 3. BXT can select PIPE for MIPI transcoders. 4. BXT needs to program register MIPI_INIT_COUNT for both the ports, even if only one is being used. v2: Fixed Jani's review comments. Rectified the DSI Macros to get proper register offsets using _MIPI_PORT instead of _TRANSCODER v3: Rebased on latest drm-nightly branch. Fixed Jani's review comments. Signed-off-by: Shashank Sharma Signed-off-by: Uma Shankar Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 21 ++++++++++ drivers/gpu/drm/i915/intel_dsi.c | 67 +++++++++++++++++++++++++++----- 2 files changed, 79 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4ef16aabc30a..c5287a1818f3 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7507,6 +7507,22 @@ enum skl_disp_power_wells { #define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */ +/* BXT MIPI mode configure */ +#define _BXT_MIPIA_TRANS_HACTIVE 0x6B0F8 +#define _BXT_MIPIC_TRANS_HACTIVE 0x6B8F8 +#define BXT_MIPI_TRANS_HACTIVE(tc) _MIPI_PORT(tc, \ + _BXT_MIPIA_TRANS_HACTIVE, _BXT_MIPIC_TRANS_HACTIVE) + +#define _BXT_MIPIA_TRANS_VACTIVE 0x6B0FC +#define _BXT_MIPIC_TRANS_VACTIVE 0x6B8FC +#define BXT_MIPI_TRANS_VACTIVE(tc) _MIPI_PORT(tc, \ + _BXT_MIPIA_TRANS_VACTIVE, _BXT_MIPIC_TRANS_VACTIVE) + +#define _BXT_MIPIA_TRANS_VTOTAL 0x6B100 +#define _BXT_MIPIC_TRANS_VTOTAL 0x6B900 +#define BXT_MIPI_TRANS_VTOTAL(tc) _MIPI_PORT(tc, \ + _BXT_MIPIA_TRANS_VTOTAL, _BXT_MIPIC_TRANS_VTOTAL) + #define BXT_DSI_PLL_CTL 0x161000 #define BXT_DSI_PLL_PVD_RATIO_SHIFT 16 #define BXT_DSI_PLL_PVD_RATIO_MASK (3 << BXT_DSI_PLL_PVD_RATIO_SHIFT) @@ -7942,6 +7958,11 @@ enum skl_disp_power_wells { #define READ_REQUEST_PRIORITY_HIGH (3 << 3) #define RGB_FLIP_TO_BGR (1 << 2) +#define BXT_PIPE_SELECT_MASK (7 << 7) +#define BXT_PIPE_SELECT_C (2 << 7) +#define BXT_PIPE_SELECT_B (1 << 7) +#define BXT_PIPE_SELECT_A (0 << 7) + #define _MIPIA_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb108) #define _MIPIC_DATA_ADDRESS (dev_priv->mipi_mmio_base + 0xb908) #define MIPI_DATA_ADDRESS(port) _MIPI_PORT(port, _MIPIA_DATA_ADDRESS, \ diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 50159a99d58a..5b69b4126282 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -737,6 +737,21 @@ static void set_dsi_timings(struct drm_encoder *encoder, hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio); for_each_dsi_port(port, intel_dsi->ports) { + if (IS_BROXTON(dev)) { + /* + * Program hdisplay and vdisplay on MIPI transcoder. + * This is different from calculated hactive and + * vactive, as they are calculated per channel basis, + * whereas these values should be based on resolution. + */ + I915_WRITE(BXT_MIPI_TRANS_HACTIVE(port), + mode->hdisplay); + I915_WRITE(BXT_MIPI_TRANS_VACTIVE(port), + mode->vdisplay); + I915_WRITE(BXT_MIPI_TRANS_VTOTAL(port), + mode->vtotal); + } + I915_WRITE(MIPI_HACTIVE_AREA_COUNT(port), hactive); I915_WRITE(MIPI_HFP_COUNT(port), hfp); @@ -777,16 +792,39 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) } for_each_dsi_port(port, intel_dsi->ports) { - /* escape clock divider, 20MHz, shared for A and C. - * device ready must be off when doing this! txclkesc? */ - tmp = I915_READ(MIPI_CTRL(PORT_A)); - tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK; - I915_WRITE(MIPI_CTRL(PORT_A), tmp | ESCAPE_CLOCK_DIVIDER_1); + if (IS_VALLEYVIEW(dev)) { + /* + * escape clock divider, 20MHz, shared for A and C. + * device ready must be off when doing this! txclkesc? + */ + tmp = I915_READ(MIPI_CTRL(PORT_A)); + tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK; + I915_WRITE(MIPI_CTRL(PORT_A), tmp | + ESCAPE_CLOCK_DIVIDER_1); - /* read request priority is per pipe */ - tmp = I915_READ(MIPI_CTRL(port)); - tmp &= ~READ_REQUEST_PRIORITY_MASK; - I915_WRITE(MIPI_CTRL(port), tmp | READ_REQUEST_PRIORITY_HIGH); + /* read request priority is per pipe */ + tmp = I915_READ(MIPI_CTRL(port)); + tmp &= ~READ_REQUEST_PRIORITY_MASK; + I915_WRITE(MIPI_CTRL(port), tmp | + READ_REQUEST_PRIORITY_HIGH); + } else if (IS_BROXTON(dev)) { + /* + * FIXME: + * BXT can connect any PIPE to any MIPI port. + * Select the pipe based on the MIPI port read from + * VBT for now. Pick PIPE A for MIPI port A and C + * for port C. + */ + tmp = I915_READ(MIPI_CTRL(port)); + tmp &= ~BXT_PIPE_SELECT_MASK; + + if (port == PORT_A) + tmp |= BXT_PIPE_SELECT_A; + else if (port == PORT_C) + tmp |= BXT_PIPE_SELECT_C; + + I915_WRITE(MIPI_CTRL(port), tmp); + } /* XXX: why here, why like this? handling in irq handler?! */ I915_WRITE(MIPI_INTR_STAT(port), 0xffffffff); @@ -863,6 +901,17 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) I915_WRITE(MIPI_INIT_COUNT(port), txclkesc(intel_dsi->escape_clk_div, 100)); + if (IS_BROXTON(dev) && (!intel_dsi->dual_link)) { + /* + * BXT spec says write MIPI_INIT_COUNT for + * both the ports, even if only one is + * getting used. So write the other port + * if not in dual link mode. + */ + I915_WRITE(MIPI_INIT_COUNT(port == + PORT_A ? PORT_C : PORT_A), + intel_dsi->init_count); + } /* recovery disables */ I915_WRITE(MIPI_EOT_DISABLE(port), tmp); From 237ed86c693d8a8e4db476976aeb30df4deac74b Mon Sep 17 00:00:00 2001 From: Sonika Jindal Date: Tue, 15 Sep 2015 09:44:20 +0530 Subject: [PATCH 37/80] drm/i915: Check live status before reading edid The Bspec is very clear that Live status must be checked about before trying to read EDID over DDC channel. This patch makes sure that HDMI EDID is read only when live status is up. The live status doesn't seem to perform very consistent across various platforms when tested with different monitors. The reason behind that is some monitors are late to provide right voltage to set live_status up. So, after getting the interrupt, for a small duration, live status reg fluctuates, and then settles down showing the correct staus. This is explained here in, in a rough way: HPD line ________________ |\ T1 = Monitor Hotplug causing IRQ | \______________________________________ | | | | | | T2 = Live status is stable | | _____________________________________ | | /| Live status _____________|_|/ | | | | | | | | | | T0 T1 T2 (Between T1 and T2 Live status fluctuates or can be even low, depending on the monitor) After several experiments, we have concluded that a max delay of 30ms is enough to allow the live status to settle down with most of the monitors. This total delay of 30ms has been split into a resolution of 3 retries of 10ms each, for the better cases. This delay is kept at 30ms, keeping in consideration that, HDCP compliance expect the HPD handler to respond a plug out in 100ms, by disabling port. v2: Adding checks for VLV/CHV as well. Reusing old ibx and g4x functions to check digital port status. Adding a separate function to get bxt live status (Daniel) v3: Using intel_encoder->hpd_pin to check the live status (Siva) Moving the live status read to intel_hdmi_probe and passing parameter to read/not to read the edid. (me) v4: * Added live status check for all platforms using intel_digital_port_connected. * Rebased on top of Jani's DP cleanup series * Some monitors take time in setting the live status. So retry for few times if this is a connect HPD v5: Removed extra "drm/i915" from commit message. Adding Shashank's sob which was missed. v6: Drop the (!detect_edid && !live_status check) check because for DDI ports which are enumerated as hdmi as well as DP, we don't have a mechanism to differentiate between DP and hdmi inside the encoder's hot_plug. This leads to call to the hdmi's hot_plug hook for DP as well as hdmi which leads to issues during unplug because of the above check. v7: Make intel_digital_port_connected global in this patch, some reformatting of while loop, adding a print when live status is not up. (Rodrigo) v8: Rebase it on nightly which involved skipping the hot_plug hook for now and letting the live_status check happen in detect until the hpd handling part is finalized (Daniel) Signed-off-by: Shashank Sharma Signed-off-by: Sonika Jindal Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_hdmi.c | 28 +++++++++++++++++++++------- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9700f774dc6c..02401a397dcc 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4672,7 +4672,7 @@ static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv, * * Return %true if @port is connected, %false otherwise. */ -static bool intel_digital_port_connected(struct drm_i915_private *dev_priv, +bool intel_digital_port_connected(struct drm_i915_private *dev_priv, struct intel_digital_port *port) { if (HAS_PCH_IBX(dev_priv)) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8760814e81f6..394018ead36b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1218,6 +1218,8 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp); void intel_edp_drrs_invalidate(struct drm_device *dev, unsigned frontbuffer_bits); void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits); +bool intel_digital_port_connected(struct drm_i915_private *dev_priv, + struct intel_digital_port *port); void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config); /* intel_dp_mst.c */ diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index e978c59dc243..bb33c66b0b12 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1329,22 +1329,23 @@ intel_hdmi_unset_edid(struct drm_connector *connector) } static bool -intel_hdmi_set_edid(struct drm_connector *connector) +intel_hdmi_set_edid(struct drm_connector *connector, bool force) { struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct intel_encoder *intel_encoder = &hdmi_to_dig_port(intel_hdmi)->base; enum intel_display_power_domain power_domain; - struct edid *edid; + struct edid *edid = NULL; bool connected = false; power_domain = intel_display_port_power_domain(intel_encoder); intel_display_power_get(dev_priv, power_domain); - edid = drm_get_edid(connector, - intel_gmbus_get_adapter(dev_priv, - intel_hdmi->ddc_bus)); + if (force) + edid = drm_get_edid(connector, + intel_gmbus_get_adapter(dev_priv, + intel_hdmi->ddc_bus)); intel_display_power_put(dev_priv, power_domain); @@ -1372,13 +1373,26 @@ static enum drm_connector_status intel_hdmi_detect(struct drm_connector *connector, bool force) { enum drm_connector_status status; + struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); + struct drm_i915_private *dev_priv = to_i915(connector->dev); + bool live_status = false; + unsigned int retry = 3; DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); + while (!live_status && --retry) { + live_status = intel_digital_port_connected(dev_priv, + hdmi_to_dig_port(intel_hdmi)); + mdelay(10); + } + + if (!live_status) + DRM_DEBUG_KMS("Live status not up!"); + intel_hdmi_unset_edid(connector); - if (intel_hdmi_set_edid(connector)) { + if (intel_hdmi_set_edid(connector, live_status)) { struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; @@ -1402,7 +1416,7 @@ intel_hdmi_force(struct drm_connector *connector) if (connector->status != connector_status_connected) return; - intel_hdmi_set_edid(connector); + intel_hdmi_set_edid(connector, true); hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; } From 7f4c62840cc416986f983a8c68f7010c97e06daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Sep 2015 18:59:07 +0300 Subject: [PATCH 38/80] drm/i915: Assign hwmode after encoder state readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dotclock is often calculated in encoder .get_config(), so we shouldn't copy the adjusted_mode to hwmode until we have read out the dotclock. Gets rid of some warnings like these: [drm:drm_calc_timestamping_constants [drm]] *ERROR* crtc 21: Can't calculate constants, dotclock = 0! [drm:i915_get_vblank_timestamp] crtc 0 is disabled v2: Steal Maarten's idea to move crtc->mode etc. assignment too Cc: Maarten Lankhorst Cc: Patrik Jakobsson Signed-off-by: Ville Syrjälä Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91428 Reviewed-by: Patrik Jakobsson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 57 +++++++++++++++------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a001cbbb855b..ce9bb47399a7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -15121,33 +15121,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) crtc->base.state->active = crtc->active; crtc->base.enabled = crtc->active; - memset(&crtc->base.mode, 0, sizeof(crtc->base.mode)); - if (crtc->base.state->active) { - intel_mode_from_pipe_config(&crtc->base.mode, crtc->config); - intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config); - WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode)); - - /* - * The initial mode needs to be set in order to keep - * the atomic core happy. It wants a valid mode if the - * crtc's enabled, so we do the above call. - * - * At this point some state updated by the connectors - * in their ->detect() callback has not run yet, so - * no recalculation can be done yet. - * - * Even if we could do a recalculation and modeset - * right now it would cause a double modeset if - * fbdev or userspace chooses a different initial mode. - * - * If that happens, someone indicated they wanted a - * mode change, which means it's safe to do a full - * recalculation. - */ - crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED; - } - - crtc->base.hwmode = crtc->config->base.adjusted_mode; readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state)); DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n", @@ -15207,6 +15180,36 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) connector->base.name, connector->base.encoder ? "enabled" : "disabled"); } + + for_each_intel_crtc(dev, crtc) { + crtc->base.hwmode = crtc->config->base.adjusted_mode; + + memset(&crtc->base.mode, 0, sizeof(crtc->base.mode)); + if (crtc->base.state->active) { + intel_mode_from_pipe_config(&crtc->base.mode, crtc->config); + intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config); + WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode)); + + /* + * The initial mode needs to be set in order to keep + * the atomic core happy. It wants a valid mode if the + * crtc's enabled, so we do the above call. + * + * At this point some state updated by the connectors + * in their ->detect() callback has not run yet, so + * no recalculation can be done yet. + * + * Even if we could do a recalculation and modeset + * right now it would cause a double modeset if + * fbdev or userspace chooses a different initial mode. + * + * If that happens, someone indicated they wanted a + * mode change, which means it's safe to do a full + * recalculation. + */ + crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED; + } + } } /* Scan out the current hw modeset state, From f9cd7b881a042dcc8f1b1236ecea6deb3eb4d5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Sep 2015 18:59:08 +0300 Subject: [PATCH 39/80] drm/i915: Move sprite/cursor plane disable to intel_sanitize_crtc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the sprite/cursor plane disabling to occur in intel_sanitize_crtc() where it belongs instead of doing it in intel_modeset_readout_hw_state(). The plane disabling was first added in 4cf0ebbd4fafbdf8e6431dbb315e5511c3efdc3b drm/i915: Rework plane readout. I got the idea from some patches from Partik and/or Maarten but those moved also the plane state readout to intel_sanitize_crtc() which isn't quite right in my opinion. Cc: Maarten Lankhorst Cc: Patrik Jakobsson Signed-off-by: Ville Syrjälä References: https://bugs.freedesktop.org/show_bug.cgi?id=91910 Reviewed-by: Patrik Jakobsson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 44 +++++++++++++--------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ce9bb47399a7..5064d8f4d00c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14905,9 +14905,19 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) /* restore vblank interrupts to correct state */ drm_crtc_vblank_reset(&crtc->base); if (crtc->active) { + struct intel_plane *plane; + drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode); update_scanline_offset(crtc); drm_crtc_vblank_on(&crtc->base); + + /* Disable everything but the primary plane */ + for_each_intel_plane_on_crtc(dev, crtc, plane) { + if (plane->base.type == DRM_PLANE_TYPE_PRIMARY) + continue; + + plane->disable_plane(&plane->base, &crtc->base); + } } /* We need to sanitize the plane -> pipe mapping first because this will @@ -15070,35 +15080,21 @@ void i915_redisable_vga(struct drm_device *dev) i915_redisable_vga_power_on(dev); } -static bool primary_get_hw_state(struct intel_crtc *crtc) +static bool primary_get_hw_state(struct intel_plane *plane) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - return !!(I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE); + return I915_READ(DSPCNTR(plane->plane)) & DISPLAY_PLANE_ENABLE; } -static void readout_plane_state(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) +/* FIXME read out full plane state for all planes */ +static void readout_plane_state(struct intel_crtc *crtc) { - struct intel_plane *p; - struct intel_plane_state *plane_state; - bool active = crtc_state->base.active; + struct intel_plane_state *plane_state = + to_intel_plane_state(crtc->base.primary->state); - for_each_intel_plane(crtc->base.dev, p) { - if (crtc->pipe != p->pipe) - continue; - - plane_state = to_intel_plane_state(p->base.state); - - if (p->base.type == DRM_PLANE_TYPE_PRIMARY) - plane_state->visible = primary_get_hw_state(crtc); - else { - if (active) - p->disable_plane(&p->base, &crtc->base); - - plane_state->visible = false; - } - } + plane_state->visible = + primary_get_hw_state(to_intel_plane(crtc->base.primary)); } static void intel_modeset_readout_hw_state(struct drm_device *dev) @@ -15121,7 +15117,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) crtc->base.state->active = crtc->active; crtc->base.enabled = crtc->active; - readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state)); + readout_plane_state(crtc); DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n", crtc->base.base.id, From 9eca6832f7254d49d25494da7d47c0f8a24f7862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Sep 2015 18:59:10 +0300 Subject: [PATCH 40/80] drm/i915: Move scanline_offset and timestamping constant setup to intel_modeset_readout_hw_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_modeset_readout_hw_state() seems like the more appropriate place for populating the scanline_offset and timestamping constants than intel_sanitize_crtc() since they are basically part of the state we read out. Cc: Maarten Lankhorst Cc: Patrik Jakobsson Signed-off-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Reviewed-by: Patrik Jakobsson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5064d8f4d00c..8db2b13499ba 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14907,8 +14907,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) if (crtc->active) { struct intel_plane *plane; - drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode); - update_scanline_offset(crtc); drm_crtc_vblank_on(&crtc->base); /* Disable everything but the primary plane */ @@ -15204,6 +15202,9 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) * recalculation. */ crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED; + + drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode); + update_scanline_offset(crtc); } } } From 3a5a0393ab5de28f8dad100bf604e4ab55550836 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 15 Sep 2015 10:03:01 -0700 Subject: [PATCH 41/80] drm/i915: fix crash in error state readout on non-execlist platforms v2 Looks like this was introduced in: commit d1675198ed1f21aec6e036336e4340c40b726497 Author: Alex Dai Date: Wed Aug 12 15:43:43 2015 +0100 drm/i915: Integrate GuC-based command submission This patch assumed LRC contexts and HWS layout, which is incorrect on platforms without execlists. This can lead to a crash in GPU error state readout on those platforms. I don't see a bug filed for this, but there may be one that I haven't found. v2: fixup offset handling for error capture fix (Dave) Cc: Alex Dai Reviewed-by: Dave Gordon Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gpu_error.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 3379f9c1ef88..f95de05f793d 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -457,17 +457,23 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, } if ((obj = error->ring[i].hws_page)) { + u64 hws_offset = obj->gtt_offset; + u32 *hws_page = &obj->pages[0][0]; + + if (i915.enable_execlists) { + hws_offset += LRC_PPHWSP_PN * PAGE_SIZE; + hws_page = &obj->pages[LRC_PPHWSP_PN][0]; + } err_printf(m, "%s --- HW Status = 0x%08llx\n", - dev_priv->ring[i].name, - obj->gtt_offset + LRC_PPHWSP_PN * PAGE_SIZE); + dev_priv->ring[i].name, hws_offset); offset = 0; for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { err_printf(m, "[%04x] %08x %08x %08x %08x\n", offset, - obj->pages[LRC_PPHWSP_PN][elt], - obj->pages[LRC_PPHWSP_PN][elt+1], - obj->pages[LRC_PPHWSP_PN][elt+2], - obj->pages[LRC_PPHWSP_PN][elt+3]); + hws_page[elt], + hws_page[elt+1], + hws_page[elt+2], + hws_page[elt+3]); offset += 16; } } From 7a58bad0e63295dfa803973efcebc80cb730c7bd Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 12 Sep 2015 10:17:50 +0530 Subject: [PATCH 42/80] drm/i915: Add IS_SKL_GT3 and IS_SKL_GT4 macro. It will be usefull to specify w/a that affects only SKL GT3 and GT4. Signed-off-by: Sagar Arun Kamble Reviewed-by: Alex Dai Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3795fdfcd1c3..7cbc81f718a7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2488,6 +2488,11 @@ struct drm_i915_cmd_table { #define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \ INTEL_DEVID(dev) == 0x1915 || \ INTEL_DEVID(dev) == 0x191E) +#define IS_SKL_GT3(dev) (IS_SKYLAKE(dev) && \ + (INTEL_DEVID(dev) & 0x00F0) == 0x0020) +#define IS_SKL_GT4(dev) (IS_SKYLAKE(dev) && \ + (INTEL_DEVID(dev) & 0x00F0) == 0x0030) + #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) #define SKL_REVID_A0 (0x0) From f2d2fe95072acd5404f8051b8bf1195c61a47fb5 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 12 Sep 2015 10:17:51 +0530 Subject: [PATCH 43/80] drm/i915: WaRsDisableCoarsePowerGating WaRsDisableCoarsePowerGating: Coarse Power Gating (CPG) needs to be disabled for platforms prior to BXT B0 and SKL GT3/GT4 till E0. v2: Added GT3/GT4 Check. Change-Id: Ia3c4c16e050c88d3e259f601054875c812d69c3a Signed-off-by: Sagar Arun Kamble Reviewed-by: Alex Dai [danvet: Align continuation properly.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f52431b1a058..09be8fc590d5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4877,11 +4877,14 @@ static void gen9_enable_rc6(struct drm_device *dev) /* * 3b: Enable Coarse Power Gating only when RC6 is enabled. - * WaDisableRenderPowerGating:skl,bxt - Render PG need to be disabled with RC6. + * WaRsDisableCoarsePowerGating:skl,bxt - Render/Media PG need to be disabled with RC6. */ - I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? - GEN9_MEDIA_PG_ENABLE : 0); - + if ((IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) || + ((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && (INTEL_REVID(dev) <= SKL_REVID_E0))) + I915_WRITE(GEN9_PG_ENABLE, 0); + else + I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? + (GEN9_RENDER_PG_ENABLE | GEN9_MEDIA_PG_ENABLE) : 0); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); From e3429cd240b06c79df3ea90f28065a7e011744cd Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 12 Sep 2015 10:17:52 +0530 Subject: [PATCH 44/80] drm/i915: WaRsUseTimeoutMode Enable TO mode for RC6 for SKL till D0 and BXT till A0. Cc: Tom O'Rourke Cc: Akash Goel Signed-off-by: Sagar Arun Kamble Reviewed-by: Alex Dai [danvet: Fixup line continuation alignment.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 09be8fc590d5..b4e0d1570ec6 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4871,9 +4871,16 @@ static void gen9_enable_rc6(struct drm_device *dev) rc6_mask = GEN6_RC_CTL_RC6_ENABLE; DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off"); - I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | - GEN6_RC_CTL_EI_MODE(1) | - rc6_mask); + + if ((IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_D0) || + (IS_BROXTON(dev) && INTEL_REVID(dev) <= BXT_REVID_A0)) + I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | + GEN7_RC_CTL_TO_MODE | + rc6_mask); + else + I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | + GEN6_RC_CTL_EI_MODE(1) | + rc6_mask); /* * 3b: Enable Coarse Power Gating only when RC6 is enabled. From 63a4dec2c168b74a39df1eac494501f0f6bf3708 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 12 Sep 2015 10:17:53 +0530 Subject: [PATCH 45/80] drm/i915: WaRsDoubleRc6WrlWithCoarsePowerGating Cc: Tom O'Rourke Cc: Akash Goel Signed-off-by: Sagar Arun Kamble Reviewed-by: Alex Dai [danvet: Fix continuation alignment.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b4e0d1570ec6..61162b2e3fea 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4854,7 +4854,13 @@ static void gen9_enable_rc6(struct drm_device *dev) I915_WRITE(GEN6_RC_CONTROL, 0); /* 2b: Program RC6 thresholds.*/ - I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16); + + /* WaRsDoubleRc6WrlWithCoarsePowerGating: Doubling WRL only when CPG is enabled */ + if (IS_SKYLAKE(dev) && !((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && + (INTEL_REVID(dev) <= SKL_REVID_E0))) + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 108 << 16); + else + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16); I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ for_each_ring(ring, dev_priv, unused) From 97c322e713b92b5071ad276f65cabf8a503a7408 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Sat, 12 Sep 2015 10:17:54 +0530 Subject: [PATCH 46/80] drm/i915: Program GuC MAX IDLE Count Cc: Alex Dai Cc: Tom O'Rourke Cc: Akash Goel Signed-off-by: Sagar Arun Kamble Reviewed-by: Alex Dai Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_guc_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h b/drivers/gpu/drm/i915/i915_guc_reg.h index 8c8e574e63ba..9d79a6b7cc2f 100644 --- a/drivers/gpu/drm/i915/i915_guc_reg.h +++ b/drivers/gpu/drm/i915/i915_guc_reg.h @@ -53,6 +53,7 @@ #define START_DMA (1<<0) #define DMA_GUC_WOPCM_OFFSET 0xc340 #define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */ +#define GUC_MAX_IDLE_COUNT 0xC3E4 #define GUC_WOPCM_SIZE 0xc050 #define GUC_WOPCM_SIZE_VALUE (0x80 << 12) /* 512KB */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 61162b2e3fea..566f5cd85101 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4865,6 +4865,10 @@ static void gen9_enable_rc6(struct drm_device *dev) I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ for_each_ring(ring, dev_priv, unused) I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + + if (HAS_GUC_UCODE(dev)) + I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA); + I915_WRITE(GEN6_RC_SLEEP, 0); I915_WRITE(GEN6_RC6_THRESHOLD, 37500); /* 37.5/125ms per EI */ From 7aefe2b50a0be5c85e7702bff110e5e187fbe4b5 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 14 Sep 2015 11:30:10 +0200 Subject: [PATCH 47/80] drm/i915: Fix fastboot scalers for skylake. The scaler_id in intel_pipe_config_compare should not be checked when adjusting in intel_pipe_config_compare. The hw scaler id may be changed in intel_update_pipe_config. Signed-off-by: Maarten Lankhorst Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8db2b13499ba..6d718c0c3beb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12459,9 +12459,9 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_X(pch_pfit.pos); PIPE_CONF_CHECK_X(pch_pfit.size); } - } - PIPE_CONF_CHECK_I(scaler_state.scaler_id); + PIPE_CONF_CHECK_I(scaler_state.scaler_id); + } /* BDW+ don't expose a synchronous way to read the state */ if (IS_HASWELL(dev)) From e8cb8d69d125f56fa3ba5239b215a56718e2ca44 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:19:55 -0300 Subject: [PATCH 48/80] drm/i915: fix the FBC work allocation failure path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always update the currrent crtc, fb and vertical offset after calling enable_fbc. We were forgetting to do so along the failure paths when enabling fbc synchronously. Fix this with a new helper to enable_fbc() and update the state simultaneously. v2: Improve commit message (Chris). v3: Constify struct drm_framebuffer (Ville). Reviewed-by: Ville Syrjälä Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_fbc.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 1f97fb548c2a..9e42079e1705 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -308,6 +308,18 @@ bool intel_fbc_enabled(struct drm_i915_private *dev_priv) return dev_priv->fbc.enabled; } +static void intel_fbc_enable(struct intel_crtc *crtc, + const struct drm_framebuffer *fb) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + + dev_priv->fbc.enable_fbc(crtc); + + dev_priv->fbc.crtc = crtc; + dev_priv->fbc.fb_id = fb->base.id; + dev_priv->fbc.y = crtc->base.y; +} + static void intel_fbc_work_fn(struct work_struct *__work) { struct intel_fbc_work *work = @@ -321,13 +333,8 @@ static void intel_fbc_work_fn(struct work_struct *__work) /* Double check that we haven't switched fb without cancelling * the prior work. */ - if (crtc_fb == work->fb) { - dev_priv->fbc.enable_fbc(work->crtc); - - dev_priv->fbc.crtc = work->crtc; - dev_priv->fbc.fb_id = crtc_fb->base.id; - dev_priv->fbc.y = work->crtc->base.y; - } + if (crtc_fb == work->fb) + intel_fbc_enable(work->crtc, work->fb); dev_priv->fbc.fbc_work = NULL; } @@ -361,7 +368,7 @@ static void intel_fbc_cancel_work(struct drm_i915_private *dev_priv) dev_priv->fbc.fbc_work = NULL; } -static void intel_fbc_enable(struct intel_crtc *crtc) +static void intel_fbc_schedule_enable(struct intel_crtc *crtc) { struct intel_fbc_work *work; struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; @@ -373,7 +380,7 @@ static void intel_fbc_enable(struct intel_crtc *crtc) work = kzalloc(sizeof(*work), GFP_KERNEL); if (work == NULL) { DRM_ERROR("Failed to allocate FBC work structure\n"); - dev_priv->fbc.enable_fbc(crtc); + intel_fbc_enable(crtc, crtc->base.primary->fb); return; } @@ -824,7 +831,7 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) __intel_fbc_disable(dev_priv); } - intel_fbc_enable(intel_crtc); + intel_fbc_schedule_enable(intel_crtc); dev_priv->fbc.no_fbc_reason = FBC_OK; return; From adf70c65cff66d843d66469dbe13ef1ed21e062b Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:19:56 -0300 Subject: [PATCH 49/80] drm/i915: check for the supported strides on HSW+ FBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't allow FBC for cases where the spec says we can't FBC. v2: - Just WARN_ON() the strides that should have been caught earlier (Daniel) - Make it a new function since I expect this to grow more. v3: - Document which IGT test is exercised by this. v4: - Implement the restrictions for gens 2-6 too (Ville). - Fix off-by-one mistake (Ville). Testcase: igt/kms_frontbuffer_tracking/fbc-badstride Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_fbc.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7cbc81f718a7..d4240dba16ff 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -948,6 +948,7 @@ struct i915_fbc { FBC_CHIP_DEFAULT, /* disabled by default on this chip */ FBC_ROTATION, /* rotation is not supported */ FBC_IN_DBG_MASTER, /* kernel debugger is active */ + FBC_BAD_STRIDE, /* stride is not supported */ } no_fbc_reason; bool (*fbc_enabled)(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 9e42079e1705..db3809134a29 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -480,6 +480,8 @@ const char *intel_no_fbc_reason_str(enum no_fbc_reason reason) return "rotation unsupported"; case FBC_IN_DBG_MASTER: return "Kernel debugger is active"; + case FBC_BAD_STRIDE: + return "framebuffer stride not supported"; default: MISSING_CASE(reason); return "unknown reason"; @@ -671,6 +673,27 @@ static int intel_fbc_setup_cfb(struct drm_i915_private *dev_priv, int size, return intel_fbc_alloc_cfb(dev_priv, size, fb_cpp); } +static bool stride_is_valid(struct drm_i915_private *dev_priv, + unsigned int stride) +{ + /* These should have been caught earlier. */ + WARN_ON(stride < 512); + WARN_ON((stride & (64 - 1)) != 0); + + /* Below are the additional FBC restrictions. */ + + if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv)) + return stride == 4096 || stride == 8192; + + if (IS_GEN4(dev_priv) && !IS_G4X(dev_priv) && stride < 2048) + return false; + + if (stride > 16384) + return false; + + return true; +} + /** * __intel_fbc_update - enable/disable FBC as needed, unlocked * @dev_priv: i915 device instance @@ -781,6 +804,11 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) goto out_disable; } + if (!stride_is_valid(dev_priv, fb->pitches[0])) { + set_no_fbc_reason(dev_priv, FBC_BAD_STRIDE); + goto out_disable; + } + /* If the kernel debugger is active, always disable compression */ if (in_dbg_master()) { set_no_fbc_reason(dev_priv, FBC_IN_DBG_MASTER); From a9da512b3ed73045253afd778e40d4298f42905b Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:19:57 -0300 Subject: [PATCH 50/80] drm/i915: avoid the last 8mb of stolen on BDW/SKL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FBC hardware for these platforms doesn't have access to the bios_reserved range, so it always assumes the maximum (8mb) is used. So avoid this range while allocating. This solves a bunch of FIFO underruns that happen if you end up putting the CFB in that memory range. On my machine, with 32mb of stolen, I need a 2560x1440 mode for that. Testcase: igt/kms_frontbuffer_tracking/fbc-* (given the right setup) Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++++ drivers/gpu/drm/i915/i915_gem_gtt.h | 1 + drivers/gpu/drm/i915/i915_gem_stolen.c | 26 +++++++++++++++++++------- drivers/gpu/drm/i915/intel_fbc.c | 16 ++++++++++++++-- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d4240dba16ff..ffd4ab111957 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3175,6 +3175,10 @@ static inline void i915_gem_chipset_flush(struct drm_device *dev) int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, struct drm_mm_node *node, u64 size, unsigned alignment); +int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv, + struct drm_mm_node *node, u64 size, + unsigned alignment, u64 start, + u64 end); void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, struct drm_mm_node *node); int i915_gem_init_stolen(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 82750073d5b3..96ebb98a476d 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -341,6 +341,7 @@ struct i915_gtt { struct i915_address_space base; size_t stolen_size; /* Total size of stolen memory */ + size_t stolen_usable_size; /* Total size minus BIOS reserved */ u64 mappable_end; /* End offset that we can CPU map */ struct io_mapping *mappable; /* Mapping to our CPU mappable region */ phys_addr_t mappable_base; /* PA of our GMADR */ diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index bf26ecc3781b..081ef6d6c94f 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -42,9 +42,9 @@ * for is a boon. */ -int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, - struct drm_mm_node *node, u64 size, - unsigned alignment) +int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv, + struct drm_mm_node *node, u64 size, + unsigned alignment, u64 start, u64 end) { int ret; @@ -52,13 +52,23 @@ int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, return -ENODEV; mutex_lock(&dev_priv->mm.stolen_lock); - ret = drm_mm_insert_node(&dev_priv->mm.stolen, node, size, alignment, - DRM_MM_SEARCH_DEFAULT); + ret = drm_mm_insert_node_in_range(&dev_priv->mm.stolen, node, size, + alignment, start, end, + DRM_MM_SEARCH_DEFAULT); mutex_unlock(&dev_priv->mm.stolen_lock); return ret; } +int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, + struct drm_mm_node *node, u64 size, + unsigned alignment) +{ + return i915_gem_stolen_insert_node_in_range(dev_priv, node, size, + alignment, 0, + dev_priv->gtt.stolen_usable_size); +} + void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, struct drm_mm_node *node) { @@ -355,9 +365,11 @@ int i915_gem_init_stolen(struct drm_device *dev) dev_priv->gtt.stolen_size >> 10, (dev_priv->gtt.stolen_size - reserved_total) >> 10); + dev_priv->gtt.stolen_usable_size = dev_priv->gtt.stolen_size - + reserved_total; + /* Basic memrange allocator for stolen space */ - drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size - - reserved_total); + drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_usable_size); return 0; } diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index db3809134a29..6f3c2ea75dd8 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -551,6 +551,16 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, { int compression_threshold = 1; int ret; + u64 end; + + /* The FBC hardware for BDW/SKL doesn't have access to the stolen + * reserved range size, so it always assumes the maximum (8mb) is used. + * If we enable FBC using a CFB on that memory range we'll get FIFO + * underruns, even if that range is not reserved by the BIOS. */ + if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv)) + end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024; + else + end = dev_priv->gtt.stolen_usable_size; /* HACK: This code depends on what we will do in *_enable_fbc. If that * code changes, this code needs to change as well. @@ -560,7 +570,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, */ /* Try to over-allocate to reduce reallocations and fragmentation. */ - ret = i915_gem_stolen_insert_node(dev_priv, node, size <<= 1, 4096); + ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size <<= 1, + 4096, 0, end); if (ret == 0) return compression_threshold; @@ -570,7 +581,8 @@ again: (fb_cpp == 2 && compression_threshold == 2)) return 0; - ret = i915_gem_stolen_insert_node(dev_priv, node, size >>= 1, 4096); + ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size >>= 1, + 4096, 0, end); if (ret && INTEL_INFO(dev_priv)->gen <= 4) { return 0; } else if (ret) { From b8bf5d7fe0dee64ed0a73fa1e95ba8e464d605da Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:19:58 -0300 Subject: [PATCH 51/80] drm/i915: print the correct amount of bytes allocated for the CFB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And also print the threshold. I was surprised to see a log message claiming the CFB size was 32mb when there was less than 24mb available for it. Reviewed-by: Ville Syrjälä Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_fbc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 6f3c2ea75dd8..69726a7ed0d0 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -634,8 +634,9 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv, int size, dev_priv->fbc.uncompressed_size = size; - DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n", - size); + DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n", + dev_priv->fbc.compressed_fb.size, + dev_priv->fbc.threshold); return 0; From 7b24c9a696c1c68eaa471a27bf467e97a9986fa9 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:19:59 -0300 Subject: [PATCH 52/80] drm/i915: don't enable FBC when pixel rate exceeds 95% on HSW/BDW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BSpec says we shouldn't enable FBC on HSW/BDW when the pipe pixel rate exceeds 95% of the core display clock. v2: - HSW also needs the WA (Ville). - Add the WA name (Ville). - Use the current cdclk (Ville). Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_fbc.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ffd4ab111957..e5242c0ce4f1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -949,6 +949,7 @@ struct i915_fbc { FBC_ROTATION, /* rotation is not supported */ FBC_IN_DBG_MASTER, /* kernel debugger is active */ FBC_BAD_STRIDE, /* stride is not supported */ + FBC_PIXEL_RATE, /* pixel rate is too big */ } no_fbc_reason; bool (*fbc_enabled)(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 69726a7ed0d0..1c4536ad4de9 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -482,6 +482,8 @@ const char *intel_no_fbc_reason_str(enum no_fbc_reason reason) return "Kernel debugger is active"; case FBC_BAD_STRIDE: return "framebuffer stride not supported"; + case FBC_PIXEL_RATE: + return "pixel rate is too big"; default: MISSING_CASE(reason); return "unknown reason"; @@ -828,6 +830,14 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) goto out_disable; } + /* WaFbcExceedCdClockThreshold:hsw,bdw */ + if ((IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) && + ilk_pipe_pixel_rate(intel_crtc->config) >= + dev_priv->cdclk_freq * 95 / 100) { + set_no_fbc_reason(dev_priv, FBC_PIXEL_RATE); + goto out_disable; + } + if (intel_fbc_setup_cfb(dev_priv, obj->base.size, drm_format_plane_cpp(fb->pixel_format, 0))) { set_no_fbc_reason(dev_priv, FBC_STOLEN_TOO_SMALL); From 57012be9289b4f6d12b05878411d903982ec2a4e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:20:00 -0300 Subject: [PATCH 53/80] drm/i915: apply WaFbcAsynchFlipDisableFbcQueue earlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spec says the register should have that value for the entire time that FBC is enabled, so apply the WA before we enable FBC. Notice that we also have this WA for ILK/SNB, but it is implemented at init_clock_gating(). I could move the IVB/HSW/BDW WA code to init_clock_gating() too, but since we recently had some complaints about WAs not staying after being set, I'm going to play safe and keep this here for now. Reviewed-by: Ville Syrjälä Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_fbc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 1c4536ad4de9..2b75003eb79e 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -272,8 +272,6 @@ static void gen7_fbc_enable(struct intel_crtc *crtc) if (dev_priv->fbc.false_color) dpfc_ctl |= FBC_CTL_FALSE_COLOR; - I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); - if (IS_IVYBRIDGE(dev_priv)) { /* WaFbcAsynchFlipDisableFbcQueue:ivb */ I915_WRITE(ILK_DISPLAY_CHICKEN1, @@ -286,6 +284,8 @@ static void gen7_fbc_enable(struct intel_crtc *crtc) HSW_FBCQ_DIS); } + I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); + I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj->fence_reg); I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->base.y); From 40f4022ef67f30cc0b7ee7453926d1803277d1af Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:20:01 -0300 Subject: [PATCH 54/80] drm/i915: don't apply WaFbcAsynchFlipDisableFbcQueue on SKL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This WA is only for HSW/BDW. Reviewed-by: Ville Syrjälä Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_fbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 2b75003eb79e..56cf11094a04 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -277,7 +277,7 @@ static void gen7_fbc_enable(struct intel_crtc *crtc) I915_WRITE(ILK_DISPLAY_CHICKEN1, I915_READ(ILK_DISPLAY_CHICKEN1) | ILK_FBCQ_DIS); - } else { + } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { /* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */ I915_WRITE(CHICKEN_PIPESL_1(crtc->pipe), I915_READ(CHICKEN_PIPESL_1(crtc->pipe)) | From b9e831dc3973bddfaa8e27629745c5948ed8b92d Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 21 Sep 2015 19:48:06 -0300 Subject: [PATCH 55/80] drm/i915: reject invalid formats for FBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is essentially a rewrite of "drm/i915: Check pixel format for fbc" from Ville Syrjälä. The idea is the same, but the code is different due to all the changes that happened since his original patch. So any bugs are due to my bad rewrite. v2: - Drop the alpha formats (Ville). v3: - Drop the stale comment (Ville). Testcases: igt/kms_frontbuffer_tracking/*fbc*-${format_name}-draw-* Credits-to: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_fbc.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e5242c0ce4f1..3044cbecb151 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -950,6 +950,7 @@ struct i915_fbc { FBC_IN_DBG_MASTER, /* kernel debugger is active */ FBC_BAD_STRIDE, /* stride is not supported */ FBC_PIXEL_RATE, /* pixel rate is too big */ + FBC_PIXEL_FORMAT /* pixel format is invalid */ } no_fbc_reason; bool (*fbc_enabled)(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 56cf11094a04..9d2f56ebd46e 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -484,6 +484,8 @@ const char *intel_no_fbc_reason_str(enum no_fbc_reason reason) return "framebuffer stride not supported"; case FBC_PIXEL_RATE: return "pixel rate is too big"; + case FBC_PIXEL_FORMAT: + return "pixel format is invalid"; default: MISSING_CASE(reason); return "unknown reason"; @@ -709,6 +711,29 @@ static bool stride_is_valid(struct drm_i915_private *dev_priv, return true; } +static bool pixel_format_is_valid(struct drm_framebuffer *fb) +{ + struct drm_device *dev = fb->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + switch (fb->pixel_format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + return true; + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_RGB565: + /* 16bpp not supported on gen2 */ + if (IS_GEN2(dev)) + return false; + /* WaFbcOnly1to1Ratio:ctg */ + if (IS_G4X(dev_priv)) + return false; + return true; + default: + return false; + } +} + /** * __intel_fbc_update - enable/disable FBC as needed, unlocked * @dev_priv: i915 device instance @@ -824,6 +849,11 @@ static void __intel_fbc_update(struct drm_i915_private *dev_priv) goto out_disable; } + if (!pixel_format_is_valid(fb)) { + set_no_fbc_reason(dev_priv, FBC_PIXEL_FORMAT); + goto out_disable; + } + /* If the kernel debugger is active, always disable compression */ if (in_dbg_master()) { set_no_fbc_reason(dev_priv, FBC_IN_DBG_MASTER); From 2db3366b18e6ee5c6cb09b5f3902bcacfa3d534e Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Mon, 14 Sep 2015 15:20:03 -0300 Subject: [PATCH 56/80] drm/i915: fix FBC for cases where crtc->base.y is non-zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I only tested this on BDW and SKL, but since the register description is the same ever since gen4, let's assume that all gens take the same register format. If that's not true, then hopefully someone will bisect a bug to this patch and we'll fix it. Notice that the wrong fence offset register just means that the hardware tracking will be wrong. Testcases: - igt/kms_frontbuffer_tracking/fbc-1p-primscrn-pri-shrfb-draw-mmap-gtt - igt/kms_frontbuffer_tracking/fbc-2p-primscrn-pri-shrfb-draw-mmap-gtt v2: - Add intel_crtc->adjusted_{x,y} so this code can work independently of intel_gen4_compute_page_offset(). (Ville). - This version also works on SKL. Signed-off-by: Paulo Zanoni Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 9 +++++++++ drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_fbc.c | 25 ++++++++++++++++++++----- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6d718c0c3beb..bf8754f07b8d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2730,6 +2730,9 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc, (intel_crtc->config->pipe_src_w - 1) * pixel_size; } + intel_crtc->adjusted_x = x; + intel_crtc->adjusted_y = y; + I915_WRITE(reg, dspcntr); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); @@ -2830,6 +2833,9 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc, } } + intel_crtc->adjusted_x = x; + intel_crtc->adjusted_y = y; + I915_WRITE(reg, dspcntr); I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); @@ -3082,6 +3088,9 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, } plane_offset = y_offset << 16 | x_offset; + intel_crtc->adjusted_x = x_offset; + intel_crtc->adjusted_y = y_offset; + I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset); I915_WRITE(PLANE_SIZE(pipe, 0), plane_size); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 394018ead36b..ab3c29639857 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -537,6 +537,8 @@ struct intel_crtc { * gen4+ this only adjusts up to a tile, offsets within a tile are * handled in the hw itself (with the TILEOFF register). */ unsigned long dspaddr_offset; + int adjusted_x; + int adjusted_y; struct drm_i915_gem_object *cursor_bo; uint32_t cursor_addr; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 9d2f56ebd46e..d38f46433bcd 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -41,6 +41,19 @@ #include "intel_drv.h" #include "i915_drv.h" +/* + * In some platforms where the CRTC's x:0/y:0 coordinates doesn't match the + * frontbuffer's x:0/y:0 coordinates we lie to the hardware about the plane's + * origin so the x and y offsets can actually fit the registers. As a + * consequence, the fence doesn't really start exactly at the display plane + * address we program because it starts at the real start of the buffer, so we + * have to take this into consideration here. + */ +static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc) +{ + return crtc->base.y - crtc->adjusted_y; +} + static void i8xx_fbc_disable(struct drm_i915_private *dev_priv) { u32 fbc_ctl; @@ -97,7 +110,7 @@ static void i8xx_fbc_enable(struct intel_crtc *crtc) fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | FBC_CTL_CPU_FENCE; fbc_ctl2 |= FBC_CTL_PLANE(crtc->plane); I915_WRITE(FBC_CONTROL2, fbc_ctl2); - I915_WRITE(FBC_FENCE_OFF, crtc->base.y); + I915_WRITE(FBC_FENCE_OFF, get_crtc_fence_y_offset(crtc)); } /* enable it... */ @@ -135,7 +148,7 @@ static void g4x_fbc_enable(struct intel_crtc *crtc) dpfc_ctl |= DPFC_CTL_LIMIT_1X; dpfc_ctl |= DPFC_CTL_FENCE_EN | obj->fence_reg; - I915_WRITE(DPFC_FENCE_YOFF, crtc->base.y); + I915_WRITE(DPFC_FENCE_YOFF, get_crtc_fence_y_offset(crtc)); /* enable it... */ I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); @@ -177,6 +190,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc) struct drm_i915_gem_object *obj = intel_fb_obj(fb); u32 dpfc_ctl; int threshold = dev_priv->fbc.threshold; + unsigned int y_offset; dev_priv->fbc.enabled = true; @@ -200,7 +214,8 @@ static void ilk_fbc_enable(struct intel_crtc *crtc) if (IS_GEN5(dev_priv)) dpfc_ctl |= obj->fence_reg; - I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->base.y); + y_offset = get_crtc_fence_y_offset(crtc); + I915_WRITE(ILK_DPFC_FENCE_YOFF, y_offset); I915_WRITE(ILK_FBC_RT_BASE, i915_gem_obj_ggtt_offset(obj) | ILK_FBC_RT_VALID); /* enable it... */ I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); @@ -208,7 +223,7 @@ static void ilk_fbc_enable(struct intel_crtc *crtc) if (IS_GEN6(dev_priv)) { I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj->fence_reg); - I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->base.y); + I915_WRITE(DPFC_CPU_FENCE_OFFSET, y_offset); } intel_fbc_nuke(dev_priv); @@ -288,7 +303,7 @@ static void gen7_fbc_enable(struct intel_crtc *crtc) I915_WRITE(SNB_DPFC_CTL_SA, SNB_CPU_FENCE_ENABLE | obj->fence_reg); - I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->base.y); + I915_WRITE(DPFC_CPU_FENCE_OFFSET, get_crtc_fence_y_offset(crtc)); intel_fbc_nuke(dev_priv); From 7d316aecf883a19c9883e4dcbc058806fd25b152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 16 Sep 2015 21:28:50 +0300 Subject: [PATCH 57/80] drm/i915: Implement stolen reserved detection for ctg/elk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finally managed to dig up enough hints as to where the stolen reserved stuff lives on ctg/elk. So add the code to decode it. This was a combination of old chipset specs, diggin up an old elk grits release with an ctg/elk AubLoad etc. This was only tested on an elk as I don't have a ctg here unfortunately. This leaves ilk as the only platform that doesn't have a way to detect this stuff. Looking at the register contents on my ilk, it might be that the elk way works there too, but I can't be sure since I can't affect the amount of reserved memory on that machine, and if I am to trust the register contents, by default it would reserve 0 bytes. v2: s/WARN_ON_ONCE/WARN_ON/ since it's in one time init code anyway (Paulo) Cc: Paulo Zanoni Cc: Chris Wilson Acked-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_stolen.c | 31 +++++++++++++++++++++++--- drivers/gpu/drm/i915/i915_reg.h | 5 +++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 081ef6d6c94f..55df6ce34751 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -196,6 +196,29 @@ void i915_gem_cleanup_stolen(struct drm_device *dev) drm_mm_takedown(&dev_priv->mm.stolen); } +static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, + unsigned long *base, unsigned long *size) +{ + uint32_t reg_val = I915_READ(IS_GM45(dev_priv) ? + CTG_STOLEN_RESERVED : + ELK_STOLEN_RESERVED); + unsigned long stolen_top = dev_priv->mm.stolen_base + + dev_priv->gtt.stolen_size; + + *base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16; + + WARN_ON((reg_val & G4X_STOLEN_RESERVED_ADDR1_MASK) < *base); + + /* On these platforms, the register doesn't have a size field, so the + * size is the distance between the base and the top of the stolen + * memory. We also have the genuine case where base is zero and there's + * nothing reserved. */ + if (*base == 0) + *size = 0; + else + *size = stolen_top - *base; +} + static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv, unsigned long *base, unsigned long *size) { @@ -315,10 +338,12 @@ int i915_gem_init_stolen(struct drm_device *dev) switch (INTEL_INFO(dev_priv)->gen) { case 2: case 3: + break; case 4: - if (!IS_G4X(dev)) - break; - /* fall through */ + if (IS_G4X(dev)) + g4x_get_stolen_reserved(dev_priv, &reserved_base, + &reserved_size); + break; case 5: /* Assume the gen6 maximum for the older platforms. */ reserved_size = 1024 * 1024; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c5287a1818f3..881a47a98820 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2494,6 +2494,11 @@ enum skl_disp_power_wells { #define MCHBAR_MIRROR_BASE_SNB 0x140000 +#define CTG_STOLEN_RESERVED (MCHBAR_MIRROR_BASE + 0x34) +#define ELK_STOLEN_RESERVED (MCHBAR_MIRROR_BASE + 0x48) +#define G4X_STOLEN_RESERVED_ADDR1_MASK (0xFFFF << 16) +#define G4X_STOLEN_RESERVED_ADDR2_MASK (0xFFF << 4) + /* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */ #define DCLK (MCHBAR_MIRROR_BASE_SNB + 0x5e04) From a2cad9dff4dd44d0244b966d980de9d602d87593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= Date: Wed, 16 Sep 2015 11:49:00 +0200 Subject: [PATCH 58/80] drm/i915/gtt: Do not initialize drm_mm twice. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It would be initialized just moments later by i915_init_vm. Rearrange the code such that i915_init_vm() is next to its callers inside i915_gem_gtt (and so we can make it static). After removing the dance around the files, it is clear that we are repeating some work inside the initializers (such as calling drm_mm_init() multiple times), so take advantage of the refactor to also remove some redundant code and clean up the interface. v2: Commit msg update, s/i915_init_vm/i915_address_space_init, move to i915_gem_gtt.c, init address_space during i915_gem_setup_global_gtt for ggtt. v3: Do not init global_link - we are adding it to vm_list moments later, make i915_address_space_init static, use OOP style parameter order. Cc: Chris Wilson Cc: Michel Thierry Cc: Mika Kuoppala Signed-off-by: Michał Winiarski Reviewed-by Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_gem.c | 14 -------------- drivers/gpu/drm/i915/i915_gem_gtt.c | 26 ++++++++++++++++++-------- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3044cbecb151..4e8178d34a34 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2809,8 +2809,6 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, size_t size); struct drm_i915_gem_object *i915_gem_object_create_from_data( struct drm_device *dev, const void *data, size_t size); -void i915_init_vm(struct drm_i915_private *dev_priv, - struct i915_address_space *vm); void i915_gem_free_object(struct drm_gem_object *obj); void i915_gem_vma_destroy(struct i915_vma *vma); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e1b6457b5404..58c7ad058c41 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4844,18 +4844,6 @@ init_ring_lists(struct intel_engine_cs *ring) INIT_LIST_HEAD(&ring->request_list); } -void i915_init_vm(struct drm_i915_private *dev_priv, - struct i915_address_space *vm) -{ - if (!i915_is_ggtt(vm)) - drm_mm_init(&vm->mm, vm->start, vm->total); - vm->dev = dev_priv->dev; - INIT_LIST_HEAD(&vm->active_list); - INIT_LIST_HEAD(&vm->inactive_list); - INIT_LIST_HEAD(&vm->global_link); - list_add_tail(&vm->global_link, &dev_priv->vm_list); -} - void i915_gem_load(struct drm_device *dev) { @@ -4879,8 +4867,6 @@ i915_gem_load(struct drm_device *dev) NULL); INIT_LIST_HEAD(&dev_priv->vm_list); - i915_init_vm(dev_priv, &dev_priv->gtt.base); - INIT_LIST_HEAD(&dev_priv->context_list); INIT_LIST_HEAD(&dev_priv->mm.unbound_list); INIT_LIST_HEAD(&dev_priv->mm.bound_list); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 87862813cfde..01f3521e77d3 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2121,6 +2121,16 @@ static int __hw_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) return gen8_ppgtt_init(ppgtt); } +static void i915_address_space_init(struct i915_address_space *vm, + struct drm_i915_private *dev_priv) +{ + drm_mm_init(&vm->mm, vm->start, vm->total); + vm->dev = dev_priv->dev; + INIT_LIST_HEAD(&vm->active_list); + INIT_LIST_HEAD(&vm->inactive_list); + list_add_tail(&vm->global_link, &dev_priv->vm_list); +} + int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2129,9 +2139,7 @@ int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt) ret = __hw_ppgtt_init(dev, ppgtt); if (ret == 0) { kref_init(&ppgtt->ref); - drm_mm_init(&ppgtt->base.mm, ppgtt->base.start, - ppgtt->base.total); - i915_init_vm(dev_priv, &ppgtt->base); + i915_address_space_init(&ppgtt->base, dev_priv); } return ret; @@ -2618,11 +2626,13 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, BUG_ON(mappable_end > end); - /* Subtract the guard page ... */ - drm_mm_init(&ggtt_vm->mm, start, end - start - PAGE_SIZE); + ggtt_vm->start = start; - dev_priv->gtt.base.start = start; - dev_priv->gtt.base.total = end - start; + /* Subtract the guard page before address space initialization to + * shrink the range used by drm_mm */ + ggtt_vm->total = end - start - PAGE_SIZE; + i915_address_space_init(ggtt_vm, dev_priv); + ggtt_vm->total += PAGE_SIZE; if (intel_vgpu_active(dev)) { ret = intel_vgt_balloon(dev); @@ -2631,7 +2641,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, } if (!HAS_LLC(dev)) - dev_priv->gtt.base.mm.color_adjust = i915_gtt_color_adjust; + ggtt_vm->mm.color_adjust = i915_gtt_color_adjust; /* Mark any preallocated objects as occupied */ list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { From 8204502a6aa2eab8cd5779020c2881fbc6361a96 Mon Sep 17 00:00:00 2001 From: Dongwon Kim Date: Thu, 17 Sep 2015 11:26:35 -0700 Subject: [PATCH 59/80] drm/i915: Do not hardcode s_max, ss_max and eu_mask for BXT We can calculate BXT values correctly from GFX fuse values without hardcoding special limits. Cc: Imre Deak Cc: Matthew D Roper Signed-off-by: Dongwon Kim Reviewed-by: Arun Siluvery Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c0695504dd8f..817b05ce8dd3 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -631,17 +631,6 @@ static void gen9_sseu_info_init(struct drm_device *dev) u32 fuse2, s_enable, ss_disable, eu_disable; u8 eu_mask = 0xff; - /* - * BXT has a single slice. BXT also has at most 6 EU per subslice, - * and therefore only the lowest 6 bits of the 8-bit EU disable - * fields are valid. - */ - if (IS_BROXTON(dev)) { - s_max = 1; - eu_max = 6; - eu_mask = 0x3f; - } - info = (struct intel_device_info *)&dev_priv->info; fuse2 = I915_READ(GEN8_FUSE2); s_enable = (fuse2 & GEN8_F2_S_ENA_MASK) >> From 0706f17c307b056ff6f1848320ba82d76945a6ff Mon Sep 17 00:00:00 2001 From: Egbert Eich Date: Wed, 23 Sep 2015 16:15:27 +0200 Subject: [PATCH 60/80] drm/i915: Avoid race of intel_crt_detect_hotplug() with HPD interrupt, v2 An HPD interrupt may fire while we are in a function that changes the PORT_HOTPLUG_EN register - especially when an HPD interrupt storm occurs. Since the interrupt handler changes the enabled HPD lines when it detects such a storm the read-modify-write cycles may interfere. To avoid this, shiled the rmw cycles with IRQ save spinlocks. Changes since v1: - Implement a function which takes care of accessing PORT_HOTPLUG_EN. Signed-off-by: Egbert Eich Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 ++ drivers/gpu/drm/i915/i915_irq.c | 64 +++++++++++++++++++++++++------- drivers/gpu/drm/i915/intel_crt.c | 11 +++--- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4e8178d34a34..ba4596e9e7eb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2742,6 +2742,9 @@ i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv); void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv); +void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, + uint32_t mask, + uint32_t bits); void ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask); void diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ca6d806a195a..6ca6c16fe500 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -167,6 +167,44 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); +/* For display hotplug interrupt */ +static inline void +i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv, + uint32_t mask, + uint32_t bits) +{ + uint32_t val; + + assert_spin_locked(&dev_priv->irq_lock); + WARN_ON(bits & ~mask); + + val = I915_READ(PORT_HOTPLUG_EN); + val &= ~mask; + val |= bits; + I915_WRITE(PORT_HOTPLUG_EN, val); +} + +/** + * i915_hotplug_interrupt_update - update hotplug interrupt enable + * @dev_priv: driver private + * @mask: bits to update + * @bits: bits to enable + * NOTE: the HPD enable bits are modified both inside and outside + * of an interrupt context. To avoid that read-modify-write cycles + * interfer, these bits are protected by a spinlock. Since this + * function is usually not called from a context where the lock is + * held already, this function acquires the lock itself. A non-locking + * version is also available. + */ +void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv, + uint32_t mask, + uint32_t bits) +{ + spin_lock_irq(&dev_priv->irq_lock); + i915_hotplug_interrupt_update_locked(dev_priv, mask, bits); + spin_unlock_irq(&dev_priv->irq_lock); +} + /** * ilk_update_display_irq - update DEIMR * @dev_priv: driver private @@ -3050,7 +3088,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) { enum pipe pipe; - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xFFFFFFFF, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); for_each_pipe(dev_priv, pipe) @@ -3466,7 +3504,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) { dev_priv->irq_mask = ~0; - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); POSTING_READ(PORT_HOTPLUG_EN); I915_WRITE(VLV_IIR, 0xffffffff); @@ -3840,7 +3878,7 @@ static void i915_irq_preinstall(struct drm_device * dev) int pipe; if (I915_HAS_HOTPLUG(dev)) { - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); } @@ -3874,7 +3912,7 @@ static int i915_irq_postinstall(struct drm_device *dev) I915_USER_INTERRUPT; if (I915_HAS_HOTPLUG(dev)) { - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); POSTING_READ(PORT_HOTPLUG_EN); /* Enable in IER... */ @@ -4036,7 +4074,7 @@ static void i915_irq_uninstall(struct drm_device * dev) int pipe; if (I915_HAS_HOTPLUG(dev)) { - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); } @@ -4057,7 +4095,7 @@ static void i965_irq_preinstall(struct drm_device * dev) struct drm_i915_private *dev_priv = dev->dev_private; int pipe; - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(HWSTAM, 0xeffe); @@ -4118,7 +4156,7 @@ static int i965_irq_postinstall(struct drm_device *dev) I915_WRITE(IER, enable_mask); POSTING_READ(IER); - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); POSTING_READ(PORT_HOTPLUG_EN); i915_enable_asle_pipestat(dev); @@ -4133,22 +4171,22 @@ static void i915_hpd_irq_setup(struct drm_device *dev) assert_spin_locked(&dev_priv->irq_lock); - hotplug_en = I915_READ(PORT_HOTPLUG_EN); - hotplug_en &= ~HOTPLUG_INT_EN_MASK; /* Note HDMI and DP share hotplug bits */ /* enable bits are the same for all generations */ - hotplug_en |= intel_hpd_enabled_irqs(dev, hpd_mask_i915); + hotplug_en = intel_hpd_enabled_irqs(dev, hpd_mask_i915); /* Programming the CRT detection parameters tends to generate a spurious hotplug event about three seconds later. So just do it once. */ if (IS_G4X(dev)) hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64; - hotplug_en &= ~CRT_HOTPLUG_VOLTAGE_COMPARE_MASK; hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; /* Ignore TV since it's buggy */ - I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); + i915_hotplug_interrupt_update_locked(dev_priv, + (HOTPLUG_INT_EN_MASK + | CRT_HOTPLUG_VOLTAGE_COMPARE_MASK), + hotplug_en); } static irqreturn_t i965_irq_handler(int irq, void *arg) @@ -4261,7 +4299,7 @@ static void i965_irq_uninstall(struct drm_device * dev) if (!dev_priv) return; - I915_WRITE(PORT_HOTPLUG_EN, 0); + i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); I915_WRITE(HWSTAM, 0xffffffff); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index af5e43bef4a4..6ce38e3edf21 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -376,7 +376,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; struct drm_i915_private *dev_priv = dev->dev_private; - u32 hotplug_en, orig, stat; + u32 stat; bool ret = false; int i, tries = 0; @@ -395,12 +395,12 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) tries = 2; else tries = 1; - hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN); - hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; for (i = 0; i < tries ; i++) { /* turn on the FORCE_DETECT */ - I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); + i915_hotplug_interrupt_update(dev_priv, + CRT_HOTPLUG_FORCE_DETECT, + CRT_HOTPLUG_FORCE_DETECT); /* wait for FORCE_DETECT to go off */ if (wait_for((I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0, @@ -415,8 +415,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) /* clear the interrupt we just generated, if any */ I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS); - /* and put the bits back */ - I915_WRITE(PORT_HOTPLUG_EN, orig); + i915_hotplug_interrupt_update(dev_priv, CRT_HOTPLUG_FORCE_DETECT, 0); return ret; } From 53ce81a761fb130c5d7ad653239fc9f9adc32237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Sep 2015 21:04:38 +0300 Subject: [PATCH 61/80] drm/i915: Make sure we don't detect eDP on g4x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't support eDP on g4x, so let's not even look at the VBT to determine the port type, just in case the VBT is bonkers on some g4x machines and indicates the precense of eDP. Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 02401a397dcc..5fe1648cd9c8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -5255,6 +5255,13 @@ bool intel_dp_is_edp(struct drm_device *dev, enum port port) [PORT_E] = DVO_PORT_DPE, }; + /* + * eDP not supported on g4x. so bail out early just + * for a bit extra safety in case the VBT is bonkers. + */ + if (INTEL_INFO(dev)->gen < 5) + return false; + if (port == PORT_A) return true; From 972e7d71c82ea70100b808695d5cf735c1df5ef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Sep 2015 21:04:39 +0300 Subject: [PATCH 62/80] drm/i915: Ignore "digital output" and "not HDMI output" bits for eDP detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ignore DEVICE_TYPE_NOT_HDMI_OUTPUT and DEVICE_TYPE_DIGITAL_OUTPUT when trying to determine the presence of eDP based on the VBT child device type. Apparently a significant portion of VLV systems have these bits set incorrectly, and so we currently fail to detect eDP on said systems. This is based on an earlier patch [1] from Andreas Lampersperger. Instead of ignoring the bits just on VLV as was done in the orignal patch, we now ignore them for all platforms. We should still have enough bits in there to avoid false positives (unless the VBT is totally bonkers). Quoting the orignal patch: > When the i915.ko identify an eDP output on a valleyview > board, it should be more slackly. The reason for that is, > that BIOS DATA TABLES generated with intel BMP (Binary > Modification Program) do not set bits for NOT_HDMI or > DIGITAL_OUTPUT on the device type. Due to Adolfo > Sanchez from Intel EMGD, this is not possible. > To solve this problem and enable i915.ko on embedded > vlv boards with eDP, we ignore this two bits. [1] http://lists.freedesktop.org/archives/intel-gfx/2015-June/069416.html Cc: Andreas Lampersperger Cc: "Sanchez, AdolfoX" Signed-off-by: Ville Syrjälä Acked-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_bios.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 1b7417e3131b..7ec8c9aefb84 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -741,7 +741,6 @@ int intel_parse_bios(struct drm_device *dev); */ #define DEVICE_TYPE_eDP_BITS \ (DEVICE_TYPE_INTERNAL_CONNECTOR | \ - DEVICE_TYPE_NOT_HDMI_OUTPUT | \ DEVICE_TYPE_MIPI_OUTPUT | \ DEVICE_TYPE_COMPOSITE_OUTPUT | \ DEVICE_TYPE_DUAL_CHANNEL | \ @@ -749,7 +748,6 @@ int intel_parse_bios(struct drm_device *dev); DEVICE_TYPE_TMDS_DVI_SIGNALING | \ DEVICE_TYPE_VIDEO_SIGNALING | \ DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ - DEVICE_TYPE_DIGITAL_OUTPUT | \ DEVICE_TYPE_ANALOG_OUTPUT) /* define the DVO port for HDMI output type */ From 8bd864b81a7472a19eb6ed536e028a10e7d71239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:14 +0300 Subject: [PATCH 63/80] drm/i915: Don't pass sdvo_reg to intel_sdvo_select_{ddc, i2c}_bus() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_sdvo_select_ddc_bus() and intel_sdvo_select_i2c_bus() have no used for the passed in 'reg', so just drop it. Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_sdvo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index ca3dd7c682bd..05521b5c6878 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2222,7 +2222,7 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo) */ static void intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, - struct intel_sdvo *sdvo, u32 reg) + struct intel_sdvo *sdvo) { struct sdvo_device_mapping *mapping; @@ -2239,7 +2239,7 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, static void intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, - struct intel_sdvo *sdvo, u32 reg) + struct intel_sdvo *sdvo) { struct sdvo_device_mapping *mapping; u8 pin; @@ -2925,7 +2925,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) intel_sdvo->sdvo_reg = sdvo_reg; intel_sdvo->is_sdvob = is_sdvob; intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, intel_sdvo) >> 1; - intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo, sdvo_reg); + intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo); if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev)) goto err_i2c_bus; @@ -2987,7 +2987,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) */ intel_sdvo->base.cloneable = 0; - intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); + intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo); /* Set the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) From 83843d84fcd38a7e9b30ff0b9af04669c77ecf8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:15 +0300 Subject: [PATCH 64/80] drm/i915: Parametrize LRC registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 8 ++++---- drivers/gpu/drm/i915/intel_lrc.c | 8 +++----- drivers/gpu/drm/i915/intel_lrc.h | 6 ++++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 72ae3472ddbe..5615d3d3ab59 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2069,8 +2069,8 @@ static int i915_execlists(struct seq_file *m, void *data) seq_printf(m, "%s\n", ring->name); - status = I915_READ(RING_EXECLIST_STATUS(ring)); - ctx_id = I915_READ(RING_EXECLIST_STATUS(ring) + 4); + status = I915_READ(RING_EXECLIST_STATUS_LO(ring)); + ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(ring)); seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n", status, ctx_id); @@ -2085,8 +2085,8 @@ static int i915_execlists(struct seq_file *m, void *data) read_pointer, write_pointer); for (i = 0; i < 6; i++) { - status = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + 8*i); - ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + 8*i + 4); + status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, i)); + ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, i)); seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n", i, status, ctx_id); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index ff9a481ed997..7417650ed9cf 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -349,7 +349,7 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0, I915_WRITE_FW(RING_ELSP(ring), lower_32_bits(desc[0])); /* ELSP is a wo register, use another nearby reg for posting */ - POSTING_READ_FW(RING_EXECLIST_STATUS(ring)); + POSTING_READ_FW(RING_EXECLIST_STATUS_LO(ring)); intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); spin_unlock(&dev_priv->uncore.lock); } @@ -519,10 +519,8 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) while (read_pointer < write_pointer) { read_pointer++; - status = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + - (read_pointer % 6) * 8); - status_id = I915_READ(RING_CONTEXT_STATUS_BUF(ring) + - (read_pointer % 6) * 8 + 4); + status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer % 6)); + status_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, read_pointer % 6)); if (status & GEN8_CTX_STATUS_IDLE_ACTIVE) continue; diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 69d99f0df400..8a08a2780321 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -28,12 +28,14 @@ /* Execlists regs */ #define RING_ELSP(ring) ((ring)->mmio_base+0x230) -#define RING_EXECLIST_STATUS(ring) ((ring)->mmio_base+0x234) +#define RING_EXECLIST_STATUS_LO(ring) ((ring)->mmio_base+0x234) +#define RING_EXECLIST_STATUS_HI(ring) ((ring)->mmio_base+0x234 + 4) #define RING_CONTEXT_CONTROL(ring) ((ring)->mmio_base+0x244) #define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH (1 << 3) #define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT (1 << 0) #define CTX_CTRL_RS_CTX_ENABLE (1 << 1) -#define RING_CONTEXT_STATUS_BUF(ring) ((ring)->mmio_base+0x370) +#define RING_CONTEXT_STATUS_BUF_LO(ring, i) ((ring)->mmio_base+0x370 + (i) * 8) +#define RING_CONTEXT_STATUS_BUF_HI(ring, i) ((ring)->mmio_base+0x370 + (i) * 8 + 4) #define RING_CONTEXT_STATUS_PTR(ring) ((ring)->mmio_base+0x3a0) /* Logical Rings */ From 22dfe79fd9c3951017bd68cad1d3257631307dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:16 +0300 Subject: [PATCH 65/80] drm/i915: Parametrize GEN7_GT_SCRATCH and GEN7_LRA_LIMITS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 8 ++++---- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index bdec64ca6f13..947bd4385292 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1120,7 +1120,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv) s->gfx_pend_tlb1 = I915_READ(GEN7_GFX_PEND_TLB1); for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++) - s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4); + s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS(i)); s->media_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); s->gfx_max_req_count = I915_READ(GEN7_GFX_MAX_REQ_COUNT); @@ -1164,7 +1164,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv) s->pm_ier = I915_READ(GEN6_PMIER); for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++) - s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH_BASE + i * 4); + s->gt_scratch[i] = I915_READ(GEN7_GT_SCRATCH(i)); /* GT SA CZ domain, 0x100000-0x138124 */ s->tilectl = I915_READ(TILECTL); @@ -1202,7 +1202,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv) I915_WRITE(GEN7_GFX_PEND_TLB1, s->gfx_pend_tlb1); for (i = 0; i < ARRAY_SIZE(s->lra_limits); i++) - I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]); + I915_WRITE(GEN7_LRA_LIMITS(i), s->lra_limits[i]); I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count); I915_WRITE(GEN7_GFX_MAX_REQ_COUNT, s->gfx_max_req_count); @@ -1246,7 +1246,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_PMIER, s->pm_ier); for (i = 0; i < ARRAY_SIZE(s->gt_scratch); i++) - I915_WRITE(GEN7_GT_SCRATCH_BASE + i * 4, s->gt_scratch[i]); + I915_WRITE(GEN7_GT_SCRATCH(i), s->gt_scratch[i]); /* GT SA CZ domain, 0x100000-0x138124 */ I915_WRITE(TILECTL, s->tilectl); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 881a47a98820..90ce688696c7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1527,7 +1527,7 @@ enum skl_disp_power_wells { #define GEN7_GFX_PEND_TLB0 0x4034 #define GEN7_GFX_PEND_TLB1 0x4038 /* L3, CVS, ZTLB, RCC, CASC LRA min, max values */ -#define GEN7_LRA_LIMITS_BASE 0x403C +#define GEN7_LRA_LIMITS(i) (0x403C + (i) * 4) #define GEN7_LRA_LIMITS_REG_NUM 13 #define GEN7_MEDIA_MAX_REQ_COUNT 0x4070 #define GEN7_GFX_MAX_REQ_COUNT 0x4074 @@ -6813,7 +6813,7 @@ enum skl_disp_power_wells { GEN6_PM_RP_DOWN_THRESHOLD | \ GEN6_PM_RP_DOWN_TIMEOUT) -#define GEN7_GT_SCRATCH_BASE 0x4F100 +#define GEN7_GT_SCRATCH(i) (0x4F100 + (i) * 4) #define GEN7_GT_SCRATCH_REG_NUM 8 #define VLV_GTLC_SURVIVABILITY_REG 0x130098 From 4d110c71fb87c5601832e918c36af8cd4ef739f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:18 +0300 Subject: [PATCH 66/80] drm/i915: Parametrize FBC_TAG registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_fbc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 90ce688696c7..ffd0f6b07470 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2011,7 +2011,7 @@ enum skl_disp_power_wells { #define FBC_CTL_CPU_FENCE (1<<1) #define FBC_CTL_PLANE(plane) ((plane)<<0) #define FBC_FENCE_OFF 0x03218 /* BSpec typo has 321Bh */ -#define FBC_TAG 0x03300 +#define FBC_TAG(i) (0x03300 + (i) * 4) #define FBC_STATUS2 0x43214 #define FBC_COMPRESSION_MASK 0x7ff diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index d38f46433bcd..6777fbb25d07 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -101,7 +101,7 @@ static void i8xx_fbc_enable(struct intel_crtc *crtc) /* Clear old tags */ for (i = 0; i < (FBC_LL_SIZE / 32) + 1; i++) - I915_WRITE(FBC_TAG + (i * 4), 0); + I915_WRITE(FBC_TAG(i), 0); if (IS_GEN4(dev_priv)) { u32 fbc_ctl2; From 616847e7e8569a28e46a56d4cc1ac28f061e29e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:19 +0300 Subject: [PATCH 67/80] drm/i915: Parametrize ILK turbo registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 10 +++++----- drivers/gpu/drm/i915/intel_pm.c | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ffd0f6b07470..07fcd06bec9f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2579,7 +2579,7 @@ enum skl_disp_power_wells { #define TSFS_INTR_MASK 0x000000ff #define CRSTANDVID 0x11100 -#define PXVFREQ_BASE 0x11110 /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */ +#define PXVFREQ(i) (0x11110 + (i) * 4) /* P[0-15]VIDFREQ (0x1114c) (Ironlake) */ #define PXVFREQ_PX_MASK 0x7f000000 #define PXVFREQ_PX_SHIFT 24 #define VIDFREQ_BASE 0x11110 @@ -2763,8 +2763,8 @@ enum skl_disp_power_wells { #define CSIEW0 0x11250 #define CSIEW1 0x11254 #define CSIEW2 0x11258 -#define PEW 0x1125c -#define DEW 0x11270 +#define PEW(i) (0x1125c + (i) * 4) /* 5 registers */ +#define DEW(i) (0x11270 + (i) * 4) /* 3 registers */ #define MCHAFE 0x112c0 #define CSIEC 0x112e0 #define DMIEC 0x112e4 @@ -2788,8 +2788,8 @@ enum skl_disp_power_wells { #define EG5 0x11624 #define EG6 0x11628 #define EG7 0x1162c -#define PXW 0x11664 -#define PXWL 0x11680 +#define PXW(i) (0x11664 + (i) * 4) /* 4 registers */ +#define PXWL(i) (0x11680 + (i) * 4) /* 8 registers */ #define LCFUSE02 0x116c0 #define LCFUSE_HIV_MASK 0x000000ff #define CSIPLL0 0x12c10 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 566f5cd85101..cb747f1c6650 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4282,7 +4282,7 @@ static void ironlake_enable_drps(struct drm_device *dev) fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT; - vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >> + vstart = (I915_READ(PXVFREQ(fstart)) & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT; dev_priv->ips.fmax = fmax; /* IPS callback will increase this */ @@ -5915,7 +5915,7 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv) assert_spin_locked(&mchdev_lock); - pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_freq * 4)); + pxvid = I915_READ(PXVFREQ(dev_priv->rps.cur_freq)); pxvid = (pxvid >> 24) & 0x7f; ext_v = pvid_to_extvid(dev_priv, pxvid); @@ -6158,13 +6158,13 @@ static void intel_init_emon(struct drm_device *dev) I915_WRITE(CSIEW2, 0x04000004); for (i = 0; i < 5; i++) - I915_WRITE(PEW + (i * 4), 0); + I915_WRITE(PEW(i), 0); for (i = 0; i < 3; i++) - I915_WRITE(DEW + (i * 4), 0); + I915_WRITE(DEW(i), 0); /* Program P-state weights to account for frequency power adjustment */ for (i = 0; i < 16; i++) { - u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4)); + u32 pxvidfreq = I915_READ(PXVFREQ(i)); unsigned long freq = intel_pxfreq(pxvidfreq); unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT; @@ -6185,7 +6185,7 @@ static void intel_init_emon(struct drm_device *dev) for (i = 0; i < 4; i++) { u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) | (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]); - I915_WRITE(PXW + (i * 4), val); + I915_WRITE(PXW(i), val); } /* Adjust magic regs to magic values (more experimental results) */ @@ -6201,7 +6201,7 @@ static void intel_init_emon(struct drm_device *dev) I915_WRITE(EG7, 0); for (i = 0; i < 8; i++) - I915_WRITE(PXWL + (i * 4), 0); + I915_WRITE(PXWL(i), 0); /* Enable PMON + select events */ I915_WRITE(ECR, 0x80000019); From 7d81c3e02b685074e437cdb48ea3a9efd82873c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:20 +0300 Subject: [PATCH 68/80] drm/i915: Replace raw numbers with the approproate register name in ILK turbo code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cb747f1c6650..68700692127d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4313,10 +4313,10 @@ static void ironlake_enable_drps(struct drm_device *dev) ironlake_set_drps(dev, fstart); - dev_priv->ips.last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) + - I915_READ(0x112e0); + dev_priv->ips.last_count1 = I915_READ(DMIEC) + + I915_READ(DDREC) + I915_READ(CSIEC); dev_priv->ips.last_time1 = jiffies_to_msecs(jiffies); - dev_priv->ips.last_count2 = I915_READ(0x112f4); + dev_priv->ips.last_count2 = I915_READ(GFXEC); dev_priv->ips.last_time2 = ktime_get_raw_ns(); spin_unlock_irq(&mchdev_lock); From 184d7c06227349aad07921e8da63f61ab67e6727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:21 +0300 Subject: [PATCH 69/80] drm/i915: Parametrize TV luma/chroma filter registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 12 ++++-------- drivers/gpu/drm/i915/intel_tv.c | 8 ++++---- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 07fcd06bec9f..dad7307932be 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4082,14 +4082,10 @@ enum skl_disp_power_wells { # define TV_CC_DATA_1_MASK 0x0000007f # define TV_CC_DATA_1_SHIFT 0 -#define TV_H_LUMA_0 0x68100 -#define TV_H_LUMA_59 0x681ec -#define TV_H_CHROMA_0 0x68200 -#define TV_H_CHROMA_59 0x682ec -#define TV_V_LUMA_0 0x68300 -#define TV_V_LUMA_42 0x683a8 -#define TV_V_CHROMA_0 0x68400 -#define TV_V_CHROMA_42 0x684a8 +#define TV_H_LUMA(i) (0x68100 + (i) * 4) /* 60 registers */ +#define TV_H_CHROMA(i) (0x68200 + (i) * 4) /* 60 registers */ +#define TV_V_LUMA(i) (0x68300 + (i) * 4) /* 43 registers */ +#define TV_V_CHROMA(i) (0x68400 + (i) * 4) /* 43 registers */ /* Display Port */ #define DP_A 0x64000 /* eDP */ diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index cbe39dcc7bc0..c69e1af37ca8 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1138,13 +1138,13 @@ static void intel_tv_pre_enable(struct intel_encoder *encoder) j = 0; for (i = 0; i < 60; i++) - I915_WRITE(TV_H_LUMA_0 + (i<<2), tv_mode->filter_table[j++]); + I915_WRITE(TV_H_LUMA(i), tv_mode->filter_table[j++]); for (i = 0; i < 60; i++) - I915_WRITE(TV_H_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]); + I915_WRITE(TV_H_CHROMA(i), tv_mode->filter_table[j++]); for (i = 0; i < 43; i++) - I915_WRITE(TV_V_LUMA_0 + (i<<2), tv_mode->filter_table[j++]); + I915_WRITE(TV_V_LUMA(i), tv_mode->filter_table[j++]); for (i = 0; i < 43; i++) - I915_WRITE(TV_V_CHROMA_0 + (i<<2), tv_mode->filter_table[j++]); + I915_WRITE(TV_V_CHROMA(i), tv_mode->filter_table[j++]); I915_WRITE(TV_DAC, I915_READ(TV_DAC) & TV_DAC_SAVE); I915_WRITE(TV_CTL, tv_ctl); } From 9712e68840cf09d138be6226f6e6f6dcd9b009f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:22 +0300 Subject: [PATCH 70/80] drm/i915: Parametrize DDI_BUF_TRANS registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FIXME: Should there be a WARN(i != 9) or something, or what does the entry 9 comment mean? Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 ++- drivers/gpu/drm/i915/intel_ddi.c | 19 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index dad7307932be..56157eb8719b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7197,7 +7197,8 @@ enum skl_disp_power_wells { /* DDI Buffer Translations */ #define DDI_BUF_TRANS_A 0x64E00 #define DDI_BUF_TRANS_B 0x64E60 -#define DDI_BUF_TRANS(port) _PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) +#define DDI_BUF_TRANS_LO(port, i) (_PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + (i) * 8) +#define DDI_BUF_TRANS_HI(port, i) (_PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B) + (i) * 8 + 4) /* Sideband Interface (SBI) is programmed indirectly, via * SBI_ADDR, which contains the register offset; and SBI_DATA, diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 5b600bf1adcb..9e640eafc50d 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -414,7 +414,6 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bool supports_hdmi) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 reg; u32 iboost_bit = 0; int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_default_entry, size; @@ -505,11 +504,11 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, BUG(); } - for (i = 0, reg = DDI_BUF_TRANS(port); i < size; i++) { - I915_WRITE(reg, ddi_translations[i].trans1 | iboost_bit); - reg += 4; - I915_WRITE(reg, ddi_translations[i].trans2); - reg += 4; + for (i = 0; i < size; i++) { + I915_WRITE(DDI_BUF_TRANS_LO(port, i), + ddi_translations[i].trans1 | iboost_bit); + I915_WRITE(DDI_BUF_TRANS_HI(port, i), + ddi_translations[i].trans2); } if (!supports_hdmi) @@ -521,10 +520,10 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, hdmi_level = hdmi_default_entry; /* Entry 9 is for HDMI: */ - I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit); - reg += 4; - I915_WRITE(reg, ddi_translations_hdmi[hdmi_level].trans2); - reg += 4; + I915_WRITE(DDI_BUF_TRANS_LO(port, i), + ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit); + I915_WRITE(DDI_BUF_TRANS_HI(port, i), + ddi_translations_hdmi[hdmi_level].trans2); } /* Program DDI buffers translations for DP. By default, program ports A-D in DP From d2aa5ae8e721bfe319e68ef5c08380385d452787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Sep 2015 20:03:23 +0300 Subject: [PATCH 71/80] drm/i915: Parametrize CSR_PROGRAM registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Mika Kuoppala Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_csr.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 780d5d5464d7..61b4a4744de5 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -50,7 +50,7 @@ MODULE_FIRMWARE(I915_CSR_BXT); /* * SKL CSR registers for DC5 and DC6 */ -#define CSR_PROGRAM_BASE 0x80000 +#define CSR_PROGRAM(i) (0x80000 + (i) * 4) #define CSR_SSP_BASE_ADDR_GEN9 0x00002FC0 #define CSR_HTP_ADDR_SKL 0x00500034 #define CSR_SSP_BASE 0x8F074 @@ -268,8 +268,7 @@ void intel_csr_load_program(struct drm_device *dev) mutex_lock(&dev_priv->csr_lock); fw_size = dev_priv->csr.dmc_fw_size; for (i = 0; i < fw_size; i++) - I915_WRITE(CSR_PROGRAM_BASE + i * 4, - payload[i]); + I915_WRITE(CSR_PROGRAM(i), payload[i]); for (i = 0; i < dev_priv->csr.mmio_count; i++) { I915_WRITE(dev_priv->csr.mmioaddr[i], @@ -471,7 +470,7 @@ void assert_csr_loaded(struct drm_i915_private *dev_priv) { WARN_ONCE(intel_csr_load_status_get(dev_priv) != FW_LOADED, "CSR is not loaded.\n"); - WARN_ONCE(!I915_READ(CSR_PROGRAM_BASE), + WARN_ONCE(!I915_READ(CSR_PROGRAM(0)), "CSR program storage start is NULL\n"); WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n"); WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n"); From 5ca4163a612068d8f942c454218d3d631f22af1b Mon Sep 17 00:00:00 2001 From: Arun Siluvery Date: Fri, 18 Sep 2015 17:52:47 +0100 Subject: [PATCH 72/80] drm/i915/bxt: Update revision id for BXT C0 Cc: Nick Hoath Cc: Imre Deak Signed-off-by: Arun Siluvery Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ba4596e9e7eb..6c3ef9cde315 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2507,7 +2507,7 @@ struct drm_i915_cmd_table { #define BXT_REVID_A0 (0x0) #define BXT_REVID_B0 (0x3) -#define BXT_REVID_C0 (0x6) +#define BXT_REVID_C0 (0x9) /* * The genX designation typically refers to the render engine, so render From fe47ea0cfa4adffe2a20edb22376d7af76b6a74c Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 21 Sep 2015 10:45:32 +0100 Subject: [PATCH 73/80] drm/i915: Support planar formats in tile height calculations This will be needed for NV12 support. v2: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 10 +++++----- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_sprite.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bf8754f07b8d..1f3af2404dca 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2190,7 +2190,7 @@ static bool need_vtd_wa(struct drm_device *dev) unsigned int intel_tile_height(struct drm_device *dev, uint32_t pixel_format, - uint64_t fb_format_modifier) + uint64_t fb_format_modifier, unsigned int plane) { unsigned int tile_height; uint32_t pixel_bytes; @@ -2206,7 +2206,7 @@ intel_tile_height(struct drm_device *dev, uint32_t pixel_format, tile_height = 32; break; case I915_FORMAT_MOD_Yf_TILED: - pixel_bytes = drm_format_plane_cpp(pixel_format, 0); + pixel_bytes = drm_format_plane_cpp(pixel_format, plane); switch (pixel_bytes) { default: case 1: @@ -2240,7 +2240,7 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height, uint32_t pixel_format, uint64_t fb_format_modifier) { return ALIGN(height, intel_tile_height(dev, pixel_format, - fb_format_modifier)); + fb_format_modifier, 0)); } static int @@ -2266,7 +2266,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, info->fb_modifier = fb->modifier[0]; tile_height = intel_tile_height(fb->dev, fb->pixel_format, - fb->modifier[0]); + fb->modifier[0], 0); tile_pitch = PAGE_SIZE / tile_height; info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_pitch); info->height_pages = DIV_ROUND_UP(fb->height, tile_height); @@ -3075,7 +3075,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, if (intel_rotation_90_or_270(rotation)) { /* stride = Surface height in tiles */ tile_height = intel_tile_height(dev, fb->pixel_format, - fb->modifier[0]); + fb->modifier[0], 0); stride = DIV_ROUND_UP(fb->height, tile_height); x_offset = stride * tile_height - y - src_h; y_offset = x; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ab3c29639857..858c3821cdf7 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1089,7 +1089,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, unsigned int intel_tile_height(struct drm_device *dev, uint32_t pixel_format, - uint64_t fb_format_modifier); + uint64_t fb_format_modifier, unsigned int plane); static inline bool intel_rotation_90_or_270(unsigned int rotation) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 79f7cc247ab7..4372fa0b1ec5 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -240,7 +240,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, if (intel_rotation_90_or_270(rotation)) { /* stride: Surface height in tiles */ tile_height = intel_tile_height(dev, fb->pixel_format, - fb->modifier[0]); + fb->modifier[0], 0); stride = DIV_ROUND_UP(fb->height, tile_height); plane_size = (src_w << 16) | src_h; x_offset = stride * tile_height - y - (src_h + 1); From 804beb4b5b76e41352b41027ab2804b8462c1686 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 21 Sep 2015 10:45:33 +0100 Subject: [PATCH 74/80] drm/i915: Support appending to the rotated pages mapping By providing a start offset into the source array of pages, and returning the end position in the scatter-gather table, we will be able to append the UV plane to the rotated mapping in later patches. v2: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 01f3521e77d3..2a8f64dc5096 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3244,15 +3244,18 @@ i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj, } -static void -rotate_pages(dma_addr_t *in, unsigned int width, unsigned int height, - struct sg_table *st) +static struct scatterlist * +rotate_pages(dma_addr_t *in, unsigned int offset, + unsigned int width, unsigned int height, + struct sg_table *st, struct scatterlist *sg) { unsigned int column, row; unsigned int src_idx; - struct scatterlist *sg = st->sgl; - st->nents = 0; + if (!sg) { + st->nents = 0; + sg = st->sgl; + } for (column = 0; column < width; column++) { src_idx = width * (height - 1) + column; @@ -3263,12 +3266,14 @@ rotate_pages(dma_addr_t *in, unsigned int width, unsigned int height, * The only thing we need are DMA addresses. */ sg_set_page(sg, NULL, PAGE_SIZE, 0); - sg_dma_address(sg) = in[src_idx]; + sg_dma_address(sg) = in[offset + src_idx]; sg_dma_len(sg) = PAGE_SIZE; sg = sg_next(sg); src_idx -= width; } } + + return sg; } static struct sg_table * @@ -3306,9 +3311,9 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, } /* Rotate the pages. */ - rotate_pages(page_addr_list, + rotate_pages(page_addr_list, 0, rot_info->width_pages, rot_info->height_pages, - st); + st, NULL); DRM_DEBUG_KMS( "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages).\n", From 89e3e1427629027dc33e576fc002880a02a7e50c Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 21 Sep 2015 10:45:34 +0100 Subject: [PATCH 75/80] drm/i915: Support NV12 in rotated GGTT mapping Just adding the rotated UV plane at the end of the rotated Y plane. v2: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 37 +++++++++++++++++++++++----- drivers/gpu/drm/i915/i915_gem_gtt.h | 3 +++ drivers/gpu/drm/i915/intel_display.c | 12 +++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2a8f64dc5096..ad0e7e03a91c 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3282,10 +3282,13 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, { struct intel_rotation_info *rot_info = &ggtt_view->rotation_info; unsigned int size_pages = rot_info->size >> PAGE_SHIFT; + unsigned int size_pages_uv; struct sg_page_iter sg_iter; unsigned long i; dma_addr_t *page_addr_list; struct sg_table *st; + unsigned int uv_start_page; + struct scatterlist *sg; int ret = -ENOMEM; /* Allocate a temporary list of source pages for random access. */ @@ -3294,12 +3297,18 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, if (!page_addr_list) return ERR_PTR(ret); + /* Account for UV plane with NV12. */ + if (rot_info->pixel_format == DRM_FORMAT_NV12) + size_pages_uv = rot_info->size_uv >> PAGE_SHIFT; + else + size_pages_uv = 0; + /* Allocate target SG list. */ st = kmalloc(sizeof(*st), GFP_KERNEL); if (!st) goto err_st_alloc; - ret = sg_alloc_table(st, size_pages, GFP_KERNEL); + ret = sg_alloc_table(st, size_pages + size_pages_uv, GFP_KERNEL); if (ret) goto err_sg_alloc; @@ -3311,15 +3320,30 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, } /* Rotate the pages. */ - rotate_pages(page_addr_list, 0, + sg = rotate_pages(page_addr_list, 0, rot_info->width_pages, rot_info->height_pages, st, NULL); + /* Append the UV plane if NV12. */ + if (rot_info->pixel_format == DRM_FORMAT_NV12) { + uv_start_page = size_pages; + + /* Check for tile-row un-alignment. */ + if (offset_in_page(rot_info->uv_offset)) + uv_start_page--; + + rotate_pages(page_addr_list, uv_start_page, + rot_info->width_pages_uv, + rot_info->height_pages_uv, + st, sg); + } + DRM_DEBUG_KMS( - "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages).\n", + "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0)).\n", obj->base.size, rot_info->pitch, rot_info->height, rot_info->pixel_format, rot_info->width_pages, - rot_info->height_pages, size_pages); + rot_info->height_pages, size_pages + size_pages_uv, + size_pages); drm_free_large(page_addr_list); @@ -3331,10 +3355,11 @@ err_st_alloc: drm_free_large(page_addr_list); DRM_DEBUG_KMS( - "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages)\n", + "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0))\n", obj->base.size, ret, rot_info->pitch, rot_info->height, rot_info->pixel_format, rot_info->width_pages, - rot_info->height_pages, size_pages); + rot_info->height_pages, size_pages + size_pages_uv, + size_pages); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 96ebb98a476d..c80758628899 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -138,10 +138,13 @@ enum i915_ggtt_view_type { struct intel_rotation_info { unsigned int height; unsigned int pitch; + unsigned int uv_offset; uint32_t pixel_format; uint64_t fb_modifier; unsigned int width_pages, height_pages; uint64_t size; + unsigned int width_pages_uv, height_pages_uv; + uint64_t size_uv; }; struct i915_ggtt_view { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1f3af2404dca..bdce4588c7b5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2263,6 +2263,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, info->height = fb->height; info->pixel_format = fb->pixel_format; info->pitch = fb->pitches[0]; + info->uv_offset = fb->offsets[1]; info->fb_modifier = fb->modifier[0]; tile_height = intel_tile_height(fb->dev, fb->pixel_format, @@ -2272,6 +2273,17 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, info->height_pages = DIV_ROUND_UP(fb->height, tile_height); info->size = info->width_pages * info->height_pages * PAGE_SIZE; + if (info->pixel_format == DRM_FORMAT_NV12) { + tile_height = intel_tile_height(fb->dev, fb->pixel_format, + fb->modifier[0], 1); + tile_pitch = PAGE_SIZE / tile_height; + info->width_pages_uv = DIV_ROUND_UP(fb->pitches[0], tile_pitch); + info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, + tile_height); + info->size_uv = info->width_pages_uv * info->height_pages_uv * + PAGE_SIZE; + } + return 0; } From dedf278ce69cac6b29c324d280183da31093e0b0 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 21 Sep 2015 10:45:35 +0100 Subject: [PATCH 76/80] drm/i915: Enable querying offset of UV plane with intel_plane_obj_offset v2: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 ++ drivers/gpu/drm/i915/i915_gem_gtt.h | 1 + drivers/gpu/drm/i915/intel_display.c | 26 +++++++++++++++++++++----- drivers/gpu/drm/i915/intel_drv.h | 4 +++- drivers/gpu/drm/i915/intel_sprite.c | 2 +- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index ad0e7e03a91c..bbb96a41c57b 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3332,6 +3332,8 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view, if (offset_in_page(rot_info->uv_offset)) uv_start_page--; + rot_info->uv_start_page = uv_start_page; + rotate_pages(page_addr_list, uv_start_page, rot_info->width_pages_uv, rot_info->height_pages_uv, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index c80758628899..9fbb07d6eaad 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -145,6 +145,7 @@ struct intel_rotation_info { uint64_t size; unsigned int width_pages_uv, height_pages_uv; uint64_t size_uv; + unsigned int uv_start_page; }; struct i915_ggtt_view { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bdce4588c7b5..9b1989166dbc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2897,14 +2897,29 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier, } unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane, - struct drm_i915_gem_object *obj) + struct drm_i915_gem_object *obj, + unsigned int plane) { const struct i915_ggtt_view *view = &i915_ggtt_view_normal; + struct i915_vma *vma; + unsigned char *offset; if (intel_rotation_90_or_270(intel_plane->base.state->rotation)) view = &i915_ggtt_view_rotated; - return i915_gem_obj_ggtt_offset_view(obj, view); + vma = i915_gem_obj_to_ggtt_view(obj, view); + if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n", + view->type)) + return -1; + + offset = (unsigned char *)vma->node.start; + + if (plane == 1) { + offset += vma->ggtt_view.rotation_info.uv_start_page * + PAGE_SIZE; + } + + return (unsigned long)offset; } static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) @@ -3060,7 +3075,7 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc, obj = intel_fb_obj(fb); stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], fb->pixel_format); - surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj); + surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0); /* * FIXME: intel_plane_state->src, dst aren't set when transitional @@ -11423,8 +11438,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, if (ret) goto cleanup_pending; - work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary), obj) - + intel_crtc->dspaddr_offset; + work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary), + obj, 0); + work->gtt_offset += intel_crtc->dspaddr_offset; if (mmio_flip) { ret = intel_queue_mmio_flip(dev, crtc, fb, obj, ring, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 858c3821cdf7..bc674aac59cb 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1170,7 +1170,9 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state); unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane, - struct drm_i915_gem_object *obj); + struct drm_i915_gem_object *obj, + unsigned int plane); + u32 skl_plane_ctl_format(uint32_t pixel_format); u32 skl_plane_ctl_tiling(uint64_t fb_modifier); u32 skl_plane_ctl_rotation(unsigned int rotation); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 4372fa0b1ec5..4349fde4b72c 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -235,7 +235,7 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, else if (key->flags & I915_SET_COLORKEY_SOURCE) plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE; - surf_addr = intel_plane_obj_offset(intel_plane, obj); + surf_addr = intel_plane_obj_offset(intel_plane, obj, 0); if (intel_rotation_90_or_270(rotation)) { /* stride: Surface height in tiles */ From cd1736ad0a6f0f7a31773ddf90040bd15969bc21 Mon Sep 17 00:00:00 2001 From: Nick Hoath Date: Mon, 21 Sep 2015 14:02:29 +0100 Subject: [PATCH 77/80] drm/i915: Remove extraneous request cancel. Remove extraneous request cancel in request allocation failure path in intel_lr_context_deferred_alloc (Tvrtko Ursulin) Regression from: commit e84fe80337dc85cca07d0417ea97edbec4789d8b Author: Nick Hoath Date: Fri Sep 11 12:53:46 2015 +0100 drm/i915: Split alloc from init for lrc Signed-off-by: Nick Hoath Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lrc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7417650ed9cf..256167b2e2ab 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2487,7 +2487,6 @@ int intel_lr_context_deferred_alloc(struct intel_context *ctx, if (ret) { DRM_ERROR("ring create req: %d\n", ret); - i915_gem_request_cancel(req); goto error_ringbuf; } From 7c4a7d60bcda9449bca1ed2ee47392cd7acb8535 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 24 Sep 2015 11:57:45 +0100 Subject: [PATCH 78/80] drm/i915: Defer adding preallocated stolen objects to the VM list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When preallocating a stolen object during early initialisation, we may be running before we have setup the the global GTT VM state, in particular before we have initialised the range manager and associated lists. As this is the case, we defer binding the stolen object until we call i915_gem_setup_global_gtt(). Not only should we defer the binding, but we should also defer the VM list manipulation. Fixes regression uncovered by commit a2cad9dff4dd44d0244b966d980de9d602d87593 Author: Michał Winiarski Date: Wed Sep 16 11:49:00 2015 +0200 drm/i915/gtt: Do not initialize drm_mm twice. Whilst I am here remove the duplicate work leaving dangling pointers from the error path... v2: Typos galore before coffee. Reported-by: Jesse Barnes Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92099 Signed-off-by: Chris Wilson Cc: Jesse Barnes Cc: Michel Thierry Cc: Mika Kuoppala Cc: Michał Winiarski Cc: Daniel Vetter Cc: Jani Nikula Reviewed-by: Michał Winiarski Tested-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/i915_gem_stolen.c | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index bbb96a41c57b..47344d068f9a 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2533,7 +2533,6 @@ static int ggtt_bind_vma(struct i915_vma *vma, * the bound flag ourselves. */ vma->bound |= GLOBAL_BIND; - } if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) { @@ -2657,6 +2656,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, return ret; } vma->bound |= GLOBAL_BIND; + list_add_tail(&vma->mm_list, &ggtt_vm->inactive_list); } /* Clear any non-preallocated blocks */ diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 55df6ce34751..15207796e1b3 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -584,7 +584,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, vma = i915_gem_obj_lookup_or_create_vma(obj, ggtt); if (IS_ERR(vma)) { ret = PTR_ERR(vma); - goto err_out; + goto err; } /* To simplify the initialisation sequence between KMS and GTT, @@ -598,23 +598,19 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, ret = drm_mm_reserve_node(&ggtt->mm, &vma->node); if (ret) { DRM_DEBUG_KMS("failed to allocate stolen GTT space\n"); - goto err_vma; + goto err; } + + vma->bound |= GLOBAL_BIND; + list_add_tail(&vma->mm_list, &ggtt->inactive_list); } - vma->bound |= GLOBAL_BIND; - list_add_tail(&obj->global_list, &dev_priv->mm.bound_list); - list_add_tail(&vma->mm_list, &ggtt->inactive_list); i915_gem_object_pin_pages(obj); return obj; -err_vma: - i915_gem_vma_destroy(vma); -err_out: - i915_gem_stolen_remove_node(dev_priv, stolen); - kfree(stolen); +err: drm_gem_object_unreference(&obj->base); return NULL; } From 7cb5dff8d59da8008c6ec30d4161e8e96aa4afe8 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 25 Sep 2015 03:58:11 -0700 Subject: [PATCH 79/80] drm/i915: fix task reference leak in i915_debugfs.c Leak a task reference in i915_ppgtt_info(), add put_task_struct() to fix it. Introduced by commit 1c60fef535d143860d5bf6593e24ab6417f5227c Author: Ben Widawsky Date: Fri Dec 6 14:11:30 2013 -0800 drm/i915: Dump all ppgtt Signed-off-by: Geliang Tang [danvet: Add note provided by Jani about which commit introduced this issue.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5615d3d3ab59..879771766973 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2288,9 +2288,13 @@ static int i915_ppgtt_info(struct seq_file *m, void *data) list_for_each_entry_reverse(file, &dev->filelist, lhead) { struct drm_i915_file_private *file_priv = file->driver_priv; + struct task_struct *task; - seq_printf(m, "\nproc: %s\n", - get_pid_task(file->pid, PIDTYPE_PID)->comm); + task = get_pid_task(file->pid, PIDTYPE_PID); + if (!task) + return -ESRCH; + seq_printf(m, "\nproc: %s\n", task->comm); + put_task_struct(task); idr_for_each(&file_priv->context_idr, per_file_ctx, (void *)(unsigned long)m); } From 40a4a5727f21a0e439d317aa99953e24467605eb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 28 Sep 2015 08:35:34 +0200 Subject: [PATCH 80/80] drm/i915: Update DRIVER_DATE to 20150928 Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6c3ef9cde315..c20f2c77c102 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -57,7 +57,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20150911" +#define DRIVER_DATE "20150928" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */