From ed4a6a7ca853253f9b86f3005d76345482a71283 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 23 Feb 2016 17:20:13 -0800 Subject: drm/i915: Add two-stage ILK-style watermark programming (v11) In addition to calculating final watermarks, let's also pre-calculate a set of intermediate watermark values at atomic check time. These intermediate watermarks are a combination of the watermarks for the old state and the new state; they should satisfy the requirements of both states which means they can be programmed immediately when we commit the atomic state (without waiting for a vblank). Once the vblank does happen, we can then re-program watermarks to the more optimal final value. v2: Significant rebasing/rewriting. v3: - Move 'need_postvbl_update' flag to CRTC state (Daniel) - Don't forget to check intermediate watermark values for validity (Maarten) - Don't due async watermark optimization; just do it at the end of the atomic transaction, after waiting for vblanks. We do want it to be async eventually, but adding that now will cause more trouble for Maarten's in-progress work. (Maarten) - Don't allocate space in crtc_state for intermediate watermarks on platforms that don't need it (gen9+). - Move WaCxSRDisabledForSpriteScaling:ivb into intel_begin_crtc_commit now that ilk_update_wm is gone. v4: - Add a wm_mutex to cover updates to intel_crtc->active and the need_postvbl_update flag. Since we don't have async yet it isn't terribly important yet, but might as well add it now. - Change interface to program watermarks. Platforms will now expose .initial_watermarks() and .optimize_watermarks() functions to do watermark programming. These should lock wm_mutex, copy the appropriate state values into intel_crtc->active, and then call the internal program watermarks function. v5: - Skip intermediate watermark calculation/check during initial hardware readout since we don't trust the existing HW values (and don't have valid values of our own yet). - Don't try to call .optimize_watermarks() on platforms that don't have atomic watermarks yet. (Maarten) v6: - Rebase v7: - Further rebase v8: - A few minor indentation and line length fixes v9: - Yet another rebase since Maarten's patches reworked a bunch of the code (wm_pre, wm_post, etc.) that this was previously based on. v10: - Move wm_mutex to dev_priv to protect against racing commits against disjoint CRTC sets. (Maarten) - Drop unnecessary clearing of cstate->wm.need_postvbl_update (Maarten) v11: - Now that we've moved to atomic watermark updates, make sure we call the proper function to program watermarks in {ironlake,haswell}_crtc_enable(); the failure to do so on the previous patch iteration led to us not actually programming the watermarks before turning on the CRTC, which was the cause of the underruns that the CI system was seeing. - Fix inverted logic for determining when to optimize watermarks. We were needlessly optimizing when the intermediate/optimal values were the same (harmless), but not actually optimizing when they differed (also harmless, but wasteful from a power/bandwidth perspective). Cc: Maarten Lankhorst Signed-off-by: Matt Roper Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1456276813-5689-1-git-send-email-matthew.d.roper@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 1c6d227..36c0cf1 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1010,6 +1010,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) mutex_init(&dev_priv->sb_lock); mutex_init(&dev_priv->modeset_restore_lock); mutex_init(&dev_priv->av_mutex); + mutex_init(&dev_priv->wm.wm_mutex); ret = i915_workqueues_init(dev_priv); if (ret < 0) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1048093..6712955 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -631,7 +631,11 @@ struct drm_i915_display_funcs { struct dpll *best_clock); int (*compute_pipe_wm)(struct intel_crtc *crtc, struct drm_atomic_state *state); - void (*program_watermarks)(struct intel_crtc_state *cstate); + int (*compute_intermediate_wm)(struct drm_device *dev, + struct intel_crtc *intel_crtc, + struct intel_crtc_state *newstate); + void (*initial_watermarks)(struct intel_crtc_state *cstate); + void (*optimize_watermarks)(struct intel_crtc_state *cstate); void (*update_wm)(struct drm_crtc *crtc); int (*modeset_calc_cdclk)(struct drm_atomic_state *state); void (*modeset_commit_cdclk)(struct drm_atomic_state *state); @@ -1980,6 +1984,13 @@ struct drm_i915_private { }; uint8_t max_level; + + /* + * Should be held around atomic WM register writing; also + * protects * intel_crtc->wm.active and + * cstate->wm.need_postvbl_update. + */ + struct mutex wm_mutex; } wm; struct i915_runtime_pm pm; diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 8e579a8..6a661e7 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -98,6 +98,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state->disable_cxsr = false; crtc_state->wm_changed = false; crtc_state->fb_changed = false; + crtc_state->wm.need_postvbl_update = false; return &crtc_state->base; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8b7b8b6..79bf527 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4843,7 +4843,42 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) intel_set_memory_cxsr(dev_priv, false); } - if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed) + /* + * IVB workaround: must disable low power watermarks for at least + * one frame before enabling scaling. LP watermarks can be re-enabled + * when scaling is disabled. + * + * WaCxSRDisabledForSpriteScaling:ivb + */ + if (pipe_config->disable_lp_wm) { + ilk_disable_lp_wm(dev); + intel_wait_for_vblank(dev, crtc->pipe); + } + + /* + * If we're doing a modeset, we're done. No need to do any pre-vblank + * watermark programming here. + */ + if (needs_modeset(&pipe_config->base)) + return; + + /* + * For platforms that support atomic watermarks, program the + * 'intermediate' watermarks immediately. On pre-gen9 platforms, these + * will be the intermediate values that are safe for both pre- and + * post- vblank; when vblank happens, the 'active' values will be set + * to the final 'target' values and we'll do this again to get the + * optimal watermarks. For gen9+ platforms, the values we program here + * will be the final target values which will get automatically latched + * at vblank time; no further programming will be necessary. + * + * If a platform hasn't been transitioned to atomic watermarks yet, + * we'll continue to update watermarks the old way, if flags tell + * us to. + */ + if (dev_priv->display.initial_watermarks != NULL) + dev_priv->display.initial_watermarks(pipe_config); + else if (pipe_config->wm_changed) intel_update_watermarks(&crtc->base); } @@ -4922,7 +4957,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) */ intel_crtc_load_lut(crtc); - intel_update_watermarks(crtc); + dev_priv->display.initial_watermarks(intel_crtc->config); intel_enable_pipe(intel_crtc); if (intel_crtc->config->has_pch_encoder) @@ -5021,7 +5056,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) if (!intel_crtc->config->has_dsi_encoder) intel_ddi_enable_transcoder_func(crtc); - intel_update_watermarks(crtc); + dev_priv->display.initial_watermarks(pipe_config); intel_enable_pipe(intel_crtc); if (intel_crtc->config->has_pch_encoder) @@ -11785,6 +11820,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_plane *plane = plane_state->plane; struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_plane_state *old_plane_state = to_intel_plane_state(plane->state); int idx = intel_crtc->base.base.id, ret; @@ -11843,6 +11879,11 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, pipe_config->wm_changed = true; } + /* Pre-gen9 platforms need two-step watermark updates */ + if (pipe_config->wm_changed && INTEL_INFO(dev)->gen < 9 && + dev_priv->display.optimize_watermarks) + to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true; + if (visible || was_visible) intel_crtc->atomic.fb_bits |= to_intel_plane(plane)->frontbuffer_bit; @@ -11954,8 +11995,29 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, ret = 0; if (dev_priv->display.compute_pipe_wm) { ret = dev_priv->display.compute_pipe_wm(intel_crtc, state); - if (ret) + if (ret) { + DRM_DEBUG_KMS("Target pipe watermarks are invalid\n"); + return ret; + } + } + + if (dev_priv->display.compute_intermediate_wm && + !to_intel_atomic_state(state)->skip_intermediate_wm) { + if (WARN_ON(!dev_priv->display.compute_pipe_wm)) + return 0; + + /* + * Calculate 'intermediate' watermarks that satisfy both the + * old state and the new state. We can program these + * immediately. + */ + ret = dev_priv->display.compute_intermediate_wm(crtc->dev, + intel_crtc, + pipe_config); + if (ret) { + DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n"); return ret; + } } if (INTEL_INFO(dev)->gen >= 9) { @@ -13488,6 +13550,7 @@ static int intel_atomic_commit(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc_state *crtc_state; struct drm_crtc *crtc; + struct intel_crtc_state *intel_cstate; int ret = 0, i; bool hw_check = intel_state->modeset; unsigned long put_domains[I915_MAX_PIPES] = {}; @@ -13603,6 +13666,20 @@ static int intel_atomic_commit(struct drm_device *dev, if (intel_state->modeset) intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET); + /* + * Now that the vblank has passed, we can go ahead and program the + * optimal watermarks on platforms that need two-step watermark + * programming. + * + * TODO: Move this (and other cleanup) to an async worker eventually. + */ + for_each_crtc_in_state(state, crtc, crtc_state, i) { + intel_cstate = to_intel_crtc_state(crtc->state); + + if (dev_priv->display.optimize_watermarks) + dev_priv->display.optimize_watermarks(intel_cstate); + } + mutex_lock(&dev->struct_mutex); drm_atomic_helper_cleanup_planes(dev, state); mutex_unlock(&dev->struct_mutex); @@ -15273,7 +15350,7 @@ static void sanitize_watermarks(struct drm_device *dev) int i; /* Only supported on platforms that use atomic watermark design */ - if (!dev_priv->display.program_watermarks) + if (!dev_priv->display.optimize_watermarks) return; /* @@ -15294,6 +15371,13 @@ retry: if (WARN_ON(IS_ERR(state))) goto fail; + /* + * Hardware readout is the only time we don't want to calculate + * intermediate watermarks (since we don't trust the current + * watermarks). + */ + to_intel_atomic_state(state)->skip_intermediate_wm = true; + ret = intel_atomic_check(dev, state); if (ret) { /* @@ -15316,7 +15400,8 @@ retry: for_each_crtc_in_state(state, crtc, cstate, i) { struct intel_crtc_state *cs = to_intel_crtc_state(cstate); - dev_priv->display.program_watermarks(cs); + cs->wm.need_postvbl_update = true; + dev_priv->display.optimize_watermarks(cs); } drm_atomic_state_free(state); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 4c027d6..5daf53c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -260,6 +260,12 @@ struct intel_atomic_state { struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS]; struct intel_wm_config wm_config; + + /* + * Current watermarks can't be trusted during hardware readout, so + * don't bother calculating intermediate watermarks. + */ + bool skip_intermediate_wm; }; struct intel_plane_state { @@ -510,13 +516,29 @@ struct intel_crtc_state { struct { /* - * optimal watermarks, programmed post-vblank when this state - * is committed + * Optimal watermarks, programmed post-vblank when this state + * is committed. */ union { struct intel_pipe_wm ilk; struct skl_pipe_wm skl; } optimal; + + /* + * Intermediate watermarks; these can be programmed immediately + * since they satisfy both the current configuration we're + * switching away from and the new configuration we're switching + * to. + */ + struct intel_pipe_wm intermediate; + + /* + * Platforms with two-step watermark programming will need to + * update watermark programming post-vblank to switch from the + * safe intermediate watermarks to the optimal final + * watermarks. + */ + bool need_postvbl_update; } wm; }; @@ -600,6 +622,7 @@ struct intel_crtc { struct intel_pipe_wm ilk; struct skl_pipe_wm skl; } active; + /* allow CxSR on this pipe */ bool cxsr_allowed; } wm; @@ -1565,6 +1588,7 @@ void skl_wm_get_hw_state(struct drm_device *dev); void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb /* out */); uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); +bool ilk_disable_lp_wm(struct drm_device *dev); int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6); /* intel_sdvo.c */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 347d4df..ccdb581 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2278,6 +2278,29 @@ static void skl_setup_wm_latency(struct drm_device *dev) intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency); } +static bool ilk_validate_pipe_wm(struct drm_device *dev, + struct intel_pipe_wm *pipe_wm) +{ + /* LP0 watermark maximums depend on this pipe alone */ + const struct intel_wm_config config = { + .num_pipes_active = 1, + .sprites_enabled = pipe_wm->sprites_enabled, + .sprites_scaled = pipe_wm->sprites_scaled, + }; + struct ilk_wm_maximums max; + + /* LP0 watermarks always use 1/2 DDB partitioning */ + ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); + + /* At least LP0 must be valid */ + if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) { + DRM_DEBUG_KMS("LP0 watermark invalid\n"); + return false; + } + + return true; +} + /* Compute new watermarks for the pipe */ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, struct drm_atomic_state *state) @@ -2292,10 +2315,6 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, struct intel_plane_state *sprstate = NULL; struct intel_plane_state *curstate = NULL; int level, max_level = ilk_wm_max_level(dev); - /* LP0 watermark maximums depend on this pipe alone */ - struct intel_wm_config config = { - .num_pipes_active = 1, - }; struct ilk_wm_maximums max; cstate = intel_atomic_get_crtc_state(state, intel_crtc); @@ -2319,21 +2338,18 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, curstate = to_intel_plane_state(ps); } - config.sprites_enabled = sprstate->visible; - config.sprites_scaled = sprstate->visible && + pipe_wm->pipe_enabled = cstate->base.active; + pipe_wm->sprites_enabled = sprstate->visible; + pipe_wm->sprites_scaled = sprstate->visible && (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 || drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16); - pipe_wm->pipe_enabled = cstate->base.active; - pipe_wm->sprites_enabled = config.sprites_enabled; - pipe_wm->sprites_scaled = config.sprites_scaled; - /* ILK/SNB: LP2+ watermarks only w/o sprites */ if (INTEL_INFO(dev)->gen <= 6 && sprstate->visible) max_level = 1; /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */ - if (config.sprites_scaled) + if (pipe_wm->sprites_scaled) max_level = 0; ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, @@ -2342,12 +2358,8 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, if (IS_HASWELL(dev) || IS_BROADWELL(dev)) pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate); - /* LP0 watermarks always use 1/2 DDB partitioning */ - ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); - - /* At least LP0 must be valid */ - if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) - return -EINVAL; + if (!ilk_validate_pipe_wm(dev, pipe_wm)) + return false; ilk_compute_wm_reg_maximums(dev, 1, &max); @@ -2372,6 +2384,59 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, } /* + * Build a set of 'intermediate' watermark values that satisfy both the old + * state and the new state. These can be programmed to the hardware + * immediately. + */ +static int ilk_compute_intermediate_wm(struct drm_device *dev, + struct intel_crtc *intel_crtc, + struct intel_crtc_state *newstate) +{ + struct intel_pipe_wm *a = &newstate->wm.intermediate; + struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk; + int level, max_level = ilk_wm_max_level(dev); + + /* + * Start with the final, target watermarks, then combine with the + * currently active watermarks to get values that are safe both before + * and after the vblank. + */ + *a = newstate->wm.optimal.ilk; + a->pipe_enabled |= b->pipe_enabled; + a->sprites_enabled |= b->sprites_enabled; + a->sprites_scaled |= b->sprites_scaled; + + for (level = 0; level <= max_level; level++) { + struct intel_wm_level *a_wm = &a->wm[level]; + const struct intel_wm_level *b_wm = &b->wm[level]; + + a_wm->enable &= b_wm->enable; + a_wm->pri_val = max(a_wm->pri_val, b_wm->pri_val); + a_wm->spr_val = max(a_wm->spr_val, b_wm->spr_val); + a_wm->cur_val = max(a_wm->cur_val, b_wm->cur_val); + a_wm->fbc_val = max(a_wm->fbc_val, b_wm->fbc_val); + } + + /* + * We need to make sure that these merged watermark values are + * actually a valid configuration themselves. If they're not, + * there's no safe way to transition from the old state to + * the new state, so we need to fail the atomic transaction. + */ + if (!ilk_validate_pipe_wm(dev, a)) + return -EINVAL; + + /* + * If our intermediate WM are identical to the final WM, then we can + * omit the post-vblank programming; only update if it's different. + */ + if (memcmp(a, &newstate->wm.optimal.ilk, sizeof(*a)) == 0) + newstate->wm.need_postvbl_update = false; + + return 0; +} + +/* * Merge the watermarks from all active pipes for a specific level. */ static void ilk_merge_wm_level(struct drm_device *dev, @@ -2383,9 +2448,7 @@ static void ilk_merge_wm_level(struct drm_device *dev, ret_wm->enable = true; for_each_intel_crtc(dev, intel_crtc) { - const struct intel_crtc_state *cstate = - to_intel_crtc_state(intel_crtc->base.state); - const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk; + const struct intel_pipe_wm *active = &intel_crtc->wm.active.ilk; const struct intel_wm_level *wm = &active->wm[level]; if (!active->pipe_enabled) @@ -2533,15 +2596,14 @@ static void ilk_compute_wm_results(struct drm_device *dev, /* LP0 register values */ for_each_intel_crtc(dev, intel_crtc) { - const struct intel_crtc_state *cstate = - to_intel_crtc_state(intel_crtc->base.state); enum pipe pipe = intel_crtc->pipe; - const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0]; + const struct intel_wm_level *r = + &intel_crtc->wm.active.ilk.wm[0]; if (WARN_ON(!r->enable)) continue; - results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime; + results->wm_linetime[pipe] = intel_crtc->wm.active.ilk.linetime; results->wm_pipe[pipe] = (r->pri_val << WM0_PIPE_PLANE_SHIFT) | @@ -2748,7 +2810,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv, dev_priv->wm.hw = *results; } -static bool ilk_disable_lp_wm(struct drm_device *dev) +bool ilk_disable_lp_wm(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3643,11 +3705,9 @@ static void ilk_compute_wm_config(struct drm_device *dev, } } -static void ilk_program_watermarks(struct intel_crtc_state *cstate) +static void ilk_program_watermarks(struct drm_i915_private *dev_priv) { - struct drm_crtc *crtc = cstate->base.crtc; - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_device *dev = dev_priv->dev; struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm; struct ilk_wm_maximums max; struct intel_wm_config config = {}; @@ -3678,28 +3738,28 @@ static void ilk_program_watermarks(struct intel_crtc_state *cstate) ilk_write_wm_values(dev_priv, &results); } -static void ilk_update_wm(struct drm_crtc *crtc) +static void ilk_initial_watermarks(struct intel_crtc_state *cstate) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); - - WARN_ON(cstate->base.active != intel_crtc->active); + struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); - /* - * IVB workaround: must disable low power watermarks for at least - * one frame before enabling scaling. LP watermarks can be re-enabled - * when scaling is disabled. - * - * WaCxSRDisabledForSpriteScaling:ivb - */ - if (cstate->disable_lp_wm) { - ilk_disable_lp_wm(crtc->dev); - intel_wait_for_vblank(crtc->dev, intel_crtc->pipe); - } + mutex_lock(&dev_priv->wm.wm_mutex); + intel_crtc->wm.active.ilk = cstate->wm.intermediate; + ilk_program_watermarks(dev_priv); + mutex_unlock(&dev_priv->wm.wm_mutex); +} - intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk; +static void ilk_optimize_watermarks(struct intel_crtc_state *cstate) +{ + struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); - ilk_program_watermarks(cstate); + mutex_lock(&dev_priv->wm.wm_mutex); + if (cstate->wm.need_postvbl_update) { + intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk; + ilk_program_watermarks(dev_priv); + } + mutex_unlock(&dev_priv->wm.wm_mutex); } static void skl_pipe_wm_active_state(uint32_t val, @@ -7076,9 +7136,13 @@ void intel_init_pm(struct drm_device *dev) dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) || (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] && dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) { - dev_priv->display.update_wm = ilk_update_wm; dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm; - dev_priv->display.program_watermarks = ilk_program_watermarks; + dev_priv->display.compute_intermediate_wm = + ilk_compute_intermediate_wm; + dev_priv->display.initial_watermarks = + ilk_initial_watermarks; + dev_priv->display.optimize_watermarks = + ilk_optimize_watermarks; } else { DRM_DEBUG_KMS("Failed to read display plane latency. " "Disable CxSR\n"); -- cgit v0.10.2 From c3454d575da162cd310d9b83696baefb29d10a70 Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 29 Feb 2016 16:24:06 +0000 Subject: drm/i915: remove left over dead code ae80152ddad252f33893b92dd69f00cc53c5949f ("drm/i915: Rewrite VLV/CHV watermark code") removed everything that would have used those vars. Signed-off-by: Eric Engestrom Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1456763047-28828-1-git-send-email-eric.engestrom@imgtec.com diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ccdb581..d33de95 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -487,20 +487,6 @@ static const struct intel_watermark_params g4x_cursor_wm_info = { .guard_size = 2, .cacheline_size = G4X_FIFO_LINE_SIZE, }; -static const struct intel_watermark_params valleyview_wm_info = { - .fifo_size = VALLEYVIEW_FIFO_SIZE, - .max_wm = VALLEYVIEW_MAX_WM, - .default_wm = VALLEYVIEW_MAX_WM, - .guard_size = 2, - .cacheline_size = G4X_FIFO_LINE_SIZE, -}; -static const struct intel_watermark_params valleyview_cursor_wm_info = { - .fifo_size = I965_CURSOR_FIFO, - .max_wm = VALLEYVIEW_CURSOR_MAX_WM, - .default_wm = I965_CURSOR_DFT_WM, - .guard_size = 2, - .cacheline_size = G4X_FIFO_LINE_SIZE, -}; static const struct intel_watermark_params i965_cursor_wm_info = { .fifo_size = I965_CURSOR_FIFO, .max_wm = I965_CURSOR_MAX_WM, -- cgit v0.10.2 From d9f8e52b22454a30aaaf26b7ef029598b30abf8e Mon Sep 17 00:00:00 2001 From: Eric Engestrom Date: Mon, 29 Feb 2016 16:24:07 +0000 Subject: drm/i915: remove dead code 79e539453b34e35f39299a899d263b0a1f1670bd ("DRM: i915: add mode setting support") added those variables but never used them. Signed-off-by: Eric Engestrom Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1456763047-28828-2-git-send-email-eric.engestrom@imgtec.com diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 6745bad..d5570c8 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -326,24 +326,12 @@ static const struct color_conversion sdtv_csc_yprpb = { .rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0200, }; -static const struct color_conversion sdtv_csc_rgb = { - .ry = 0x0000, .gy = 0x0f00, .by = 0x0000, .ay = 0x0166, - .ru = 0x0000, .gu = 0x0000, .bu = 0x0f00, .au = 0x0166, - .rv = 0x0f00, .gv = 0x0000, .bv = 0x0000, .av = 0x0166, -}; - static const struct color_conversion hdtv_csc_yprpb = { .ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145, .ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200, .rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200, }; -static const struct color_conversion hdtv_csc_rgb = { - .ry = 0x0000, .gy = 0x0f00, .by = 0x0000, .ay = 0x0166, - .ru = 0x0000, .gu = 0x0000, .bu = 0x0f00, .au = 0x0166, - .rv = 0x0f00, .gv = 0x0000, .bv = 0x0000, .av = 0x0166, -}; - static const struct video_levels component_levels = { .blank = 279, .black = 279, .burst = 0, }; -- cgit v0.10.2 From 3ba86073edcbe2be53d9862d5a3098f0ebf8ae9a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 29 Feb 2016 09:18:57 +0100 Subject: drm/i915: Handle -EDEADLK in drm_atomic_commit from load-detect. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI runs with DEBUG_WW_MUTEX_SLOWPATH, so -EDEADLK occurs a lot more. Handle the case where drm_atomic_commit fails with -EDEADLK correctly. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/56D3FEF1.6070306@linux.intel.com Reviewed-by: Ville Syrjälä diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 79bf527..c803690 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10577,7 +10577,8 @@ found: goto fail; } - if (drm_atomic_commit(state)) { + ret = drm_atomic_commit(state); + if (ret) { DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n"); goto fail; } -- cgit v0.10.2 From c6a2ac712d7dee13c13e44c4c4184478853dcb37 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 26 Feb 2016 16:58:32 +0000 Subject: drm/i915: Execlists small cleanups and micro-optimisations Assorted changes in the areas of code cleanup, reduction of invariant conditional in the interrupt handler and lock contention and MMIO access optimisation. * Remove needless initialization. * Improve cache locality by reorganizing code and/or using branch hints to keep unexpected or error conditions out of line. * Favor busy submit path vs. empty queue. * Less branching in hot-paths. v2: * Avoid mmio reads when possible. (Chris Wilson) * Use natural integer size for csb indices. * Remove useless return value from execlists_update_context. * Extract 32-bit ppgtt PDPs update so it is out of line and shared with two callers. * Grab forcewake across all mmio operations to ease the load on uncore lock and use chepear mmio ops. v3: * Removed some more pointless u8 data types. * Removed unused return from execlists_context_queue. * Commit message updates. v4: * Unclumsify the unqueue if statement. (Chris Wilson) * Hide forcewake from the queuing function. (Chris Wilson) Version 3 now makes the irq handling code path ~20% smaller on 48-bit PPGTT hardware, and a little bit less elsewhere. Hot paths are mostly in-line now and hammering on the uncore spinlock is greatly reduced together with mmio traffic to an extent. Benchmarking with "gem_latency -n 100" (keep submitting batches with 100 nop instruction) shows approximately 4% higher throughput, 2% less CPU time and 22% smaller latencies. This was on a big-core while small-cores could benefit even more. Most likely reason for the improvements are the MMIO optimization and uncore lock traffic reduction. One odd result is with "gem_latency -n 0" (dispatching empty batches) which shows 5% more throughput, 8% less CPU time, 25% better producer and consumer latencies, but 15% higher dispatch latency which is yet unexplained. Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1456505912-22286-1-git-send-email-tvrtko.ursulin@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 6a978ce..27c9ee3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -270,6 +270,9 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *ring) { struct drm_device *dev = ring->dev; + if (IS_GEN8(dev) || IS_GEN9(dev)) + ring->idle_lite_restore_wa = ~0; + ring->disable_lite_restore_wa = (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || IS_BXT_REVID(dev, 0, BXT_REVID_A1)) && (ring->id == VCS || ring->id == VCS2); @@ -373,8 +376,6 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0, rq0->elsp_submitted++; /* You must always write both descriptors in the order below. */ - spin_lock(&dev_priv->uncore.lock); - intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); I915_WRITE_FW(RING_ELSP(ring), upper_32_bits(desc[1])); I915_WRITE_FW(RING_ELSP(ring), lower_32_bits(desc[1])); @@ -384,11 +385,18 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0, /* ELSP is a wo register, use another nearby reg for posting */ POSTING_READ_FW(RING_EXECLIST_STATUS_LO(ring)); - intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); - spin_unlock(&dev_priv->uncore.lock); } -static int execlists_update_context(struct drm_i915_gem_request *rq) +static void +execlists_update_context_pdps(struct i915_hw_ppgtt *ppgtt, u32 *reg_state) +{ + ASSIGN_CTX_PDP(ppgtt, reg_state, 3); + ASSIGN_CTX_PDP(ppgtt, reg_state, 2); + ASSIGN_CTX_PDP(ppgtt, reg_state, 1); + ASSIGN_CTX_PDP(ppgtt, reg_state, 0); +} + +static void execlists_update_context(struct drm_i915_gem_request *rq) { struct intel_engine_cs *ring = rq->ring; struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt; @@ -396,19 +404,13 @@ static int execlists_update_context(struct drm_i915_gem_request *rq) reg_state[CTX_RING_TAIL+1] = rq->tail; - if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { - /* True 32b PPGTT with dynamic page allocation: update PDP - * registers and point the unallocated PDPs to scratch page. - * PML4 is allocated during ppgtt init, so this is not needed - * in 48-bit mode. - */ - ASSIGN_CTX_PDP(ppgtt, reg_state, 3); - ASSIGN_CTX_PDP(ppgtt, reg_state, 2); - ASSIGN_CTX_PDP(ppgtt, reg_state, 1); - ASSIGN_CTX_PDP(ppgtt, reg_state, 0); - } - - return 0; + /* True 32b PPGTT with dynamic page allocation: update PDP + * registers and point the unallocated PDPs to scratch page. + * PML4 is allocated during ppgtt init, so this is not needed + * in 48-bit mode. + */ + if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) + execlists_update_context_pdps(ppgtt, reg_state); } static void execlists_submit_requests(struct drm_i915_gem_request *rq0, @@ -422,10 +424,10 @@ static void execlists_submit_requests(struct drm_i915_gem_request *rq0, execlists_elsp_write(rq0, rq1); } -static void execlists_context_unqueue(struct intel_engine_cs *ring) +static void execlists_context_unqueue__locked(struct intel_engine_cs *ring) { struct drm_i915_gem_request *req0 = NULL, *req1 = NULL; - struct drm_i915_gem_request *cursor = NULL, *tmp = NULL; + struct drm_i915_gem_request *cursor, *tmp; assert_spin_locked(&ring->execlist_lock); @@ -435,9 +437,6 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) */ WARN_ON(!intel_irqs_enabled(ring->dev->dev_private)); - if (list_empty(&ring->execlist_queue)) - return; - /* Try to read in pairs */ list_for_each_entry_safe(cursor, tmp, &ring->execlist_queue, execlist_link) { @@ -452,37 +451,48 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) req0 = cursor; } else { req1 = cursor; + WARN_ON(req1->elsp_submitted); break; } } - if (IS_GEN8(ring->dev) || IS_GEN9(ring->dev)) { + if (unlikely(!req0)) + return; + + if (req0->elsp_submitted & ring->idle_lite_restore_wa) { /* - * WaIdleLiteRestore: make sure we never cause a lite - * restore with HEAD==TAIL + * WaIdleLiteRestore: make sure we never cause a lite restore + * with HEAD==TAIL. + * + * Apply the wa NOOPS to prevent ring:HEAD == req:TAIL as we + * resubmit the request. See gen8_emit_request() for where we + * prepare the padding after the end of the request. */ - if (req0->elsp_submitted) { - /* - * Apply the wa NOOPS to prevent ring:HEAD == req:TAIL - * as we resubmit the request. See gen8_emit_request() - * for where we prepare the padding after the end of the - * request. - */ - struct intel_ringbuffer *ringbuf; + struct intel_ringbuffer *ringbuf; - ringbuf = req0->ctx->engine[ring->id].ringbuf; - req0->tail += 8; - req0->tail &= ringbuf->size - 1; - } + ringbuf = req0->ctx->engine[ring->id].ringbuf; + req0->tail += 8; + req0->tail &= ringbuf->size - 1; } - WARN_ON(req1 && req1->elsp_submitted); - execlists_submit_requests(req0, req1); } -static bool execlists_check_remove_request(struct intel_engine_cs *ring, - u32 request_id) +static void execlists_context_unqueue(struct intel_engine_cs *ring) +{ + struct drm_i915_private *dev_priv = ring->dev->dev_private; + + spin_lock(&dev_priv->uncore.lock); + intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); + + execlists_context_unqueue__locked(ring); + + intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); + spin_unlock(&dev_priv->uncore.lock); +} + +static unsigned int +execlists_check_remove_request(struct intel_engine_cs *ring, u32 request_id) { struct drm_i915_gem_request *head_req; @@ -492,33 +502,41 @@ static bool execlists_check_remove_request(struct intel_engine_cs *ring, struct drm_i915_gem_request, execlist_link); - if (head_req != NULL) { - if (intel_execlists_ctx_id(head_req->ctx, ring) == request_id) { - WARN(head_req->elsp_submitted == 0, - "Never submitted head request\n"); + if (!head_req) + return 0; - if (--head_req->elsp_submitted <= 0) { - list_move_tail(&head_req->execlist_link, - &ring->execlist_retired_req_list); - return true; - } - } - } + if (unlikely(intel_execlists_ctx_id(head_req->ctx, ring) != request_id)) + return 0; + + WARN(head_req->elsp_submitted == 0, "Never submitted head request\n"); + + if (--head_req->elsp_submitted > 0) + return 0; + + list_move_tail(&head_req->execlist_link, + &ring->execlist_retired_req_list); - return false; + return 1; } -static void get_context_status(struct intel_engine_cs *ring, - u8 read_pointer, - u32 *status, u32 *context_id) +static u32 +get_context_status(struct intel_engine_cs *ring, unsigned int read_pointer, + u32 *context_id) { struct drm_i915_private *dev_priv = ring->dev->dev_private; + u32 status; - if (WARN_ON(read_pointer >= GEN8_CSB_ENTRIES)) - return; + read_pointer %= GEN8_CSB_ENTRIES; + + status = I915_READ_FW(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer)); + + if (status & GEN8_CTX_STATUS_IDLE_ACTIVE) + return 0; - *status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer)); - *context_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, read_pointer)); + *context_id = I915_READ_FW(RING_CONTEXT_STATUS_BUF_HI(ring, + read_pointer)); + + return status; } /** @@ -532,30 +550,27 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) { struct drm_i915_private *dev_priv = ring->dev->dev_private; u32 status_pointer; - u8 read_pointer; - u8 write_pointer; + unsigned int read_pointer, write_pointer; u32 status = 0; u32 status_id; - u32 submit_contexts = 0; + unsigned int submit_contexts = 0; + + spin_lock(&ring->execlist_lock); - status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring)); + spin_lock(&dev_priv->uncore.lock); + intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); + + status_pointer = I915_READ_FW(RING_CONTEXT_STATUS_PTR(ring)); read_pointer = ring->next_context_status_buffer; write_pointer = GEN8_CSB_WRITE_PTR(status_pointer); if (read_pointer > write_pointer) write_pointer += GEN8_CSB_ENTRIES; - spin_lock(&ring->execlist_lock); - while (read_pointer < write_pointer) { + status = get_context_status(ring, ++read_pointer, &status_id); - get_context_status(ring, ++read_pointer % GEN8_CSB_ENTRIES, - &status, &status_id); - - if (status & GEN8_CTX_STATUS_IDLE_ACTIVE) - continue; - - if (status & GEN8_CTX_STATUS_PREEMPTED) { + if (unlikely(status & GEN8_CTX_STATUS_PREEMPTED)) { if (status & GEN8_CTX_STATUS_LITE_RESTORE) { if (execlists_check_remove_request(ring, status_id)) WARN(1, "Lite Restored request removed from queue\n"); @@ -563,37 +578,36 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) WARN(1, "Preemption without Lite Restore\n"); } - if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) || - (status & GEN8_CTX_STATUS_ELEMENT_SWITCH)) { - if (execlists_check_remove_request(ring, status_id)) - submit_contexts++; - } + if (status & (GEN8_CTX_STATUS_ACTIVE_IDLE | + GEN8_CTX_STATUS_ELEMENT_SWITCH)) + submit_contexts += + execlists_check_remove_request(ring, status_id); } - if (ring->disable_lite_restore_wa) { - /* 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); + if (submit_contexts) { + if (!ring->disable_lite_restore_wa || + (status & GEN8_CTX_STATUS_ACTIVE_IDLE)) + execlists_context_unqueue__locked(ring); } - spin_unlock(&ring->execlist_lock); - - if (unlikely(submit_contexts > 2)) - DRM_ERROR("More than two context complete events?\n"); - ring->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES; /* Update the read pointer to the old write pointer. Manual ringbuffer * management ftw */ - I915_WRITE(RING_CONTEXT_STATUS_PTR(ring), - _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, - ring->next_context_status_buffer << 8)); + I915_WRITE_FW(RING_CONTEXT_STATUS_PTR(ring), + _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, + ring->next_context_status_buffer << 8)); + + intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); + spin_unlock(&dev_priv->uncore.lock); + + spin_unlock(&ring->execlist_lock); + + if (unlikely(submit_contexts > 2)) + DRM_ERROR("More than two context complete events?\n"); } -static int execlists_context_queue(struct drm_i915_gem_request *request) +static void execlists_context_queue(struct drm_i915_gem_request *request) { struct intel_engine_cs *ring = request->ring; struct drm_i915_gem_request *cursor; @@ -630,8 +644,6 @@ static int execlists_context_queue(struct drm_i915_gem_request *request) execlists_context_unqueue(ring); spin_unlock_irq(&ring->execlist_lock); - - return 0; } static int logical_ring_invalidate_all_caches(struct drm_i915_gem_request *req) @@ -1550,7 +1562,7 @@ 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; - u8 next_context_status_buffer_hw; + unsigned int next_context_status_buffer_hw; lrc_setup_hardware_status_page(ring, dev_priv->kernel_context->engine[ring->id].state); @@ -2013,6 +2025,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring) ring->status_page.obj = NULL; } + ring->idle_lite_restore_wa = 0; ring->disable_lite_restore_wa = false; ring->ctx_desc_template = 0; @@ -2439,10 +2452,7 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o * With dynamic page allocation, PDPs may not be allocated at * this point. Point the unallocated PDPs to the scratch page */ - ASSIGN_CTX_PDP(ppgtt, reg_state, 3); - ASSIGN_CTX_PDP(ppgtt, reg_state, 2); - ASSIGN_CTX_PDP(ppgtt, reg_state, 1); - ASSIGN_CTX_PDP(ppgtt, reg_state, 0); + execlists_update_context_pdps(ppgtt, reg_state); } if (ring->id == RCS) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 566b0ae..dd910d3 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -271,7 +271,8 @@ struct intel_engine_cs { spinlock_t execlist_lock; struct list_head execlist_queue; struct list_head execlist_retired_req_list; - u8 next_context_status_buffer; + unsigned int next_context_status_buffer; + unsigned int idle_lite_restore_wa; bool disable_lite_restore_wa; u32 ctx_desc_template; u32 irq_keep_mask; /* bitmask for interrupts that should not be masked */ -- cgit v0.10.2 From 1d5bf5d9d9ef0c1e639d36178a224d83888c5a29 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 29 Feb 2016 22:10:33 +0200 Subject: drm/i915: Add missing NULL check before calling initial_watermarks Not all platforms set this callback, so NULL check it before calling it. v2: - Call intel_update_watermarks() on HSW+ where the callback is not set. (Matt) CC: Matt Roper Fixes: commit ed4a6a7ca853 ("drm/i915: Add two-stage ILK-style watermark programming (v11)") Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1456776633-3401-1-git-send-email-imre.deak@intel.com Reviewed-by: Matt Roper diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c803690..368d247 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4957,7 +4957,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) */ intel_crtc_load_lut(crtc); - dev_priv->display.initial_watermarks(intel_crtc->config); + if (dev_priv->display.initial_watermarks != NULL) + dev_priv->display.initial_watermarks(intel_crtc->config); intel_enable_pipe(intel_crtc); if (intel_crtc->config->has_pch_encoder) @@ -5056,7 +5057,10 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) if (!intel_crtc->config->has_dsi_encoder) intel_ddi_enable_transcoder_func(crtc); - dev_priv->display.initial_watermarks(pipe_config); + if (dev_priv->display.initial_watermarks != NULL) + dev_priv->display.initial_watermarks(pipe_config); + else + intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); if (intel_crtc->config->has_pch_encoder) -- cgit v0.10.2 From 9106cf1747cc16ea5ef301a215e336f88e2ce1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 15 Feb 2016 22:54:39 +0200 Subject: drm/i915: Account for the size of the chroma plane for the rotated gtt view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The size of the rotated ggtt mapping ought to include the size of the chroma plane as well. Not a huge deal since we don't expose NV12 (or any pother planar format for that matter) yet. Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Fixes: 89e3e1427629 ("drm/i915: Support NV12 in rotated GGTT mapping") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1455569699-27905-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Tvrtko Ursulin Reviewed-by: Joonas Lahtinen diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 49e4f26..a1930f9 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3634,7 +3634,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj, if (view->type == I915_GGTT_VIEW_NORMAL) { return obj->base.size; } else if (view->type == I915_GGTT_VIEW_ROTATED) { - return view->params.rotated.size; + return view->params.rotated.size + view->params.rotated.size_uv; } else if (view->type == I915_GGTT_VIEW_PARTIAL) { return view->params.partial.size << PAGE_SHIFT; } else { -- cgit v0.10.2 From 27ba39101404b694d4ae199fe7aa485ac693ba27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 15 Feb 2016 22:54:40 +0200 Subject: drm/i915: s/tile_width/tile_width_bytes/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make if clear whether we're talking tile widths in bytes or in pixels. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1455569699-27905-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 368d247..dd68164 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2225,8 +2225,8 @@ static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv) return IS_GEN2(dev_priv) ? 2048 : 4096; } -static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv, - uint64_t fb_modifier, unsigned int cpp) +static unsigned int intel_tile_width_bytes(const struct drm_i915_private *dev_priv, + uint64_t fb_modifier, unsigned int cpp) { switch (fb_modifier) { case DRM_FORMAT_MOD_NONE: @@ -2269,7 +2269,7 @@ unsigned int intel_tile_height(const struct drm_i915_private *dev_priv, return 1; else return intel_tile_size(dev_priv) / - intel_tile_width(dev_priv, fb_modifier, cpp); + intel_tile_width_bytes(dev_priv, fb_modifier, cpp); } unsigned int @@ -2288,7 +2288,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, { struct drm_i915_private *dev_priv = to_i915(fb->dev); struct intel_rotation_info *info = &view->params.rotated; - unsigned int tile_size, tile_width, tile_height, cpp; + unsigned int tile_size, tile_width_bytes, tile_height, cpp; *view = i915_ggtt_view_normal; @@ -2309,19 +2309,19 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, tile_size = intel_tile_size(dev_priv); cpp = drm_format_plane_cpp(fb->pixel_format, 0); - tile_width = intel_tile_width(dev_priv, fb->modifier[0], cpp); - tile_height = tile_size / tile_width; + tile_width_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[0], cpp); + tile_height = tile_size / tile_width_bytes; - info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width); + info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width_bytes); info->height_pages = DIV_ROUND_UP(fb->height, tile_height); info->size = info->width_pages * info->height_pages * tile_size; if (info->pixel_format == DRM_FORMAT_NV12) { cpp = drm_format_plane_cpp(fb->pixel_format, 1); - tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp); - tile_height = tile_size / tile_width; + tile_width_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[1], cpp); + tile_height = tile_size / tile_width_bytes; - info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width); + info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width_bytes); info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height); info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size; } @@ -2458,18 +2458,18 @@ u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv, unsigned int pitch) { if (fb_modifier != DRM_FORMAT_MOD_NONE) { - unsigned int tile_size, tile_width, tile_height; + unsigned int tile_size, tile_width_bytes, tile_height; unsigned int tile_rows, tiles; tile_size = intel_tile_size(dev_priv); - tile_width = intel_tile_width(dev_priv, fb_modifier, cpp); - tile_height = tile_size / tile_width; + tile_width_bytes = intel_tile_width_bytes(dev_priv, fb_modifier, cpp); + tile_height = tile_size / tile_width_bytes; tile_rows = *y / tile_height; *y %= tile_height; - tiles = *x / (tile_width/cpp); - *x %= tile_width/cpp; + tiles = *x / (tile_width_bytes/cpp); + *x %= tile_width_bytes/cpp; return tile_rows * pitch * tile_height + tiles * tile_size; } else { @@ -2931,7 +2931,7 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv, } else { int cpp = drm_format_plane_cpp(pixel_format, 0); - return intel_tile_width(dev_priv, fb_modifier, cpp); + return intel_tile_width_bytes(dev_priv, fb_modifier, cpp); } } -- cgit v0.10.2 From 8d0deca8c6e0b25c409c6f4b2dc081596d7dffd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 15 Feb 2016 22:54:41 +0200 Subject: drm/i915: Pass 90/270 vs. 0/180 rotation info for intel_gen4_compute_page_offset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The page aligned surface address calculation needs to know which way things are rotated. The contract now says that the caller must pass the rotate x/y coordinates, as well as the tile_height aligned stride in the tile_height direction. This will make it fairly simple to deal with 90/270 degree rotation on SKL+ where we have to deal with the rotated view into the GTT. v2: Pass rotation instead of bool even thoughwe only care about 0/180 vs. 90/270 v3: Introduce intel_tile_dims(), and don't mix up different units so much v4: Unconfuse bytes vs. pixels even more Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1455569699-27905-4-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dd68164..9cec8e2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2272,6 +2272,20 @@ unsigned int intel_tile_height(const struct drm_i915_private *dev_priv, intel_tile_width_bytes(dev_priv, fb_modifier, cpp); } +/* Return the tile dimensions in pixel units */ +static void intel_tile_dims(const struct drm_i915_private *dev_priv, + unsigned int *tile_width, + unsigned int *tile_height, + uint64_t fb_modifier, + unsigned int cpp) +{ + unsigned int tile_width_bytes = + intel_tile_width_bytes(dev_priv, fb_modifier, cpp); + + *tile_width = tile_width_bytes / cpp; + *tile_height = intel_tile_size(dev_priv) / tile_width_bytes; +} + unsigned int intel_fb_align_height(struct drm_device *dev, unsigned int height, uint32_t pixel_format, uint64_t fb_modifier) @@ -2288,7 +2302,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, { struct drm_i915_private *dev_priv = to_i915(fb->dev); struct intel_rotation_info *info = &view->params.rotated; - unsigned int tile_size, tile_width_bytes, tile_height, cpp; + unsigned int tile_size, tile_width, tile_height, cpp; *view = i915_ggtt_view_normal; @@ -2309,19 +2323,19 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, tile_size = intel_tile_size(dev_priv); cpp = drm_format_plane_cpp(fb->pixel_format, 0); - tile_width_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[0], cpp); - tile_height = tile_size / tile_width_bytes; + intel_tile_dims(dev_priv, &tile_width, &tile_height, + fb->modifier[0], cpp); - info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width_bytes); + info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp); info->height_pages = DIV_ROUND_UP(fb->height, tile_height); info->size = info->width_pages * info->height_pages * tile_size; if (info->pixel_format == DRM_FORMAT_NV12) { cpp = drm_format_plane_cpp(fb->pixel_format, 1); - tile_width_bytes = intel_tile_width_bytes(dev_priv, fb->modifier[1], cpp); - tile_height = tile_size / tile_width_bytes; + intel_tile_dims(dev_priv, &tile_width, &tile_height, + fb->modifier[1], cpp); - info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width_bytes); + info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp); info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height); info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size; } @@ -2449,29 +2463,43 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, i915_gem_object_unpin_from_display_plane(obj, &view); } -/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel - * is assumed to be a power-of-two. */ +/* + * Computes the linear offset to the base tile and adjusts + * x, y. bytes per pixel is assumed to be a power-of-two. + * + * In the 90/270 rotated case, x and y are assumed + * to be already rotated to match the rotated GTT view, and + * pitch is the tile_height aligned framebuffer height. + */ u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv, int *x, int *y, uint64_t fb_modifier, unsigned int cpp, - unsigned int pitch) + unsigned int pitch, + unsigned int rotation) { if (fb_modifier != DRM_FORMAT_MOD_NONE) { - unsigned int tile_size, tile_width_bytes, tile_height; - unsigned int tile_rows, tiles; + unsigned int tile_size, tile_width, tile_height; + unsigned int tile_rows, tiles, pitch_tiles; tile_size = intel_tile_size(dev_priv); - tile_width_bytes = intel_tile_width_bytes(dev_priv, fb_modifier, cpp); - tile_height = tile_size / tile_width_bytes; + intel_tile_dims(dev_priv, &tile_width, &tile_height, + fb_modifier, cpp); + + if (intel_rotation_90_or_270(rotation)) { + pitch_tiles = pitch / tile_height; + swap(tile_width, tile_height); + } else { + pitch_tiles = pitch / (tile_width * cpp); + } tile_rows = *y / tile_height; *y %= tile_height; - tiles = *x / (tile_width_bytes/cpp); - *x %= tile_width_bytes/cpp; + tiles = *x / tile_width; + *x %= tile_width; - return tile_rows * pitch * tile_height + tiles * tile_size; + return (tile_rows * pitch_tiles + tiles) * tile_size; } else { unsigned int alignment = intel_linear_alignment(dev_priv) - 1; unsigned int offset; @@ -2716,6 +2744,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, u32 linear_offset; u32 dspcntr; i915_reg_t reg = DSPCNTR(plane); + unsigned int rotation = plane_state->base.rotation; int cpp = drm_format_plane_cpp(fb->pixel_format, 0); int x = plane_state->src.x1 >> 16; int y = plane_state->src.y1 >> 16; @@ -2782,13 +2811,13 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, intel_crtc->dspaddr_offset = intel_compute_tile_offset(dev_priv, &x, &y, fb->modifier[0], cpp, - fb->pitches[0]); + fb->pitches[0], rotation); linear_offset -= intel_crtc->dspaddr_offset; } else { intel_crtc->dspaddr_offset = linear_offset; } - if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { + if (rotation == BIT(DRM_ROTATE_180)) { dspcntr |= DISPPLANE_ROTATE_180; x += (crtc_state->pipe_src_w - 1); @@ -2846,6 +2875,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, u32 linear_offset; u32 dspcntr; i915_reg_t reg = DSPCNTR(plane); + unsigned int rotation = plane_state->base.rotation; int cpp = drm_format_plane_cpp(fb->pixel_format, 0); int x = plane_state->src.x1 >> 16; int y = plane_state->src.y1 >> 16; @@ -2889,9 +2919,9 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, intel_crtc->dspaddr_offset = intel_compute_tile_offset(dev_priv, &x, &y, fb->modifier[0], cpp, - fb->pitches[0]); + fb->pitches[0], rotation); linear_offset -= intel_crtc->dspaddr_offset; - if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { + if (rotation == BIT(DRM_ROTATE_180)) { dspcntr |= DISPPLANE_ROTATE_180; if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5daf53c..af70f49 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1199,7 +1199,8 @@ u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv, int *x, int *y, uint64_t fb_modifier, unsigned int cpp, - unsigned int pitch); + unsigned int pitch, + unsigned int rotation); void intel_prepare_reset(struct drm_device *dev); void intel_finish_reset(struct drm_device *dev); void hsw_enable_pc8(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index a2582c4..7dc2b8b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -193,7 +193,7 @@ skl_update_plane(struct drm_plane *drm_plane, const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 surf_addr; u32 tile_height, plane_offset, plane_size; - unsigned int rotation; + unsigned int rotation = plane_state->base.rotation; int x_offset, y_offset; int crtc_x = plane_state->dst.x1; int crtc_y = plane_state->dst.y1; @@ -213,7 +213,6 @@ skl_update_plane(struct drm_plane *drm_plane, plane_ctl |= skl_plane_ctl_format(fb->pixel_format); plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]); - rotation = plane_state->base.rotation; plane_ctl |= skl_plane_ctl_rotation(rotation); stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0], @@ -351,6 +350,7 @@ vlv_update_plane(struct drm_plane *dplane, int plane = intel_plane->plane; u32 sprctl; u32 sprsurf_offset, linear_offset; + unsigned int rotation = dplane->state->rotation; int cpp = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->dst.x1; @@ -425,10 +425,10 @@ vlv_update_plane(struct drm_plane *dplane, linear_offset = y * fb->pitches[0] + x * cpp; sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, fb->modifier[0], cpp, - fb->pitches[0]); + fb->pitches[0], rotation); linear_offset -= sprsurf_offset; - if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { + if (rotation == BIT(DRM_ROTATE_180)) { sprctl |= SP_ROTATE_180; x += src_w; @@ -493,6 +493,7 @@ ivb_update_plane(struct drm_plane *plane, enum pipe pipe = intel_plane->pipe; u32 sprctl, sprscale = 0; u32 sprsurf_offset, linear_offset; + unsigned int rotation = plane_state->base.rotation; int cpp = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->dst.x1; @@ -558,10 +559,10 @@ ivb_update_plane(struct drm_plane *plane, linear_offset = y * fb->pitches[0] + x * cpp; sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, fb->modifier[0], cpp, - fb->pitches[0]); + fb->pitches[0], rotation); linear_offset -= sprsurf_offset; - if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { + if (rotation == BIT(DRM_ROTATE_180)) { sprctl |= SPRITE_ROTATE_180; /* HSW and BDW does this automagically in hardware */ @@ -634,6 +635,7 @@ ilk_update_plane(struct drm_plane *plane, int pipe = intel_plane->pipe; u32 dvscntr, dvsscale; u32 dvssurf_offset, linear_offset; + unsigned int rotation = plane_state->base.rotation; int cpp = drm_format_plane_cpp(fb->pixel_format, 0); const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->dst.x1; @@ -695,10 +697,10 @@ ilk_update_plane(struct drm_plane *plane, linear_offset = y * fb->pitches[0] + x * cpp; dvssurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, fb->modifier[0], cpp, - fb->pitches[0]); + fb->pitches[0], rotation); linear_offset -= dvssurf_offset; - if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) { + if (rotation == BIT(DRM_ROTATE_180)) { dvscntr |= DVS_ROTATE_180; x += src_w; -- cgit v0.10.2 From 29cf9491590119b9ebf1bf211bdd7a3cea4e040c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 15 Feb 2016 22:54:42 +0200 Subject: drm/i915: Support for extra alignment for tiled surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SKL+ needs >4K alignment for tiled surfaces, so make intel_compute_page_offset() handle it. The way we do it is first we compute the closest tile boundary as before, and then figure out how many tiles we need to go to reach the desired alignment. The difference in the offset is then added into the x/y offsets. v2: Be less confusing wrt. units (pixels vs. bytes) (Daniel) v3: Use u32 for offsets Have intel_adjust_tile_offset() return the new offset (will be useful later) Add an offset_aligned variable (Daniel) Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1455569699-27905-5-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9cec8e2..f3ca95d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2464,6 +2464,35 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb, } /* + * Adjust the tile offset by moving the difference into + * the x/y offsets. + * + * Input tile dimensions and pitch must already be + * rotated to match x and y, and in pixel units. + */ +static u32 intel_adjust_tile_offset(int *x, int *y, + unsigned int tile_width, + unsigned int tile_height, + unsigned int tile_size, + unsigned int pitch_tiles, + u32 old_offset, + u32 new_offset) +{ + unsigned int tiles; + + WARN_ON(old_offset & (tile_size - 1)); + WARN_ON(new_offset & (tile_size - 1)); + WARN_ON(new_offset > old_offset); + + tiles = (old_offset - new_offset) / tile_size; + + *y += tiles / pitch_tiles * tile_height; + *x += tiles % pitch_tiles * tile_width; + + return new_offset; +} + +/* * Computes the linear offset to the base tile and adjusts * x, y. bytes per pixel is assumed to be a power-of-two. * @@ -2478,6 +2507,12 @@ u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv, unsigned int pitch, unsigned int rotation) { + u32 offset, offset_aligned, alignment; + + alignment = intel_surf_alignment(dev_priv, fb_modifier); + if (alignment) + alignment--; + if (fb_modifier != DRM_FORMAT_MOD_NONE) { unsigned int tile_size, tile_width, tile_height; unsigned int tile_rows, tiles, pitch_tiles; @@ -2499,16 +2534,21 @@ u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv, tiles = *x / tile_width; *x %= tile_width; - return (tile_rows * pitch_tiles + tiles) * tile_size; - } else { - unsigned int alignment = intel_linear_alignment(dev_priv) - 1; - unsigned int offset; + offset = (tile_rows * pitch_tiles + tiles) * tile_size; + offset_aligned = offset & ~alignment; + intel_adjust_tile_offset(x, y, tile_width, tile_height, + tile_size, pitch_tiles, + offset, offset_aligned); + } else { offset = *y * pitch + *x * cpp; + offset_aligned = offset & ~alignment; + *y = (offset & alignment) / pitch; *x = ((offset & alignment) - *y * pitch) / cpp; - return offset & ~alignment; } + + return offset_aligned; } static int i9xx_format_to_fourcc(int format) -- cgit v0.10.2 From 3465c580afc86c066cc55842bae38ba3cb1acb99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 15 Feb 2016 22:54:43 +0200 Subject: drm/i915: Don't pass plane+plane_state to intel_pin_and_fence_fb_obj() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_pin_and_fence_fb_obj() only needs the framebuffer, and the desird rotation (to find the right GTT view for it), so no need to pass all kinds of plane stuff. The main motivation is to get rid of the uggy NULL plane_state handling due to fbdev. v2: Add a note why I really want this Signed-off-by: Ville Syrjälä Grumpily-Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1455569699-27905-6-git-send-email-ville.syrjala@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f3ca95d..bf65f1f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2297,8 +2297,9 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height, } static void -intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, - const struct drm_plane_state *plane_state) +intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, + const struct drm_framebuffer *fb, + unsigned int rotation) { struct drm_i915_private *dev_priv = to_i915(fb->dev); struct intel_rotation_info *info = &view->params.rotated; @@ -2306,10 +2307,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb, *view = i915_ggtt_view_normal; - if (!plane_state) - return; - - if (!intel_rotation_90_or_270(plane_state->rotation)) + if (!intel_rotation_90_or_270(rotation)) return; *view = i915_ggtt_view_rotated; @@ -2374,9 +2372,8 @@ static unsigned int intel_surf_alignment(const struct drm_i915_private *dev_priv } int -intel_pin_and_fence_fb_obj(struct drm_plane *plane, - struct drm_framebuffer *fb, - const struct drm_plane_state *plane_state) +intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, + unsigned int rotation) { struct drm_device *dev = fb->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -2389,7 +2386,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane, alignment = intel_surf_alignment(dev_priv, fb->modifier[0]); - intel_fill_fb_ggtt_view(&view, fb, plane_state); + intel_fill_fb_ggtt_view(&view, fb, rotation); /* Note that the w/a also requires 64 PTE of padding following the * bo. We currently fill all unused PTE with the shadow page and so @@ -2447,15 +2444,14 @@ err_pm: return ret; } -static void intel_unpin_fb_obj(struct drm_framebuffer *fb, - const struct drm_plane_state *plane_state) +static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) { struct drm_i915_gem_object *obj = intel_fb_obj(fb); struct i915_ggtt_view view; WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex)); - intel_fill_fb_ggtt_view(&view, fb, plane_state); + intel_fill_fb_ggtt_view(&view, fb, rotation); if (view.type == I915_GGTT_VIEW_NORMAL) i915_gem_object_unpin_fence(obj); @@ -3014,7 +3010,7 @@ u32 intel_plane_obj_offset(struct intel_plane *intel_plane, u64 offset; intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb, - intel_plane->base.state); + intel_plane->base.state->rotation); vma = i915_gem_obj_to_ggtt_view(obj, &view); if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n", @@ -10959,7 +10955,7 @@ static void intel_unpin_work_fn(struct work_struct *__work) struct drm_plane *primary = crtc->base.primary; mutex_lock(&dev->struct_mutex); - intel_unpin_fb_obj(work->old_fb, primary->state); + intel_unpin_fb_obj(work->old_fb, primary->state->rotation); drm_gem_object_unreference(&work->pending_flip_obj->base); if (work->flip_queued_req) @@ -11731,8 +11727,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, goto cleanup_pending; } - ret = intel_pin_and_fence_fb_obj(crtc->primary, fb, - crtc->primary->state); + ret = intel_pin_and_fence_fb_obj(fb, primary->state->rotation); if (ret) goto cleanup_pending; @@ -11782,7 +11777,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, return 0; cleanup_unpin: - intel_unpin_fb_obj(fb, crtc->primary->state); + intel_unpin_fb_obj(fb, crtc->primary->state->rotation); cleanup_pending: if (!IS_ERR_OR_NULL(request)) i915_gem_request_cancel(request); @@ -14004,7 +13999,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, if (ret) DRM_DEBUG_KMS("failed to attach phys object\n"); } else { - ret = intel_pin_and_fence_fb_obj(plane, fb, new_state); + ret = intel_pin_and_fence_fb_obj(fb, new_state->rotation); } if (ret == 0) { @@ -14048,7 +14043,7 @@ intel_cleanup_plane_fb(struct drm_plane *plane, if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR || !INTEL_INFO(dev)->cursor_needs_physical)) - intel_unpin_fb_obj(old_state->fb, old_state); + intel_unpin_fb_obj(old_state->fb, old_state->rotation); /* prepare_fb aborted? */ if ((old_obj && (old_obj->frontbuffer_bits & intel_plane->frontbuffer_bit)) || @@ -14056,7 +14051,6 @@ intel_cleanup_plane_fb(struct drm_plane *plane, i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit); i915_gem_request_assign(&old_intel_state->wait_req, NULL); - } int @@ -16179,9 +16173,8 @@ void intel_modeset_gem_init(struct drm_device *dev) continue; mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(c->primary, - c->primary->fb, - c->primary->state); + ret = intel_pin_and_fence_fb_obj(c->primary->fb, + c->primary->state->rotation); mutex_unlock(&dev->struct_mutex); if (ret) { DRM_ERROR("failed to pin boot fb on pipe %d\n", diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index af70f49..a3831f6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1129,9 +1129,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector, void intel_release_load_detect_pipe(struct drm_connector *connector, struct intel_load_detect_pipe *old, struct drm_modeset_acquire_ctx *ctx); -int intel_pin_and_fence_fb_obj(struct drm_plane *plane, - struct drm_framebuffer *fb, - const struct drm_plane_state *plane_state); +int intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, + unsigned int rotation); struct drm_framebuffer * __intel_framebuffer_create(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 97a91e6..ae9cf6f 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -220,7 +220,7 @@ static int intelfb_create(struct drm_fb_helper *helper, * This also validates that any existing fb inherited from the * BIOS is suitable for own access. */ - ret = intel_pin_and_fence_fb_obj(NULL, &ifbdev->fb->base, NULL); + ret = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, BIT(DRM_ROTATE_0)); if (ret) goto out_unlock; -- cgit v0.10.2 From 4f2d9934bd6ac73950832c96b385822846670668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 15 Feb 2016 22:54:44 +0200 Subject: drm/i915: Pass drm_frambuffer to intel_compute_page_offset() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_compute_page_offsets() gets passed a bunch of the framebuffer metadate sepearately. Just pass the framebuffer itself to make life simpler for the caller, and make it less likely they would make a mistake in the order of the arguments (as most as just unsigned ints and such). We still pass the pitch explicitly since for 90/270 degree rotation the caller has to pass in the right thing. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1455569699-27905-7-git-send-email-ville.syrjala@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bf65f1f..f742f04 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2496,13 +2496,14 @@ static u32 intel_adjust_tile_offset(int *x, int *y, * to be already rotated to match the rotated GTT view, and * pitch is the tile_height aligned framebuffer height. */ -u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv, - int *x, int *y, - uint64_t fb_modifier, - unsigned int cpp, +u32 intel_compute_tile_offset(int *x, int *y, + const struct drm_framebuffer *fb, int plane, unsigned int pitch, unsigned int rotation) { + const struct drm_i915_private *dev_priv = to_i915(fb->dev); + uint64_t fb_modifier = fb->modifier[plane]; + unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane); u32 offset, offset_aligned, alignment; alignment = intel_surf_alignment(dev_priv, fb_modifier); @@ -2845,8 +2846,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, if (INTEL_INFO(dev)->gen >= 4) { intel_crtc->dspaddr_offset = - intel_compute_tile_offset(dev_priv, &x, &y, - fb->modifier[0], cpp, + intel_compute_tile_offset(&x, &y, fb, 0, fb->pitches[0], rotation); linear_offset -= intel_crtc->dspaddr_offset; } else { @@ -2953,8 +2953,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, linear_offset = y * fb->pitches[0] + x * cpp; intel_crtc->dspaddr_offset = - intel_compute_tile_offset(dev_priv, &x, &y, - fb->modifier[0], cpp, + intel_compute_tile_offset(&x, &y, fb, 0, fb->pitches[0], rotation); linear_offset -= intel_crtc->dspaddr_offset; if (rotation == BIT(DRM_ROTATE_180)) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a3831f6..5afc1b5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1194,10 +1194,8 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); #define assert_pipe_enabled(d, p) assert_pipe(d, p, true) #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) -u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv, - int *x, int *y, - uint64_t fb_modifier, - unsigned int cpp, +u32 intel_compute_tile_offset(int *x, int *y, + const struct drm_framebuffer *fb, int plane, unsigned int pitch, unsigned int rotation); void intel_prepare_reset(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 7dc2b8b..8821533 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -423,8 +423,7 @@ vlv_update_plane(struct drm_plane *dplane, crtc_h--; linear_offset = y * fb->pitches[0] + x * cpp; - sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, - fb->modifier[0], cpp, + sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0, fb->pitches[0], rotation); linear_offset -= sprsurf_offset; @@ -557,8 +556,7 @@ ivb_update_plane(struct drm_plane *plane, sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; linear_offset = y * fb->pitches[0] + x * cpp; - sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, - fb->modifier[0], cpp, + sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0, fb->pitches[0], rotation); linear_offset -= sprsurf_offset; @@ -695,8 +693,7 @@ ilk_update_plane(struct drm_plane *plane, dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; linear_offset = y * fb->pitches[0] + x * cpp; - dvssurf_offset = intel_compute_tile_offset(dev_priv, &x, &y, - fb->modifier[0], cpp, + dvssurf_offset = intel_compute_tile_offset(&x, &y, fb, 0, fb->pitches[0], rotation); linear_offset -= dvssurf_offset; -- cgit v0.10.2 From 1663b9d6a26a4d118e497b0a1604948b0fb0c86e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 15 Feb 2016 22:54:45 +0200 Subject: drm/i915: Reorganize intel_rotation_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Throw out a bunch of unnecessary stuff from struct intel_rotation_info, and pull most of the remaining stuff to live under an array of per-color plane sub-structures. What still remains outside the sub-structure will be reorgranized later as well, but that requires more work elsewhere so leave it be for now. v2: Split the vma size == luma+chroma size fix to prep patch (Daniel) Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter (v1) Link: http://patchwork.freedesktop.org/patch/msgid/1455569699-27905-8-git-send-email-ville.syrjala@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index a1930f9..a794bbd 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3405,7 +3405,7 @@ static struct sg_table * intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info, struct drm_i915_gem_object *obj) { - unsigned int size_pages = rot_info->size >> PAGE_SHIFT; + unsigned int size_pages = rot_info->plane[0].width * rot_info->plane[0].height; unsigned int size_pages_uv; struct sg_page_iter sg_iter; unsigned long i; @@ -3423,7 +3423,7 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info, /* Account for UV plane with NV12. */ if (rot_info->pixel_format == DRM_FORMAT_NV12) - size_pages_uv = rot_info->size_uv >> PAGE_SHIFT; + size_pages_uv = rot_info->plane[1].width * rot_info->plane[1].height; else size_pages_uv = 0; @@ -3445,9 +3445,9 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info, /* Rotate the pages. */ sg = rotate_pages(page_addr_list, 0, - rot_info->width_pages, rot_info->height_pages, - rot_info->width_pages, - st, NULL); + rot_info->plane[0].width, rot_info->plane[0].height, + rot_info->plane[0].width, + st, NULL); /* Append the UV plane if NV12. */ if (rot_info->pixel_format == DRM_FORMAT_NV12) { @@ -3459,18 +3459,15 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info, 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, - rot_info->width_pages_uv, + rotate_pages(page_addr_list, rot_info->uv_start_page, + rot_info->plane[1].width, rot_info->plane[1].height, + rot_info->plane[1].width, 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 (%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 + size_pages_uv, + DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages (%u plane 0)).\n", + obj->base.size, rot_info->plane[0].width, + rot_info->plane[0].height, size_pages + size_pages_uv, size_pages); drm_free_large(page_addr_list); @@ -3482,11 +3479,9 @@ err_sg_alloc: 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 (%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 + size_pages_uv, + DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%d) (%ux%u tiles, %u pages (%u plane 0))\n", + obj->base.size, ret, rot_info->plane[0].width, + rot_info->plane[0].height, size_pages + size_pages_uv, size_pages); return ERR_PTR(ret); } @@ -3634,7 +3629,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj, if (view->type == I915_GGTT_VIEW_NORMAL) { return obj->base.size; } else if (view->type == I915_GGTT_VIEW_ROTATED) { - return view->params.rotated.size + view->params.rotated.size_uv; + return intel_rotation_info_size(&view->params.rotated) << PAGE_SHIFT; } else if (view->type == I915_GGTT_VIEW_PARTIAL) { return view->params.partial.size << PAGE_SHIFT; } else { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 8774f1b..dc208c0 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -135,16 +135,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; unsigned int uv_start_page; + struct { + /* tiles */ + unsigned int width, height; + } plane[2]; }; struct i915_ggtt_view { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f742f04..0e7cb4d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2296,6 +2296,17 @@ intel_fb_align_height(struct drm_device *dev, unsigned int height, return ALIGN(height, tile_height); } +unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info) +{ + unsigned int size = 0; + int i; + + for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++) + size += rot_info->plane[i].width * rot_info->plane[i].height; + + return size; +} + static void intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, const struct drm_framebuffer *fb, @@ -2312,11 +2323,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, *view = i915_ggtt_view_rotated; - 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_size = intel_tile_size(dev_priv); @@ -2324,18 +2331,16 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, intel_tile_dims(dev_priv, &tile_width, &tile_height, fb->modifier[0], cpp); - info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp); - info->height_pages = DIV_ROUND_UP(fb->height, tile_height); - info->size = info->width_pages * info->height_pages * tile_size; + info->plane[0].width = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp); + info->plane[0].height = DIV_ROUND_UP(fb->height, tile_height); if (info->pixel_format == DRM_FORMAT_NV12) { cpp = drm_format_plane_cpp(fb->pixel_format, 1); intel_tile_dims(dev_priv, &tile_width, &tile_height, fb->modifier[1], cpp); - info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp); - info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height); - info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size; + info->plane[1].width = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp); + info->plane[1].height = DIV_ROUND_UP(fb->height / 2, tile_height); } } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5afc1b5..8b1d187 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1082,6 +1082,7 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); /* intel_display.c */ extern const struct drm_plane_funcs intel_plane_funcs; +unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info); bool intel_has_pending_fb_unpin(struct drm_device *dev); int intel_pch_rawclk(struct drm_device *dev); int intel_hrawclk(struct drm_device *dev); -- cgit v0.10.2 From 11f20322e00fb48e53ac66d2889cec3341a8e814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 15 Feb 2016 22:54:46 +0200 Subject: drm/i915: Move the NULL sg handling out from rotate_pages() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rotate_pages() checks to see if it got called with a NULL sg, and then goes to extract it from sg->sgl. It always gets called with a NULL sg for the first plane, so moving the initial 'sg=st->sgl' assignment out into intel_rotate_fb_obj_pages() seems less special-casey. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1455569699-27905-9-git-send-email-ville.syrjala@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index a794bbd..7b8de85 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3377,11 +3377,6 @@ rotate_pages(const dma_addr_t *in, unsigned int offset, unsigned int column, row; unsigned int src_idx; - if (!sg) { - st->nents = 0; - sg = st->sgl; - } - for (column = 0; column < width; column++) { src_idx = stride * (height - 1) + column; for (row = 0; row < height; row++) { @@ -3443,11 +3438,14 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info, i++; } + st->nents = 0; + sg = st->sgl; + /* Rotate the pages. */ sg = rotate_pages(page_addr_list, 0, rot_info->plane[0].width, rot_info->plane[0].height, rot_info->plane[0].width, - st, NULL); + st, sg); /* Append the UV plane if NV12. */ if (rot_info->pixel_format == DRM_FORMAT_NV12) { @@ -3459,10 +3457,10 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info, rot_info->uv_start_page = uv_start_page; - rotate_pages(page_addr_list, rot_info->uv_start_page, - rot_info->plane[1].width, rot_info->plane[1].height, - rot_info->plane[1].width, - st, sg); + sg = rotate_pages(page_addr_list, rot_info->uv_start_page, + rot_info->plane[1].width, rot_info->plane[1].height, + rot_info->plane[1].width, + st, sg); } DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages (%u plane 0)).\n", -- cgit v0.10.2 From 2d7a215f8b917067efc9999d3d733dbab37ada5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 15 Feb 2016 22:54:47 +0200 Subject: drm/i915: Embed rotation_info under intel_framebuffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of repopulatin the rotation_info struct for the fb every time we try to use the fb, we can just populate it once when creating the fb, and later we can just copy the pre-populate struct into the gtt_view. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1455569699-27905-10-git-send-email-ville.syrjala@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0e7cb4d..a03c12ab 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2312,18 +2312,20 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, const struct drm_framebuffer *fb, unsigned int rotation) { - struct drm_i915_private *dev_priv = to_i915(fb->dev); - struct intel_rotation_info *info = &view->params.rotated; - unsigned int tile_size, tile_width, tile_height, cpp; - - *view = i915_ggtt_view_normal; - - if (!intel_rotation_90_or_270(rotation)) - return; - - *view = i915_ggtt_view_rotated; + if (intel_rotation_90_or_270(rotation)) { + *view = i915_ggtt_view_rotated; + view->params.rotated = to_intel_framebuffer(fb)->rot_info; + } else { + *view = i915_ggtt_view_normal; + } +} - info->uv_offset = fb->offsets[1]; +static void +intel_fill_fb_info(struct drm_i915_private *dev_priv, + struct drm_framebuffer *fb) +{ + struct intel_rotation_info *info = &to_intel_framebuffer(fb)->rot_info; + unsigned int tile_size, tile_width, tile_height, cpp; tile_size = intel_tile_size(dev_priv); @@ -2339,6 +2341,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, intel_tile_dims(dev_priv, &tile_width, &tile_height, fb->modifier[1], cpp); + info->uv_offset = fb->offsets[1]; info->plane[1].width = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp); info->plane[1].height = DIV_ROUND_UP(fb->height / 2, tile_height); } @@ -14986,6 +14989,8 @@ static int intel_framebuffer_init(struct drm_device *dev, drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); intel_fb->obj = obj; + intel_fill_fb_info(dev_priv, &intel_fb->base); + ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); if (ret) { DRM_ERROR("framebuffer init failed %d\n", ret); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8b1d187..48f7e84 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -118,6 +118,7 @@ enum intel_output_type { struct intel_framebuffer { struct drm_framebuffer base; struct drm_i915_gem_object *obj; + struct intel_rotation_info rot_info; }; struct intel_fbdev { -- cgit v0.10.2 From 1260f07e3e2ff0a9184918b59000713c33f71441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Feb 2016 21:41:08 +0200 Subject: drm/i915: Dump ddi_pll_sel in hex instead of decimal on HSW/BDW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On HSW/BDW ddi_pll_sel is the actual register value. Let's dump it in hex so that people migth actually understand what it says. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1455738073-14502-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a03c12ab..adc034a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12304,7 +12304,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, pipe_config->dpll_hw_state.cfgcr1, pipe_config->dpll_hw_state.cfgcr2); } else if (HAS_DDI(dev)) { - DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n", + DRM_DEBUG_KMS("ddi_pll_sel: 0x%x; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n", pipe_config->ddi_pll_sel, pipe_config->dpll_hw_state.wrpll, pipe_config->dpll_hw_state.spll); -- cgit v0.10.2 From e3b247da89f0adb04010f9dad6a3e41ed085d24e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Feb 2016 21:41:09 +0200 Subject: drm/i915: Move the encoder vs. FDI dotclock check out from encoder .get_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we check if the encoder's idea of dotclock agrees with what we calculated based on the FDI parameters. We do this in the encoder .get_config() hooks, which isn't so nice in case the BIOS (or some other outside party) made a mess of the state and we're just trying to take over. So as a prep step to being able sanitize such a bogus state, move the the sanity check to just after we've read out the entire state. If we then need to sanitize a bad state, it should be easier to move the sanity check to occur after sanitation instead of before it. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1455738073-14502-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 505fc5c..7fe13bc 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -120,17 +120,9 @@ static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) static void intel_crt_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { - struct drm_device *dev = encoder->base.dev; - int dotclock; - pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder); - dotclock = pipe_config->port_clock; - - if (HAS_PCH_SPLIT(dev)) - ironlake_check_encoder_dotclock(pipe_config, dotclock); - - pipe_config->base.adjusted_mode.crtc_clock = dotclock; + pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; } static void hsw_crt_get_config(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index adc034a..992d4d5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -224,12 +224,11 @@ static void intel_update_czclk(struct drm_i915_private *dev_priv) } static inline u32 /* units of 100MHz */ -intel_fdi_link_freq(struct drm_device *dev) +intel_fdi_link_freq(struct drm_i915_private *dev_priv) { - if (IS_GEN5(dev)) { - struct drm_i915_private *dev_priv = dev->dev_private; + if (IS_GEN5(dev_priv)) return (I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2; - } else + else return 27; } @@ -6680,7 +6679,7 @@ retry: * Hence the bw of each lane in terms of the mode signal * is: */ - link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; + link_bw = intel_fdi_link_freq(to_i915(dev)) * MHz(100)/KHz(1)/10; fdi_dotclock = adjusted_mode->crtc_clock; @@ -6692,8 +6691,7 @@ retry: intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock, link_bw, &pipe_config->fdi_m_n); - ret = ironlake_check_fdi_lanes(intel_crtc->base.dev, - intel_crtc->pipe, pipe_config); + ret = ironlake_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config); if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) { pipe_config->pipe_bpp -= 2*3; DRM_DEBUG_KMS("fdi link bw constraint, reducing pipe bpp to %i\n", @@ -10831,19 +10829,18 @@ int intel_dotclock_calculate(int link_freq, static void ironlake_pch_clock_get(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { - struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); /* read out port_clock from the DPLL */ i9xx_crtc_clock_get(crtc, pipe_config); /* - * This value does not include pixel_multiplier. - * We will check that port_clock and adjusted_mode.crtc_clock - * agree once we know their relationship in the encoder's - * get_config() function. + * In case there is an active pipe without active ports, + * we may need some idea for the dotclock anyway. + * Calculate one based on the FDI configuration. */ pipe_config->base.adjusted_mode.crtc_clock = - intel_dotclock_calculate(intel_fdi_link_freq(dev) * 10000, + intel_dotclock_calculate(intel_fdi_link_freq(dev_priv) * 10000, &pipe_config->fdi_m_n); } @@ -12872,6 +12869,24 @@ intel_pipe_config_compare(struct drm_device *dev, return ret; } +static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv, + const struct intel_crtc_state *pipe_config) +{ + if (pipe_config->has_pch_encoder) { + int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv) * 10000, + &pipe_config->fdi_m_n); + int dotclock = pipe_config->base.adjusted_mode.crtc_clock; + + /* + * FDI already provided one idea for the dotclock. + * Yell if the encoder disagrees. + */ + WARN(!intel_fuzzy_clock_check(fdi_dotclock, dotclock), + "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n", + fdi_dotclock, dotclock); + } +} + static void check_wm_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -13045,6 +13060,8 @@ check_crtc_state(struct drm_device *dev, struct drm_atomic_state *old_state) if (!crtc->state->active) continue; + intel_pipe_config_sanity_check(dev_priv, pipe_config); + sw_config = to_intel_crtc_state(crtc->state); if (!intel_pipe_config_compare(dev, sw_config, pipe_config, false)) { @@ -13117,18 +13134,6 @@ intel_modeset_check_state(struct drm_device *dev, check_shared_dpll_state(dev); } -void ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config, - int dotclock) -{ - /* - * FDI already provided one idea for the dotclock. - * Yell if the encoder disagrees. - */ - WARN(!intel_fuzzy_clock_check(pipe_config->base.adjusted_mode.crtc_clock, dotclock), - "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n", - pipe_config->base.adjusted_mode.crtc_clock, dotclock); -} - static void update_scanline_offset(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; @@ -16034,6 +16039,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode); update_scanline_offset(crtc); } + + intel_pipe_config_sanity_check(dev_priv, crtc->config); } } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f6e4a87..75acb1d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2422,7 +2422,6 @@ static void intel_dp_get_config(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = dev->dev_private; enum port port = dp_to_dig_port(intel_dp)->port; struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); - int dotclock; tmp = I915_READ(intel_dp->output_reg); @@ -2472,13 +2471,9 @@ static void intel_dp_get_config(struct intel_encoder *encoder, pipe_config->port_clock = 270000; } - dotclock = intel_dotclock_calculate(pipe_config->port_clock, - &pipe_config->dp_m_n); - - if (HAS_PCH_SPLIT(dev_priv->dev) && port != PORT_A) - ironlake_check_encoder_dotclock(pipe_config, dotclock); - - pipe_config->base.adjusted_mode.crtc_clock = dotclock; + pipe_config->base.adjusted_mode.crtc_clock = + intel_dotclock_calculate(pipe_config->port_clock, + &pipe_config->dp_m_n); if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp && pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 48f7e84..859dfc5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1219,9 +1219,6 @@ void intel_dp_get_m_n(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config); void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n); int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n); -void -ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config, - int dotclock); bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock, intel_clock_t *best_clock); int chv_calc_dpll_params(int refclk, intel_clock_t *pll_clock); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 80b44c0..d8060e6 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -952,9 +952,6 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, if (pipe_config->pixel_multiplier) dotclock /= pipe_config->pixel_multiplier; - if (HAS_PCH_SPLIT(dev_priv->dev)) - ironlake_check_encoder_dotclock(pipe_config, dotclock); - pipe_config->base.adjusted_mode.crtc_clock = dotclock; } diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 30a8403..b35342f 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -109,7 +109,6 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); u32 tmp, flags = 0; - int dotclock; tmp = I915_READ(lvds_encoder->reg); if (tmp & LVDS_HSYNC_POLARITY) @@ -130,12 +129,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE; } - dotclock = pipe_config->port_clock; - - if (HAS_PCH_SPLIT(dev_priv->dev)) - ironlake_check_encoder_dotclock(pipe_config, dotclock); - - pipe_config->base.adjusted_mode.crtc_clock = dotclock; + pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock; } static void intel_pre_enable_lvds(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 4ecc076..fae64bc 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1398,12 +1398,10 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, } dotclock = pipe_config->port_clock; + if (pipe_config->pixel_multiplier) dotclock /= pipe_config->pixel_multiplier; - if (HAS_PCH_SPLIT(dev)) - ironlake_check_encoder_dotclock(pipe_config, dotclock); - pipe_config->base.adjusted_mode.crtc_clock = dotclock; /* Cross check the port pixel multiplier with the sdvo encoder state. */ -- cgit v0.10.2 From 21a727b365f8617e9f57229f55c9712b13ab38a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Feb 2016 21:41:10 +0200 Subject: drm/i915: Remove the SPLL==270Mhz assumption from intel_fdi_link_freq() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of assuming we've correctly set up SPLL to run at 270Mhz for FDI, let's use the port_clock from pipe_config which should be what we want. This would catch problems if someone misconfigures SPLL for whatever reason. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1455738073-14502-4-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 992d4d5..36c470f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -224,12 +224,15 @@ static void intel_update_czclk(struct drm_i915_private *dev_priv) } static inline u32 /* units of 100MHz */ -intel_fdi_link_freq(struct drm_i915_private *dev_priv) +intel_fdi_link_freq(struct drm_i915_private *dev_priv, + const struct intel_crtc_state *pipe_config) { - if (IS_GEN5(dev_priv)) - return (I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2; + if (HAS_DDI(dev_priv)) + return pipe_config->port_clock; /* SPLL */ + else if (IS_GEN5(dev_priv)) + return ((I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2) * 10000; else - return 27; + return 270000; } static const intel_limit_t intel_limits_i8xx_dac = { @@ -6679,7 +6682,7 @@ retry: * Hence the bw of each lane in terms of the mode signal * is: */ - link_bw = intel_fdi_link_freq(to_i915(dev)) * MHz(100)/KHz(1)/10; + link_bw = intel_fdi_link_freq(to_i915(dev), pipe_config); fdi_dotclock = adjusted_mode->crtc_clock; @@ -10840,7 +10843,7 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc, * Calculate one based on the FDI configuration. */ pipe_config->base.adjusted_mode.crtc_clock = - intel_dotclock_calculate(intel_fdi_link_freq(dev_priv) * 10000, + intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config), &pipe_config->fdi_m_n); } @@ -12873,7 +12876,7 @@ static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv, const struct intel_crtc_state *pipe_config) { if (pipe_config->has_pch_encoder) { - int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv) * 10000, + int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config), &pipe_config->fdi_m_n); int dotclock = pipe_config->base.adjusted_mode.crtc_clock; -- cgit v0.10.2 From 64b46a06313634cf9ce5808ebd63dc82573be34c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Feb 2016 21:41:11 +0200 Subject: drm/i915: Make the LPT iclkip 20MHz case more generic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reason for spcial casing 20MHz in the iclkip calculations is that it would overflow the 7 bit divisor value. Let's rewrite the special case to check for just that, and bump up auxdiv when needed. This makes the code work for freqeuencies close to but not exactly 20MHz. The real lower limit for auxdiv=0 is actually: 172800000/(0x7f+2)*64)=~20930 kHz, and below that we must resort to auxdiv=1. Actually this is all very theoretical since we limit the dotclock to min 25MHz with CRT on all platforms. 25Mhz is actually the documented limit in Bspec, so it seems we ought to never need to worry about the auxdiv=1 case. But no harm in having it. Cc: Paulo Zanoni Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1455738073-14502-5-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Paulo Zanoni Reviewed-by: Imre Deak diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 36c470f..1f35523 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4030,37 +4030,35 @@ static void lpt_disable_iclkip(struct drm_i915_private *dev_priv) /* Program iCLKIP clock to the desired frequency */ static void lpt_program_iclkip(struct drm_crtc *crtc) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(crtc->dev); int clock = to_intel_crtc(crtc)->config->base.adjusted_mode.crtc_clock; u32 divsel, phaseinc, auxdiv, phasedir = 0; u32 temp; lpt_disable_iclkip(dev_priv); - /* 20MHz is a corner case which is out of range for the 7-bit divisor */ - if (clock == 20000) { - auxdiv = 1; - divsel = 0x41; - phaseinc = 0x20; - } else { - /* The iCLK virtual clock root frequency is in MHz, - * but the adjusted_mode->crtc_clock in in KHz. To get the - * divisors, it is necessary to divide one by another, so we - * convert the virtual clock precision to KHz here for higher - * precision. - */ + /* The iCLK virtual clock root frequency is in MHz, + * but the adjusted_mode->crtc_clock in in KHz. To get the + * divisors, it is necessary to divide one by another, so we + * convert the virtual clock precision to KHz here for higher + * precision. + */ + for (auxdiv = 0; auxdiv < 2; auxdiv++) { u32 iclk_virtual_root_freq = 172800 * 1000; u32 iclk_pi_range = 64; - u32 desired_divisor, msb_divisor_value, pi_value; + u32 desired_divisor; - desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, clock); - msb_divisor_value = desired_divisor / iclk_pi_range; - pi_value = desired_divisor % iclk_pi_range; + desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, + clock << auxdiv); + divsel = (desired_divisor / iclk_pi_range) - 2; + phaseinc = desired_divisor % iclk_pi_range; - auxdiv = 0; - divsel = msb_divisor_value - 2; - phaseinc = pi_value; + /* + * Near 20MHz is a corner case which is + * out of range for the 7-bit divisor + */ + if (divsel <= 0x7f) + break; } /* This should not happen with any sane values */ -- cgit v0.10.2 From 8802e5b6de51ebbedb8a03e816ca847d860e07f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Feb 2016 21:41:12 +0200 Subject: drm/i915: Read out VGA dotclock properly on LPT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than assume the VGA dotclock is really the FDI based thing, let's read out the real thing via iclkip, and after readout it'll get to compare it with the FDI based number to make sure they're in sync. Cc: Paulo Zanoni Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1455738073-14502-6-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f76cbf3..71abf57 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7362,9 +7362,11 @@ enum skl_disp_power_wells { /* SBI offsets */ #define SBI_SSCDIVINTPHASE 0x0200 #define SBI_SSCDIVINTPHASE6 0x0600 -#define SBI_SSCDIVINTPHASE_DIVSEL_MASK ((0x7f)<<1) +#define SBI_SSCDIVINTPHASE_DIVSEL_SHIFT 1 +#define SBI_SSCDIVINTPHASE_DIVSEL_MASK (0x7f<<1) #define SBI_SSCDIVINTPHASE_DIVSEL(x) ((x)<<1) -#define SBI_SSCDIVINTPHASE_INCVAL_MASK ((0x7f)<<8) +#define SBI_SSCDIVINTPHASE_INCVAL_SHIFT 8 +#define SBI_SSCDIVINTPHASE_INCVAL_MASK (0x7f<<8) #define SBI_SSCDIVINTPHASE_INCVAL(x) ((x)<<8) #define SBI_SSCDIVINTPHASE_DIR(x) ((x)<<15) #define SBI_SSCDIVINTPHASE_PROPAGATE (1<<0) @@ -7374,6 +7376,8 @@ enum skl_disp_power_wells { #define SBI_SSCCTL_PATHALT (1<<3) #define SBI_SSCCTL_DISABLE (1<<0) #define SBI_SSCAUXDIV6 0x0610 +#define SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT 4 +#define SBI_SSCAUXDIV_FINALDIV2SEL_MASK (1<<4) #define SBI_SSCAUXDIV_FINALDIV2SEL(x) ((x)<<4) #define SBI_DBUFF0 0x2a00 #define SBI_GEN0 0x1f00 diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 7fe13bc..61eaac2 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -128,6 +128,8 @@ static void intel_crt_get_config(struct intel_encoder *encoder, static void hsw_crt_get_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + intel_ddi_get_config(encoder, pipe_config); pipe_config->base.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | @@ -135,6 +137,8 @@ static void hsw_crt_get_config(struct intel_encoder *encoder, DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC); pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder); + + pipe_config->base.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv); } /* Note: The caller is required to filter out dpms modes not supported by the diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1f35523..44fcff0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4105,6 +4105,43 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE); } +int lpt_get_iclkip(struct drm_i915_private *dev_priv) +{ + u32 divsel, phaseinc, auxdiv; + u32 iclk_virtual_root_freq = 172800 * 1000; + u32 iclk_pi_range = 64; + u32 desired_divisor; + u32 temp; + + if ((I915_READ(PIXCLK_GATE) & PIXCLK_GATE_UNGATE) == 0) + return 0; + + mutex_lock(&dev_priv->sb_lock); + + temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK); + if (temp & SBI_SSCCTL_DISABLE) { + mutex_unlock(&dev_priv->sb_lock); + return 0; + } + + temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK); + divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >> + SBI_SSCDIVINTPHASE_DIVSEL_SHIFT; + phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >> + SBI_SSCDIVINTPHASE_INCVAL_SHIFT; + + temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK); + auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >> + SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT; + + mutex_unlock(&dev_priv->sb_lock); + + desired_divisor = (divsel + 2) * iclk_pi_range + phaseinc; + + return DIV_ROUND_CLOSEST(iclk_virtual_root_freq, + desired_divisor << auxdiv); +} + static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc, enum pipe pch_transcoder) { diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 859dfc5..cb413e2 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1181,6 +1181,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, const struct dpll *dpll); void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe); +int lpt_get_iclkip(struct drm_i915_private *dev_priv); /* modesetting asserts */ void assert_panel_unlocked(struct drm_i915_private *dev_priv, -- cgit v0.10.2 From debded848dee028d7f1f1e42a4e118df9636fb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 17 Feb 2016 21:41:13 +0200 Subject: drm/i915: Try to fix CRT port clock limits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LPT/WPT-H are limited to max 180 MHz CRT dotclock. Most other platforms have a limit of 350 MHz. Supposedly gen3 and gen4 go up to 400 MHz. VLV is a bit special since the docs are poor. Supposedly the DAC would be good up to 355 MHz, but currently we limit the DPLL to 270 MHz, so we'll have to limit the port clock to the same unless we change the DPLL limits. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1455738073-14502-7-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 61eaac2..583cae7 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -218,18 +218,26 @@ intel_crt_mode_valid(struct drm_connector *connector, { struct drm_device *dev = connector->dev; int max_dotclk = to_i915(dev)->max_dotclk_freq; + int max_clock; - int max_clock = 0; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; if (mode->clock < 25000) return MODE_CLOCK_LOW; - if (IS_GEN2(dev)) - max_clock = 350000; - else + if (HAS_PCH_LPT(dev)) + max_clock = 180000; + else if (IS_VALLEYVIEW(dev)) + /* + * 270 MHz due to current DPLL limits, + * DAC limit supposedly 355 MHz. + */ + max_clock = 270000; + else if (IS_GEN3(dev) || IS_GEN4(dev)) max_clock = 400000; + else + max_clock = 350000; if (mode->clock > max_clock) return MODE_CLOCK_HIGH; -- cgit v0.10.2 From f85db0590dd8601a1fc513a40dd002c3bdf56b84 Mon Sep 17 00:00:00 2001 From: "arun.siluvery@linux.intel.com" Date: Tue, 1 Mar 2016 11:24:36 +0000 Subject: drm/i915/error: Capture WA ctx batch in error state execute during context save/restore, good to have them in error state. v2: use wa_ctx->size and print only size values (Mika) v3: simplify conditions when recording and freeing object (Chris) v4: resolve checkpatch errors (Tvrtko) Cc: Tvrtko Ursulin Cc: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Signed-off-by: Arun Siluvery Signed-off-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/1456831476-10782-1-git-send-email-arun.siluvery@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6712955..7d2b07f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -561,6 +561,8 @@ struct drm_i915_error_state { u32 *pages[0]; } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page; + struct drm_i915_error_object *wa_ctx; + struct drm_i915_error_request { long jiffies; u32 seqno; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 831895b..3b6bfbf 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -493,6 +493,28 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, } } + obj = error->ring[i].wa_ctx; + if (obj) { + u64 wa_ctx_offset = obj->gtt_offset; + u32 *wa_ctx_page = &obj->pages[0][0]; + struct intel_engine_cs *ring = &dev_priv->ring[RCS]; + u32 wa_ctx_size = (ring->wa_ctx.indirect_ctx.size + + ring->wa_ctx.per_ctx.size); + + err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n", + dev_priv->ring[i].name, wa_ctx_offset); + offset = 0; + for (elt = 0; elt < wa_ctx_size; elt += 4) { + err_printf(m, "[%04x] %08x %08x %08x %08x\n", + offset, + wa_ctx_page[elt + 0], + wa_ctx_page[elt + 1], + wa_ctx_page[elt + 2], + wa_ctx_page[elt + 3]); + offset += 16; + } + } + if ((obj = error->ring[i].ctx)) { err_printf(m, "%s --- HW Context = 0x%08x\n", dev_priv->ring[i].name, @@ -585,6 +607,7 @@ static void i915_error_state_free(struct kref *error_ref) i915_error_object_free(error->ring[i].hws_page); i915_error_object_free(error->ring[i].ctx); kfree(error->ring[i].requests); + i915_error_object_free(error->ring[i].wa_ctx); } i915_error_object_free(error->semaphore_obj); @@ -1067,6 +1090,12 @@ static void i915_gem_record_rings(struct drm_device *dev, error->ring[i].hws_page = i915_error_ggtt_object_create(dev_priv, ring->status_page.obj); + if (ring->wa_ctx.obj) { + error->ring[i].wa_ctx = + i915_error_ggtt_object_create(dev_priv, + ring->wa_ctx.obj); + } + i915_gem_record_active_context(ring, error, &error->ring[i]); count = 0; -- cgit v0.10.2 From 2622d79bd9d18fd04b650234e6a218c5f95cf308 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 29 Feb 2016 22:49:02 +0200 Subject: drm/i915/skl: Fix power domain suspend sequence During system suspend we need to first disable power wells then unitialize the display core. In case power well support is disabled we did this in the wrong order, so fix this up. Fixes: d314cd43 ("drm/i915: fix handling of the disable_power_well module option") CC: stable@vger.kernel.org CC: Patrik Jakobsson Signed-off-by: Imre Deak Reviewed-by: Patrik Jakobsson Link: http://patchwork.freedesktop.org/patch/msgid/1456778945-5411-1-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 4172e73..6e54d97 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2319,15 +2319,15 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) */ void intel_power_domains_suspend(struct drm_i915_private *dev_priv) { - if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) - skl_display_core_uninit(dev_priv); - /* * Even if power well support was disabled we still want to disable * power wells while we are system suspended. */ if (!i915.disable_power_well) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); + + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) + skl_display_core_uninit(dev_priv); } /** -- cgit v0.10.2 From a37baf3b832b862d09e10067b7d2065b3b42a729 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 29 Feb 2016 22:49:03 +0200 Subject: drm/i915/gen9: Sanitize handling of allowed DC states We can simplify the conditions selecting the target DC state during runtime by calculating the allowed DC states in advance during driver loading. This also makes it easier to disable DC states depending on the i915.disable_power_well module option, added in the next patch. v2: - Print a debug message if the requested max DC value was adjusted due to a platform limit. Also debug print the calculated mask value. (Patrik) CC: Patrik Jakobsson Signed-off-by: Imre Deak Reviewed-by: Patrik Jakobsson Link: http://patchwork.freedesktop.org/patch/msgid/1456778945-5411-2-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7d2b07f..0e2fb5b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -756,6 +756,7 @@ struct intel_csr { i915_reg_t mmioaddr[8]; uint32_t mmiodata[8]; uint32_t dc_state; + uint32_t allowed_dc_mask; }; #define DEV_INFO_FOR_EACH_FLAG(func, sep) \ diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 6e54d97..30df9de 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -538,12 +538,8 @@ static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state) else mask |= DC_STATE_EN_UPTO_DC6; - WARN_ON_ONCE(state & ~mask); - - if (i915.enable_dc == 0) - state = DC_STATE_DISABLE; - else if (i915.enable_dc == 1 && state > DC_STATE_EN_UPTO_DC5) - state = DC_STATE_EN_UPTO_DC5; + if (WARN_ON_ONCE(state & ~dev_priv->csr.allowed_dc_mask)) + state &= dev_priv->csr.allowed_dc_mask; val = I915_READ(DC_STATE_EN); DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n", @@ -659,8 +655,7 @@ static void gen9_disable_dc5_dc6(struct drm_i915_private *dev_priv) { assert_can_disable_dc5(dev_priv); - if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && - i915.enable_dc != 0 && i915.enable_dc != 1) + if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC6) assert_can_disable_dc6(dev_priv); gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); @@ -839,26 +834,19 @@ static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && - i915.enable_dc != 0 && i915.enable_dc != 1) + if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC6) skl_enable_dc6(dev_priv); - else + else if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5) gen9_enable_dc5(dev_priv); } static void gen9_dc_off_power_well_sync_hw(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - if (power_well->count > 0) { - gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); - } else { - if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && - i915.enable_dc != 0 && - i915.enable_dc != 1) - gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); - else - gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC5); - } + if (power_well->count > 0) + gen9_dc_off_power_well_enable(dev_priv, power_well); + else + gen9_dc_off_power_well_disable(dev_priv, power_well); } static void i9xx_always_on_power_well_noop(struct drm_i915_private *dev_priv, @@ -2023,6 +2011,52 @@ sanitize_disable_power_well_option(const struct drm_i915_private *dev_priv, return 1; } +static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv, + int enable_dc) +{ + uint32_t mask; + int requested_dc; + int max_dc; + + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { + max_dc = 2; + mask = 0; + } else if (IS_BROXTON(dev_priv)) { + max_dc = 1; + /* + * DC9 has a separate HW flow from the rest of the DC states, + * not depending on the DMC firmware. It's needed by system + * suspend/resume, so allow it unconditionally. + */ + mask = DC_STATE_EN_DC9; + } else { + max_dc = 0; + mask = 0; + } + + if (enable_dc >= 0 && enable_dc <= max_dc) { + requested_dc = enable_dc; + } else if (enable_dc == -1) { + requested_dc = max_dc; + } else if (enable_dc > max_dc && enable_dc <= 2) { + DRM_DEBUG_KMS("Adjusting requested max DC state (%d->%d)\n", + enable_dc, max_dc); + requested_dc = max_dc; + } else { + DRM_ERROR("Unexpected value for enable_dc (%d)\n", enable_dc); + requested_dc = max_dc; + } + + if (requested_dc > 1) + mask |= DC_STATE_EN_UPTO_DC6; + if (requested_dc > 0) + mask |= DC_STATE_EN_UPTO_DC5; + + DRM_DEBUG_KMS("Allowed DC state mask %02x\n", mask); + + return mask; +} + #define set_power_wells(power_domains, __power_wells) ({ \ (power_domains)->power_wells = (__power_wells); \ (power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \ @@ -2041,6 +2075,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) i915.disable_power_well = sanitize_disable_power_well_option(dev_priv, i915.disable_power_well); + dev_priv->csr.allowed_dc_mask = get_allowed_dc_mask(dev_priv, + i915.enable_dc); BUILD_BUG_ON(POWER_DOMAIN_NUM > 31); -- cgit v0.10.2 From 66e2c4c39cc37beaccc24c9d14c75d627fce9cf4 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 29 Feb 2016 22:49:04 +0200 Subject: drm/i915/gen9: Disable DC states if power well support is disabled If power well support is disabled via the i915.disable_power_well module option we should never enable DC states. Currently we would enable DC states even in this case during system suspend, where we need to disable all power wells regardless of the disable_power_well option. CC: Patrik Jakobsson Signed-off-by: Imre Deak Reviewed-by: Patrik Jakobsson Link: http://patchwork.freedesktop.org/patch/msgid/1456778945-5411-3-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 30df9de..f0ca5134 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2034,6 +2034,9 @@ static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv, mask = 0; } + if (!i915.disable_power_well) + max_dc = 0; + if (enable_dc >= 0 && enable_dc <= max_dc) { requested_dc = enable_dc; } else if (enable_dc == -1) { -- cgit v0.10.2 From 5b773eb422f1671852f78548b18ec7c7de34b3cb Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 29 Feb 2016 22:49:05 +0200 Subject: drm/i915/gen9: Remove state asserts when disabling DC states Disabling the DC states when it's already disabled is a valid scenario, for example during HW state sanitization during driver loading and resuming or when DC states are disabled via the i915.enable_dc or disable_power_well option. CC: Patrik Jakobsson Signed-off-by: Imre Deak Reviewed-by: Patrik Jakobsson Link: http://patchwork.freedesktop.org/patch/msgid/1456778945-5411-4-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index f0ca5134..09c52b1 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -458,8 +458,6 @@ static void assert_can_enable_dc9(struct drm_i915_private *dev_priv) static void assert_can_disable_dc9(struct drm_i915_private *dev_priv) { WARN(intel_irqs_enabled(dev_priv), "Interrupts not disabled yet.\n"); - WARN(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9), - "DC9 already programmed to be disabled.\n"); WARN(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5, "DC5 still not disabled.\n"); @@ -602,18 +600,6 @@ static void assert_can_enable_dc5(struct drm_i915_private *dev_priv) assert_csr_loaded(dev_priv); } -static void assert_can_disable_dc5(struct drm_i915_private *dev_priv) -{ - /* - * During initialization, the firmware may not be loaded yet. - * We still want to make sure that the DC enabling flag is cleared. - */ - if (dev_priv->power_domains.initializing) - return; - - assert_rpm_wakelock_held(dev_priv); -} - static void gen9_enable_dc5(struct drm_i915_private *dev_priv) { assert_can_enable_dc5(dev_priv); @@ -638,29 +624,6 @@ static void assert_can_enable_dc6(struct drm_i915_private *dev_priv) assert_csr_loaded(dev_priv); } -static void assert_can_disable_dc6(struct drm_i915_private *dev_priv) -{ - /* - * During initialization, the firmware may not be loaded yet. - * We still want to make sure that the DC enabling flag is cleared. - */ - if (dev_priv->power_domains.initializing) - return; - - WARN_ONCE(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6), - "DC6 already programmed to be disabled.\n"); -} - -static void gen9_disable_dc5_dc6(struct drm_i915_private *dev_priv) -{ - assert_can_disable_dc5(dev_priv); - - if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC6) - assert_can_disable_dc6(dev_priv); - - gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); -} - void skl_enable_dc6(struct drm_i915_private *dev_priv) { assert_can_enable_dc6(dev_priv); @@ -673,8 +636,6 @@ void skl_enable_dc6(struct drm_i915_private *dev_priv) void skl_disable_dc6(struct drm_i915_private *dev_priv) { - assert_can_disable_dc6(dev_priv); - DRM_DEBUG_KMS("Disabling DC6\n"); gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); @@ -828,7 +789,7 @@ static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv, static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - gen9_disable_dc5_dc6(dev_priv); + gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); } static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv, -- cgit v0.10.2 From 32fff610f7cf05260300f6c18700e9e0ac5910fb Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 1 Mar 2016 17:04:01 +0100 Subject: drm/i915: Do not return unknown status when load detection is tested. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the IGT test, which interprets unknown status as failed to acquire load detect pipe. Cc: Gabriel Feceoru Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1456848241-6431-1-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 583cae7..5f12a19 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -656,6 +656,8 @@ intel_crt_detect(struct drm_connector *connector, bool force) else if (INTEL_INFO(dev)->gen < 4) status = intel_crt_load_detect(crt, to_intel_crtc(connector->state->crtc)->pipe); + else if (i915.load_detect_test) + status = connector_status_disconnected; else status = connector_status_unknown; intel_release_load_detect_pipe(connector, &tmp, &ctx); -- cgit v0.10.2 From ca377809d657ea3ba249e97d073a7373e383ab6a Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 2 Mar 2016 12:10:31 +0000 Subject: drm/i915: Avoid snooping with userptr where not supported commit e5756c10d841ddb448293c849392f3d6b809561f Author: Imre Deak Date: Fri Aug 14 18:43:30 2015 +0300 drm/i915/bxt: don't allow cached GEM mappings on A stepping Added an exception of disallowing snooping for Broxton A stepping hardware but userptr was still enabling it regardless. Move the check to HAS_SNOOP now that it is used from multiple call sites and use it. v2: Userptr cannot be supported when it cannot be coherent and generalize the code better. (Chris Wilson) v3: Make has_snoop true only when !has_llc. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Cc: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1456920631-34302-1-git-send-email-tvrtko.ursulin@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 36c0cf1..4aa3db6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -853,6 +853,10 @@ static void intel_device_info_runtime_init(struct drm_device *dev) else if (INTEL_INFO(dev)->gen >= 9) gen9_sseu_info_init(dev); + /* Snooping is broken on BXT A stepping. */ + info->has_snoop = !info->has_llc; + info->has_snoop &= !IS_BXT_REVID(dev, 0, BXT_REVID_A1); + DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total); DRM_DEBUG_DRIVER("subslice total: %u\n", info->subslice_total); DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->subslice_per_slice); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0e2fb5b..2cb0a41 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -786,6 +786,7 @@ struct intel_csr { func(overlay_needs_physical) sep \ func(supports_tv) sep \ func(has_llc) sep \ + func(has_snoop) sep \ func(has_ddi) sep \ func(has_fpga_dbg) @@ -2630,6 +2631,7 @@ struct drm_i915_cmd_table { #define HAS_BLT(dev) (INTEL_INFO(dev)->ring_mask & BLT_RING) #define HAS_VEBOX(dev) (INTEL_INFO(dev)->ring_mask & VEBOX_RING) #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) +#define HAS_SNOOP(dev) (INTEL_INFO(dev)->has_snoop) #define HAS_WT(dev) ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && \ __I915__(dev)->ellc_size) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 3d31d3a..b854af2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3949,7 +3949,7 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, * cacheline, whereas normally such cachelines would get * invalidated. */ - if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) + if (!HAS_LLC(dev) && !HAS_SNOOP(dev)) return -ENODEV; level = I915_CACHE_LLC; diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 4b09c84..54088a4 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -758,6 +758,13 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file int ret; u32 handle; + if (!HAS_LLC(dev) && !HAS_SNOOP(dev)) { + /* We cannot support coherent userptr objects on hw without + * LLC and broken snooping. + */ + return -ENODEV; + } + if (args->flags & ~(I915_USERPTR_READ_ONLY | I915_USERPTR_UNSYNCHRONIZED)) return -EINVAL; -- cgit v0.10.2 From 933bfb44b228f26e09364d122576c8e938588d4f Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Mon, 8 Feb 2016 22:47:11 +0530 Subject: drm/i915: Hold RPM reference while setting freq limits through sysfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This changes ensures device is active when frequency limits are changed. This is needed as we are writing to register RPNSWREQ in intel_set_rps. If not done, might lead to undesired errors like: [ 1965.189137] [drm:fw_domains_get] *ERROR* blitter: timed out waiting for forcewake ack to clear. v2: Added elaborate commit message. (Jani) Fixing RPM reference drop in early exit paths. (Ville) Signed-off-by: Sagar Arun Kamble Link: http://patchwork.freedesktop.org/patch/msgid/1454951831-11778-1-git-send-email-sagar.a.kamble@intel.com Signed-off-by: Ville Syrjälä diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index c6188dd..2d576b7 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -370,6 +370,8 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, flush_delayed_work(&dev_priv->rps.delayed_resume_work); + intel_runtime_pm_get(dev_priv); + mutex_lock(&dev_priv->rps.hw_lock); val = intel_freq_opcode(dev_priv, val); @@ -378,6 +380,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, val > dev_priv->rps.max_freq || val < dev_priv->rps.min_freq_softlimit) { mutex_unlock(&dev_priv->rps.hw_lock); + intel_runtime_pm_put(dev_priv); return -EINVAL; } @@ -398,6 +401,8 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, mutex_unlock(&dev_priv->rps.hw_lock); + intel_runtime_pm_put(dev_priv); + return count; } @@ -433,6 +438,8 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, flush_delayed_work(&dev_priv->rps.delayed_resume_work); + intel_runtime_pm_get(dev_priv); + mutex_lock(&dev_priv->rps.hw_lock); val = intel_freq_opcode(dev_priv, val); @@ -441,6 +448,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, val > dev_priv->rps.max_freq || val > dev_priv->rps.max_freq_softlimit) { mutex_unlock(&dev_priv->rps.hw_lock); + intel_runtime_pm_put(dev_priv); return -EINVAL; } @@ -457,6 +465,8 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, mutex_unlock(&dev_priv->rps.hw_lock); + intel_runtime_pm_put(dev_priv); + return count; } -- cgit v0.10.2 From 1a426d6116467e09954289ee8c273e1bcc003adc Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 2 Mar 2016 12:36:03 +0100 Subject: drm/i915: Handle invalid ilk pipe watermarks correctly. This function returns an int, but when ilk_validate_pipe_wm fails it returns false, which is 0 (success). As a result invalid watermarks are applied, while they should have been rejected. Fix this by returning -EINVAL. Fixes: ed4a6a7ca853 ("drm/i915: Add two-stage ILK-style watermark programming (v11)") Cc: Matt Roper Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1456918563-28696-1-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Matt Roper diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d33de95..7df5a63 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2345,7 +2345,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate); if (!ilk_validate_pipe_wm(dev, pipe_wm)) - return false; + return -EINVAL; ilk_compute_wm_reg_maximums(dev, 1, &max); -- cgit v0.10.2 From d81f04c5ef5d6086e70656a32ff7c1b2bf998724 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 2 Mar 2016 12:38:06 +0100 Subject: drm/i915: Allow preservation of watermarks, v2. As Paulo has noted we can help bisectability by separating computing watermarks on a noop in 2 separate commits. This patch no longer clears the crtc watermark state, but recalculates it completely. Regardless whether a level is used the full values for each level are calculated. If a level is invalid wm[level].enable is unset. Changes since v1: - Only call ilk_validate_wm_level when level <= usable_level. (Ville) Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/56D6D09E.5040007@linux.intel.com Reviewed-by: Paulo Zanoni diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7df5a63..161c66b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2300,7 +2300,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, struct intel_plane_state *pristate = NULL; struct intel_plane_state *sprstate = NULL; struct intel_plane_state *curstate = NULL; - int level, max_level = ilk_wm_max_level(dev); + int level, max_level = ilk_wm_max_level(dev), usable_level; struct ilk_wm_maximums max; cstate = intel_atomic_get_crtc_state(state, intel_crtc); @@ -2308,7 +2308,6 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, return PTR_ERR(cstate); pipe_wm = &cstate->wm.optimal.ilk; - memset(pipe_wm, 0, sizeof(*pipe_wm)); for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { ps = drm_atomic_get_plane_state(state, @@ -2330,13 +2329,15 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 || drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16); + usable_level = max_level; + /* ILK/SNB: LP2+ watermarks only w/o sprites */ if (INTEL_INFO(dev)->gen <= 6 && sprstate->visible) - max_level = 1; + usable_level = 1; /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */ if (pipe_wm->sprites_scaled) - max_level = 0; + usable_level = 0; ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, pristate, sprstate, curstate, &pipe_wm->wm[0]); @@ -2350,20 +2351,22 @@ static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, ilk_compute_wm_reg_maximums(dev, 1, &max); for (level = 1; level <= max_level; level++) { - struct intel_wm_level wm = {}; + struct intel_wm_level *wm = &pipe_wm->wm[level]; ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate, - pristate, sprstate, curstate, &wm); + pristate, sprstate, curstate, wm); /* * Disable any watermark level that exceeds the * register maximums since such watermarks are * always invalid. */ - if (!ilk_validate_wm_level(level, &max, &wm)) - break; - - pipe_wm->wm[level] = wm; + if (level > usable_level) { + wm->enable = false; + } else if (!ilk_validate_wm_level(level, &max, wm)) { + wm->enable = false; + usable_level = level; + } } return 0; -- cgit v0.10.2 From e3bddded40e23a4a40f4cc7df65180a6041646dd Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 1 Mar 2016 11:07:22 +0100 Subject: drm/i915: Only recalculate wm's for planes part of the state, v2. Only planes that are part of the state should be used for recalculating watermarks. For planes not part of the state the previous patch allows us to re-use the old values since they're calculated even for levels that are not actively used. Changes since v1: - Remove big if from intel_crtc_atomic_check. - Remove extra newline. - Remove memset in ilk_compute_pipe_wm. Signed-off-by: Maarten Lankhorst Cc: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1456826842-32553-2-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Paulo Zanoni diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2cb0a41..c8791f6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -631,8 +631,7 @@ struct drm_i915_display_funcs { int target, int refclk, struct dpll *match_clock, struct dpll *best_clock); - int (*compute_pipe_wm)(struct intel_crtc *crtc, - struct drm_atomic_state *state); + int (*compute_pipe_wm)(struct intel_crtc_state *cstate); int (*compute_intermediate_wm)(struct drm_device *dev, struct intel_crtc *intel_crtc, struct intel_crtc_state *newstate); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 44fcff0..08c3631 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12106,7 +12106,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, ret = 0; if (dev_priv->display.compute_pipe_wm) { - ret = dev_priv->display.compute_pipe_wm(intel_crtc, state); + ret = dev_priv->display.compute_pipe_wm(pipe_config); if (ret) { DRM_DEBUG_KMS("Target pipe watermarks are invalid\n"); return ret; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index cb413e2..6c00854 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1628,6 +1628,18 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state, return to_intel_crtc_state(crtc_state); } + +static inline struct intel_plane_state * +intel_atomic_get_existing_plane_state(struct drm_atomic_state *state, + struct intel_plane *plane) +{ + struct drm_plane_state *plane_state; + + plane_state = drm_atomic_get_existing_plane_state(state, &plane->base); + + return to_intel_plane_state(plane_state); +} + int intel_atomic_setup_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 161c66b..f65e841 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1996,11 +1996,18 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv, cur_latency *= 5; } - result->pri_val = ilk_compute_pri_wm(cstate, pristate, - pri_latency, level); - result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency); - result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency); - result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val); + if (pristate) { + result->pri_val = ilk_compute_pri_wm(cstate, pristate, + pri_latency, level); + result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val); + } + + if (sprstate) + result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency); + + if (curstate) + result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency); + result->enable = true; } @@ -2288,51 +2295,51 @@ static bool ilk_validate_pipe_wm(struct drm_device *dev, } /* Compute new watermarks for the pipe */ -static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc, - struct drm_atomic_state *state) +static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate) { + struct drm_atomic_state *state = cstate->base.state; + struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); struct intel_pipe_wm *pipe_wm; - struct drm_device *dev = intel_crtc->base.dev; + struct drm_device *dev = state->dev; const struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc_state *cstate = NULL; struct intel_plane *intel_plane; - struct drm_plane_state *ps; struct intel_plane_state *pristate = NULL; struct intel_plane_state *sprstate = NULL; struct intel_plane_state *curstate = NULL; int level, max_level = ilk_wm_max_level(dev), usable_level; struct ilk_wm_maximums max; - cstate = intel_atomic_get_crtc_state(state, intel_crtc); - if (IS_ERR(cstate)) - return PTR_ERR(cstate); - pipe_wm = &cstate->wm.optimal.ilk; for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { - ps = drm_atomic_get_plane_state(state, - &intel_plane->base); - if (IS_ERR(ps)) - return PTR_ERR(ps); + struct intel_plane_state *ps; + + ps = intel_atomic_get_existing_plane_state(state, + intel_plane); + if (!ps) + continue; if (intel_plane->base.type == DRM_PLANE_TYPE_PRIMARY) - pristate = to_intel_plane_state(ps); + pristate = ps; else if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY) - sprstate = to_intel_plane_state(ps); + sprstate = ps; else if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR) - curstate = to_intel_plane_state(ps); + curstate = ps; } pipe_wm->pipe_enabled = cstate->base.active; - pipe_wm->sprites_enabled = sprstate->visible; - pipe_wm->sprites_scaled = sprstate->visible && - (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 || - drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16); + if (sprstate) { + pipe_wm->sprites_enabled = sprstate->visible; + pipe_wm->sprites_scaled = sprstate->visible && + (drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 || + drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16); + } + usable_level = max_level; /* ILK/SNB: LP2+ watermarks only w/o sprites */ - if (INTEL_INFO(dev)->gen <= 6 && sprstate->visible) + if (INTEL_INFO(dev)->gen <= 6 && pipe_wm->sprites_enabled) usable_level = 1; /* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */ -- cgit v0.10.2 From 782d25cac6373457b9a1c8a5efcd9194eb97ba80 Mon Sep 17 00:00:00 2001 From: Deepak M Date: Mon, 15 Feb 2016 22:43:57 +0530 Subject: drm/i915/bxt: Additional MIPI clock divider form B0 stepping onwards The MIPI clock calculations for the addtional clock are revised from B0 stepping onwards, the bit definitions have changed compared to old stepping. v2: Fixing compilation warning. v3: Retained the old Macros (Jani) Signed-off-by: Deepak M Tested-by: Ramalingam C # BXT-T with Tianma panel Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1455556437-29267-1-git-send-email-m.deepak@intel.com diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 71abf57..65f9bb9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7669,58 +7669,62 @@ enum skl_disp_power_wells { #define BXT_MIPI_DIV_SHIFT(port) \ _MIPI_PORT(port, BXT_MIPI1_DIV_SHIFT, \ BXT_MIPI2_DIV_SHIFT) -/* Var clock divider to generate TX source. Result must be < 39.5 M */ -#define BXT_MIPI1_ESCLK_VAR_DIV_MASK (0x3F << 26) -#define BXT_MIPI2_ESCLK_VAR_DIV_MASK (0x3F << 10) -#define BXT_MIPI_ESCLK_VAR_DIV_MASK(port) \ - _MIPI_PORT(port, BXT_MIPI1_ESCLK_VAR_DIV_MASK, \ - BXT_MIPI2_ESCLK_VAR_DIV_MASK) - -#define BXT_MIPI_ESCLK_VAR_DIV(port, val) \ - (val << BXT_MIPI_DIV_SHIFT(port)) + /* TX control divider to select actual TX clock output from (8x/var) */ -#define BXT_MIPI1_TX_ESCLK_SHIFT 21 -#define BXT_MIPI2_TX_ESCLK_SHIFT 5 +#define BXT_MIPI1_TX_ESCLK_SHIFT 26 +#define BXT_MIPI2_TX_ESCLK_SHIFT 10 #define BXT_MIPI_TX_ESCLK_SHIFT(port) \ _MIPI_PORT(port, BXT_MIPI1_TX_ESCLK_SHIFT, \ BXT_MIPI2_TX_ESCLK_SHIFT) -#define BXT_MIPI1_TX_ESCLK_FIXDIV_MASK (3 << 21) -#define BXT_MIPI2_TX_ESCLK_FIXDIV_MASK (3 << 5) +#define BXT_MIPI1_TX_ESCLK_FIXDIV_MASK (0x3F << 26) +#define BXT_MIPI2_TX_ESCLK_FIXDIV_MASK (0x3F << 10) #define BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port) \ _MIPI_PORT(port, BXT_MIPI1_TX_ESCLK_FIXDIV_MASK, \ - BXT_MIPI2_TX_ESCLK_FIXDIV_MASK) -#define BXT_MIPI_TX_ESCLK_8XDIV_BY2(port) \ - (0x0 << BXT_MIPI_TX_ESCLK_SHIFT(port)) -#define BXT_MIPI_TX_ESCLK_8XDIV_BY4(port) \ - (0x1 << BXT_MIPI_TX_ESCLK_SHIFT(port)) -#define BXT_MIPI_TX_ESCLK_8XDIV_BY8(port) \ - (0x2 << BXT_MIPI_TX_ESCLK_SHIFT(port)) -/* RX control divider to select actual RX clock output from 8x*/ -#define BXT_MIPI1_RX_ESCLK_SHIFT 19 -#define BXT_MIPI2_RX_ESCLK_SHIFT 3 -#define BXT_MIPI_RX_ESCLK_SHIFT(port) \ - _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_SHIFT, \ - BXT_MIPI2_RX_ESCLK_SHIFT) -#define BXT_MIPI1_RX_ESCLK_FIXDIV_MASK (3 << 19) -#define BXT_MIPI2_RX_ESCLK_FIXDIV_MASK (3 << 3) -#define BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port) \ - (3 << BXT_MIPI_RX_ESCLK_SHIFT(port)) -#define BXT_MIPI_RX_ESCLK_8X_BY2(port) \ - (1 << BXT_MIPI_RX_ESCLK_SHIFT(port)) -#define BXT_MIPI_RX_ESCLK_8X_BY3(port) \ - (2 << BXT_MIPI_RX_ESCLK_SHIFT(port)) -#define BXT_MIPI_RX_ESCLK_8X_BY4(port) \ - (3 << BXT_MIPI_RX_ESCLK_SHIFT(port)) -/* BXT-A WA: Always prog DPHY dividers to 00 */ -#define BXT_MIPI1_DPHY_DIV_SHIFT 16 -#define BXT_MIPI2_DPHY_DIV_SHIFT 0 -#define BXT_MIPI_DPHY_DIV_SHIFT(port) \ - _MIPI_PORT(port, BXT_MIPI1_DPHY_DIV_SHIFT, \ - BXT_MIPI2_DPHY_DIV_SHIFT) -#define BXT_MIPI_1_DPHY_DIVIDER_MASK (3 << 16) -#define BXT_MIPI_2_DPHY_DIVIDER_MASK (3 << 0) -#define BXT_MIPI_DPHY_DIVIDER_MASK(port) \ - (3 << BXT_MIPI_DPHY_DIV_SHIFT(port)) + BXT_MIPI2_TX_ESCLK_FIXDIV_MASK) +#define BXT_MIPI_TX_ESCLK_DIVIDER(port, val) \ + ((val & 0x3F) << BXT_MIPI_TX_ESCLK_SHIFT(port)) +/* RX upper control divider to select actual RX clock output from 8x */ +#define BXT_MIPI1_RX_ESCLK_UPPER_SHIFT 21 +#define BXT_MIPI2_RX_ESCLK_UPPER_SHIFT 5 +#define BXT_MIPI_RX_ESCLK_UPPER_SHIFT(port) \ + _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_UPPER_SHIFT, \ + BXT_MIPI2_RX_ESCLK_UPPER_SHIFT) +#define BXT_MIPI1_RX_ESCLK_UPPER_FIXDIV_MASK (3 << 21) +#define BXT_MIPI2_RX_ESCLK_UPPER_FIXDIV_MASK (3 << 5) +#define BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port) \ + _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_UPPER_FIXDIV_MASK, \ + BXT_MIPI2_RX_ESCLK_UPPER_FIXDIV_MASK) +#define BXT_MIPI_RX_ESCLK_UPPER_DIVIDER(port, val) \ + ((val & 3) << BXT_MIPI_RX_ESCLK_UPPER_SHIFT(port)) +/* 8/3X divider to select the actual 8/3X clock output from 8x */ +#define BXT_MIPI1_8X_BY3_SHIFT 19 +#define BXT_MIPI2_8X_BY3_SHIFT 3 +#define BXT_MIPI_8X_BY3_SHIFT(port) \ + _MIPI_PORT(port, BXT_MIPI1_8X_BY3_SHIFT, \ + BXT_MIPI2_8X_BY3_SHIFT) +#define BXT_MIPI1_8X_BY3_DIVIDER_MASK (3 << 19) +#define BXT_MIPI2_8X_BY3_DIVIDER_MASK (3 << 3) +#define BXT_MIPI_8X_BY3_DIVIDER_MASK(port) \ + _MIPI_PORT(port, BXT_MIPI1_8X_BY3_DIVIDER_MASK, \ + BXT_MIPI2_8X_BY3_DIVIDER_MASK) +#define BXT_MIPI_8X_BY3_DIVIDER(port, val) \ + ((val & 3) << BXT_MIPI_8X_BY3_SHIFT(port)) +/* RX lower control divider to select actual RX clock output from 8x */ +#define BXT_MIPI1_RX_ESCLK_LOWER_SHIFT 16 +#define BXT_MIPI2_RX_ESCLK_LOWER_SHIFT 0 +#define BXT_MIPI_RX_ESCLK_LOWER_SHIFT(port) \ + _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_LOWER_SHIFT, \ + BXT_MIPI2_RX_ESCLK_LOWER_SHIFT) +#define BXT_MIPI1_RX_ESCLK_LOWER_FIXDIV_MASK (3 << 16) +#define BXT_MIPI2_RX_ESCLK_LOWER_FIXDIV_MASK (3 << 0) +#define BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port) \ + _MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_LOWER_FIXDIV_MASK, \ + BXT_MIPI2_RX_ESCLK_LOWER_FIXDIV_MASK) +#define BXT_MIPI_RX_ESCLK_LOWER_DIVIDER(port, val) \ + ((val & 3) << BXT_MIPI_RX_ESCLK_LOWER_SHIFT(port)) + +#define RX_DIVIDER_BIT_1_2 0x3 +#define RX_DIVIDER_BIT_3_4 0xC /* BXT MIPI mode configure */ #define _BXT_MIPIA_TRANS_HACTIVE 0x6B0F8 diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 70883c5..2451c84 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -362,35 +362,57 @@ static void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) /* Program BXT Mipi clocks and dividers */ static void bxt_dsi_program_clocks(struct drm_device *dev, enum port port) { - u32 tmp; - u32 divider; - u32 dsi_rate; - u32 pll_ratio; struct drm_i915_private *dev_priv = dev->dev_private; + u32 tmp; + u32 dsi_rate = 0; + u32 pll_ratio = 0; + u32 rx_div; + u32 tx_div; + u32 rx_div_upper; + u32 rx_div_lower; + u32 mipi_8by3_divider; /* Clear old configurations */ tmp = I915_READ(BXT_MIPI_CLOCK_CTL); tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port)); - tmp &= ~(BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port)); - tmp &= ~(BXT_MIPI_ESCLK_VAR_DIV_MASK(port)); - tmp &= ~(BXT_MIPI_DPHY_DIVIDER_MASK(port)); + tmp &= ~(BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port)); + tmp &= ~(BXT_MIPI_8X_BY3_DIVIDER_MASK(port)); + tmp &= ~(BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port)); /* Get the current DSI rate(actual) */ pll_ratio = I915_READ(BXT_DSI_PLL_CTL) & BXT_DSI_PLL_RATIO_MASK; dsi_rate = (BXT_REF_CLOCK_KHZ * pll_ratio) / 2; - /* Max possible output of clock is 39.5 MHz, program value -1 */ - divider = (dsi_rate / BXT_MAX_VAR_OUTPUT_KHZ) - 1; - tmp |= BXT_MIPI_ESCLK_VAR_DIV(port, divider); + /* + * tx clock should be <= 20MHz and the div value must be + * subtracted by 1 as per bspec + */ + tx_div = DIV_ROUND_UP(dsi_rate, 20000) - 1; + /* + * rx clock should be <= 150MHz and the div value must be + * subtracted by 1 as per bspec + */ + rx_div = DIV_ROUND_UP(dsi_rate, 150000) - 1; /* - * Tx escape clock must be as close to 20MHz possible, but should - * not exceed it. Hence select divide by 2 + * rx divider value needs to be updated in the + * two differnt bit fields in the register hence splitting the + * rx divider value accordingly */ - tmp |= BXT_MIPI_TX_ESCLK_8XDIV_BY2(port); + rx_div_lower = rx_div & RX_DIVIDER_BIT_1_2; + rx_div_upper = (rx_div & RX_DIVIDER_BIT_3_4) >> 2; + + /* As per bpsec program the 8/3X clock divider to the below value */ + if (dev_priv->vbt.dsi.config->is_cmd_mode) + mipi_8by3_divider = 0x2; + else + mipi_8by3_divider = 0x3; - tmp |= BXT_MIPI_RX_ESCLK_8X_BY3(port); + tmp |= BXT_MIPI_8X_BY3_DIVIDER(port, mipi_8by3_divider); + tmp |= BXT_MIPI_TX_ESCLK_DIVIDER(port, tx_div); + tmp |= BXT_MIPI_RX_ESCLK_LOWER_DIVIDER(port, rx_div_lower); + tmp |= BXT_MIPI_RX_ESCLK_UPPER_DIVIDER(port, rx_div_upper); I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp); } @@ -513,9 +535,9 @@ static void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) /* Clear old configurations */ tmp = I915_READ(BXT_MIPI_CLOCK_CTL); tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port)); - tmp &= ~(BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port)); - tmp &= ~(BXT_MIPI_ESCLK_VAR_DIV_MASK(port)); - tmp &= ~(BXT_MIPI_DPHY_DIVIDER_MASK(port)); + tmp &= ~(BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port)); + tmp &= ~(BXT_MIPI_8X_BY3_DIVIDER_MASK(port)); + tmp &= ~(BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port)); I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp); I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP); } -- cgit v0.10.2 From 3f177625ee896f5d3c62fa6a49554a9c0243bceb Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 3 Mar 2016 14:36:41 +0000 Subject: drm/i915: Add wait_for_us This is for callers who want micro-second precision but are not waiting from the atomic context. v2: * Fix atomic waits. (Dave Gordon) * Use USEC_PER_SEC and USEC_PER_MSEC. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Cc: Dave Gordon Cc: Chris Wilson Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 75acb1d..5a13879 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1792,11 +1792,11 @@ static void wait_panel_status(struct intel_dp *intel_dp, I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg)); - if (_wait_for((I915_READ(pp_stat_reg) & mask) == value, 5000, 10)) { + if (_wait_for((I915_READ(pp_stat_reg) & mask) == value, + 5 * USEC_PER_SEC, 10 * USEC_PER_MSEC)) DRM_ERROR("Panel status timeout: status %08x control %08x\n", I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg)); - } DRM_DEBUG_KMS("Wait complete\n"); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6c00854..c2a62e9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -45,8 +45,8 @@ * having timed out, since the timeout could be due to preemption or similar and * we've never had a chance to check the condition before the timeout. */ -#define _wait_for(COND, MS, W) ({ \ - unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1; \ +#define _wait_for(COND, US, W) ({ \ + unsigned long timeout__ = jiffies + usecs_to_jiffies(US) + 1; \ int ret__ = 0; \ while (!(COND)) { \ if (time_after(jiffies, timeout__)) { \ @@ -55,7 +55,7 @@ break; \ } \ if ((W) && drm_can_sleep()) { \ - usleep_range((W)*1000, (W)*2000); \ + usleep_range((W), (W)*2); \ } else { \ cpu_relax(); \ } \ @@ -63,10 +63,11 @@ ret__; \ }) -#define wait_for(COND, MS) _wait_for(COND, MS, 1) -#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0) -#define wait_for_atomic_us(COND, US) _wait_for((COND), \ - DIV_ROUND_UP((US), 1000), 0) +#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 1000) +#define wait_for_us(COND, US) _wait_for((COND), (US), 1) + +#define wait_for_atomic(COND, MS) _wait_for((COND), (MS) * 1000, 0) +#define wait_for_atomic_us(COND, US) _wait_for((COND), (US), 0) #define KHz(x) (1000 * (x)) #define MHz(x) KHz(1000 * (x)) diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 0b42ada..b1413be 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -507,7 +507,8 @@ static void hsw_psr_disable(struct intel_dp *intel_dp) /* Wait till PSR is idle */ if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL) & - EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10)) + EDP_PSR_STATUS_STATE_MASK) == 0, + 2 * USEC_PER_SEC, 10 * USEC_PER_MSEC)) DRM_ERROR("Timed out waiting for PSR Idle State\n"); dev_priv->psr.active = false; -- cgit v0.10.2 From 8de1b23efaede0e355cba017992ab032e983c61c Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 3 Mar 2016 14:36:42 +0000 Subject: drm/i915/lrc: Do not wait atomically when stopping engines I do not see that this needs to be done atomically and up to one second is quite a long time to busy loop. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 27c9ee3..6fcbf6b 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1062,7 +1062,7 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring) /* TODO: Is this correct with Execlists enabled? */ I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); - if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { + if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); return; } -- cgit v0.10.2 From 643a24b6ecdcb3ed866cdf25a60df3d731504126 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 3 Mar 2016 14:36:43 +0000 Subject: drm/i915: Kconfig for extra driver debugging v2: Added a submenu based on an idea by Chris Wilson. Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Cc: Jani Nikula Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 20a5d04..29a32b1 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -56,3 +56,9 @@ config DRM_I915_USERPTR selected to enabled full userptr support. If in doubt, say "Y". + +menu "drm/i915 Debugging" +depends on DRM_I915 +depends on EXPERT +source drivers/gpu/drm/i915/Kconfig.debug +endmenu diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug new file mode 100644 index 0000000..649a562 --- /dev/null +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -0,0 +1,12 @@ +config DRM_I915_DEBUG + bool "Enable additional driver debugging" + depends on DRM_I915 + default n + help + Choose this option to turn on extra driver debugging that may affect + performance but will catch some internal issues. + + Recommended for driver developers only. + + If in doubt, say "N". + -- cgit v0.10.2 From 0351b93992aa463cc3e7f358ddec2709f9390756 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 3 Mar 2016 16:21:27 +0000 Subject: drm/i915: Do not lie about atomic timeout granularity Currently the wait_for_atomic_us only allows for a jiffie timeout granularity which is not nice towards callers requesting small micro-second timeouts. Re-implement it so micro-second timeout granularity is really supported and not just in the name of the macro. This has another beneficial side effect that it improves "gem_latency -n 100" results by approximately 2.5% (throughput and latencies) and 3% (CPU usage). (Note this improvement is relative to not yet merged execlist lock uncontention patch which moves the CSB MMIO outside this lock.) It also shrinks some hot functions like fw_domains_get by a tiny 3%. v2: * Warn when used from non-atomic context (if possible). * Warn on too long atomic waits. v3: * Added comment explaining CONFIG_PREEMPT_COUNT. * Fixed pre-processor indentation. (Chris Wilson) v4: * Commit msg update (gem_latency) and rebase. v5: * Commit message re-wording. * Added comment about no need for double cond check. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c2a62e9..d8b4916 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -44,6 +44,10 @@ * contexts. Note that it's important that we check the condition again after * having timed out, since the timeout could be due to preemption or similar and * we've never had a chance to check the condition before the timeout. + * + * TODO: When modesetting has fully transitioned to atomic, the below + * drm_can_sleep() can be removed and in_atomic()/!in_atomic() asserts + * added. */ #define _wait_for(COND, US, W) ({ \ unsigned long timeout__ = jiffies + usecs_to_jiffies(US) + 1; \ @@ -66,8 +70,37 @@ #define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 1000) #define wait_for_us(COND, US) _wait_for((COND), (US), 1) -#define wait_for_atomic(COND, MS) _wait_for((COND), (MS) * 1000, 0) -#define wait_for_atomic_us(COND, US) _wait_for((COND), (US), 0) +/* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */ +#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT) +# define _WAIT_FOR_ATOMIC_CHECK WARN_ON_ONCE(!in_atomic()) +#else +# define _WAIT_FOR_ATOMIC_CHECK do { } while (0) +#endif + +#define _wait_for_atomic(COND, US) ({ \ + unsigned long end__; \ + int ret__ = 0; \ + _WAIT_FOR_ATOMIC_CHECK; \ + BUILD_BUG_ON((US) > 50000); \ + end__ = (local_clock() >> 10) + (US) + 1; \ + while (!(COND)) { \ + if (time_after((unsigned long)(local_clock() >> 10), end__)) { \ + /* Unlike the regular wait_for(), this atomic variant \ + * cannot be preempted (and we'll just ignore the issue\ + * of irq interruptions) and so we know that no time \ + * has passed since the last check of COND and can \ + * immediately report the timeout. \ + */ \ + ret__ = -ETIMEDOUT; \ + break; \ + } \ + cpu_relax(); \ + } \ + ret__; \ +}) + +#define wait_for_atomic(COND, MS) _wait_for_atomic((COND), (MS) * 1000) +#define wait_for_atomic_us(COND, US) _wait_for_atomic((COND), (US)) #define KHz(x) (1000 * (x)) #define MHz(x) KHz(1000 * (x)) -- cgit v0.10.2 From 5ba001783ba6451fd3db0259d30549ca1fe91870 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 3 Mar 2016 14:36:45 +0000 Subject: drm/i915: Do not wait atomically for display clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks like this code does not need to wait atomically since it otherwise takes the mutex. Signed-off-by: Tvrtko Ursulin Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1457015805-23742-1-git-send-email-tvrtko.ursulin@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 08c3631..124342b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9857,8 +9857,8 @@ static void broadwell_set_cdclk(struct drm_device *dev, int cdclk) val |= LCPLL_CD_SOURCE_FCLK; I915_WRITE(LCPLL_CTL, val); - if (wait_for_atomic_us(I915_READ(LCPLL_CTL) & - LCPLL_CD_SOURCE_FCLK_DONE, 1)) + if (wait_for_us(I915_READ(LCPLL_CTL) & + LCPLL_CD_SOURCE_FCLK_DONE, 1)) DRM_ERROR("Switching to FCLK failed\n"); val = I915_READ(LCPLL_CTL); @@ -9892,8 +9892,8 @@ static void broadwell_set_cdclk(struct drm_device *dev, int cdclk) val &= ~LCPLL_CD_SOURCE_FCLK; I915_WRITE(LCPLL_CTL, val); - if (wait_for_atomic_us((I915_READ(LCPLL_CTL) & - LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1)) + if (wait_for_us((I915_READ(LCPLL_CTL) & + LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1)) DRM_ERROR("Switching back to LCPLL failed\n"); mutex_lock(&dev_priv->rps.hw_lock); -- cgit v0.10.2 From e7dc33f332c7188a96722a69fe99c2de9ada3ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 2 Mar 2016 17:22:13 +0200 Subject: drm/i915: Store rawclk_freq in dev_priv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generalize rawclk handling by storing it in dev_priv. Presumably our hrawclk readout works at least for CTG and ELK since we've been using it for DP AUX on those platforms. There are no real docs anymore after configdb vanished, so the only reference is the public CTG GMCH spec. What bits are listed in that doc match our code. The ELK GMCH spec have no relevant details unfortunately. The PNV situation is less clear. Starting from commit aa17cdb4f836 ("drm/i915: initialize backlight max from VBT") we assume that the CTG/ELK hrawclk readout works for PNV as well. At least the results *seem* reasonable for one PNV machine (Lenovo Ideapad S10-3t). Sadly the PNV GMCH spec doesn't have the goods on the relevant register either. So let's keep assuming it works for PNV,ELK,CTG and read it out on those platforms. G33 also has hrawclk according to some notes in BSpec, but we don't actually need it for anything, so let's not even try to read it out there. v2: Rebase due to IS_VALLYVIEW vs. IS_CHERRYVIEW split Use KHz() all over, and kill off a few useless temp variables Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1456932138-14004-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c8791f6..f37ac12 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1836,6 +1836,7 @@ struct drm_i915_private { unsigned int skl_boot_cdclk; unsigned int cdclk_freq, max_cdclk_freq, atomic_cdclk_freq; unsigned int max_dotclk_freq; + unsigned int rawclk_freq; unsigned int hpll_freq; unsigned int czclk_freq; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 124342b..dd9118b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -169,49 +169,61 @@ static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv, return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, divider + 1); } -int -intel_pch_rawclk(struct drm_device *dev) +static int +intel_pch_rawclk(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; - - WARN_ON(!HAS_PCH_SPLIT(dev)); + return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000; +} - return I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK; +static int +intel_vlv_hrawclk(struct drm_i915_private *dev_priv) +{ + return 200000; } -/* hrawclock is 1/4 the FSB frequency */ -int intel_hrawclk(struct drm_device *dev) +static int +intel_g4x_hrawclk(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; uint32_t clkcfg; - /* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */ - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) - return 200; - + /* hrawclock is 1/4 the FSB frequency */ clkcfg = I915_READ(CLKCFG); switch (clkcfg & CLKCFG_FSB_MASK) { case CLKCFG_FSB_400: - return 100; + return 100000; case CLKCFG_FSB_533: - return 133; + return 133333; case CLKCFG_FSB_667: - return 166; + return 166667; case CLKCFG_FSB_800: - return 200; + return 200000; case CLKCFG_FSB_1067: - return 266; + return 266667; case CLKCFG_FSB_1333: - return 333; + return 333333; /* these two are just a guess; one of them might be right */ case CLKCFG_FSB_1600: case CLKCFG_FSB_1600_ALT: - return 400; + return 400000; default: - return 133; + return 133333; } } +static void intel_update_rawclk(struct drm_i915_private *dev_priv) +{ + if (HAS_PCH_SPLIT(dev_priv)) + dev_priv->rawclk_freq = intel_pch_rawclk(dev_priv); + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + dev_priv->rawclk_freq = intel_vlv_hrawclk(dev_priv); + else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv)) + dev_priv->rawclk_freq = intel_g4x_hrawclk(dev_priv); + else + return; /* no rawclk on other platforms, or no need to know it */ + + DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq); +} + static void intel_update_czclk(struct drm_i915_private *dev_priv) { if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))) @@ -15617,6 +15629,7 @@ void intel_modeset_init(struct drm_device *dev) } intel_update_czclk(dev_priv); + intel_update_rawclk(dev_priv); intel_update_cdclk(dev); intel_shared_dpll_init(dev); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5a13879..2625652 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -674,13 +674,13 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq) static uint32_t i9xx_get_aux_clock_divider(struct intel_dp *intel_dp, int index) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); /* * The clock divider is based off the hrawclk, and would like to run at * 2MHz. So, take the hrawclk value and divide by 2 and use that */ - return index ? 0 : DIV_ROUND_CLOSEST(intel_hrawclk(dev), 2); + return index ? 0 : DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000); } static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) @@ -692,12 +692,10 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) if (index) return 0; - if (intel_dig_port->port == PORT_A) { + if (intel_dig_port->port == PORT_A) return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000); - - } else { - return DIV_ROUND_CLOSEST(intel_pch_rawclk(dev), 2); - } + else + return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000); } static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index) @@ -718,7 +716,7 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index) default: return 0; } } else { - return index ? 0 : DIV_ROUND_CLOSEST(intel_pch_rawclk(dev), 2); + return index ? 0 : DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000); } } @@ -5268,7 +5266,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; u32 pp_on, pp_off, pp_div, port_sel = 0; - int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev); + int div = dev_priv->rawclk_freq / 1000; i915_reg_t pp_on_reg, pp_off_reg, pp_div_reg, pp_ctrl_reg; enum port port = dp_to_dig_port(intel_dp)->port; const struct edp_power_seq *seq = &intel_dp->pps_delays; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d8b4916..cd0b4ea 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1119,8 +1119,6 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); extern const struct drm_plane_funcs intel_plane_funcs; unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info); bool intel_has_pending_fb_unpin(struct drm_device *dev); -int intel_pch_rawclk(struct drm_device *dev); -int intel_hrawclk(struct drm_device *dev); void intel_mark_busy(struct drm_device *dev); void intel_mark_idle(struct drm_device *dev); void intel_crtc_restore_mode(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 21ee647..5cf3775 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1251,16 +1251,14 @@ static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - u32 mul, clock; + u32 mul; if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY) mul = 128; else mul = 16; - clock = MHz(24); - - return clock / (pwm_freq_hz * mul); + return MHz(24) / (pwm_freq_hz * mul); } /* @@ -1292,10 +1290,9 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_device *dev = connector->base.dev; - int clock = MHz(intel_pch_rawclk(dev)); + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - return clock / (pwm_freq_hz * 128); + return KHz(dev_priv->rawclk_freq) / (pwm_freq_hz * 128); } /* @@ -1308,14 +1305,13 @@ static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); int clock; - if (IS_PINEVIEW(dev)) - clock = MHz(intel_hrawclk(dev)); + if (IS_PINEVIEW(dev_priv)) + clock = KHz(dev_priv->rawclk_freq); else - clock = 1000 * dev_priv->cdclk_freq; + clock = KHz(dev_priv->cdclk_freq); return clock / (pwm_freq_hz * 32); } @@ -1332,9 +1328,9 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) int clock; if (IS_G4X(dev_priv)) - clock = MHz(intel_hrawclk(dev)); + clock = KHz(dev_priv->rawclk_freq); else - clock = 1000 * dev_priv->cdclk_freq; + clock = KHz(dev_priv->cdclk_freq); return clock / (pwm_freq_hz * 128); } @@ -1346,19 +1342,21 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) */ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - struct drm_device *dev = connector->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int clock; + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + int mul, clock; if ((I915_READ(CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) { - if (IS_CHERRYVIEW(dev)) - return KHz(19200) / (pwm_freq_hz * 16); + if (IS_CHERRYVIEW(dev_priv)) + clock = KHz(19200); else - return MHz(25) / (pwm_freq_hz * 16); + clock = MHz(25); + mul = 16; } else { - clock = intel_hrawclk(dev); - return MHz(clock) / (pwm_freq_hz * 128); + clock = KHz(dev_priv->rawclk_freq); + mul = 128; } + + return clock / (pwm_freq_hz * mul); } static u32 get_backlight_max_vbt(struct intel_connector *connector) -- cgit v0.10.2 From 6ffb1be708ccbefc1a833b3d7d186eefbcf5f12e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 2 Mar 2016 17:22:14 +0200 Subject: drm/i915: Rename s/i9xx/g4x/ in DP code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit g4x is the first platform with DP support, so let's name the relevant functions as g4x_ instead i9xx_ to avoid confusion. Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1456932138-14004-3-git-send-email-ville.syrjala@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2625652..c9be578 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -671,7 +671,7 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq) return status; } -static uint32_t i9xx_get_aux_clock_divider(struct intel_dp *intel_dp, int index) +static uint32_t g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); @@ -735,10 +735,10 @@ static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index) return index ? 0 : 1; } -static uint32_t i9xx_get_aux_send_ctl(struct intel_dp *intel_dp, - bool has_aux_irq, - int send_bytes, - uint32_t aux_clock_divider) +static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp, + bool has_aux_irq, + int send_bytes, + uint32_t aux_clock_divider) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; @@ -5866,12 +5866,12 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, else if (HAS_PCH_SPLIT(dev)) intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider; else - intel_dp->get_aux_clock_divider = i9xx_get_aux_clock_divider; + intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider; if (INTEL_INFO(dev)->gen >= 9) intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl; else - intel_dp->get_aux_send_ctl = i9xx_get_aux_send_ctl; + intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl; if (HAS_DDI(dev)) intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain; -- cgit v0.10.2 From 193709c1c4d2543eac5d49428db732837ebcf61f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 2 Mar 2016 17:22:15 +0200 Subject: drm/i915: Use g4x_get_aux_clock_divider() for VLV/CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the hrawclk frequency cached in dev_priv, we can simply use g4x_get_aux_clock_divider() for VLV/CHV. v2: Rebase due to IS_VALLYVIEW vs. IS_CHERRYVIEW split Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1456932138-14004-4-git-send-email-ville.syrjala@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c9be578..ddf35bd 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -720,11 +720,6 @@ static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index) } } -static uint32_t vlv_get_aux_clock_divider(struct intel_dp *intel_dp, int index) -{ - return index ? 0 : 100; -} - static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index) { /* @@ -5859,8 +5854,6 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, /* intel_dp vfuncs */ if (INTEL_INFO(dev)->gen >= 9) intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider; - else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) - intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider; else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider; else if (HAS_PCH_SPLIT(dev)) -- cgit v0.10.2 From 35d38d1f17b853a014b500350ab3135790d47ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 2 Mar 2016 17:22:16 +0200 Subject: drm/i915: Read out hrawclk from CCK on vlv/chv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we assume that hrawclk is 200MHz on VLV/CHV. That should be true always, but just to avoid such asumptions we can read out the actual frequency from CCK. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1456932138-14004-5-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Imre Deak diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 65f9bb9..7dfc400 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -786,6 +786,7 @@ enum skl_disp_power_wells { #define DSI_PLL_M1_DIV_MASK (0x1ff << 0) #define CCK_CZ_CLOCK_CONTROL 0x62 #define CCK_DISPLAY_CLOCK_CONTROL 0x6b +#define CCK_DISPLAY_REF_CLOCK_CONTROL 0x6c #define CCK_TRUNK_FORCE_ON (1 << 17) #define CCK_TRUNK_FORCE_OFF (1 << 16) #define CCK_FREQUENCY_STATUS (0x1f << 8) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dd9118b..62d36a7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -178,7 +178,8 @@ intel_pch_rawclk(struct drm_i915_private *dev_priv) static int intel_vlv_hrawclk(struct drm_i915_private *dev_priv) { - return 200000; + return vlv_get_cck_clock_hpll(dev_priv, "hrawclk", + CCK_DISPLAY_REF_CLOCK_CONTROL); } static int -- cgit v0.10.2 From a457f54b293c82fc6b222d9bc59fed4984321d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 2 Mar 2016 17:22:17 +0200 Subject: drm/i915: Clean up .get_aux_clock_divider() functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the mess with AUX clock divder rounding is sorted out and we have both cdclk and rawclk cached in dev_priv, we can clean up the .get_aux_clock_divider() functions a bit. The main thing here is just calling ilk_get_aux_clock_divider() from hsw_get_aux_clock_divider() except for the LPT:H special case. We could go further and call g4x_get_aux_clock_divider() from ilk_get_aux_clock_divider() for the PCH ports, but I'm sure Jani would object, so leave that be. While at it repeat the comment where the AUX clock comes from in ilk_get_aux_clock_divider(). Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1456932138-14004-6-git-send-email-ville.syrjala@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ddf35bd..7a0f99d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -676,22 +676,29 @@ static uint32_t g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index) struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); + if (index) + return 0; + /* * The clock divider is based off the hrawclk, and would like to run at - * 2MHz. So, take the hrawclk value and divide by 2 and use that + * 2MHz. So, take the hrawclk value and divide by 2000 and use that */ - return index ? 0 : DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000); + return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000); } static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); if (index) return 0; + /* + * The clock divider is based off the cdclk or PCH rawclk, and would + * like to run at 2MHz. So, take the cdclk or PCH rawclk value and + * divide by 2000 and use that + */ if (intel_dig_port->port == PORT_A) return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000); else @@ -701,23 +708,18 @@ static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = intel_dig_port->base.base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); - if (intel_dig_port->port == PORT_A) { - if (index) - return 0; - return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000); - } else if (HAS_PCH_LPT_H(dev_priv)) { + if (intel_dig_port->port != PORT_A && HAS_PCH_LPT_H(dev_priv)) { /* Workaround for non-ULT HSW */ switch (index) { case 0: return 63; case 1: return 72; default: return 0; } - } else { - return index ? 0 : DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000); } + + return ilk_get_aux_clock_divider(intel_dp, index); } static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index) -- cgit v0.10.2 From 37f2248e3d422f0463800b574ea9288ede97cea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 2 Mar 2016 17:22:18 +0200 Subject: drm/i915: Use DIV_ROUND_CLOSEST for PWM calculations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supposedly we would want to get the PWM output as close as possible to the target, so let's round to closest. Cc: Jani Nikula Suggested-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1456932138-14004-7-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 5cf3775..0fe059b 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1240,7 +1240,7 @@ static void intel_backlight_device_unregister(struct intel_connector *connector) */ static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { - return KHz(19200) / pwm_freq_hz; + return DIV_ROUND_CLOSEST(KHz(19200), pwm_freq_hz); } /* @@ -1258,7 +1258,7 @@ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) else mul = 16; - return MHz(24) / (pwm_freq_hz * mul); + return DIV_ROUND_CLOSEST(MHz(24), pwm_freq_hz * mul); } /* @@ -1281,7 +1281,7 @@ static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) else clock = MHz(24); /* LPT:LP */ - return clock / (pwm_freq_hz * mul); + return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul); } /* @@ -1292,7 +1292,7 @@ static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - return KHz(dev_priv->rawclk_freq) / (pwm_freq_hz * 128); + return DIV_ROUND_CLOSEST(KHz(dev_priv->rawclk_freq), pwm_freq_hz * 128); } /* @@ -1313,7 +1313,7 @@ static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) else clock = KHz(dev_priv->cdclk_freq); - return clock / (pwm_freq_hz * 32); + return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32); } /* @@ -1332,7 +1332,7 @@ static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) else clock = KHz(dev_priv->cdclk_freq); - return clock / (pwm_freq_hz * 128); + return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128); } /* @@ -1356,7 +1356,7 @@ static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) mul = 128; } - return clock / (pwm_freq_hz * mul); + return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul); } static u32 get_backlight_max_vbt(struct intel_connector *connector) -- cgit v0.10.2 From d431440cce2427dcdd665d936865fe802637b4c2 Mon Sep 17 00:00:00 2001 From: Tomas Elf Date: Wed, 2 Mar 2016 16:46:24 +0200 Subject: drm/i915: Generalise common GPU engine reset request/unrequest code GPU engine reset handshaking is something that is applicable to both full GPU reset and engine reset, which is something that is part of the upcoming TDR per-engine hang recovery patches. Break out the common engine reset request/unrequest code (originally written by Mika Kuoppala) for reuse later in the TDR enablement patch series. v2: correct indentation and drop unused returned value (Mika) v3: We have forcewake during reset so use *_FW reg access (Mika) Reviewed-by: Mika Kuoppala Signed-off-by: Tomas Elf Cc: Mika Kuoppala Signed-off-by: Arun Siluvery [Mika: Fixed format warning] Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1456929984-16323-1-git-send-email-mika.kuoppala@intel.com diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 436d8f2..d31447f 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1531,13 +1531,40 @@ static int gen6_do_reset(struct drm_device *dev) return ret; } -static int wait_for_register(struct drm_i915_private *dev_priv, - i915_reg_t reg, - const u32 mask, - const u32 value, - const unsigned long timeout_ms) +static int wait_for_register_fw(struct drm_i915_private *dev_priv, + i915_reg_t reg, + const u32 mask, + const u32 value, + const unsigned long timeout_ms) { - return wait_for((I915_READ(reg) & mask) == value, timeout_ms); + return wait_for((I915_READ_FW(reg) & mask) == value, timeout_ms); +} + +static int gen8_request_engine_reset(struct intel_engine_cs *engine) +{ + int ret; + struct drm_i915_private *dev_priv = engine->dev->dev_private; + + I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base), + _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET)); + + ret = wait_for_register_fw(dev_priv, + RING_RESET_CTL(engine->mmio_base), + RESET_CTL_READY_TO_RESET, + RESET_CTL_READY_TO_RESET, + 700); + if (ret) + DRM_ERROR("%s: reset request timeout\n", engine->name); + + return ret; +} + +static void gen8_unrequest_engine_reset(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->dev->dev_private; + + I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base), + _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET)); } static int gen8_do_reset(struct drm_device *dev) @@ -1546,26 +1573,15 @@ static int gen8_do_reset(struct drm_device *dev) struct intel_engine_cs *engine; int i; - for_each_ring(engine, dev_priv, i) { - I915_WRITE(RING_RESET_CTL(engine->mmio_base), - _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET)); - - if (wait_for_register(dev_priv, - RING_RESET_CTL(engine->mmio_base), - RESET_CTL_READY_TO_RESET, - RESET_CTL_READY_TO_RESET, - 700)) { - DRM_ERROR("%s: reset request timeout\n", engine->name); + for_each_ring(engine, dev_priv, i) + if (gen8_request_engine_reset(engine)) goto not_ready; - } - } return gen6_do_reset(dev); not_ready: for_each_ring(engine, dev_priv, i) - I915_WRITE(RING_RESET_CTL(engine->mmio_base), - _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET)); + gen8_unrequest_engine_reset(engine); return -EIO; } -- cgit v0.10.2 From 24a65e624bcdc726c7711ae90efeffaf0a8e9f32 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 2 Mar 2016 16:48:29 +0200 Subject: drm/i915/hangcheck: Prevent long walks across full-ppgtt With full-ppgtt, it takes the GPU an eon to traverse the entire 256PiB address space, causing a loop to be detected. Under the current scheme, if ACTHD walks off the end of a batch buffer and into an empty address space, we "never" detect the hang. If we always increment the score as the ACTHD is progressing then we will eventually timeout (after ~46.5s (31 * 1.5s) without advancing onto a new batch). To counter act this, increase the amount we reduce the score for good batches, so that only a series of almost-bad batches trigger a full reset. DoS detection suffers slightly but series of long running shader tests will benefit. Based on a patch from Chris Wilson. Testcase: igt/drv_hangman/hangcheck-unterminated Cc: Daniele Ceraolo Spurio Cc: Chris Wilson Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1456930109-21532-1-git-send-email-mika.kuoppala@intel.com diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a0f1bd7..15aacd0 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1367,8 +1367,6 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n", (long long)ring->hangcheck.acthd, (long long)acthd[i]); - seq_printf(m, "\tmax ACTHD = 0x%08llx\n", - (long long)ring->hangcheck.max_acthd); seq_printf(m, "\tscore = %d\n", ring->hangcheck.score); seq_printf(m, "\taction = %d\n", ring->hangcheck.action); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 3b6bfbf..13b5f3a 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -230,8 +230,6 @@ static const char *hangcheck_action_to_str(enum intel_ring_hangcheck_action a) return "wait"; case HANGCHECK_ACTIVE: return "active"; - case HANGCHECK_ACTIVE_LOOP: - return "active (loop)"; case HANGCHECK_KICK: return "kick"; case HANGCHECK_HUNG: diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index d1a46ef..53e5104 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3001,12 +3001,7 @@ head_stuck(struct intel_engine_cs *ring, u64 acthd) memset(ring->hangcheck.instdone, 0, sizeof(ring->hangcheck.instdone)); - if (acthd > ring->hangcheck.max_acthd) { - ring->hangcheck.max_acthd = acthd; - return HANGCHECK_ACTIVE; - } - - return HANGCHECK_ACTIVE_LOOP; + return HANGCHECK_ACTIVE; } if (!subunits_stuck(ring)) @@ -3083,6 +3078,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) #define BUSY 1 #define KICK 5 #define HUNG 20 +#define ACTIVE_DECAY 15 if (!i915.enable_hangcheck) return; @@ -3151,9 +3147,8 @@ static void i915_hangcheck_elapsed(struct work_struct *work) switch (ring->hangcheck.action) { case HANGCHECK_IDLE: case HANGCHECK_WAIT: - case HANGCHECK_ACTIVE: break; - case HANGCHECK_ACTIVE_LOOP: + case HANGCHECK_ACTIVE: ring->hangcheck.score += BUSY; break; case HANGCHECK_KICK: @@ -3172,10 +3167,12 @@ static void i915_hangcheck_elapsed(struct work_struct *work) * attempts across multiple batches. */ if (ring->hangcheck.score > 0) - ring->hangcheck.score--; + ring->hangcheck.score -= ACTIVE_DECAY; + if (ring->hangcheck.score < 0) + ring->hangcheck.score = 0; /* Clear head and subunit states on seqno movement */ - ring->hangcheck.acthd = ring->hangcheck.max_acthd = 0; + ring->hangcheck.acthd = 0; memset(ring->hangcheck.instdone, 0, sizeof(ring->hangcheck.instdone)); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index dd910d3..4b1439d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -79,7 +79,6 @@ enum intel_ring_hangcheck_action { HANGCHECK_IDLE = 0, HANGCHECK_WAIT, HANGCHECK_ACTIVE, - HANGCHECK_ACTIVE_LOOP, HANGCHECK_KICK, HANGCHECK_HUNG, }; @@ -88,7 +87,6 @@ enum intel_ring_hangcheck_action { struct intel_ring_hangcheck { u64 acthd; - u64 max_acthd; u32 seqno; int score; enum intel_ring_hangcheck_action action; -- cgit v0.10.2 From 2abc525bf5c62fd1f2a2994e5231842221dfdddb Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 4 Mar 2016 21:57:41 +0200 Subject: drm/i915/gen9: Fix DMC firmware initialization In commit 1e657ad7 we moved the last step of firmware initialization to skl_display_core_init(), where it will be run only during system resume, but not during driver loading. Since this init step needs to be done whenever we program the firmware fix this by moving the initialization to the end of intel_csr_load_program(). While at it simplify a bit csr_load_work_fn(). This issue prevented DC5/6 transitions, this change will re-enable those. v2: - remove debugging left-over and redundant comment in csr_load_work_fn() Fixes: 1e657ad7a48f ("drm/i915/gen9: Write dc state debugmask bits only once") CC: Mika Kuoppala CC: Patrik Jakobsson Signed-off-by: Imre Deak Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1457121461-16729-1-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 902054e..d417d9a 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -212,6 +212,24 @@ static const struct stepping_info *intel_get_stepping_info(struct drm_device *de return NULL; } +static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv) +{ + uint32_t val, mask; + + mask = DC_STATE_DEBUG_MASK_MEMORY_UP; + + if (IS_BROXTON(dev_priv)) + mask |= DC_STATE_DEBUG_MASK_CORES; + + /* The below bit doesn't need to be cleared ever afterwards */ + val = I915_READ(DC_STATE_DEBUG); + if ((val & mask) != mask) { + val |= mask; + I915_WRITE(DC_STATE_DEBUG, val); + POSTING_READ(DC_STATE_DEBUG); + } +} + /** * intel_csr_load_program() - write the firmware from memory to register. * @dev_priv: i915 drm device. @@ -220,19 +238,19 @@ static const struct stepping_info *intel_get_stepping_info(struct drm_device *de * Everytime display comes back from low power state this function is called to * copy the firmware from internal memory to registers. */ -bool intel_csr_load_program(struct drm_i915_private *dev_priv) +void intel_csr_load_program(struct drm_i915_private *dev_priv) { u32 *payload = dev_priv->csr.dmc_payload; uint32_t i, fw_size; if (!IS_GEN9(dev_priv)) { DRM_ERROR("No CSR support available for this platform\n"); - return false; + return; } if (!dev_priv->csr.dmc_payload) { DRM_ERROR("Tried to program CSR with empty payload\n"); - return false; + return; } fw_size = dev_priv->csr.dmc_fw_size; @@ -246,7 +264,7 @@ bool intel_csr_load_program(struct drm_i915_private *dev_priv) dev_priv->csr.dc_state = 0; - return true; + gen9_set_dc_state_debugmask(dev_priv); } static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, @@ -388,18 +406,12 @@ static void csr_load_work_fn(struct work_struct *work) ret = request_firmware(&fw, dev_priv->csr.fw_path, &dev_priv->dev->pdev->dev); - if (!fw) - goto out; + if (fw) + dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw); - dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw); - if (!dev_priv->csr.dmc_payload) - goto out; - - /* load csr program during system boot, as needed for DC states */ - intel_csr_load_program(dev_priv); - -out: if (dev_priv->csr.dmc_payload) { + intel_csr_load_program(dev_priv); + intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); DRM_INFO("Finished loading %s (v%u.%u)\n", diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index cd0b4ea..3daf1e3 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1279,7 +1279,7 @@ u32 skl_plane_ctl_rotation(unsigned int rotation); /* intel_csr.c */ void intel_csr_ucode_init(struct drm_i915_private *); -bool intel_csr_load_program(struct drm_i915_private *); +void intel_csr_load_program(struct drm_i915_private *); void intel_csr_ucode_fini(struct drm_i915_private *); /* intel_dp.c */ diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 09c52b1..5adf4b3 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -470,24 +470,6 @@ static void assert_can_disable_dc9(struct drm_i915_private *dev_priv) */ } -static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv) -{ - uint32_t val, mask; - - mask = DC_STATE_DEBUG_MASK_MEMORY_UP; - - if (IS_BROXTON(dev_priv)) - mask |= DC_STATE_DEBUG_MASK_CORES; - - /* The below bit doesn't need to be cleared ever afterwards */ - val = I915_READ(DC_STATE_DEBUG); - if ((val & mask) != mask) { - val |= mask; - I915_WRITE(DC_STATE_DEBUG, val); - POSTING_READ(DC_STATE_DEBUG); - } -} - static void gen9_write_dc_state(struct drm_i915_private *dev_priv, u32 state) { @@ -2141,8 +2123,8 @@ static void skl_display_core_init(struct drm_i915_private *dev_priv, skl_init_cdclk(dev_priv); - if (dev_priv->csr.dmc_payload && intel_csr_load_program(dev_priv)) - gen9_set_dc_state_debugmask(dev_priv); + if (dev_priv->csr.dmc_payload) + intel_csr_load_program(dev_priv); } static void skl_display_core_uninit(struct drm_i915_private *dev_priv) -- cgit v0.10.2 From 9dfbffcf4ac0707097af9e6c1372192b9d03a357 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 24 Feb 2016 15:35:22 +0100 Subject: drm/i915: Fix bogus dig_port_map[] assignment for pre-HSW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The recent commit [0bdf5a05647a: drm/i915: Add reverse mapping between port and intel_encoder] introduced a reverse mapping to retrieve intel_dig_port object from the port number. The code assumed that the port vs intel_dig_port are 1:1 mapping. But in reality, this was a too naive assumption. As Martin reported about the missing HDMI audio on his SNB machine, pre-HSW chips may have multiple intel_dig_port objects corresponding to the same port. Since we assign the mapping statically at the init time and the multiple objects override the map, it may not match with the actually enabled output. This patch tries to address the regression above. The reverse mapping is provided basically only for the audio callbacks, so now we set / clear the mapping dynamically at enabling and disabling HDMI/DP audio, so that we can always track the latest and correct object corresponding to the given port. Fixes: 0bdf5a05647a ('drm/i915: Add reverse mapping between port and intel_encoder') Reported-and-tested-by: Martin Kepplinger Cc: drm-intel-fixes@lists.freedesktop.org Signed-off-by: Takashi Iwai Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1456324522-21591-1-git-send-email-tiwai@suse.de diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 31f6d21..30f9214 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -527,6 +527,8 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) mutex_lock(&dev_priv->av_mutex); intel_dig_port->audio_connector = connector; + /* referred in audio callbacks */ + dev_priv->dig_port_map[port] = intel_encoder; mutex_unlock(&dev_priv->av_mutex); if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) @@ -554,6 +556,7 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder) mutex_lock(&dev_priv->av_mutex); intel_dig_port->audio_connector = NULL; + dev_priv->dig_port_map[port] = NULL; mutex_unlock(&dev_priv->av_mutex); if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 21a9b83..62de9f4 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -3326,7 +3326,6 @@ void intel_ddi_init(struct drm_device *dev, enum port port) intel_encoder->get_config = intel_ddi_get_config; intel_dig_port->port = port; - dev_priv->dig_port_map[port] = intel_encoder; intel_dig_port->saved_port_bits = I915_READ(DDI_BUF_CTL(port)) & (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7a0f99d..109ae61 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -6045,7 +6045,6 @@ intel_dp_init(struct drm_device *dev, } intel_dig_port->port = port; - dev_priv->dig_port_map[port] = intel_encoder; intel_dig_port->dp.output_reg = output_reg; intel_dig_port->max_lanes = 4; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index d8060e6..e2dab48 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -2164,7 +2164,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, void intel_hdmi_init(struct drm_device *dev, i915_reg_t hdmi_reg, enum port port) { - struct drm_i915_private *dev_priv = dev->dev_private; struct intel_digital_port *intel_dig_port; struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; @@ -2233,7 +2232,6 @@ void intel_hdmi_init(struct drm_device *dev, intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI; intel_dig_port->port = port; - dev_priv->dig_port_map[port] = intel_encoder; intel_dig_port->hdmi.hdmi_reg = hdmi_reg; intel_dig_port->dp.output_reg = INVALID_MMIO_REG; intel_dig_port->max_lanes = 4; -- cgit v0.10.2 From acad889f9eb86ba8830de33cc7a391e9f68ca5ea Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 8 Mar 2016 21:00:56 +0200 Subject: drm/i915/bxt: add missing DSI power domain to power well 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DSI power domain was missing from BXT power well 1 definitions, failing to get the power well for DSI transcoders. As pipe A is in the same power well as DSI transcoders, the problem should only occur with pipes B and C. According to Ville, this is basically a nop since pw1 is under dmc control. But given that we still have this stuff defined here, it's clearly correct to include DSI here. Cc: Ramalingam C Cc: Deepak M Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1457463656-29357-1-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 5adf4b3..2e88a5e 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -421,6 +421,7 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, BIT(POWER_DOMAIN_TRANSCODER_EDP) | \ BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \ BIT(POWER_DOMAIN_PORT_DDI_A_LANES) | \ + BIT(POWER_DOMAIN_PORT_DSI) | \ BIT(POWER_DOMAIN_AUX_A) | \ BIT(POWER_DOMAIN_PLLS) | \ BIT(POWER_DOMAIN_INIT)) -- cgit v0.10.2 From 71f0a626143368b8aead361ffaff7e36d043fd8e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 8 Mar 2016 10:57:16 +0100 Subject: drm/i915: Only use sanitized values for ILK watermarks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The raw watermark values are needed when planes are not part of the state, but this introduced a regression and possibly an overflow when merging the watermarks because invalid values may end up used. Solve this by calculating raw watermarks for all levels, and only setting non-zero values when the level is valid. Fixes the SNB warning: WARNING: CPU: 1 PID: 25405 at drivers/gpu/drm/i915/intel_pm.c:2580 ilk_program_watermarks+0x7b2/0x9d0 [i915]() WARN_ON(wm_lp != 1) Modules linked in: i915 drm_kms_helper drm bluetooth fuse iTCO_wdt iTCO_vendor_support syscopyarea sysfillrect sysimgblt fb_sys_fops tpm_tis mei_me e1000e snd_hda_codec_hdmi pcspkr tpm mei i2c_i801 lpc_ich snd_hda_codec snd_hda_core CPU: 1 PID: 25405 Comm: kms_universal_p Tainted: G U W 4.5.0-rc6apollolake+ #462 Hardware name: /DH67GD, BIOS BLH6710H.86A.0160.2012.1204.1156 12/04/2012 0000000000000000 ffff88009d42b918 ffffffff8143cfab ffff88009d42b960 ffffffffa0363580 ffff88009d42b950 ffffffff81082746 ffff8800b9a24928 ffff88009d42ba00 ffff88009d4a0000 0000000000000000 ffff88009d42ba6c Call Trace: [] dump_stack+0x4d/0x72 [] warn_slowpath_common+0x86/0xc0 [] warn_slowpath_fmt+0x4c/0x50 [] ilk_program_watermarks+0x7b2/0x9d0 [i915] [] ilk_initial_watermarks+0x107/0x120 [i915] [] intel_pre_plane_update+0x12a/0x190 [i915] [] intel_atomic_commit+0x546/0xd50 [i915] [] drm_atomic_commit+0x37/0x60 [drm] [] drm_atomic_helper_disable_plane+0xb1/0xf0 [drm_kms_helper] [] __setplane_internal+0x184/0x280 [drm] [] ? drm_modeset_lock_all_ctx+0x9a/0xb0 [drm] [] drm_mode_setplane+0x13f/0x1c0 [drm] [] drm_ioctl+0x142/0x590 [drm] [] ? drm_plane_check_pixel_format+0x50/0x50 [drm] [] ? mntput+0x24/0x40 [] ? __fput+0x194/0x200 [] drm_compat_ioctl+0x33/0x40 [drm] [] i915_compat_ioctl+0x32/0x40 [i915] [] compat_SyS_ioctl+0xc2/0x330 [] ? exit_to_usermode_loop+0x95/0xb0 [] do_fast_syscall_32+0x9e/0x210 [] entry_SYSENTER_compat+0x52/0x70 Cc: Matt Roper Cc: Chris Wilson Cc: Paulo Zanoni Cc: Ville Syrjälä Testcase: kms_universal_plane Fixes: d81f04c5ef ("drm/i915: Allow preservation of watermarks, v2.") Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/56DEA1FC.8080703@linux.intel.com Reviewed-by: Ville Syrjälä diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3daf1e3..7b2d66d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -390,6 +390,7 @@ struct intel_crtc_scaler_state { struct intel_pipe_wm { struct intel_wm_level wm[5]; + struct intel_wm_level raw_wm[5]; uint32_t linetime; bool fbc_wm_enabled; bool pipe_enabled; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f65e841..d7aef17 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2335,7 +2335,6 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate) drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16); } - usable_level = max_level; /* ILK/SNB: LP2+ watermarks only w/o sprites */ @@ -2347,7 +2346,10 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate) usable_level = 0; ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate, - pristate, sprstate, curstate, &pipe_wm->wm[0]); + pristate, sprstate, curstate, &pipe_wm->raw_wm[0]); + + memset(&pipe_wm->wm, 0, sizeof(pipe_wm->wm)); + pipe_wm->wm[0] = pipe_wm->raw_wm[0]; if (IS_HASWELL(dev) || IS_BROADWELL(dev)) pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate); @@ -2358,7 +2360,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate) ilk_compute_wm_reg_maximums(dev, 1, &max); for (level = 1; level <= max_level; level++) { - struct intel_wm_level *wm = &pipe_wm->wm[level]; + struct intel_wm_level *wm = &pipe_wm->raw_wm[level]; ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate, pristate, sprstate, curstate, wm); @@ -2368,12 +2370,13 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate) * register maximums since such watermarks are * always invalid. */ - if (level > usable_level) { - wm->enable = false; - } else if (!ilk_validate_wm_level(level, &max, wm)) { - wm->enable = false; + if (level > usable_level) + continue; + + if (ilk_validate_wm_level(level, &max, wm)) + pipe_wm->wm[level] = *wm; + else usable_level = level; - } } return 0; -- cgit v0.10.2 From 7abd4b35a577d6541bf07493a448eee9dfc8ba2d Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:15 +0200 Subject: drm/i915: Move shared dpll code to a new file Create the new file intel_dpll_mgr.c and move the shared dpll code to it. Follow up patches that reorganize pll handling will move more code there and tweak the interface. No functional changes. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-2-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 0851de07..5558a03 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -56,6 +56,7 @@ i915-y += intel_audio.o \ intel_atomic_plane.o \ intel_bios.o \ intel_display.o \ + intel_dpll_mgr.o \ intel_fbc.o \ intel_fifo_underrun.o \ intel_frontbuffer.o \ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 62d36a7..1d5695d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1197,34 +1197,6 @@ static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state) #define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true) #define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false) -struct intel_shared_dpll * -intel_crtc_to_shared_dpll(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - - if (crtc->config->shared_dpll < 0) - return NULL; - - return &dev_priv->shared_dplls[crtc->config->shared_dpll]; -} - -/* For ILK+ */ -void assert_shared_dpll(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll, - bool state) -{ - bool cur_state; - struct intel_dpll_hw_state hw_state; - - if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state))) - return; - - cur_state = pll->get_hw_state(dev_priv, pll, &hw_state); - I915_STATE_WARN(cur_state != state, - "%s assertion failure (expected %s, current %s)\n", - pll->name, onoff(state), onoff(cur_state)); -} - static void assert_fdi_tx(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) { @@ -1461,21 +1433,8 @@ static void assert_vblank_disabled(struct drm_crtc *crtc) drm_crtc_vblank_put(crtc); } -static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) -{ - u32 val; - bool enabled; - - I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev))); - - val = I915_READ(PCH_DREF_CONTROL); - enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK | - DREF_SUPERSPREAD_SOURCE_MASK)); - I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n"); -} - -static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, - enum pipe pipe) +void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, + enum pipe pipe) { u32 val; bool enabled; @@ -1871,100 +1830,6 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, port_name(dport->port), I915_READ(dpll_reg) & port_mask, expected_mask); } -static void intel_prepare_shared_dpll(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); - - if (WARN_ON(pll == NULL)) - return; - - WARN_ON(!pll->config.crtc_mask); - if (pll->active == 0) { - DRM_DEBUG_DRIVER("setting up %s\n", pll->name); - WARN_ON(pll->on); - assert_shared_dpll_disabled(dev_priv, pll); - - pll->mode_set(dev_priv, pll); - } -} - -/** - * intel_enable_shared_dpll - enable PCH PLL - * @dev_priv: i915 private structure - * @pipe: pipe PLL to enable - * - * The PCH PLL needs to be enabled before the PCH transcoder, since it - * drives the transcoder clock. - */ -static void intel_enable_shared_dpll(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); - - if (WARN_ON(pll == NULL)) - return; - - if (WARN_ON(pll->config.crtc_mask == 0)) - return; - - DRM_DEBUG_KMS("enable %s (active %d, on? %d) for crtc %d\n", - pll->name, pll->active, pll->on, - crtc->base.base.id); - - if (pll->active++) { - WARN_ON(!pll->on); - assert_shared_dpll_enabled(dev_priv, pll); - return; - } - WARN_ON(pll->on); - - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); - - DRM_DEBUG_KMS("enabling %s\n", pll->name); - pll->enable(dev_priv, pll); - pll->on = true; -} - -static void intel_disable_shared_dpll(struct intel_crtc *crtc) -{ - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); - - /* PCH only available on ILK+ */ - if (INTEL_INFO(dev)->gen < 5) - return; - - if (pll == NULL) - return; - - if (WARN_ON(!(pll->config.crtc_mask & (1 << drm_crtc_index(&crtc->base))))) - return; - - DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n", - pll->name, pll->active, pll->on, - crtc->base.base.id); - - if (WARN_ON(pll->active == 0)) { - assert_shared_dpll_disabled(dev_priv, pll); - return; - } - - assert_shared_dpll_enabled(dev_priv, pll); - WARN_ON(!pll->on); - if (--pll->active) - return; - - DRM_DEBUG_KMS("disabling %s\n", pll->name); - pll->disable(dev_priv, pll); - pll->on = false; - - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); -} - static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { @@ -4361,113 +4226,6 @@ static void lpt_pch_enable(struct drm_crtc *crtc) lpt_enable_pch_transcoder(dev_priv, cpu_transcoder); } -struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct intel_shared_dpll *pll; - struct intel_shared_dpll_config *shared_dpll; - enum intel_dpll_id i; - int max = dev_priv->num_shared_dpll; - - shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); - - if (HAS_PCH_IBX(dev_priv->dev)) { - /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ - i = (enum intel_dpll_id) crtc->pipe; - pll = &dev_priv->shared_dplls[i]; - - DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", - crtc->base.base.id, pll->name); - - WARN_ON(shared_dpll[i].crtc_mask); - - goto found; - } - - if (IS_BROXTON(dev_priv->dev)) { - /* PLL is attached to port in bxt */ - struct intel_encoder *encoder; - struct intel_digital_port *intel_dig_port; - - encoder = intel_ddi_get_crtc_new_encoder(crtc_state); - if (WARN_ON(!encoder)) - return NULL; - - intel_dig_port = enc_to_dig_port(&encoder->base); - /* 1:1 mapping between ports and PLLs */ - i = (enum intel_dpll_id)intel_dig_port->port; - pll = &dev_priv->shared_dplls[i]; - DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", - crtc->base.base.id, pll->name); - WARN_ON(shared_dpll[i].crtc_mask); - - goto found; - } else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv)) - /* Do not consider SPLL */ - max = 2; - - for (i = 0; i < max; i++) { - pll = &dev_priv->shared_dplls[i]; - - /* Only want to check enabled timings first */ - if (shared_dpll[i].crtc_mask == 0) - continue; - - if (memcmp(&crtc_state->dpll_hw_state, - &shared_dpll[i].hw_state, - sizeof(crtc_state->dpll_hw_state)) == 0) { - DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n", - crtc->base.base.id, pll->name, - shared_dpll[i].crtc_mask, - pll->active); - goto found; - } - } - - /* Ok no matching timings, maybe there's a free one? */ - for (i = 0; i < dev_priv->num_shared_dpll; i++) { - pll = &dev_priv->shared_dplls[i]; - if (shared_dpll[i].crtc_mask == 0) { - DRM_DEBUG_KMS("CRTC:%d allocated %s\n", - crtc->base.base.id, pll->name); - goto found; - } - } - - return NULL; - -found: - if (shared_dpll[i].crtc_mask == 0) - shared_dpll[i].hw_state = - crtc_state->dpll_hw_state; - - crtc_state->shared_dpll = i; - DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name, - pipe_name(crtc->pipe)); - - shared_dpll[i].crtc_mask |= 1 << crtc->pipe; - - return pll; -} - -static void intel_shared_dpll_commit(struct drm_atomic_state *state) -{ - struct drm_i915_private *dev_priv = to_i915(state->dev); - struct intel_shared_dpll_config *shared_dpll; - struct intel_shared_dpll *pll; - enum intel_dpll_id i; - - if (!to_intel_atomic_state(state)->dpll_set) - return; - - shared_dpll = to_intel_atomic_state(state)->shared_dpll; - for (i = 0; i < dev_priv->num_shared_dpll; i++) { - pll = &dev_priv->shared_dplls[i]; - pll->config = shared_dpll[i]; - } -} - static void cpt_verify_modeset(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -13887,108 +13645,6 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { .atomic_destroy_state = intel_crtc_destroy_state, }; -static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) -{ - uint32_t val; - - if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) - return false; - - val = I915_READ(PCH_DPLL(pll->id)); - hw_state->dpll = val; - hw_state->fp0 = I915_READ(PCH_FP0(pll->id)); - hw_state->fp1 = I915_READ(PCH_FP1(pll->id)); - - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); - - return val & DPLL_VCO_ENABLE; -} - -static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0); - I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1); -} - -static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - /* PCH refclock must be enabled first */ - ibx_assert_pch_refclk_enabled(dev_priv); - - I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll); - - /* Wait for the clocks to stabilize. */ - POSTING_READ(PCH_DPLL(pll->id)); - udelay(150); - - /* The pixel multiplier can only be updated once the - * DPLL is enabled and the clocks are stable. - * - * So write it again. - */ - I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll); - POSTING_READ(PCH_DPLL(pll->id)); - udelay(200); -} - -static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - struct drm_device *dev = dev_priv->dev; - struct intel_crtc *crtc; - - /* Make sure no transcoder isn't still depending on us. */ - for_each_intel_crtc(dev, crtc) { - if (intel_crtc_to_shared_dpll(crtc) == pll) - assert_pch_transcoder_disabled(dev_priv, crtc->pipe); - } - - I915_WRITE(PCH_DPLL(pll->id), 0); - POSTING_READ(PCH_DPLL(pll->id)); - udelay(200); -} - -static char *ibx_pch_dpll_names[] = { - "PCH DPLL A", - "PCH DPLL B", -}; - -static void ibx_pch_dpll_init(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int i; - - dev_priv->num_shared_dpll = 2; - - for (i = 0; i < dev_priv->num_shared_dpll; i++) { - dev_priv->shared_dplls[i].id = i; - dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i]; - dev_priv->shared_dplls[i].mode_set = ibx_pch_dpll_mode_set; - dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable; - dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable; - dev_priv->shared_dplls[i].get_hw_state = - ibx_pch_dpll_get_hw_state; - } -} - -static void intel_shared_dpll_init(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - - if (HAS_DDI(dev)) - intel_ddi_pll_init(dev); - else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) - ibx_pch_dpll_init(dev); - else - dev_priv->num_shared_dpll = 0; - - BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); -} - /** * intel_prepare_plane_fb - Prepare fb for usage on plane * @plane: drm plane to prepare for diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c new file mode 100644 index 0000000..d7ebac6 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -0,0 +1,368 @@ +/* + * Copyright © 2006-2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "intel_drv.h" + +struct intel_shared_dpll * +intel_crtc_to_shared_dpll(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + + if (crtc->config->shared_dpll < 0) + return NULL; + + return &dev_priv->shared_dplls[crtc->config->shared_dpll]; +} + +/* For ILK+ */ +void assert_shared_dpll(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + bool state) +{ + bool cur_state; + struct intel_dpll_hw_state hw_state; + + if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state))) + return; + + cur_state = pll->get_hw_state(dev_priv, pll, &hw_state); + I915_STATE_WARN(cur_state != state, + "%s assertion failure (expected %s, current %s)\n", + pll->name, onoff(state), onoff(cur_state)); +} + +void intel_prepare_shared_dpll(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); + + if (WARN_ON(pll == NULL)) + return; + + WARN_ON(!pll->config.crtc_mask); + if (pll->active == 0) { + DRM_DEBUG_DRIVER("setting up %s\n", pll->name); + WARN_ON(pll->on); + assert_shared_dpll_disabled(dev_priv, pll); + + pll->mode_set(dev_priv, pll); + } +} + +/** + * intel_enable_shared_dpll - enable PCH PLL + * @dev_priv: i915 private structure + * @pipe: pipe PLL to enable + * + * The PCH PLL needs to be enabled before the PCH transcoder, since it + * drives the transcoder clock. + */ +void intel_enable_shared_dpll(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); + + if (WARN_ON(pll == NULL)) + return; + + if (WARN_ON(pll->config.crtc_mask == 0)) + return; + + DRM_DEBUG_KMS("enable %s (active %d, on? %d) for crtc %d\n", + pll->name, pll->active, pll->on, + crtc->base.base.id); + + if (pll->active++) { + WARN_ON(!pll->on); + assert_shared_dpll_enabled(dev_priv, pll); + return; + } + WARN_ON(pll->on); + + intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); + + DRM_DEBUG_KMS("enabling %s\n", pll->name); + pll->enable(dev_priv, pll); + pll->on = true; +} + +void intel_disable_shared_dpll(struct intel_crtc *crtc) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); + + /* PCH only available on ILK+ */ + if (INTEL_INFO(dev)->gen < 5) + return; + + if (pll == NULL) + return; + + if (WARN_ON(!(pll->config.crtc_mask & (1 << drm_crtc_index(&crtc->base))))) + return; + + DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n", + pll->name, pll->active, pll->on, + crtc->base.base.id); + + if (WARN_ON(pll->active == 0)) { + assert_shared_dpll_disabled(dev_priv, pll); + return; + } + + assert_shared_dpll_enabled(dev_priv, pll); + WARN_ON(!pll->on); + if (--pll->active) + return; + + DRM_DEBUG_KMS("disabling %s\n", pll->name); + pll->disable(dev_priv, pll); + pll->on = false; + + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); +} + +struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_shared_dpll *pll; + struct intel_shared_dpll_config *shared_dpll; + enum intel_dpll_id i; + int max = dev_priv->num_shared_dpll; + + shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); + + if (HAS_PCH_IBX(dev_priv->dev)) { + /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ + i = (enum intel_dpll_id) crtc->pipe; + pll = &dev_priv->shared_dplls[i]; + + DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", + crtc->base.base.id, pll->name); + + WARN_ON(shared_dpll[i].crtc_mask); + + goto found; + } + + if (IS_BROXTON(dev_priv->dev)) { + /* PLL is attached to port in bxt */ + struct intel_encoder *encoder; + struct intel_digital_port *intel_dig_port; + + encoder = intel_ddi_get_crtc_new_encoder(crtc_state); + if (WARN_ON(!encoder)) + return NULL; + + intel_dig_port = enc_to_dig_port(&encoder->base); + /* 1:1 mapping between ports and PLLs */ + i = (enum intel_dpll_id)intel_dig_port->port; + pll = &dev_priv->shared_dplls[i]; + DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", + crtc->base.base.id, pll->name); + WARN_ON(shared_dpll[i].crtc_mask); + + goto found; + } else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv)) + /* Do not consider SPLL */ + max = 2; + + for (i = 0; i < max; i++) { + pll = &dev_priv->shared_dplls[i]; + + /* Only want to check enabled timings first */ + if (shared_dpll[i].crtc_mask == 0) + continue; + + if (memcmp(&crtc_state->dpll_hw_state, + &shared_dpll[i].hw_state, + sizeof(crtc_state->dpll_hw_state)) == 0) { + DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n", + crtc->base.base.id, pll->name, + shared_dpll[i].crtc_mask, + pll->active); + goto found; + } + } + + /* Ok no matching timings, maybe there's a free one? */ + for (i = 0; i < dev_priv->num_shared_dpll; i++) { + pll = &dev_priv->shared_dplls[i]; + if (shared_dpll[i].crtc_mask == 0) { + DRM_DEBUG_KMS("CRTC:%d allocated %s\n", + crtc->base.base.id, pll->name); + goto found; + } + } + + return NULL; + +found: + if (shared_dpll[i].crtc_mask == 0) + shared_dpll[i].hw_state = + crtc_state->dpll_hw_state; + + crtc_state->shared_dpll = i; + DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name, + pipe_name(crtc->pipe)); + + shared_dpll[i].crtc_mask |= 1 << crtc->pipe; + + return pll; +} + +void intel_shared_dpll_commit(struct drm_atomic_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->dev); + struct intel_shared_dpll_config *shared_dpll; + struct intel_shared_dpll *pll; + enum intel_dpll_id i; + + if (!to_intel_atomic_state(state)->dpll_set) + return; + + shared_dpll = to_intel_atomic_state(state)->shared_dpll; + for (i = 0; i < dev_priv->num_shared_dpll; i++) { + pll = &dev_priv->shared_dplls[i]; + pll->config = shared_dpll[i]; + } +} + +static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + uint32_t val; + + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) + return false; + + val = I915_READ(PCH_DPLL(pll->id)); + hw_state->dpll = val; + hw_state->fp0 = I915_READ(PCH_FP0(pll->id)); + hw_state->fp1 = I915_READ(PCH_FP1(pll->id)); + + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return val & DPLL_VCO_ENABLE; +} + +static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0); + I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1); +} + +static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) +{ + u32 val; + bool enabled; + + I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev))); + + val = I915_READ(PCH_DREF_CONTROL); + enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK | + DREF_SUPERSPREAD_SOURCE_MASK)); + I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n"); +} + +static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + /* PCH refclock must be enabled first */ + ibx_assert_pch_refclk_enabled(dev_priv); + + I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll); + + /* Wait for the clocks to stabilize. */ + POSTING_READ(PCH_DPLL(pll->id)); + udelay(150); + + /* The pixel multiplier can only be updated once the + * DPLL is enabled and the clocks are stable. + * + * So write it again. + */ + I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll); + POSTING_READ(PCH_DPLL(pll->id)); + udelay(200); +} + +static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + struct drm_device *dev = dev_priv->dev; + struct intel_crtc *crtc; + + /* Make sure no transcoder isn't still depending on us. */ + for_each_intel_crtc(dev, crtc) { + if (intel_crtc_to_shared_dpll(crtc) == pll) + assert_pch_transcoder_disabled(dev_priv, crtc->pipe); + } + + I915_WRITE(PCH_DPLL(pll->id), 0); + POSTING_READ(PCH_DPLL(pll->id)); + udelay(200); +} + +static char *ibx_pch_dpll_names[] = { + "PCH DPLL A", + "PCH DPLL B", +}; + +static void ibx_pch_dpll_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int i; + + dev_priv->num_shared_dpll = 2; + + for (i = 0; i < dev_priv->num_shared_dpll; i++) { + dev_priv->shared_dplls[i].id = i; + dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i]; + dev_priv->shared_dplls[i].mode_set = ibx_pch_dpll_mode_set; + dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable; + dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable; + dev_priv->shared_dplls[i].get_hw_state = + ibx_pch_dpll_get_hw_state; + } +} + +void intel_shared_dpll_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (HAS_DDI(dev)) + intel_ddi_pll_init(dev); + else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) + ibx_pch_dpll_init(dev); + else + dev_priv->num_shared_dpll = 0; + + BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); +} diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7b2d66d..63b36b5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1201,6 +1201,9 @@ intel_rotation_90_or_270(unsigned int rotation) void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane); +void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, + enum pipe pipe); + /* shared dpll functions */ struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc); void assert_shared_dpll(struct drm_i915_private *dev_priv, @@ -1210,6 +1213,11 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false) struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, struct intel_crtc_state *state); +void intel_prepare_shared_dpll(struct intel_crtc *crtc); +void intel_enable_shared_dpll(struct intel_crtc *crtc); +void intel_disable_shared_dpll(struct intel_crtc *crtc); +void intel_shared_dpll_commit(struct drm_atomic_state *state); +void intel_shared_dpll_init(struct drm_device *dev); int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, const struct dpll *dpll); -- cgit v0.10.2 From 55be2f0854613b97aa606122bbe8b12a4b068bd9 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:16 +0200 Subject: drm/i915: Move ddi shared dpll code to intel_dpll_mgr.c No functional changes. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-3-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 62de9f4..54880662 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2430,235 +2430,6 @@ static void intel_disable_ddi(struct intel_encoder *intel_encoder) } } -static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll); - POSTING_READ(WRPLL_CTL(pll->id)); - udelay(20); -} - -static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - I915_WRITE(SPLL_CTL, pll->config.hw_state.spll); - POSTING_READ(SPLL_CTL); - udelay(20); -} - -static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - uint32_t val; - - val = I915_READ(WRPLL_CTL(pll->id)); - I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE); - POSTING_READ(WRPLL_CTL(pll->id)); -} - -static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - uint32_t val; - - val = I915_READ(SPLL_CTL); - I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE); - POSTING_READ(SPLL_CTL); -} - -static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) -{ - uint32_t val; - - if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) - return false; - - val = I915_READ(WRPLL_CTL(pll->id)); - hw_state->wrpll = val; - - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); - - return val & WRPLL_PLL_ENABLE; -} - -static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) -{ - uint32_t val; - - if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) - return false; - - val = I915_READ(SPLL_CTL); - hw_state->spll = val; - - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); - - return val & SPLL_PLL_ENABLE; -} - - -static const char * const hsw_ddi_pll_names[] = { - "WRPLL 1", - "WRPLL 2", - "SPLL" -}; - -static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv) -{ - int i; - - dev_priv->num_shared_dpll = 3; - - for (i = 0; i < 2; i++) { - dev_priv->shared_dplls[i].id = i; - dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; - dev_priv->shared_dplls[i].disable = hsw_ddi_wrpll_disable; - dev_priv->shared_dplls[i].enable = hsw_ddi_wrpll_enable; - dev_priv->shared_dplls[i].get_hw_state = - hsw_ddi_wrpll_get_hw_state; - } - - /* SPLL is special, but needs to be initialized anyway.. */ - dev_priv->shared_dplls[i].id = i; - dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; - dev_priv->shared_dplls[i].disable = hsw_ddi_spll_disable; - dev_priv->shared_dplls[i].enable = hsw_ddi_spll_enable; - dev_priv->shared_dplls[i].get_hw_state = hsw_ddi_spll_get_hw_state; - -} - -static const char * const skl_ddi_pll_names[] = { - "DPLL 1", - "DPLL 2", - "DPLL 3", -}; - -struct skl_dpll_regs { - i915_reg_t ctl, cfgcr1, cfgcr2; -}; - -/* this array is indexed by the *shared* pll id */ -static const struct skl_dpll_regs skl_dpll_regs[3] = { - { - /* DPLL 1 */ - .ctl = LCPLL2_CTL, - .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1), - .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1), - }, - { - /* DPLL 2 */ - .ctl = WRPLL_CTL(0), - .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2), - .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2), - }, - { - /* DPLL 3 */ - .ctl = WRPLL_CTL(1), - .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3), - .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3), - }, -}; - -static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - uint32_t val; - unsigned int dpll; - const struct skl_dpll_regs *regs = skl_dpll_regs; - - /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ - dpll = pll->id + 1; - - val = I915_READ(DPLL_CTRL1); - - val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) | - DPLL_CTRL1_LINK_RATE_MASK(dpll)); - val |= pll->config.hw_state.ctrl1 << (dpll * 6); - - I915_WRITE(DPLL_CTRL1, val); - POSTING_READ(DPLL_CTRL1); - - I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1); - I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2); - POSTING_READ(regs[pll->id].cfgcr1); - POSTING_READ(regs[pll->id].cfgcr2); - - /* the enable bit is always bit 31 */ - I915_WRITE(regs[pll->id].ctl, - I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE); - - if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5)) - DRM_ERROR("DPLL %d not locked\n", dpll); -} - -static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - const struct skl_dpll_regs *regs = skl_dpll_regs; - - /* the enable bit is always bit 31 */ - I915_WRITE(regs[pll->id].ctl, - I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE); - POSTING_READ(regs[pll->id].ctl); -} - -static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) -{ - uint32_t val; - unsigned int dpll; - const struct skl_dpll_regs *regs = skl_dpll_regs; - bool ret; - - if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) - return false; - - ret = false; - - /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ - dpll = pll->id + 1; - - val = I915_READ(regs[pll->id].ctl); - if (!(val & LCPLL_PLL_ENABLE)) - goto out; - - val = I915_READ(DPLL_CTRL1); - hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f; - - /* avoid reading back stale values if HDMI mode is not enabled */ - if (val & DPLL_CTRL1_HDMI_MODE(dpll)) { - hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1); - hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2); - } - ret = true; - -out: - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); - - return ret; -} - -static void skl_shared_dplls_init(struct drm_i915_private *dev_priv) -{ - int i; - - dev_priv->num_shared_dpll = 3; - - for (i = 0; i < dev_priv->num_shared_dpll; i++) { - dev_priv->shared_dplls[i].id = i; - dev_priv->shared_dplls[i].name = skl_ddi_pll_names[i]; - dev_priv->shared_dplls[i].disable = skl_ddi_pll_disable; - dev_priv->shared_dplls[i].enable = skl_ddi_pll_enable; - dev_priv->shared_dplls[i].get_hw_state = - skl_ddi_pll_get_hw_state; - } -} - static void broxton_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) { @@ -2783,249 +2554,6 @@ void broxton_ddi_phy_uninit(struct drm_device *dev) I915_WRITE(BXT_P_CR_GT_DISP_PWRON, 0); } -static const char * const bxt_ddi_pll_names[] = { - "PORT PLL A", - "PORT PLL B", - "PORT PLL C", -}; - -static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - uint32_t temp; - enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ - - temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); - temp &= ~PORT_PLL_REF_SEL; - /* Non-SSC reference */ - I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); - - /* Disable 10 bit clock */ - temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); - temp &= ~PORT_PLL_10BIT_CLK_ENABLE; - I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); - - /* Write P1 & P2 */ - temp = I915_READ(BXT_PORT_PLL_EBB_0(port)); - temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK); - temp |= pll->config.hw_state.ebb0; - I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp); - - /* Write M2 integer */ - temp = I915_READ(BXT_PORT_PLL(port, 0)); - temp &= ~PORT_PLL_M2_MASK; - temp |= pll->config.hw_state.pll0; - I915_WRITE(BXT_PORT_PLL(port, 0), temp); - - /* Write N */ - temp = I915_READ(BXT_PORT_PLL(port, 1)); - temp &= ~PORT_PLL_N_MASK; - temp |= pll->config.hw_state.pll1; - I915_WRITE(BXT_PORT_PLL(port, 1), temp); - - /* Write M2 fraction */ - temp = I915_READ(BXT_PORT_PLL(port, 2)); - temp &= ~PORT_PLL_M2_FRAC_MASK; - temp |= pll->config.hw_state.pll2; - I915_WRITE(BXT_PORT_PLL(port, 2), temp); - - /* Write M2 fraction enable */ - temp = I915_READ(BXT_PORT_PLL(port, 3)); - temp &= ~PORT_PLL_M2_FRAC_ENABLE; - temp |= pll->config.hw_state.pll3; - I915_WRITE(BXT_PORT_PLL(port, 3), temp); - - /* Write coeff */ - temp = I915_READ(BXT_PORT_PLL(port, 6)); - temp &= ~PORT_PLL_PROP_COEFF_MASK; - temp &= ~PORT_PLL_INT_COEFF_MASK; - temp &= ~PORT_PLL_GAIN_CTL_MASK; - temp |= pll->config.hw_state.pll6; - I915_WRITE(BXT_PORT_PLL(port, 6), temp); - - /* Write calibration val */ - temp = I915_READ(BXT_PORT_PLL(port, 8)); - temp &= ~PORT_PLL_TARGET_CNT_MASK; - temp |= pll->config.hw_state.pll8; - I915_WRITE(BXT_PORT_PLL(port, 8), temp); - - temp = I915_READ(BXT_PORT_PLL(port, 9)); - temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK; - temp |= pll->config.hw_state.pll9; - I915_WRITE(BXT_PORT_PLL(port, 9), temp); - - temp = I915_READ(BXT_PORT_PLL(port, 10)); - temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H; - temp &= ~PORT_PLL_DCO_AMP_MASK; - temp |= pll->config.hw_state.pll10; - I915_WRITE(BXT_PORT_PLL(port, 10), temp); - - /* Recalibrate with new settings */ - temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); - temp |= PORT_PLL_RECALIBRATE; - I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); - temp &= ~PORT_PLL_10BIT_CLK_ENABLE; - temp |= pll->config.hw_state.ebb4; - I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); - - /* Enable PLL */ - temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); - temp |= PORT_PLL_ENABLE; - I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); - POSTING_READ(BXT_PORT_PLL_ENABLE(port)); - - if (wait_for_atomic_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & - PORT_PLL_LOCK), 200)) - DRM_ERROR("PLL %d not locked\n", port); - - /* - * While we write to the group register to program all lanes at once we - * can read only lane registers and we pick lanes 0/1 for that. - */ - temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); - temp &= ~LANE_STAGGER_MASK; - temp &= ~LANESTAGGER_STRAP_OVRD; - temp |= pll->config.hw_state.pcsdw12; - I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp); -} - -static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) -{ - enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ - uint32_t temp; - - temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); - temp &= ~PORT_PLL_ENABLE; - I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); - POSTING_READ(BXT_PORT_PLL_ENABLE(port)); -} - -static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) -{ - enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ - uint32_t val; - bool ret; - - if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) - return false; - - ret = false; - - val = I915_READ(BXT_PORT_PLL_ENABLE(port)); - if (!(val & PORT_PLL_ENABLE)) - goto out; - - hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port)); - hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK; - - hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port)); - hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE; - - hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0)); - hw_state->pll0 &= PORT_PLL_M2_MASK; - - hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1)); - hw_state->pll1 &= PORT_PLL_N_MASK; - - hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2)); - hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK; - - hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3)); - hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE; - - hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6)); - hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK | - PORT_PLL_INT_COEFF_MASK | - PORT_PLL_GAIN_CTL_MASK; - - hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8)); - hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK; - - hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9)); - hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK; - - hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10)); - hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H | - PORT_PLL_DCO_AMP_MASK; - - /* - * While we write to the group register to program all lanes at once we - * can read only lane registers. We configure all lanes the same way, so - * 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) - 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))); - hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD; - - ret = true; - -out: - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); - - return ret; -} - -static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv) -{ - int i; - - dev_priv->num_shared_dpll = 3; - - for (i = 0; i < dev_priv->num_shared_dpll; i++) { - dev_priv->shared_dplls[i].id = i; - dev_priv->shared_dplls[i].name = bxt_ddi_pll_names[i]; - dev_priv->shared_dplls[i].disable = bxt_ddi_pll_disable; - dev_priv->shared_dplls[i].enable = bxt_ddi_pll_enable; - dev_priv->shared_dplls[i].get_hw_state = - bxt_ddi_pll_get_hw_state; - } -} - -void intel_ddi_pll_init(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t val = I915_READ(LCPLL_CTL); - - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) - skl_shared_dplls_init(dev_priv); - else if (IS_BROXTON(dev)) - bxt_shared_dplls_init(dev_priv); - else - hsw_shared_dplls_init(dev_priv); - - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { - int cdclk_freq; - - cdclk_freq = dev_priv->display.get_display_clock_speed(dev); - dev_priv->skl_boot_cdclk = cdclk_freq; - if (skl_sanitize_cdclk(dev_priv)) - DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n"); - if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) - DRM_ERROR("LCPLL1 is disabled\n"); - } else if (IS_BROXTON(dev)) { - broxton_init_cdclk(dev); - broxton_ddi_phy_init(dev); - } else { - /* - * The LCPLL register should be turned on by the BIOS. For now - * let's just check its state and print errors in case - * something is wrong. Don't even try to turn it on. - */ - - if (val & LCPLL_CD_SOURCE_FCLK) - DRM_ERROR("CDCLK source is not LCPLL\n"); - - if (val & LCPLL_PLL_DISABLE) - DRM_ERROR("LCPLL is disabled\n"); - } -} - void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index d7ebac6..6be0cd0 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -353,6 +353,478 @@ static void ibx_pch_dpll_init(struct drm_device *dev) } } +static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll); + POSTING_READ(WRPLL_CTL(pll->id)); + udelay(20); +} + +static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + I915_WRITE(SPLL_CTL, pll->config.hw_state.spll); + POSTING_READ(SPLL_CTL); + udelay(20); +} + +static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + uint32_t val; + + val = I915_READ(WRPLL_CTL(pll->id)); + I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE); + POSTING_READ(WRPLL_CTL(pll->id)); +} + +static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + uint32_t val; + + val = I915_READ(SPLL_CTL); + I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE); + POSTING_READ(SPLL_CTL); +} + +static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + uint32_t val; + + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) + return false; + + val = I915_READ(WRPLL_CTL(pll->id)); + hw_state->wrpll = val; + + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return val & WRPLL_PLL_ENABLE; +} + +static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + uint32_t val; + + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) + return false; + + val = I915_READ(SPLL_CTL); + hw_state->spll = val; + + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return val & SPLL_PLL_ENABLE; +} + + +static const char * const hsw_ddi_pll_names[] = { + "WRPLL 1", + "WRPLL 2", + "SPLL" +}; + +static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv) +{ + int i; + + dev_priv->num_shared_dpll = 3; + + for (i = 0; i < 2; i++) { + dev_priv->shared_dplls[i].id = i; + dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; + dev_priv->shared_dplls[i].disable = hsw_ddi_wrpll_disable; + dev_priv->shared_dplls[i].enable = hsw_ddi_wrpll_enable; + dev_priv->shared_dplls[i].get_hw_state = + hsw_ddi_wrpll_get_hw_state; + } + + /* SPLL is special, but needs to be initialized anyway.. */ + dev_priv->shared_dplls[i].id = i; + dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; + dev_priv->shared_dplls[i].disable = hsw_ddi_spll_disable; + dev_priv->shared_dplls[i].enable = hsw_ddi_spll_enable; + dev_priv->shared_dplls[i].get_hw_state = hsw_ddi_spll_get_hw_state; + +} + +static const char * const skl_ddi_pll_names[] = { + "DPLL 1", + "DPLL 2", + "DPLL 3", +}; + +struct skl_dpll_regs { + i915_reg_t ctl, cfgcr1, cfgcr2; +}; + +/* this array is indexed by the *shared* pll id */ +static const struct skl_dpll_regs skl_dpll_regs[3] = { + { + /* DPLL 1 */ + .ctl = LCPLL2_CTL, + .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1), + .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1), + }, + { + /* DPLL 2 */ + .ctl = WRPLL_CTL(0), + .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2), + .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2), + }, + { + /* DPLL 3 */ + .ctl = WRPLL_CTL(1), + .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3), + .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3), + }, +}; + +static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + uint32_t val; + unsigned int dpll; + const struct skl_dpll_regs *regs = skl_dpll_regs; + + /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ + dpll = pll->id + 1; + + val = I915_READ(DPLL_CTRL1); + + val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) | + DPLL_CTRL1_LINK_RATE_MASK(dpll)); + val |= pll->config.hw_state.ctrl1 << (dpll * 6); + + I915_WRITE(DPLL_CTRL1, val); + POSTING_READ(DPLL_CTRL1); + + I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1); + I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2); + POSTING_READ(regs[pll->id].cfgcr1); + POSTING_READ(regs[pll->id].cfgcr2); + + /* the enable bit is always bit 31 */ + I915_WRITE(regs[pll->id].ctl, + I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE); + + if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5)) + DRM_ERROR("DPLL %d not locked\n", dpll); +} + +static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + const struct skl_dpll_regs *regs = skl_dpll_regs; + + /* the enable bit is always bit 31 */ + I915_WRITE(regs[pll->id].ctl, + I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE); + POSTING_READ(regs[pll->id].ctl); +} + +static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + uint32_t val; + unsigned int dpll; + const struct skl_dpll_regs *regs = skl_dpll_regs; + bool ret; + + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) + return false; + + ret = false; + + /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ + dpll = pll->id + 1; + + val = I915_READ(regs[pll->id].ctl); + if (!(val & LCPLL_PLL_ENABLE)) + goto out; + + val = I915_READ(DPLL_CTRL1); + hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f; + + /* avoid reading back stale values if HDMI mode is not enabled */ + if (val & DPLL_CTRL1_HDMI_MODE(dpll)) { + hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1); + hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2); + } + ret = true; + +out: + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return ret; +} + +static void skl_shared_dplls_init(struct drm_i915_private *dev_priv) +{ + int i; + + dev_priv->num_shared_dpll = 3; + + for (i = 0; i < dev_priv->num_shared_dpll; i++) { + dev_priv->shared_dplls[i].id = i; + dev_priv->shared_dplls[i].name = skl_ddi_pll_names[i]; + dev_priv->shared_dplls[i].disable = skl_ddi_pll_disable; + dev_priv->shared_dplls[i].enable = skl_ddi_pll_enable; + dev_priv->shared_dplls[i].get_hw_state = + skl_ddi_pll_get_hw_state; + } +} + +static const char * const bxt_ddi_pll_names[] = { + "PORT PLL A", + "PORT PLL B", + "PORT PLL C", +}; + +static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + uint32_t temp; + enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ + + temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); + temp &= ~PORT_PLL_REF_SEL; + /* Non-SSC reference */ + I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); + + /* Disable 10 bit clock */ + temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); + temp &= ~PORT_PLL_10BIT_CLK_ENABLE; + I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + + /* Write P1 & P2 */ + temp = I915_READ(BXT_PORT_PLL_EBB_0(port)); + temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK); + temp |= pll->config.hw_state.ebb0; + I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp); + + /* Write M2 integer */ + temp = I915_READ(BXT_PORT_PLL(port, 0)); + temp &= ~PORT_PLL_M2_MASK; + temp |= pll->config.hw_state.pll0; + I915_WRITE(BXT_PORT_PLL(port, 0), temp); + + /* Write N */ + temp = I915_READ(BXT_PORT_PLL(port, 1)); + temp &= ~PORT_PLL_N_MASK; + temp |= pll->config.hw_state.pll1; + I915_WRITE(BXT_PORT_PLL(port, 1), temp); + + /* Write M2 fraction */ + temp = I915_READ(BXT_PORT_PLL(port, 2)); + temp &= ~PORT_PLL_M2_FRAC_MASK; + temp |= pll->config.hw_state.pll2; + I915_WRITE(BXT_PORT_PLL(port, 2), temp); + + /* Write M2 fraction enable */ + temp = I915_READ(BXT_PORT_PLL(port, 3)); + temp &= ~PORT_PLL_M2_FRAC_ENABLE; + temp |= pll->config.hw_state.pll3; + I915_WRITE(BXT_PORT_PLL(port, 3), temp); + + /* Write coeff */ + temp = I915_READ(BXT_PORT_PLL(port, 6)); + temp &= ~PORT_PLL_PROP_COEFF_MASK; + temp &= ~PORT_PLL_INT_COEFF_MASK; + temp &= ~PORT_PLL_GAIN_CTL_MASK; + temp |= pll->config.hw_state.pll6; + I915_WRITE(BXT_PORT_PLL(port, 6), temp); + + /* Write calibration val */ + temp = I915_READ(BXT_PORT_PLL(port, 8)); + temp &= ~PORT_PLL_TARGET_CNT_MASK; + temp |= pll->config.hw_state.pll8; + I915_WRITE(BXT_PORT_PLL(port, 8), temp); + + temp = I915_READ(BXT_PORT_PLL(port, 9)); + temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK; + temp |= pll->config.hw_state.pll9; + I915_WRITE(BXT_PORT_PLL(port, 9), temp); + + temp = I915_READ(BXT_PORT_PLL(port, 10)); + temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H; + temp &= ~PORT_PLL_DCO_AMP_MASK; + temp |= pll->config.hw_state.pll10; + I915_WRITE(BXT_PORT_PLL(port, 10), temp); + + /* Recalibrate with new settings */ + temp = I915_READ(BXT_PORT_PLL_EBB_4(port)); + temp |= PORT_PLL_RECALIBRATE; + I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + temp &= ~PORT_PLL_10BIT_CLK_ENABLE; + temp |= pll->config.hw_state.ebb4; + I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp); + + /* Enable PLL */ + temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); + temp |= PORT_PLL_ENABLE; + I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); + POSTING_READ(BXT_PORT_PLL_ENABLE(port)); + + if (wait_for_atomic_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & + PORT_PLL_LOCK), 200)) + DRM_ERROR("PLL %d not locked\n", port); + + /* + * While we write to the group register to program all lanes at once we + * can read only lane registers and we pick lanes 0/1 for that. + */ + temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port)); + temp &= ~LANE_STAGGER_MASK; + temp &= ~LANESTAGGER_STRAP_OVRD; + temp |= pll->config.hw_state.pcsdw12; + I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp); +} + +static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ + uint32_t temp; + + temp = I915_READ(BXT_PORT_PLL_ENABLE(port)); + temp &= ~PORT_PLL_ENABLE; + I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp); + POSTING_READ(BXT_PORT_PLL_ENABLE(port)); +} + +static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */ + uint32_t val; + bool ret; + + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) + return false; + + ret = false; + + val = I915_READ(BXT_PORT_PLL_ENABLE(port)); + if (!(val & PORT_PLL_ENABLE)) + goto out; + + hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port)); + hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK; + + hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port)); + hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE; + + hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0)); + hw_state->pll0 &= PORT_PLL_M2_MASK; + + hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1)); + hw_state->pll1 &= PORT_PLL_N_MASK; + + hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2)); + hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK; + + hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3)); + hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE; + + hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6)); + hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK | + PORT_PLL_INT_COEFF_MASK | + PORT_PLL_GAIN_CTL_MASK; + + hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8)); + hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK; + + hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9)); + hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK; + + hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10)); + hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H | + PORT_PLL_DCO_AMP_MASK; + + /* + * While we write to the group register to program all lanes at once we + * can read only lane registers. We configure all lanes the same way, so + * 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) + 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))); + hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD; + + ret = true; + +out: + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return ret; +} + +static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv) +{ + int i; + + dev_priv->num_shared_dpll = 3; + + for (i = 0; i < dev_priv->num_shared_dpll; i++) { + dev_priv->shared_dplls[i].id = i; + dev_priv->shared_dplls[i].name = bxt_ddi_pll_names[i]; + dev_priv->shared_dplls[i].disable = bxt_ddi_pll_disable; + dev_priv->shared_dplls[i].enable = bxt_ddi_pll_enable; + dev_priv->shared_dplls[i].get_hw_state = + bxt_ddi_pll_get_hw_state; + } +} + +static void intel_ddi_pll_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t val = I915_READ(LCPLL_CTL); + + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) + skl_shared_dplls_init(dev_priv); + else if (IS_BROXTON(dev)) + bxt_shared_dplls_init(dev_priv); + else + hsw_shared_dplls_init(dev_priv); + + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { + int cdclk_freq; + + cdclk_freq = dev_priv->display.get_display_clock_speed(dev); + dev_priv->skl_boot_cdclk = cdclk_freq; + if (skl_sanitize_cdclk(dev_priv)) + DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n"); + if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE)) + DRM_ERROR("LCPLL1 is disabled\n"); + } else if (IS_BROXTON(dev)) { + broxton_init_cdclk(dev); + broxton_ddi_phy_init(dev); + } else { + /* + * The LCPLL register should be turned on by the BIOS. For now + * let's just check its state and print errors in case + * something is wrong. Don't even try to turn it on. + */ + + if (val & LCPLL_CD_SOURCE_FCLK) + DRM_ERROR("CDCLK source is not LCPLL\n"); + + if (val & LCPLL_PLL_DISABLE) + DRM_ERROR("LCPLL is disabled\n"); + } +} + void intel_shared_dpll_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 63b36b5..94aaad9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1066,7 +1066,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc); void intel_ddi_init(struct drm_device *dev, enum port port); enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder); bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe); -void intel_ddi_pll_init(struct drm_device *dev); void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc); void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder); -- cgit v0.10.2 From a4780b7744c2833ba762d64576f661a9dae045f1 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:17 +0200 Subject: drm/i915: Split intel_get_shared_dpll() into smaller functions Make the code neater by splitting the code for platforms with fixed PLL to their own functions and splitting the logic for finding a shareable or unused pll from the logic for setting it up. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-4-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 6be0cd0..11effe3 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -145,52 +145,65 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); } -struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) +static enum intel_dpll_id +ibx_get_fixed_dpll(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll; - struct intel_shared_dpll_config *shared_dpll; enum intel_dpll_id i; - int max = dev_priv->num_shared_dpll; - shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); + /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ + i = (enum intel_dpll_id) crtc->pipe; + pll = &dev_priv->shared_dplls[i]; - if (HAS_PCH_IBX(dev_priv->dev)) { - /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ - i = (enum intel_dpll_id) crtc->pipe; - pll = &dev_priv->shared_dplls[i]; + DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", + crtc->base.base.id, pll->name); - DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", - crtc->base.base.id, pll->name); + return i; +} - WARN_ON(shared_dpll[i].crtc_mask); +static enum intel_dpll_id +bxt_get_fixed_dpll(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_encoder *encoder; + struct intel_digital_port *intel_dig_port; + struct intel_shared_dpll *pll; + enum intel_dpll_id i; - goto found; - } + /* PLL is attached to port in bxt */ + encoder = intel_ddi_get_crtc_new_encoder(crtc_state); + if (WARN_ON(!encoder)) + return DPLL_ID_PRIVATE; - if (IS_BROXTON(dev_priv->dev)) { - /* PLL is attached to port in bxt */ - struct intel_encoder *encoder; - struct intel_digital_port *intel_dig_port; + intel_dig_port = enc_to_dig_port(&encoder->base); + /* 1:1 mapping between ports and PLLs */ + i = (enum intel_dpll_id)intel_dig_port->port; + pll = &dev_priv->shared_dplls[i]; + DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", + crtc->base.base.id, pll->name); - encoder = intel_ddi_get_crtc_new_encoder(crtc_state); - if (WARN_ON(!encoder)) - return NULL; + return i; +} - intel_dig_port = enc_to_dig_port(&encoder->base); - /* 1:1 mapping between ports and PLLs */ - i = (enum intel_dpll_id)intel_dig_port->port; - pll = &dev_priv->shared_dplls[i]; - DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", - crtc->base.base.id, pll->name); - WARN_ON(shared_dpll[i].crtc_mask); +static enum intel_dpll_id +intel_find_shared_dpll(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_shared_dpll *pll; + struct intel_shared_dpll_config *shared_dpll; + enum intel_dpll_id i; + int max = dev_priv->num_shared_dpll; - goto found; - } else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv)) + if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv)) /* Do not consider SPLL */ max = 2; + shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); + for (i = 0; i < max; i++) { pll = &dev_priv->shared_dplls[i]; @@ -205,7 +218,7 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, crtc->base.base.id, pll->name, shared_dpll[i].crtc_mask, pll->active); - goto found; + return i; } } @@ -215,13 +228,39 @@ struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, if (shared_dpll[i].crtc_mask == 0) { DRM_DEBUG_KMS("CRTC:%d allocated %s\n", crtc->base.base.id, pll->name); - goto found; + return i; } } - return NULL; + return DPLL_ID_PRIVATE; +} + +struct intel_shared_dpll * +intel_get_shared_dpll(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + struct intel_shared_dpll *pll; + struct intel_shared_dpll_config *shared_dpll; + enum intel_dpll_id i; + + shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); + + if (HAS_PCH_IBX(dev_priv->dev)) { + i = ibx_get_fixed_dpll(crtc, crtc_state); + WARN_ON(shared_dpll[i].crtc_mask); + } else if (IS_BROXTON(dev_priv->dev)) { + i = bxt_get_fixed_dpll(crtc, crtc_state); + WARN_ON(shared_dpll[i].crtc_mask); + } else { + i = intel_find_shared_dpll(crtc, crtc_state); + } + + if (i < 0) + return NULL; + + pll = &dev_priv->shared_dplls[i]; -found: if (shared_dpll[i].crtc_mask == 0) shared_dpll[i].hw_state = crtc_state->dpll_hw_state; -- cgit v0.10.2 From 8106ddbd7733f31205007f97be0866b408772907 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:18 +0200 Subject: drm/i915: Store a direct pointer to shared dpll in intel_crtc_state Change the type of intel_crtc_state->shared_dpll to be a pointer to a shared dpll. With this there is no need to first convert the id stored in the crtc state to a pointer in order to use it. It does introduce a bit of hassle on doing the opposite. The long term objective is to hide details about dpll ids behind the shared dpll interface. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-5-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 54880662..b6af5c0 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1209,6 +1209,7 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state, struct intel_encoder *intel_encoder) { + struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); int clock = crtc_state->port_clock; if (intel_encoder->type == INTEL_OUTPUT_HDMI) { @@ -1244,7 +1245,8 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc, WARN_ON(spll->hw_state.spll != crtc_state->dpll_hw_state.spll)) return false; - crtc_state->shared_dpll = DPLL_ID_SPLL; + crtc_state->shared_dpll = + intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_SPLL); spll->hw_state.spll = crtc_state->dpll_hw_state.spll; spll->crtc_mask |= 1 << intel_crtc->pipe; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1d5695d..579da41 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1843,8 +1843,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, BUG_ON(!HAS_PCH_SPLIT(dev)); /* Make sure PCH DPLL is enabled */ - assert_shared_dpll_enabled(dev_priv, - intel_crtc_to_shared_dpll(intel_crtc)); + assert_shared_dpll_enabled(dev_priv, intel_crtc->config->shared_dpll); /* FDI must be feeding us bits for PCH ports */ assert_fdi_tx_enabled(dev_priv, pipe); @@ -4147,7 +4146,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) temp = I915_READ(PCH_DPLL_SEL); temp |= TRANS_DPLL_ENABLE(pipe); sel = TRANS_DPLLB_SEL(pipe); - if (intel_crtc->config->shared_dpll == DPLL_ID_PCH_PLL_B) + if (intel_crtc->config->shared_dpll == + intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B)) temp |= sel; else temp &= ~sel; @@ -4883,7 +4883,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A, false); - if (intel_crtc_to_shared_dpll(intel_crtc)) + if (intel_crtc->config->shared_dpll) intel_enable_shared_dpll(intel_crtc); if (intel_crtc->config->has_dp_encoder) @@ -8052,7 +8052,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, return false; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; - pipe_config->shared_dpll = DPLL_ID_PRIVATE; + pipe_config->shared_dpll = NULL; ret = false; @@ -9256,7 +9256,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, return false; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; - pipe_config->shared_dpll = DPLL_ID_PRIVATE; + pipe_config->shared_dpll = NULL; ret = false; tmp = I915_READ(PIPECONF(crtc->pipe)); @@ -9285,6 +9285,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { struct intel_shared_dpll *pll; + enum intel_dpll_id pll_id; pipe_config->has_pch_encoder = true; @@ -9295,17 +9296,18 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, ironlake_get_fdi_m_n_config(crtc, pipe_config); if (HAS_PCH_IBX(dev_priv->dev)) { - pipe_config->shared_dpll = - (enum intel_dpll_id) crtc->pipe; + pll_id = (enum intel_dpll_id) crtc->pipe; } else { tmp = I915_READ(PCH_DPLL_SEL); if (tmp & TRANS_DPLLB_SEL(crtc->pipe)) - pipe_config->shared_dpll = DPLL_ID_PCH_PLL_B; + pll_id = DPLL_ID_PCH_PLL_B; else - pipe_config->shared_dpll = DPLL_ID_PCH_PLL_A; + pll_id= DPLL_ID_PCH_PLL_A; } - pll = &dev_priv->shared_dplls[pipe_config->shared_dpll]; + pipe_config->shared_dpll = + intel_get_shared_dpll_by_id(dev_priv, pll_id); + pll = pipe_config->shared_dpll; WARN_ON(!pll->get_hw_state(dev_priv, pll, &pipe_config->dpll_hw_state)); @@ -9741,28 +9743,34 @@ static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) { + enum intel_dpll_id id; + switch (port) { case PORT_A: pipe_config->ddi_pll_sel = SKL_DPLL0; - pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1; + id = DPLL_ID_SKL_DPLL1; break; case PORT_B: pipe_config->ddi_pll_sel = SKL_DPLL1; - pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2; + id = DPLL_ID_SKL_DPLL2; break; case PORT_C: pipe_config->ddi_pll_sel = SKL_DPLL2; - pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3; + id = DPLL_ID_SKL_DPLL3; break; default: DRM_ERROR("Incorrect port type\n"); + return; } + + pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); } static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) { + enum intel_dpll_id id; u32 temp, dpll_ctl1; temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); @@ -9777,36 +9785,53 @@ static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, */ dpll_ctl1 = I915_READ(DPLL_CTRL1); pipe_config->dpll_hw_state.ctrl1 = dpll_ctl1 & 0x3f; - break; + return; case SKL_DPLL1: - pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1; + id = DPLL_ID_SKL_DPLL1; break; case SKL_DPLL2: - pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2; + id = DPLL_ID_SKL_DPLL2; break; case SKL_DPLL3: - pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3; + id = DPLL_ID_SKL_DPLL3; break; + default: + MISSING_CASE(pipe_config->ddi_pll_sel); + return; } + + pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); } static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, struct intel_crtc_state *pipe_config) { + enum intel_dpll_id id; + pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port)); switch (pipe_config->ddi_pll_sel) { case PORT_CLK_SEL_WRPLL1: - pipe_config->shared_dpll = DPLL_ID_WRPLL1; + id = DPLL_ID_WRPLL1; break; case PORT_CLK_SEL_WRPLL2: - pipe_config->shared_dpll = DPLL_ID_WRPLL2; + id = DPLL_ID_WRPLL2; break; case PORT_CLK_SEL_SPLL: - pipe_config->shared_dpll = DPLL_ID_SPLL; + id = DPLL_ID_SPLL; break; + default: + MISSING_CASE(pipe_config->ddi_pll_sel); + /* fall through */ + case PORT_CLK_SEL_NONE: + case PORT_CLK_SEL_LCPLL_810: + case PORT_CLK_SEL_LCPLL_1350: + case PORT_CLK_SEL_LCPLL_2700: + return; } + + pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); } static void haswell_get_ddi_port_state(struct intel_crtc *crtc, @@ -9829,9 +9854,8 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, else haswell_get_ddi_pll(dev_priv, port, pipe_config); - if (pipe_config->shared_dpll >= 0) { - pll = &dev_priv->shared_dplls[pipe_config->shared_dpll]; - + pll = pipe_config->shared_dpll; + if (pll) { WARN_ON(!pll->get_hw_state(dev_priv, pll, &pipe_config->dpll_hw_state)); } @@ -9871,7 +9895,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, ret = false; pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; - pipe_config->shared_dpll = DPLL_ID_PRIVATE; + pipe_config->shared_dpll = NULL; tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); if (tmp & TRANS_DDI_FUNC_ENABLE) { @@ -11868,7 +11892,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, if (mode_changed && crtc_state->enable && dev_priv->display.crtc_compute_clock && - !WARN_ON(pipe_config->shared_dpll != DPLL_ID_PRIVATE)) { + !WARN_ON(pipe_config->shared_dpll)) { ret = dev_priv->display.crtc_compute_clock(intel_crtc, pipe_config); if (ret) @@ -12213,7 +12237,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state) struct drm_crtc_state tmp_state; struct intel_crtc_scaler_state scaler_state; struct intel_dpll_hw_state dpll_hw_state; - enum intel_dpll_id shared_dpll; + struct intel_shared_dpll *shared_dpll; uint32_t ddi_pll_sel; bool force_thru; @@ -12483,6 +12507,15 @@ intel_pipe_config_compare(struct drm_device *dev, ret = false; \ } +#define PIPE_CONF_CHECK_P(name) \ + if (current_config->name != pipe_config->name) { \ + INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \ + "(expected %p, found %p)\n", \ + current_config->name, \ + pipe_config->name); \ + ret = false; \ + } + #define PIPE_CONF_CHECK_M_N(name) \ if (!intel_compare_link_m_n(¤t_config->name, \ &pipe_config->name,\ @@ -12650,7 +12683,7 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_X(ddi_pll_sel); - PIPE_CONF_CHECK_I(shared_dpll); + PIPE_CONF_CHECK_P(shared_dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll); PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md); PIPE_CONF_CHECK_X(dpll_hw_state.fp0); @@ -12669,6 +12702,7 @@ intel_pipe_config_compare(struct drm_device *dev, #undef PIPE_CONF_CHECK_X #undef PIPE_CONF_CHECK_I +#undef PIPE_CONF_CHECK_P #undef PIPE_CONF_CHECK_I_ALT #undef PIPE_CONF_CHECK_FLAGS #undef PIPE_CONF_CHECK_CLOCK_FUZZY @@ -12892,7 +12926,8 @@ check_shared_dpll_state(struct drm_device *dev) int i; for (i = 0; i < dev_priv->num_shared_dpll; i++) { - struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; + struct intel_shared_dpll *pll = + intel_get_shared_dpll_by_id(dev_priv, i); int enabled_crtcs = 0, active_crtcs = 0; bool active; @@ -12914,9 +12949,9 @@ check_shared_dpll_state(struct drm_device *dev) pll->on, active); for_each_intel_crtc(dev, crtc) { - if (crtc->base.state->enable && intel_crtc_to_shared_dpll(crtc) == pll) + if (crtc->base.state->enable && crtc->config->shared_dpll == pll) enabled_crtcs++; - if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) + if (crtc->active && crtc->config->shared_dpll == pll) active_crtcs++; } I915_STATE_WARN(pll->active != active_crtcs, @@ -12995,20 +13030,21 @@ static void intel_modeset_clear_plls(struct drm_atomic_state *state) for_each_crtc_in_state(state, crtc, crtc_state, i) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int old_dpll = to_intel_crtc_state(crtc->state)->shared_dpll; + struct intel_shared_dpll *old_dpll = + to_intel_crtc_state(crtc->state)->shared_dpll; if (!needs_modeset(crtc_state)) continue; - to_intel_crtc_state(crtc_state)->shared_dpll = DPLL_ID_PRIVATE; + to_intel_crtc_state(crtc_state)->shared_dpll = NULL; - if (old_dpll == DPLL_ID_PRIVATE) + if (!old_dpll) continue; if (!shared_dpll) shared_dpll = intel_atomic_get_shared_dpll_state(state); - shared_dpll[old_dpll].crtc_mask &= ~(1 << intel_crtc->pipe); + intel_shared_dpll_config_put(shared_dpll, old_dpll, intel_crtc); } } @@ -15655,7 +15691,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) pll->active = 0; pll->config.crtc_mask = 0; for_each_intel_crtc(dev, crtc) { - if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) { + if (crtc->active && crtc->config->shared_dpll == pll) { pll->active++; pll->config.crtc_mask |= 1 << crtc->pipe; } diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 11effe3..889ceed 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -24,14 +24,43 @@ #include "intel_drv.h" struct intel_shared_dpll * -intel_crtc_to_shared_dpll(struct intel_crtc *crtc) +intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv, + enum intel_dpll_id id) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; + return &dev_priv->shared_dplls[id]; +} - if (crtc->config->shared_dpll < 0) - return NULL; +enum intel_dpll_id +intel_get_shared_dpll_id(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + if (WARN_ON(pll < dev_priv->shared_dplls|| + pll > &dev_priv->shared_dplls[dev_priv->num_shared_dpll])) + return -1; + + return (enum intel_dpll_id) (pll - dev_priv->shared_dplls); +} + +void +intel_shared_dpll_config_get(struct intel_shared_dpll_config *config, + struct intel_shared_dpll *pll, + struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll); + + config[id].crtc_mask |= 1 << crtc->pipe; +} + +void +intel_shared_dpll_config_put(struct intel_shared_dpll_config *config, + struct intel_shared_dpll *pll, + struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll); - return &dev_priv->shared_dplls[crtc->config->shared_dpll]; + config[id].crtc_mask &= ~(1 << crtc->pipe); } /* For ILK+ */ @@ -55,7 +84,7 @@ void intel_prepare_shared_dpll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); + struct intel_shared_dpll *pll = crtc->config->shared_dpll; if (WARN_ON(pll == NULL)) return; @@ -82,7 +111,7 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); + struct intel_shared_dpll *pll = crtc->config->shared_dpll; if (WARN_ON(pll == NULL)) return; @@ -112,7 +141,7 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc); + struct intel_shared_dpll *pll = crtc->config->shared_dpll; /* PCH only available on ILK+ */ if (INTEL_INFO(dev)->gen < 5) @@ -265,11 +294,11 @@ intel_get_shared_dpll(struct intel_crtc *crtc, shared_dpll[i].hw_state = crtc_state->dpll_hw_state; - crtc_state->shared_dpll = i; + crtc_state->shared_dpll = pll; DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name, pipe_name(crtc->pipe)); - shared_dpll[i].crtc_mask |= 1 << crtc->pipe; + intel_shared_dpll_config_get(shared_dpll, pll, crtc); return pll; } @@ -360,7 +389,7 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, /* Make sure no transcoder isn't still depending on us. */ for_each_intel_crtc(dev, crtc) { - if (intel_crtc_to_shared_dpll(crtc) == pll) + if (crtc->config->shared_dpll == pll) assert_pch_transcoder_disabled(dev_priv, crtc->pipe); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 94aaad9..1fbf069 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -483,8 +483,8 @@ struct intel_crtc_state { * haswell. */ struct dpll dpll; - /* Selected dpll when shared or DPLL_ID_PRIVATE. */ - enum intel_dpll_id shared_dpll; + /* Selected dpll when shared or NULL. */ + struct intel_shared_dpll *shared_dpll; /* * - PORT_CLK_SEL for DDI ports on HSW/BDW. @@ -1204,7 +1204,20 @@ void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, enum pipe pipe); /* shared dpll functions */ -struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc); +struct intel_shared_dpll * +intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv, + enum intel_dpll_id id); +enum intel_dpll_id +intel_get_shared_dpll_id(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll); +void +intel_shared_dpll_config_get(struct intel_shared_dpll_config *config, + struct intel_shared_dpll *pll, + struct intel_crtc *crtc); +void +intel_shared_dpll_config_put(struct intel_shared_dpll_config *config, + struct intel_shared_dpll *pll, + struct intel_crtc *crtc); void assert_shared_dpll(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, bool state); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b35342f..cbd1b0d 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -145,7 +145,7 @@ static void intel_pre_enable_lvds(struct intel_encoder *encoder) if (HAS_PCH_SPLIT(dev)) { assert_fdi_rx_pll_disabled(dev_priv, pipe); assert_shared_dpll_disabled(dev_priv, - intel_crtc_to_shared_dpll(crtc)); + crtc->config->shared_dpll); } else { assert_pll_disabled(dev_priv, pipe); } -- cgit v0.10.2 From ac7f11c6106507f1e09a970a03904c323ae741b8 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:19 +0200 Subject: drm/i915: Move shared dpll struct definitions to separate header file Move the declarations related to shared dplls from i915_drv.h to their own header file. The code that became the shared dpll infrastructre was first introcude in commit ee7b9f93fd96 ("drm/i915: manage PCH PLLs separately from pipes"), hence the 2012-2016 copyright years in the new header file. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-6-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f37ac12..e74a61b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -53,6 +53,7 @@ #include #include #include "intel_guc.h" +#include "intel_dpll_mgr.h" /* General customization: */ @@ -340,81 +341,6 @@ struct drm_i915_file_private { unsigned int bsd_ring; }; -enum intel_dpll_id { - DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */ - /* real shared dpll ids must be >= 0 */ - DPLL_ID_PCH_PLL_A = 0, - DPLL_ID_PCH_PLL_B = 1, - /* hsw/bdw */ - DPLL_ID_WRPLL1 = 0, - DPLL_ID_WRPLL2 = 1, - DPLL_ID_SPLL = 2, - - /* skl */ - DPLL_ID_SKL_DPLL1 = 0, - DPLL_ID_SKL_DPLL2 = 1, - DPLL_ID_SKL_DPLL3 = 2, -}; -#define I915_NUM_PLLS 3 - -struct intel_dpll_hw_state { - /* i9xx, pch plls */ - uint32_t dpll; - uint32_t dpll_md; - uint32_t fp0; - uint32_t fp1; - - /* hsw, bdw */ - uint32_t wrpll; - uint32_t spll; - - /* skl */ - /* - * DPLL_CTRL1 has 6 bits for each each this DPLL. We store those in - * lower part of ctrl1 and they get shifted into position when writing - * the register. This allows us to easily compare the state to share - * the DPLL. - */ - uint32_t ctrl1; - /* HDMI only, 0 when used for DP */ - uint32_t cfgcr1, cfgcr2; - - /* bxt */ - uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, - pcsdw12; -}; - -struct intel_shared_dpll_config { - unsigned crtc_mask; /* mask of CRTCs sharing this PLL */ - struct intel_dpll_hw_state hw_state; -}; - -struct intel_shared_dpll { - struct intel_shared_dpll_config config; - - int active; /* count of number of active CRTCs (i.e. DPMS on) */ - bool on; /* is the PLL actually active? Disabled during modeset */ - const char *name; - /* should match the index in the dev_priv->shared_dplls array */ - enum intel_dpll_id id; - /* The mode_set hook is optional and should be used together with the - * intel_prepare_shared_dpll function. */ - void (*mode_set)(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll); - void (*enable)(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll); - void (*disable)(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll); - bool (*get_hw_state)(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state); -}; - -#define SKL_DPLL0 0 -#define SKL_DPLL1 1 -#define SKL_DPLL2 2 -#define SKL_DPLL3 3 - /* Used by dp and fdi links */ struct intel_link_m_n { uint32_t tu; diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h new file mode 100644 index 0000000..a62d1ba --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -0,0 +1,106 @@ +/* + * Copyright © 2012-2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _INTEL_DPLL_MGR_H_ +#define _INTEL_DPLL_MGR_H_ + +struct drm_i915_private; + +enum intel_dpll_id { + DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */ + /* real shared dpll ids must be >= 0 */ + DPLL_ID_PCH_PLL_A = 0, + DPLL_ID_PCH_PLL_B = 1, + /* hsw/bdw */ + DPLL_ID_WRPLL1 = 0, + DPLL_ID_WRPLL2 = 1, + DPLL_ID_SPLL = 2, + + /* skl */ + DPLL_ID_SKL_DPLL1 = 0, + DPLL_ID_SKL_DPLL2 = 1, + DPLL_ID_SKL_DPLL3 = 2, +}; +#define I915_NUM_PLLS 3 + +struct intel_dpll_hw_state { + /* i9xx, pch plls */ + uint32_t dpll; + uint32_t dpll_md; + uint32_t fp0; + uint32_t fp1; + + /* hsw, bdw */ + uint32_t wrpll; + uint32_t spll; + + /* skl */ + /* + * DPLL_CTRL1 has 6 bits for each each this DPLL. We store those in + * lower part of ctrl1 and they get shifted into position when writing + * the register. This allows us to easily compare the state to share + * the DPLL. + */ + uint32_t ctrl1; + /* HDMI only, 0 when used for DP */ + uint32_t cfgcr1, cfgcr2; + + /* bxt */ + uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, + pcsdw12; +}; + +struct intel_shared_dpll_config { + unsigned crtc_mask; /* mask of CRTCs sharing this PLL */ + struct intel_dpll_hw_state hw_state; +}; + +struct intel_shared_dpll { + struct intel_shared_dpll_config config; + + int active; /* count of number of active CRTCs (i.e. DPMS on) */ + bool on; /* is the PLL actually active? Disabled during modeset */ + const char *name; + /* should match the index in the dev_priv->shared_dplls array */ + enum intel_dpll_id id; + /* The mode_set hook is optional and should be used together with the + * intel_prepare_shared_dpll function. */ + void (*mode_set)(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll); + void (*enable)(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll); + void (*disable)(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll); + bool (*get_hw_state)(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state); +}; + +#define SKL_DPLL0 0 +#define SKL_DPLL1 1 +#define SKL_DPLL2 2 +#define SKL_DPLL3 3 + + +#endif /* _INTEL_DPLL_MGR_H_ */ -- cgit v0.10.2 From c2a9fcd6831aee2944f5e6d3858f56f35a2ed70a Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:20 +0200 Subject: drm/i915: Move shared dpll function prototypes to intel_dpll_mgr.h Move shared dpll function prototype together with other shared dpll definitions. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-7-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index a62d1ba..a2ecf80 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -26,6 +26,8 @@ #define _INTEL_DPLL_MGR_H_ struct drm_i915_private; +struct intel_crtc; +struct intel_crtc_state; enum intel_dpll_id { DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */ @@ -102,5 +104,33 @@ struct intel_shared_dpll { #define SKL_DPLL2 2 #define SKL_DPLL3 3 +/* shared dpll functions */ +struct intel_shared_dpll * +intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv, + enum intel_dpll_id id); +enum intel_dpll_id +intel_get_shared_dpll_id(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll); +void +intel_shared_dpll_config_get(struct intel_shared_dpll_config *config, + struct intel_shared_dpll *pll, + struct intel_crtc *crtc); +void +intel_shared_dpll_config_put(struct intel_shared_dpll_config *config, + struct intel_shared_dpll *pll, + struct intel_crtc *crtc); +void assert_shared_dpll(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + bool state); +#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true) +#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false) +struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, + struct intel_crtc_state *state); +void intel_prepare_shared_dpll(struct intel_crtc *crtc); +void intel_enable_shared_dpll(struct intel_crtc *crtc); +void intel_disable_shared_dpll(struct intel_crtc *crtc); +void intel_shared_dpll_commit(struct drm_atomic_state *state); +void intel_shared_dpll_init(struct drm_device *dev); + #endif /* _INTEL_DPLL_MGR_H_ */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1fbf069..1f62fba 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1203,34 +1203,6 @@ void intel_create_rotation_property(struct drm_device *dev, void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, enum pipe pipe); -/* shared dpll functions */ -struct intel_shared_dpll * -intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv, - enum intel_dpll_id id); -enum intel_dpll_id -intel_get_shared_dpll_id(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll); -void -intel_shared_dpll_config_get(struct intel_shared_dpll_config *config, - struct intel_shared_dpll *pll, - struct intel_crtc *crtc); -void -intel_shared_dpll_config_put(struct intel_shared_dpll_config *config, - struct intel_shared_dpll *pll, - struct intel_crtc *crtc); -void assert_shared_dpll(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll, - bool state); -#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true) -#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false) -struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, - struct intel_crtc_state *state); -void intel_prepare_shared_dpll(struct intel_crtc *crtc); -void intel_enable_shared_dpll(struct intel_crtc *crtc); -void intel_disable_shared_dpll(struct intel_crtc *crtc); -void intel_shared_dpll_commit(struct drm_atomic_state *state); -void intel_shared_dpll_init(struct drm_device *dev); - int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, const struct dpll *dpll); void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe); -- cgit v0.10.2 From 2edd6443e3d03267bfc63071a86332a1711dc1bc Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:21 +0200 Subject: drm/i915: Use a table to initilize shared dplls Use a table to store the per-platform shared dpll information in one place. This way, there is no need for platform specific init funtions. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-8-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 579da41..5852a1a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9309,8 +9309,8 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, intel_get_shared_dpll_by_id(dev_priv, pll_id); pll = pipe_config->shared_dpll; - WARN_ON(!pll->get_hw_state(dev_priv, pll, - &pipe_config->dpll_hw_state)); + WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll, + &pipe_config->dpll_hw_state)); tmp = pipe_config->dpll_hw_state.dpll; pipe_config->pixel_multiplier = @@ -9856,8 +9856,8 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, pll = pipe_config->shared_dpll; if (pll) { - WARN_ON(!pll->get_hw_state(dev_priv, pll, - &pipe_config->dpll_hw_state)); + WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll, + &pipe_config->dpll_hw_state)); } /* @@ -12935,7 +12935,7 @@ check_shared_dpll_state(struct drm_device *dev) DRM_DEBUG_KMS("%s\n", pll->name); - active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state); + active = pll->funcs.get_hw_state(dev_priv, pll, &dpll_hw_state); I915_STATE_WARN(pll->active > hweight32(pll->config.crtc_mask), "more active pll users than references: %i vs %i\n", @@ -15686,8 +15686,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) for (i = 0; i < dev_priv->num_shared_dpll; i++) { struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; - pll->on = pll->get_hw_state(dev_priv, pll, - &pll->config.hw_state); + pll->on = pll->funcs.get_hw_state(dev_priv, pll, + &pll->config.hw_state); pll->active = 0; pll->config.crtc_mask = 0; for_each_intel_crtc(dev, crtc) { @@ -15824,7 +15824,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev) DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name); - pll->disable(dev_priv, pll); + pll->funcs.disable(dev_priv, pll); pll->on = false; } diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 889ceed..e88dc46 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -74,7 +74,7 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state))) return; - cur_state = pll->get_hw_state(dev_priv, pll, &hw_state); + cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state); I915_STATE_WARN(cur_state != state, "%s assertion failure (expected %s, current %s)\n", pll->name, onoff(state), onoff(cur_state)); @@ -95,7 +95,7 @@ void intel_prepare_shared_dpll(struct intel_crtc *crtc) WARN_ON(pll->on); assert_shared_dpll_disabled(dev_priv, pll); - pll->mode_set(dev_priv, pll); + pll->funcs.mode_set(dev_priv, pll); } } @@ -133,7 +133,7 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc) intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); DRM_DEBUG_KMS("enabling %s\n", pll->name); - pll->enable(dev_priv, pll); + pll->funcs.enable(dev_priv, pll); pll->on = true; } @@ -168,7 +168,7 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) return; DRM_DEBUG_KMS("disabling %s\n", pll->name); - pll->disable(dev_priv, pll); + pll->funcs.disable(dev_priv, pll); pll->on = false; intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); @@ -398,29 +398,13 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, udelay(200); } -static char *ibx_pch_dpll_names[] = { - "PCH DPLL A", - "PCH DPLL B", +static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = { + .mode_set = ibx_pch_dpll_mode_set, + .enable = ibx_pch_dpll_enable, + .disable = ibx_pch_dpll_disable, + .get_hw_state = ibx_pch_dpll_get_hw_state, }; -static void ibx_pch_dpll_init(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int i; - - dev_priv->num_shared_dpll = 2; - - for (i = 0; i < dev_priv->num_shared_dpll; i++) { - dev_priv->shared_dplls[i].id = i; - dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i]; - dev_priv->shared_dplls[i].mode_set = ibx_pch_dpll_mode_set; - dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable; - dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable; - dev_priv->shared_dplls[i].get_hw_state = - ibx_pch_dpll_get_hw_state; - } -} - static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { @@ -492,40 +476,16 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv, } -static const char * const hsw_ddi_pll_names[] = { - "WRPLL 1", - "WRPLL 2", - "SPLL" +static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = { + .enable = hsw_ddi_wrpll_enable, + .disable = hsw_ddi_wrpll_disable, + .get_hw_state = hsw_ddi_wrpll_get_hw_state, }; -static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv) -{ - int i; - - dev_priv->num_shared_dpll = 3; - - for (i = 0; i < 2; i++) { - dev_priv->shared_dplls[i].id = i; - dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; - dev_priv->shared_dplls[i].disable = hsw_ddi_wrpll_disable; - dev_priv->shared_dplls[i].enable = hsw_ddi_wrpll_enable; - dev_priv->shared_dplls[i].get_hw_state = - hsw_ddi_wrpll_get_hw_state; - } - - /* SPLL is special, but needs to be initialized anyway.. */ - dev_priv->shared_dplls[i].id = i; - dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i]; - dev_priv->shared_dplls[i].disable = hsw_ddi_spll_disable; - dev_priv->shared_dplls[i].enable = hsw_ddi_spll_enable; - dev_priv->shared_dplls[i].get_hw_state = hsw_ddi_spll_get_hw_state; - -} - -static const char * const skl_ddi_pll_names[] = { - "DPLL 1", - "DPLL 2", - "DPLL 3", +static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = { + .enable = hsw_ddi_spll_enable, + .disable = hsw_ddi_spll_disable, + .get_hw_state = hsw_ddi_spll_get_hw_state, }; struct skl_dpll_regs { @@ -634,26 +594,10 @@ out: return ret; } -static void skl_shared_dplls_init(struct drm_i915_private *dev_priv) -{ - int i; - - dev_priv->num_shared_dpll = 3; - - for (i = 0; i < dev_priv->num_shared_dpll; i++) { - dev_priv->shared_dplls[i].id = i; - dev_priv->shared_dplls[i].name = skl_ddi_pll_names[i]; - dev_priv->shared_dplls[i].disable = skl_ddi_pll_disable; - dev_priv->shared_dplls[i].enable = skl_ddi_pll_enable; - dev_priv->shared_dplls[i].get_hw_state = - skl_ddi_pll_get_hw_state; - } -} - -static const char * const bxt_ddi_pll_names[] = { - "PORT PLL A", - "PORT PLL B", - "PORT PLL C", +static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = { + .enable = skl_ddi_pll_enable, + .disable = skl_ddi_pll_disable, + .get_hw_state = skl_ddi_pll_get_hw_state, }; static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, @@ -838,34 +782,17 @@ out: return ret; } -static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv) -{ - int i; - - dev_priv->num_shared_dpll = 3; - - for (i = 0; i < dev_priv->num_shared_dpll; i++) { - dev_priv->shared_dplls[i].id = i; - dev_priv->shared_dplls[i].name = bxt_ddi_pll_names[i]; - dev_priv->shared_dplls[i].disable = bxt_ddi_pll_disable; - dev_priv->shared_dplls[i].enable = bxt_ddi_pll_enable; - dev_priv->shared_dplls[i].get_hw_state = - bxt_ddi_pll_get_hw_state; - } -} +static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = { + .enable = bxt_ddi_pll_enable, + .disable = bxt_ddi_pll_disable, + .get_hw_state = bxt_ddi_pll_get_hw_state, +}; static void intel_ddi_pll_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t val = I915_READ(LCPLL_CTL); - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) - skl_shared_dplls_init(dev_priv); - else if (IS_BROXTON(dev)) - bxt_shared_dplls_init(dev_priv); - else - hsw_shared_dplls_init(dev_priv); - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { int cdclk_freq; @@ -893,16 +820,72 @@ static void intel_ddi_pll_init(struct drm_device *dev) } } +struct dpll_info { + const char *name; + const int id; + const struct intel_shared_dpll_funcs *funcs; +}; + +static const struct dpll_info pch_plls[] = { + { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs }, + { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs }, + { NULL, -1, NULL }, +}; + +static const struct dpll_info hsw_plls[] = { + { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs }, + { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs }, + { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs }, + { NULL, -1, NULL, }, +}; + +static const struct dpll_info skl_plls[] = { + { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs }, + { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs }, + { "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs }, + { NULL, -1, NULL, }, +}; + +static const struct dpll_info bxt_plls[] = { + { "PORT PLL A", 0, &bxt_ddi_pll_funcs }, + { "PORT PLL B", 1, &bxt_ddi_pll_funcs }, + { "PORT PLL C", 2, &bxt_ddi_pll_funcs }, + { NULL, -1, NULL, }, +}; + void intel_shared_dpll_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + const struct dpll_info *dpll_info = NULL; + int i; - if (HAS_DDI(dev)) - intel_ddi_pll_init(dev); + if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) + dpll_info = skl_plls; + else if IS_BROXTON(dev) + dpll_info = bxt_plls; + else if (HAS_DDI(dev)) + dpll_info = hsw_plls; else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) - ibx_pch_dpll_init(dev); - else + dpll_info = pch_plls; + + if (!dpll_info) { dev_priv->num_shared_dpll = 0; + return; + } + + for (i = 0; dpll_info[i].id >= 0; i++) { + WARN_ON(i != dpll_info[i].id); + + dev_priv->shared_dplls[i].id = dpll_info[i].id; + dev_priv->shared_dplls[i].name = dpll_info[i].name; + dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs; + } + + dev_priv->num_shared_dpll = i; BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); + + /* FIXME: Move this to a more suitable place */ + if (HAS_DDI(dev)) + intel_ddi_pll_init(dev); } diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index a2ecf80..8be2478 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -28,6 +28,7 @@ struct drm_i915_private; struct intel_crtc; struct intel_crtc_state; +struct intel_shared_dpll; enum intel_dpll_id { DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */ @@ -78,14 +79,7 @@ struct intel_shared_dpll_config { struct intel_dpll_hw_state hw_state; }; -struct intel_shared_dpll { - struct intel_shared_dpll_config config; - - int active; /* count of number of active CRTCs (i.e. DPMS on) */ - bool on; /* is the PLL actually active? Disabled during modeset */ - const char *name; - /* should match the index in the dev_priv->shared_dplls array */ - enum intel_dpll_id id; +struct intel_shared_dpll_funcs { /* The mode_set hook is optional and should be used together with the * intel_prepare_shared_dpll function. */ void (*mode_set)(struct drm_i915_private *dev_priv, @@ -99,6 +93,18 @@ struct intel_shared_dpll { struct intel_dpll_hw_state *hw_state); }; +struct intel_shared_dpll { + struct intel_shared_dpll_config config; + + int active; /* count of number of active CRTCs (i.e. DPMS on) */ + bool on; /* is the PLL actually active? Disabled during modeset */ + const char *name; + /* should match the index in the dev_priv->shared_dplls array */ + enum intel_dpll_id id; + + struct intel_shared_dpll_funcs funcs; +}; + #define SKL_DPLL0 0 #define SKL_DPLL1 1 #define SKL_DPLL2 2 -- cgit v0.10.2 From f9476a6c6d0c33cbce271ea08a3fbef131c73dc0 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:22 +0200 Subject: drm/i915: Refactor platform specifics out of intel_get_shared_dpll() The function intel_get_shared_dpll() had a more or less generic implementation with some platform specific checks to handle smaller differences between platforms. However, the minimalist approach forces bigger differences between platforms to be implemented outside of the shared dpll code (see the *_ddi_pll_select() functions in intel_ddi.c, for instance). This patch changes the implementation of intel_get_share_dpll() so that a completely platform specific version can be used, providing helpers to reduce code duplication. This should allow the code from the ddi pll select functions to be moved, and also make room for making more dplls managed by the shared dpll infrastructure. v2: WARN_ON(!dpll_mgr) in intel_get_shared_dpll(). (Maarten) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-9-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e74a61b..1557d65 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1810,6 +1810,7 @@ struct drm_i915_private { /* dpll and cdclk state is protected by connection_mutex */ int num_shared_dpll; struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; + const struct intel_dpll_mgr *dpll_mgr; unsigned int active_crtcs; unsigned int min_pixclk[I915_MAX_PIPES]; diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index e88dc46..b711407 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -174,66 +174,20 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); } -static enum intel_dpll_id -ibx_get_fixed_dpll(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_shared_dpll *pll; - enum intel_dpll_id i; - - /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ - i = (enum intel_dpll_id) crtc->pipe; - pll = &dev_priv->shared_dplls[i]; - - DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", - crtc->base.base.id, pll->name); - - return i; -} - -static enum intel_dpll_id -bxt_get_fixed_dpll(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_encoder *encoder; - struct intel_digital_port *intel_dig_port; - struct intel_shared_dpll *pll; - enum intel_dpll_id i; - - /* PLL is attached to port in bxt */ - encoder = intel_ddi_get_crtc_new_encoder(crtc_state); - if (WARN_ON(!encoder)) - return DPLL_ID_PRIVATE; - - intel_dig_port = enc_to_dig_port(&encoder->base); - /* 1:1 mapping between ports and PLLs */ - i = (enum intel_dpll_id)intel_dig_port->port; - pll = &dev_priv->shared_dplls[i]; - DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", - crtc->base.base.id, pll->name); - - return i; -} - -static enum intel_dpll_id +static struct intel_shared_dpll * intel_find_shared_dpll(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) + struct intel_crtc_state *crtc_state, + enum intel_dpll_id range_min, + enum intel_dpll_id range_max) { struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; struct intel_shared_dpll *pll; struct intel_shared_dpll_config *shared_dpll; enum intel_dpll_id i; - int max = dev_priv->num_shared_dpll; - - if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv)) - /* Do not consider SPLL */ - max = 2; shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); - for (i = 0; i < max; i++) { + for (i = range_min; i <= range_max; i++) { pll = &dev_priv->shared_dplls[i]; /* Only want to check enabled timings first */ @@ -247,49 +201,33 @@ intel_find_shared_dpll(struct intel_crtc *crtc, crtc->base.base.id, pll->name, shared_dpll[i].crtc_mask, pll->active); - return i; + return pll; } } /* Ok no matching timings, maybe there's a free one? */ - for (i = 0; i < dev_priv->num_shared_dpll; i++) { + for (i = range_min; i <= range_max; i++) { pll = &dev_priv->shared_dplls[i]; if (shared_dpll[i].crtc_mask == 0) { DRM_DEBUG_KMS("CRTC:%d allocated %s\n", crtc->base.base.id, pll->name); - return i; + return pll; } } - return DPLL_ID_PRIVATE; + return NULL; } -struct intel_shared_dpll * -intel_get_shared_dpll(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) +static void +intel_reference_shared_dpll(struct intel_shared_dpll *pll, + struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; - struct intel_shared_dpll *pll; struct intel_shared_dpll_config *shared_dpll; - enum intel_dpll_id i; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + enum intel_dpll_id i = pll->id; shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state); - if (HAS_PCH_IBX(dev_priv->dev)) { - i = ibx_get_fixed_dpll(crtc, crtc_state); - WARN_ON(shared_dpll[i].crtc_mask); - } else if (IS_BROXTON(dev_priv->dev)) { - i = bxt_get_fixed_dpll(crtc, crtc_state); - WARN_ON(shared_dpll[i].crtc_mask); - } else { - i = intel_find_shared_dpll(crtc, crtc_state); - } - - if (i < 0) - return NULL; - - pll = &dev_priv->shared_dplls[i]; - if (shared_dpll[i].crtc_mask == 0) shared_dpll[i].hw_state = crtc_state->dpll_hw_state; @@ -299,8 +237,6 @@ intel_get_shared_dpll(struct intel_crtc *crtc, pipe_name(crtc->pipe)); intel_shared_dpll_config_get(shared_dpll, pll, crtc); - - return pll; } void intel_shared_dpll_commit(struct drm_atomic_state *state) @@ -398,6 +334,32 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, udelay(200); } +static struct intel_shared_dpll * +ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_shared_dpll *pll; + enum intel_dpll_id i; + + if (HAS_PCH_IBX(dev_priv)) { + /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ + i = (enum intel_dpll_id) crtc->pipe; + pll = &dev_priv->shared_dplls[i]; + + DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", + crtc->base.base.id, pll->name); + } else { + pll = intel_find_shared_dpll(crtc, crtc_state, + DPLL_ID_PCH_PLL_A, + DPLL_ID_PCH_PLL_B); + } + + /* reference the pll */ + intel_reference_shared_dpll(pll, crtc_state); + + return pll; +} + static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = { .mode_set = ibx_pch_dpll_mode_set, .enable = ibx_pch_dpll_enable, @@ -475,6 +437,19 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv, return val & SPLL_PLL_ENABLE; } +static struct intel_shared_dpll * +hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) +{ + struct intel_shared_dpll *pll; + + pll = intel_find_shared_dpll(crtc, crtc_state, + DPLL_ID_WRPLL1, DPLL_ID_WRPLL2); + if (pll) + intel_reference_shared_dpll(pll, crtc_state); + + return pll; +} + static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = { .enable = hsw_ddi_wrpll_enable, @@ -594,6 +569,19 @@ out: return ret; } +static struct intel_shared_dpll * +skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) +{ + struct intel_shared_dpll *pll; + + pll = intel_find_shared_dpll(crtc, crtc_state, + DPLL_ID_SKL_DPLL1, DPLL_ID_SKL_DPLL3); + if (pll) + intel_reference_shared_dpll(pll, crtc_state); + + return pll; +} + static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = { .enable = skl_ddi_pll_enable, .disable = skl_ddi_pll_disable, @@ -782,6 +770,32 @@ out: return ret; } +static struct intel_shared_dpll * +bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_encoder *encoder; + struct intel_digital_port *intel_dig_port; + struct intel_shared_dpll *pll; + enum intel_dpll_id i; + + /* PLL is attached to port in bxt */ + encoder = intel_ddi_get_crtc_new_encoder(crtc_state); + if (WARN_ON(!encoder)) + return NULL; + + intel_dig_port = enc_to_dig_port(&encoder->base); + /* 1:1 mapping between ports and PLLs */ + i = (enum intel_dpll_id)intel_dig_port->port; + pll = &dev_priv->shared_dplls[i]; + DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", + crtc->base.base.id, pll->name); + + intel_reference_shared_dpll(pll, crtc_state); + + return pll; +} + static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = { .enable = bxt_ddi_pll_enable, .disable = bxt_ddi_pll_disable, @@ -826,12 +840,24 @@ struct dpll_info { const struct intel_shared_dpll_funcs *funcs; }; +struct intel_dpll_mgr { + const struct dpll_info *dpll_info; + + struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state); +}; + static const struct dpll_info pch_plls[] = { { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs }, { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs }, { NULL, -1, NULL }, }; +static const struct intel_dpll_mgr pch_pll_mgr = { + .dpll_info = pch_plls, + .get_dpll = ibx_get_dpll, +}; + static const struct dpll_info hsw_plls[] = { { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs }, { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs }, @@ -839,6 +865,11 @@ static const struct dpll_info hsw_plls[] = { { NULL, -1, NULL, }, }; +static const struct intel_dpll_mgr hsw_pll_mgr = { + .dpll_info = hsw_plls, + .get_dpll = hsw_get_dpll, +}; + static const struct dpll_info skl_plls[] = { { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs }, { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs }, @@ -846,6 +877,11 @@ static const struct dpll_info skl_plls[] = { { NULL, -1, NULL, }, }; +static const struct intel_dpll_mgr skl_pll_mgr = { + .dpll_info = skl_plls, + .get_dpll = skl_get_dpll, +}; + static const struct dpll_info bxt_plls[] = { { "PORT PLL A", 0, &bxt_ddi_pll_funcs }, { "PORT PLL B", 1, &bxt_ddi_pll_funcs }, @@ -853,26 +889,34 @@ static const struct dpll_info bxt_plls[] = { { NULL, -1, NULL, }, }; +static const struct intel_dpll_mgr bxt_pll_mgr = { + .dpll_info = bxt_plls, + .get_dpll = bxt_get_dpll, +}; + void intel_shared_dpll_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - const struct dpll_info *dpll_info = NULL; + const struct intel_dpll_mgr *dpll_mgr = NULL; + const struct dpll_info *dpll_info; int i; if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) - dpll_info = skl_plls; + dpll_mgr = &skl_pll_mgr; else if IS_BROXTON(dev) - dpll_info = bxt_plls; + dpll_mgr = &bxt_pll_mgr; else if (HAS_DDI(dev)) - dpll_info = hsw_plls; + dpll_mgr = &hsw_pll_mgr; else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) - dpll_info = pch_plls; + dpll_mgr = &pch_pll_mgr; - if (!dpll_info) { + if (!dpll_mgr) { dev_priv->num_shared_dpll = 0; return; } + dpll_info = dpll_mgr->dpll_info; + for (i = 0; dpll_info[i].id >= 0; i++) { WARN_ON(i != dpll_info[i].id); @@ -881,6 +925,7 @@ void intel_shared_dpll_init(struct drm_device *dev) dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs; } + dev_priv->dpll_mgr = dpll_mgr; dev_priv->num_shared_dpll = i; BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); @@ -889,3 +934,16 @@ void intel_shared_dpll_init(struct drm_device *dev) if (HAS_DDI(dev)) intel_ddi_pll_init(dev); } + +struct intel_shared_dpll * +intel_get_shared_dpll(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr; + + if (WARN_ON(!dpll_mgr)) + return NULL; + + return dpll_mgr->get_dpll(crtc, crtc_state); +} diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index 8be2478..7794c7a 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -30,6 +30,8 @@ struct intel_crtc; struct intel_crtc_state; struct intel_shared_dpll; +struct intel_dpll_mgr; + enum intel_dpll_id { DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */ /* real shared dpll ids must be >= 0 */ -- cgit v0.10.2 From daedf20a4f69685a636c9104cf6f1f5d8835345b Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:23 +0200 Subject: drm/i915: Move HSW/BDW pll selection logic to intel_dpll_mgr.c Move the code for selecting and configuring HSW/BDW DDI PLLs into the shared dpll infrastructure. With this most of the PLL selection logic for those platforms is in one place. DisplayPort is handled separately, but that should be fixed on a follow up patch. It also allows a small clean up of the SPLL logic. v2: Rebase. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-10-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 5f12a19..a2a31fd 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -265,15 +265,9 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder, pipe_config->pipe_bpp = 24; /* FDI must always be 2.7 GHz */ - if (HAS_DDI(dev)) { - pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL; + if (HAS_DDI(dev)) pipe_config->port_clock = 135000 * 2; - pipe_config->dpll_hw_state.wrpll = 0; - pipe_config->dpll_hw_state.spll = - SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC; - } - return true; } diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index b6af5c0..eae3ce2 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -724,160 +724,6 @@ intel_ddi_get_crtc_new_encoder(struct intel_crtc_state *crtc_state) } #define LC_FREQ 2700 -#define LC_FREQ_2K U64_C(LC_FREQ * 2000) - -#define P_MIN 2 -#define P_MAX 64 -#define P_INC 2 - -/* Constraints for PLL good behavior */ -#define REF_MIN 48 -#define REF_MAX 400 -#define VCO_MIN 2400 -#define VCO_MAX 4800 - -#define abs_diff(a, b) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - (void) (&__a == &__b); \ - __a > __b ? (__a - __b) : (__b - __a); }) - -struct hsw_wrpll_rnp { - unsigned p, n2, r2; -}; - -static unsigned hsw_wrpll_get_budget_for_freq(int clock) -{ - unsigned budget; - - switch (clock) { - case 25175000: - case 25200000: - case 27000000: - case 27027000: - case 37762500: - case 37800000: - case 40500000: - case 40541000: - case 54000000: - case 54054000: - case 59341000: - case 59400000: - case 72000000: - case 74176000: - case 74250000: - case 81000000: - case 81081000: - case 89012000: - case 89100000: - case 108000000: - case 108108000: - case 111264000: - case 111375000: - case 148352000: - case 148500000: - case 162000000: - case 162162000: - case 222525000: - case 222750000: - case 296703000: - case 297000000: - budget = 0; - break; - case 233500000: - case 245250000: - case 247750000: - case 253250000: - case 298000000: - budget = 1500; - break; - case 169128000: - case 169500000: - case 179500000: - case 202000000: - budget = 2000; - break; - case 256250000: - case 262500000: - case 270000000: - case 272500000: - case 273750000: - case 280750000: - case 281250000: - case 286000000: - case 291750000: - budget = 4000; - break; - case 267250000: - case 268500000: - budget = 5000; - break; - default: - budget = 1000; - break; - } - - return budget; -} - -static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget, - unsigned r2, unsigned n2, unsigned p, - struct hsw_wrpll_rnp *best) -{ - uint64_t a, b, c, d, diff, diff_best; - - /* No best (r,n,p) yet */ - if (best->p == 0) { - best->p = p; - best->n2 = n2; - best->r2 = r2; - return; - } - - /* - * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to - * freq2k. - * - * delta = 1e6 * - * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) / - * freq2k; - * - * and we would like delta <= budget. - * - * If the discrepancy is above the PPM-based budget, always prefer to - * improve upon the previous solution. However, if you're within the - * budget, try to maximize Ref * VCO, that is N / (P * R^2). - */ - a = freq2k * budget * p * r2; - b = freq2k * budget * best->p * best->r2; - diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2); - diff_best = abs_diff(freq2k * best->p * best->r2, - LC_FREQ_2K * best->n2); - c = 1000000 * diff; - d = 1000000 * diff_best; - - if (a < c && b < d) { - /* If both are above the budget, pick the closer */ - if (best->p * best->r2 * diff < p * r2 * diff_best) { - best->p = p; - best->n2 = n2; - best->r2 = r2; - } - } else if (a >= c && b < d) { - /* If A is below the threshold but B is above it? Update. */ - best->p = p; - best->n2 = n2; - best->r2 = r2; - } else if (a >= c && b >= d) { - /* Both are below the limit, so pick the higher n2/(r2*r2) */ - if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) { - best->p = p; - best->n2 = n2; - best->r2 = r2; - } - } - /* Otherwise a < c && b >= d, do nothing */ -} static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, i915_reg_t reg) @@ -1139,119 +985,24 @@ void intel_ddi_clock_get(struct intel_encoder *encoder, bxt_ddi_clock_get(encoder, pipe_config); } -static void -hsw_ddi_calculate_wrpll(int clock /* in Hz */, - unsigned *r2_out, unsigned *n2_out, unsigned *p_out) -{ - uint64_t freq2k; - unsigned p, n2, r2; - struct hsw_wrpll_rnp best = { 0, 0, 0 }; - unsigned budget; - - freq2k = clock / 100; - - budget = hsw_wrpll_get_budget_for_freq(clock); - - /* Special case handling for 540 pixel clock: bypass WR PLL entirely - * and directly pass the LC PLL to it. */ - if (freq2k == 5400000) { - *n2_out = 2; - *p_out = 1; - *r2_out = 2; - return; - } - - /* - * Ref = LC_FREQ / R, where Ref is the actual reference input seen by - * the WR PLL. - * - * We want R so that REF_MIN <= Ref <= REF_MAX. - * Injecting R2 = 2 * R gives: - * REF_MAX * r2 > LC_FREQ * 2 and - * REF_MIN * r2 < LC_FREQ * 2 - * - * Which means the desired boundaries for r2 are: - * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN - * - */ - for (r2 = LC_FREQ * 2 / REF_MAX + 1; - r2 <= LC_FREQ * 2 / REF_MIN; - r2++) { - - /* - * VCO = N * Ref, that is: VCO = N * LC_FREQ / R - * - * Once again we want VCO_MIN <= VCO <= VCO_MAX. - * Injecting R2 = 2 * R and N2 = 2 * N, we get: - * VCO_MAX * r2 > n2 * LC_FREQ and - * VCO_MIN * r2 < n2 * LC_FREQ) - * - * Which means the desired boundaries for n2 are: - * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ - */ - for (n2 = VCO_MIN * r2 / LC_FREQ + 1; - n2 <= VCO_MAX * r2 / LC_FREQ; - n2++) { - - for (p = P_MIN; p <= P_MAX; p += P_INC) - hsw_wrpll_update_rnp(freq2k, budget, - r2, n2, p, &best); - } - } - - *n2_out = best.n2; - *p_out = best.p; - *r2_out = best.r2; -} - static bool hsw_ddi_pll_select(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state, struct intel_encoder *intel_encoder) { - struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); - int clock = crtc_state->port_clock; - - if (intel_encoder->type == INTEL_OUTPUT_HDMI) { - struct intel_shared_dpll *pll; - uint32_t val; - unsigned p, n2, r2; - - hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); - - val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL | - WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | - WRPLL_DIVIDER_POST(p); - - memset(&crtc_state->dpll_hw_state, 0, - sizeof(crtc_state->dpll_hw_state)); - - crtc_state->dpll_hw_state.wrpll = val; + struct intel_shared_dpll *pll; - pll = intel_get_shared_dpll(intel_crtc, crtc_state); - if (pll == NULL) { + if (intel_encoder->type == INTEL_OUTPUT_HDMI || + intel_encoder->type == INTEL_OUTPUT_ANALOG) { + pll = intel_get_shared_dpll(intel_crtc, crtc_state, + intel_encoder); + if (!pll) DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", pipe_name(intel_crtc->pipe)); - return false; - } - - crtc_state->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id); - } else if (crtc_state->ddi_pll_sel == PORT_CLK_SEL_SPLL) { - struct drm_atomic_state *state = crtc_state->base.state; - struct intel_shared_dpll_config *spll = - &intel_atomic_get_shared_dpll_state(state)[DPLL_ID_SPLL]; - - if (spll->crtc_mask && - WARN_ON(spll->hw_state.spll != crtc_state->dpll_hw_state.spll)) - return false; - - crtc_state->shared_dpll = - intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_SPLL); - spll->hw_state.spll = crtc_state->dpll_hw_state.spll; - spll->crtc_mask |= 1 << intel_crtc->pipe; + return pll; + } else { + return true; } - - return true; } struct skl_wrpll_context { @@ -1560,7 +1311,7 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, crtc_state->dpll_hw_state.cfgcr1 = cfgcr1; crtc_state->dpll_hw_state.cfgcr2 = cfgcr2; - pll = intel_get_shared_dpll(intel_crtc, crtc_state); + pll = intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder); if (pll == NULL) { DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", pipe_name(intel_crtc->pipe)); @@ -1707,7 +1458,7 @@ bxt_ddi_pll_select(struct intel_crtc *intel_crtc, crtc_state->dpll_hw_state.pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger; - pll = intel_get_shared_dpll(intel_crtc, crtc_state); + pll = intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder); if (pll == NULL) { DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", pipe_name(intel_crtc->pipe)); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5852a1a..9d2f494 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8943,7 +8943,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, else crtc_state->dpll_hw_state.fp1 = fp; - pll = intel_get_shared_dpll(crtc, crtc_state); + pll = intel_get_shared_dpll(crtc, crtc_state, NULL); if (pll == NULL) { DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", pipe_name(crtc->pipe)); diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index b711407..224c896 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -335,7 +335,8 @@ static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, } static struct intel_shared_dpll * -ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) +ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll; @@ -437,15 +438,282 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv, return val & SPLL_PLL_ENABLE; } +static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll) +{ + switch (pll->id) { + case DPLL_ID_WRPLL1: + return PORT_CLK_SEL_WRPLL1; + case DPLL_ID_WRPLL2: + return PORT_CLK_SEL_WRPLL2; + case DPLL_ID_SPLL: + return PORT_CLK_SEL_SPLL; + default: + return PORT_CLK_SEL_NONE; + } +} + +#define LC_FREQ 2700 +#define LC_FREQ_2K U64_C(LC_FREQ * 2000) + +#define P_MIN 2 +#define P_MAX 64 +#define P_INC 2 + +/* Constraints for PLL good behavior */ +#define REF_MIN 48 +#define REF_MAX 400 +#define VCO_MIN 2400 +#define VCO_MAX 4800 + +struct hsw_wrpll_rnp { + unsigned p, n2, r2; +}; + +static unsigned hsw_wrpll_get_budget_for_freq(int clock) +{ + unsigned budget; + + switch (clock) { + case 25175000: + case 25200000: + case 27000000: + case 27027000: + case 37762500: + case 37800000: + case 40500000: + case 40541000: + case 54000000: + case 54054000: + case 59341000: + case 59400000: + case 72000000: + case 74176000: + case 74250000: + case 81000000: + case 81081000: + case 89012000: + case 89100000: + case 108000000: + case 108108000: + case 111264000: + case 111375000: + case 148352000: + case 148500000: + case 162000000: + case 162162000: + case 222525000: + case 222750000: + case 296703000: + case 297000000: + budget = 0; + break; + case 233500000: + case 245250000: + case 247750000: + case 253250000: + case 298000000: + budget = 1500; + break; + case 169128000: + case 169500000: + case 179500000: + case 202000000: + budget = 2000; + break; + case 256250000: + case 262500000: + case 270000000: + case 272500000: + case 273750000: + case 280750000: + case 281250000: + case 286000000: + case 291750000: + budget = 4000; + break; + case 267250000: + case 268500000: + budget = 5000; + break; + default: + budget = 1000; + break; + } + + return budget; +} + +static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget, + unsigned r2, unsigned n2, unsigned p, + struct hsw_wrpll_rnp *best) +{ + uint64_t a, b, c, d, diff, diff_best; + + /* No best (r,n,p) yet */ + if (best->p == 0) { + best->p = p; + best->n2 = n2; + best->r2 = r2; + return; + } + + /* + * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to + * freq2k. + * + * delta = 1e6 * + * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) / + * freq2k; + * + * and we would like delta <= budget. + * + * If the discrepancy is above the PPM-based budget, always prefer to + * improve upon the previous solution. However, if you're within the + * budget, try to maximize Ref * VCO, that is N / (P * R^2). + */ + a = freq2k * budget * p * r2; + b = freq2k * budget * best->p * best->r2; + diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2); + diff_best = abs_diff(freq2k * best->p * best->r2, + LC_FREQ_2K * best->n2); + c = 1000000 * diff; + d = 1000000 * diff_best; + + if (a < c && b < d) { + /* If both are above the budget, pick the closer */ + if (best->p * best->r2 * diff < p * r2 * diff_best) { + best->p = p; + best->n2 = n2; + best->r2 = r2; + } + } else if (a >= c && b < d) { + /* If A is below the threshold but B is above it? Update. */ + best->p = p; + best->n2 = n2; + best->r2 = r2; + } else if (a >= c && b >= d) { + /* Both are below the limit, so pick the higher n2/(r2*r2) */ + if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) { + best->p = p; + best->n2 = n2; + best->r2 = r2; + } + } + /* Otherwise a < c && b >= d, do nothing */ +} + +static void +hsw_ddi_calculate_wrpll(int clock /* in Hz */, + unsigned *r2_out, unsigned *n2_out, unsigned *p_out) +{ + uint64_t freq2k; + unsigned p, n2, r2; + struct hsw_wrpll_rnp best = { 0, 0, 0 }; + unsigned budget; + + freq2k = clock / 100; + + budget = hsw_wrpll_get_budget_for_freq(clock); + + /* Special case handling for 540 pixel clock: bypass WR PLL entirely + * and directly pass the LC PLL to it. */ + if (freq2k == 5400000) { + *n2_out = 2; + *p_out = 1; + *r2_out = 2; + return; + } + + /* + * Ref = LC_FREQ / R, where Ref is the actual reference input seen by + * the WR PLL. + * + * We want R so that REF_MIN <= Ref <= REF_MAX. + * Injecting R2 = 2 * R gives: + * REF_MAX * r2 > LC_FREQ * 2 and + * REF_MIN * r2 < LC_FREQ * 2 + * + * Which means the desired boundaries for r2 are: + * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN + * + */ + for (r2 = LC_FREQ * 2 / REF_MAX + 1; + r2 <= LC_FREQ * 2 / REF_MIN; + r2++) { + + /* + * VCO = N * Ref, that is: VCO = N * LC_FREQ / R + * + * Once again we want VCO_MIN <= VCO <= VCO_MAX. + * Injecting R2 = 2 * R and N2 = 2 * N, we get: + * VCO_MAX * r2 > n2 * LC_FREQ and + * VCO_MIN * r2 < n2 * LC_FREQ) + * + * Which means the desired boundaries for n2 are: + * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ + */ + for (n2 = VCO_MIN * r2 / LC_FREQ + 1; + n2 <= VCO_MAX * r2 / LC_FREQ; + n2++) { + + for (p = P_MIN; p <= P_MAX; p += P_INC) + hsw_wrpll_update_rnp(freq2k, budget, + r2, n2, p, &best); + } + } + + *n2_out = best.n2; + *p_out = best.p; + *r2_out = best.r2; +} + static struct intel_shared_dpll * -hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) +hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) { struct intel_shared_dpll *pll; + int clock = crtc_state->port_clock; - pll = intel_find_shared_dpll(crtc, crtc_state, - DPLL_ID_WRPLL1, DPLL_ID_WRPLL2); - if (pll) - intel_reference_shared_dpll(pll, crtc_state); + if (encoder->type == INTEL_OUTPUT_HDMI) { + uint32_t val; + unsigned p, n2, r2; + + hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p); + + val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL | + WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | + WRPLL_DIVIDER_POST(p); + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + + crtc_state->dpll_hw_state.wrpll = val; + + pll = intel_find_shared_dpll(crtc, crtc_state, + DPLL_ID_WRPLL1, DPLL_ID_WRPLL2); + + } else if (encoder->type == INTEL_OUTPUT_ANALOG) { + if (WARN_ON(crtc_state->port_clock / 2 != 135000)) + return NULL; + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + + crtc_state->dpll_hw_state.spll = + SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC; + + pll = intel_find_shared_dpll(crtc, crtc_state, + DPLL_ID_SPLL, DPLL_ID_SPLL); + } else { + return NULL; + } + + if (!pll) + return NULL; + + crtc_state->ddi_pll_sel = hsw_pll_to_ddi_pll_sel(pll); + + intel_reference_shared_dpll(pll, crtc_state); return pll; } @@ -570,7 +838,8 @@ out: } static struct intel_shared_dpll * -skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) +skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) { struct intel_shared_dpll *pll; @@ -771,10 +1040,10 @@ out: } static struct intel_shared_dpll * -bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) +bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_encoder *encoder; struct intel_digital_port *intel_dig_port; struct intel_shared_dpll *pll; enum intel_dpll_id i; @@ -844,7 +1113,8 @@ struct intel_dpll_mgr { const struct dpll_info *dpll_info; struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state); + struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder); }; static const struct dpll_info pch_plls[] = { @@ -937,7 +1207,8 @@ void intel_shared_dpll_init(struct drm_device *dev) struct intel_shared_dpll * intel_get_shared_dpll(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) + struct intel_crtc_state *crtc_state, + struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr; @@ -945,5 +1216,5 @@ intel_get_shared_dpll(struct intel_crtc *crtc, if (WARN_ON(!dpll_mgr)) return NULL; - return dpll_mgr->get_dpll(crtc, crtc_state); + return dpll_mgr->get_dpll(crtc, crtc_state, encoder); } diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index 7794c7a..82e53f5 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -25,11 +25,19 @@ #ifndef _INTEL_DPLL_MGR_H_ #define _INTEL_DPLL_MGR_H_ +/*FIXME: Move this to a more appropriate place. */ +#define abs_diff(a, b) ({ \ + typeof(a) __a = (a); \ + typeof(b) __b = (b); \ + (void) (&__a == &__b); \ + __a > __b ? (__a - __b) : (__b - __a); }) + struct drm_i915_private; struct intel_crtc; struct intel_crtc_state; -struct intel_shared_dpll; +struct intel_encoder; +struct intel_shared_dpll; struct intel_dpll_mgr; enum intel_dpll_id { @@ -133,7 +141,8 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, #define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true) #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false) struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc, - struct intel_crtc_state *state); + struct intel_crtc_state *state, + struct intel_encoder *encoder); void intel_prepare_shared_dpll(struct intel_crtc *crtc); void intel_enable_shared_dpll(struct intel_crtc *crtc); void intel_disable_shared_dpll(struct intel_crtc *crtc); -- cgit v0.10.2 From 304b65cbdc8d6d73b12ea798099b7ca64f491795 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:24 +0200 Subject: drm/i915: Move SKL/KLB pll selection logic to intel_dpll_mgr.c Move the code for selecting plls for SKL/KLB into the shared dpll code, so that the platform specific details are hidden behind that interface. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-11-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index eae3ce2..2890675 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1005,311 +1005,15 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc, } } -struct skl_wrpll_context { - uint64_t min_deviation; /* current minimal deviation */ - uint64_t central_freq; /* chosen central freq */ - uint64_t dco_freq; /* chosen dco freq */ - unsigned int p; /* chosen divider */ -}; - -static void skl_wrpll_context_init(struct skl_wrpll_context *ctx) -{ - memset(ctx, 0, sizeof(*ctx)); - - ctx->min_deviation = U64_MAX; -} - -/* DCO freq must be within +1%/-6% of the DCO central freq */ -#define SKL_DCO_MAX_PDEVIATION 100 -#define SKL_DCO_MAX_NDEVIATION 600 - -static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx, - uint64_t central_freq, - uint64_t dco_freq, - unsigned int divider) -{ - uint64_t deviation; - - deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq), - central_freq); - - /* positive deviation */ - if (dco_freq >= central_freq) { - if (deviation < SKL_DCO_MAX_PDEVIATION && - deviation < ctx->min_deviation) { - ctx->min_deviation = deviation; - ctx->central_freq = central_freq; - ctx->dco_freq = dco_freq; - ctx->p = divider; - } - /* negative deviation */ - } else if (deviation < SKL_DCO_MAX_NDEVIATION && - deviation < ctx->min_deviation) { - ctx->min_deviation = deviation; - ctx->central_freq = central_freq; - ctx->dco_freq = dco_freq; - ctx->p = divider; - } -} - -static void skl_wrpll_get_multipliers(unsigned int p, - unsigned int *p0 /* out */, - unsigned int *p1 /* out */, - unsigned int *p2 /* out */) -{ - /* even dividers */ - if (p % 2 == 0) { - unsigned int half = p / 2; - - if (half == 1 || half == 2 || half == 3 || half == 5) { - *p0 = 2; - *p1 = 1; - *p2 = half; - } else if (half % 2 == 0) { - *p0 = 2; - *p1 = half / 2; - *p2 = 2; - } else if (half % 3 == 0) { - *p0 = 3; - *p1 = half / 3; - *p2 = 2; - } else if (half % 7 == 0) { - *p0 = 7; - *p1 = half / 7; - *p2 = 2; - } - } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */ - *p0 = 3; - *p1 = 1; - *p2 = p / 3; - } else if (p == 5 || p == 7) { - *p0 = p; - *p1 = 1; - *p2 = 1; - } else if (p == 15) { - *p0 = 3; - *p1 = 1; - *p2 = 5; - } else if (p == 21) { - *p0 = 7; - *p1 = 1; - *p2 = 3; - } else if (p == 35) { - *p0 = 7; - *p1 = 1; - *p2 = 5; - } -} - -struct skl_wrpll_params { - uint32_t dco_fraction; - uint32_t dco_integer; - uint32_t qdiv_ratio; - uint32_t qdiv_mode; - uint32_t kdiv; - uint32_t pdiv; - uint32_t central_freq; -}; - -static void skl_wrpll_params_populate(struct skl_wrpll_params *params, - uint64_t afe_clock, - uint64_t central_freq, - uint32_t p0, uint32_t p1, uint32_t p2) -{ - uint64_t dco_freq; - - switch (central_freq) { - case 9600000000ULL: - params->central_freq = 0; - break; - case 9000000000ULL: - params->central_freq = 1; - break; - case 8400000000ULL: - params->central_freq = 3; - } - - switch (p0) { - case 1: - params->pdiv = 0; - break; - case 2: - params->pdiv = 1; - break; - case 3: - params->pdiv = 2; - break; - case 7: - params->pdiv = 4; - break; - default: - WARN(1, "Incorrect PDiv\n"); - } - - switch (p2) { - case 5: - params->kdiv = 0; - break; - case 2: - params->kdiv = 1; - break; - case 3: - params->kdiv = 2; - break; - case 1: - params->kdiv = 3; - break; - default: - WARN(1, "Incorrect KDiv\n"); - } - - params->qdiv_ratio = p1; - params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1; - - dco_freq = p0 * p1 * p2 * afe_clock; - - /* - * Intermediate values are in Hz. - * Divide by MHz to match bsepc - */ - params->dco_integer = div_u64(dco_freq, 24 * MHz(1)); - params->dco_fraction = - div_u64((div_u64(dco_freq, 24) - - params->dco_integer * MHz(1)) * 0x8000, MHz(1)); -} - -static bool -skl_ddi_calculate_wrpll(int clock /* in Hz */, - struct skl_wrpll_params *wrpll_params) -{ - uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */ - uint64_t dco_central_freq[3] = {8400000000ULL, - 9000000000ULL, - 9600000000ULL}; - static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20, - 24, 28, 30, 32, 36, 40, 42, 44, - 48, 52, 54, 56, 60, 64, 66, 68, - 70, 72, 76, 78, 80, 84, 88, 90, - 92, 96, 98 }; - static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 }; - static const struct { - const int *list; - int n_dividers; - } dividers[] = { - { even_dividers, ARRAY_SIZE(even_dividers) }, - { odd_dividers, ARRAY_SIZE(odd_dividers) }, - }; - struct skl_wrpll_context ctx; - unsigned int dco, d, i; - unsigned int p0, p1, p2; - - skl_wrpll_context_init(&ctx); - - for (d = 0; d < ARRAY_SIZE(dividers); d++) { - for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) { - for (i = 0; i < dividers[d].n_dividers; i++) { - unsigned int p = dividers[d].list[i]; - uint64_t dco_freq = p * afe_clock; - - skl_wrpll_try_divider(&ctx, - dco_central_freq[dco], - dco_freq, - p); - /* - * Skip the remaining dividers if we're sure to - * have found the definitive divider, we can't - * improve a 0 deviation. - */ - if (ctx.min_deviation == 0) - goto skip_remaining_dividers; - } - } - -skip_remaining_dividers: - /* - * If a solution is found with an even divider, prefer - * this one. - */ - if (d == 0 && ctx.p) - break; - } - - if (!ctx.p) { - DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock); - return false; - } - - /* - * gcc incorrectly analyses that these can be used without being - * initialized. To be fair, it's hard to guess. - */ - p0 = p1 = p2 = 0; - skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2); - skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq, - p0, p1, p2); - - return true; -} - static bool skl_ddi_pll_select(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state, struct intel_encoder *intel_encoder) { struct intel_shared_dpll *pll; - uint32_t ctrl1, cfgcr1, cfgcr2; - int clock = crtc_state->port_clock; - /* - * See comment in intel_dpll_hw_state to understand why we always use 0 - * as the DPLL id in this function. - */ - - ctrl1 = DPLL_CTRL1_OVERRIDE(0); - - if (intel_encoder->type == INTEL_OUTPUT_HDMI) { - struct skl_wrpll_params wrpll_params = { 0, }; - - ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); - - if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params)) - return false; - - cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE | - DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) | - wrpll_params.dco_integer; - - cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) | - DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) | - DPLL_CFGCR2_KDIV(wrpll_params.kdiv) | - DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | - wrpll_params.central_freq; - } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT || - intel_encoder->type == INTEL_OUTPUT_DP_MST) { - switch (crtc_state->port_clock / 2) { - case 81000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0); - break; - case 135000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0); - break; - case 270000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0); - break; - } - - cfgcr1 = cfgcr2 = 0; - } else if (intel_encoder->type == INTEL_OUTPUT_EDP) { + if (intel_encoder->type == INTEL_OUTPUT_EDP) return true; - } else - return false; - - memset(&crtc_state->dpll_hw_state, 0, - sizeof(crtc_state->dpll_hw_state)); - - crtc_state->dpll_hw_state.ctrl1 = ctrl1; - crtc_state->dpll_hw_state.cfgcr1 = cfgcr1; - crtc_state->dpll_hw_state.cfgcr2 = cfgcr2; pll = intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder); if (pll == NULL) { @@ -1318,9 +1022,6 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, return false; } - /* shared DPLL id 0 is DPLL 1 */ - crtc_state->ddi_pll_sel = pll->id + 1; - return true; } diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 224c896..61887ae 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -837,16 +837,319 @@ out: return ret; } +struct skl_wrpll_context { + uint64_t min_deviation; /* current minimal deviation */ + uint64_t central_freq; /* chosen central freq */ + uint64_t dco_freq; /* chosen dco freq */ + unsigned int p; /* chosen divider */ +}; + +static void skl_wrpll_context_init(struct skl_wrpll_context *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + + ctx->min_deviation = U64_MAX; +} + +/* DCO freq must be within +1%/-6% of the DCO central freq */ +#define SKL_DCO_MAX_PDEVIATION 100 +#define SKL_DCO_MAX_NDEVIATION 600 + +static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx, + uint64_t central_freq, + uint64_t dco_freq, + unsigned int divider) +{ + uint64_t deviation; + + deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq), + central_freq); + + /* positive deviation */ + if (dco_freq >= central_freq) { + if (deviation < SKL_DCO_MAX_PDEVIATION && + deviation < ctx->min_deviation) { + ctx->min_deviation = deviation; + ctx->central_freq = central_freq; + ctx->dco_freq = dco_freq; + ctx->p = divider; + } + /* negative deviation */ + } else if (deviation < SKL_DCO_MAX_NDEVIATION && + deviation < ctx->min_deviation) { + ctx->min_deviation = deviation; + ctx->central_freq = central_freq; + ctx->dco_freq = dco_freq; + ctx->p = divider; + } +} + +static void skl_wrpll_get_multipliers(unsigned int p, + unsigned int *p0 /* out */, + unsigned int *p1 /* out */, + unsigned int *p2 /* out */) +{ + /* even dividers */ + if (p % 2 == 0) { + unsigned int half = p / 2; + + if (half == 1 || half == 2 || half == 3 || half == 5) { + *p0 = 2; + *p1 = 1; + *p2 = half; + } else if (half % 2 == 0) { + *p0 = 2; + *p1 = half / 2; + *p2 = 2; + } else if (half % 3 == 0) { + *p0 = 3; + *p1 = half / 3; + *p2 = 2; + } else if (half % 7 == 0) { + *p0 = 7; + *p1 = half / 7; + *p2 = 2; + } + } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */ + *p0 = 3; + *p1 = 1; + *p2 = p / 3; + } else if (p == 5 || p == 7) { + *p0 = p; + *p1 = 1; + *p2 = 1; + } else if (p == 15) { + *p0 = 3; + *p1 = 1; + *p2 = 5; + } else if (p == 21) { + *p0 = 7; + *p1 = 1; + *p2 = 3; + } else if (p == 35) { + *p0 = 7; + *p1 = 1; + *p2 = 5; + } +} + +struct skl_wrpll_params { + uint32_t dco_fraction; + uint32_t dco_integer; + uint32_t qdiv_ratio; + uint32_t qdiv_mode; + uint32_t kdiv; + uint32_t pdiv; + uint32_t central_freq; +}; + +static void skl_wrpll_params_populate(struct skl_wrpll_params *params, + uint64_t afe_clock, + uint64_t central_freq, + uint32_t p0, uint32_t p1, uint32_t p2) +{ + uint64_t dco_freq; + + switch (central_freq) { + case 9600000000ULL: + params->central_freq = 0; + break; + case 9000000000ULL: + params->central_freq = 1; + break; + case 8400000000ULL: + params->central_freq = 3; + } + + switch (p0) { + case 1: + params->pdiv = 0; + break; + case 2: + params->pdiv = 1; + break; + case 3: + params->pdiv = 2; + break; + case 7: + params->pdiv = 4; + break; + default: + WARN(1, "Incorrect PDiv\n"); + } + + switch (p2) { + case 5: + params->kdiv = 0; + break; + case 2: + params->kdiv = 1; + break; + case 3: + params->kdiv = 2; + break; + case 1: + params->kdiv = 3; + break; + default: + WARN(1, "Incorrect KDiv\n"); + } + + params->qdiv_ratio = p1; + params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1; + + dco_freq = p0 * p1 * p2 * afe_clock; + + /* + * Intermediate values are in Hz. + * Divide by MHz to match bsepc + */ + params->dco_integer = div_u64(dco_freq, 24 * MHz(1)); + params->dco_fraction = + div_u64((div_u64(dco_freq, 24) - + params->dco_integer * MHz(1)) * 0x8000, MHz(1)); +} + +static bool +skl_ddi_calculate_wrpll(int clock /* in Hz */, + struct skl_wrpll_params *wrpll_params) +{ + uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */ + uint64_t dco_central_freq[3] = {8400000000ULL, + 9000000000ULL, + 9600000000ULL}; + static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20, + 24, 28, 30, 32, 36, 40, 42, 44, + 48, 52, 54, 56, 60, 64, 66, 68, + 70, 72, 76, 78, 80, 84, 88, 90, + 92, 96, 98 }; + static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 }; + static const struct { + const int *list; + int n_dividers; + } dividers[] = { + { even_dividers, ARRAY_SIZE(even_dividers) }, + { odd_dividers, ARRAY_SIZE(odd_dividers) }, + }; + struct skl_wrpll_context ctx; + unsigned int dco, d, i; + unsigned int p0, p1, p2; + + skl_wrpll_context_init(&ctx); + + for (d = 0; d < ARRAY_SIZE(dividers); d++) { + for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) { + for (i = 0; i < dividers[d].n_dividers; i++) { + unsigned int p = dividers[d].list[i]; + uint64_t dco_freq = p * afe_clock; + + skl_wrpll_try_divider(&ctx, + dco_central_freq[dco], + dco_freq, + p); + /* + * Skip the remaining dividers if we're sure to + * have found the definitive divider, we can't + * improve a 0 deviation. + */ + if (ctx.min_deviation == 0) + goto skip_remaining_dividers; + } + } + +skip_remaining_dividers: + /* + * If a solution is found with an even divider, prefer + * this one. + */ + if (d == 0 && ctx.p) + break; + } + + if (!ctx.p) { + DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock); + return false; + } + + /* + * gcc incorrectly analyses that these can be used without being + * initialized. To be fair, it's hard to guess. + */ + p0 = p1 = p2 = 0; + skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2); + skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq, + p0, p1, p2); + + return true; +} + static struct intel_shared_dpll * skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { struct intel_shared_dpll *pll; + uint32_t ctrl1, cfgcr1, cfgcr2; + int clock = crtc_state->port_clock; + + /* + * See comment in intel_dpll_hw_state to understand why we always use 0 + * as the DPLL id in this function. + */ + + ctrl1 = DPLL_CTRL1_OVERRIDE(0); + + if (encoder->type == INTEL_OUTPUT_HDMI) { + struct skl_wrpll_params wrpll_params = { 0, }; + + ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); + + if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params)) + return false; + + cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE | + DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) | + wrpll_params.dco_integer; + + cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) | + DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) | + DPLL_CFGCR2_KDIV(wrpll_params.kdiv) | + DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | + wrpll_params.central_freq; + } else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT || + encoder->type == INTEL_OUTPUT_DP_MST) { + switch (crtc_state->port_clock / 2) { + case 81000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0); + break; + case 135000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0); + break; + case 270000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0); + break; + } + + cfgcr1 = cfgcr2 = 0; + } else { + return NULL; + } + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + + crtc_state->dpll_hw_state.ctrl1 = ctrl1; + crtc_state->dpll_hw_state.cfgcr1 = cfgcr1; + crtc_state->dpll_hw_state.cfgcr2 = cfgcr2; pll = intel_find_shared_dpll(crtc, crtc_state, DPLL_ID_SKL_DPLL1, DPLL_ID_SKL_DPLL3); - if (pll) - intel_reference_shared_dpll(pll, crtc_state); + if (!pll) + return NULL; + + /* shared DPLL id 0 is DPLL 1 */ + crtc_state->ddi_pll_sel = pll->id + 1; + + intel_reference_shared_dpll(pll, crtc_state); return pll; } -- cgit v0.10.2 From 34177c249af743ceccaf583bf750e8bc17c4f18a Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:25 +0200 Subject: drm/i915: Move BXT pll configuration logic to intel_dpll_mgr.c Move the code for configurating BXT plls into the shared dpll code, so that the platform specific details are hidden behind that interface. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-12-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 2890675..50cc264 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1025,151 +1025,12 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, return true; } -/* bxt clock parameters */ -struct bxt_clk_div { - int clock; - uint32_t p1; - uint32_t p2; - uint32_t m2_int; - uint32_t m2_frac; - bool m2_frac_en; - uint32_t n; -}; - -/* pre-calculated values for DP linkrates */ -static const struct bxt_clk_div bxt_dp_clk_val[] = { - {162000, 4, 2, 32, 1677722, 1, 1}, - {270000, 4, 1, 27, 0, 0, 1}, - {540000, 2, 1, 27, 0, 0, 1}, - {216000, 3, 2, 32, 1677722, 1, 1}, - {243000, 4, 1, 24, 1258291, 1, 1}, - {324000, 4, 1, 32, 1677722, 1, 1}, - {432000, 3, 1, 32, 1677722, 1, 1} -}; - static bool bxt_ddi_pll_select(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state, struct intel_encoder *intel_encoder) { - struct intel_shared_dpll *pll; - struct bxt_clk_div clk_div = {0}; - int vco = 0; - uint32_t prop_coef, int_coef, gain_ctl, targ_cnt; - uint32_t lanestagger; - int clock = crtc_state->port_clock; - - if (intel_encoder->type == INTEL_OUTPUT_HDMI) { - intel_clock_t best_clock; - - /* Calculate HDMI div */ - /* - * FIXME: tie the following calculation into - * i9xx_crtc_compute_clock - */ - if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) { - DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n", - clock, pipe_name(intel_crtc->pipe)); - return false; - } - - clk_div.p1 = best_clock.p1; - clk_div.p2 = best_clock.p2; - WARN_ON(best_clock.m1 != 2); - clk_div.n = best_clock.n; - clk_div.m2_int = best_clock.m2 >> 22; - clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1); - clk_div.m2_frac_en = clk_div.m2_frac != 0; - - vco = best_clock.vco; - } else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT || - intel_encoder->type == INTEL_OUTPUT_EDP) { - int i; - - clk_div = bxt_dp_clk_val[0]; - for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) { - if (bxt_dp_clk_val[i].clock == clock) { - clk_div = bxt_dp_clk_val[i]; - break; - } - } - vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2; - } - - if (vco >= 6200000 && vco <= 6700000) { - prop_coef = 4; - int_coef = 9; - gain_ctl = 3; - targ_cnt = 8; - } else if ((vco > 5400000 && vco < 6200000) || - (vco >= 4800000 && vco < 5400000)) { - prop_coef = 5; - int_coef = 11; - gain_ctl = 3; - targ_cnt = 9; - } else if (vco == 5400000) { - prop_coef = 3; - int_coef = 8; - gain_ctl = 1; - targ_cnt = 9; - } else { - DRM_ERROR("Invalid VCO\n"); - return false; - } - - memset(&crtc_state->dpll_hw_state, 0, - sizeof(crtc_state->dpll_hw_state)); - - if (clock > 270000) - lanestagger = 0x18; - else if (clock > 135000) - lanestagger = 0x0d; - else if (clock > 67000) - lanestagger = 0x07; - else if (clock > 33000) - lanestagger = 0x04; - else - lanestagger = 0x02; - - crtc_state->dpll_hw_state.ebb0 = - PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2); - crtc_state->dpll_hw_state.pll0 = clk_div.m2_int; - crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n); - crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac; - - if (clk_div.m2_frac_en) - crtc_state->dpll_hw_state.pll3 = - PORT_PLL_M2_FRAC_ENABLE; - - crtc_state->dpll_hw_state.pll6 = - prop_coef | PORT_PLL_INT_COEFF(int_coef); - crtc_state->dpll_hw_state.pll6 |= - PORT_PLL_GAIN_CTL(gain_ctl); - - crtc_state->dpll_hw_state.pll8 = targ_cnt; - - crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT; - - crtc_state->dpll_hw_state.pll10 = - PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT) - | PORT_PLL_DCO_AMP_OVR_EN_H; - - crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE; - - crtc_state->dpll_hw_state.pcsdw12 = - LANESTAGGER_STRAP_OVRD | lanestagger; - - pll = intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder); - if (pll == NULL) { - DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", - pipe_name(intel_crtc->pipe)); - return false; - } - - /* shared DPLL id 0 is DPLL A */ - crtc_state->ddi_pll_sel = pll->id; - - return true; + return !!intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder); } /* diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 61887ae..a90ef34 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1342,29 +1342,156 @@ out: return ret; } +/* bxt clock parameters */ +struct bxt_clk_div { + int clock; + uint32_t p1; + uint32_t p2; + uint32_t m2_int; + uint32_t m2_frac; + bool m2_frac_en; + uint32_t n; +}; + +/* pre-calculated values for DP linkrates */ +static const struct bxt_clk_div bxt_dp_clk_val[] = { + {162000, 4, 2, 32, 1677722, 1, 1}, + {270000, 4, 1, 27, 0, 0, 1}, + {540000, 2, 1, 27, 0, 0, 1}, + {216000, 3, 2, 32, 1677722, 1, 1}, + {243000, 4, 1, 24, 1258291, 1, 1}, + {324000, 4, 1, 32, 1677722, 1, 1}, + {432000, 3, 1, 32, 1677722, 1, 1} +}; + static struct intel_shared_dpll * bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct intel_digital_port *intel_dig_port; struct intel_shared_dpll *pll; enum intel_dpll_id i; + struct intel_digital_port *intel_dig_port; + struct bxt_clk_div clk_div = {0}; + int vco = 0; + uint32_t prop_coef, int_coef, gain_ctl, targ_cnt; + uint32_t lanestagger; + int clock = crtc_state->port_clock; - /* PLL is attached to port in bxt */ - encoder = intel_ddi_get_crtc_new_encoder(crtc_state); - if (WARN_ON(!encoder)) + if (encoder->type == INTEL_OUTPUT_HDMI) { + intel_clock_t best_clock; + + /* Calculate HDMI div */ + /* + * FIXME: tie the following calculation into + * i9xx_crtc_compute_clock + */ + if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) { + DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n", + clock, pipe_name(crtc->pipe)); + return NULL; + } + + clk_div.p1 = best_clock.p1; + clk_div.p2 = best_clock.p2; + WARN_ON(best_clock.m1 != 2); + clk_div.n = best_clock.n; + clk_div.m2_int = best_clock.m2 >> 22; + clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1); + clk_div.m2_frac_en = clk_div.m2_frac != 0; + + vco = best_clock.vco; + } else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT || + encoder->type == INTEL_OUTPUT_EDP) { + int i; + + clk_div = bxt_dp_clk_val[0]; + for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) { + if (bxt_dp_clk_val[i].clock == clock) { + clk_div = bxt_dp_clk_val[i]; + break; + } + } + vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2; + } + + if (vco >= 6200000 && vco <= 6700000) { + prop_coef = 4; + int_coef = 9; + gain_ctl = 3; + targ_cnt = 8; + } else if ((vco > 5400000 && vco < 6200000) || + (vco >= 4800000 && vco < 5400000)) { + prop_coef = 5; + int_coef = 11; + gain_ctl = 3; + targ_cnt = 9; + } else if (vco == 5400000) { + prop_coef = 3; + int_coef = 8; + gain_ctl = 1; + targ_cnt = 9; + } else { + DRM_ERROR("Invalid VCO\n"); return NULL; + } + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + + if (clock > 270000) + lanestagger = 0x18; + else if (clock > 135000) + lanestagger = 0x0d; + else if (clock > 67000) + lanestagger = 0x07; + else if (clock > 33000) + lanestagger = 0x04; + else + lanestagger = 0x02; + + crtc_state->dpll_hw_state.ebb0 = + PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2); + crtc_state->dpll_hw_state.pll0 = clk_div.m2_int; + crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n); + crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac; + + if (clk_div.m2_frac_en) + crtc_state->dpll_hw_state.pll3 = + PORT_PLL_M2_FRAC_ENABLE; + + crtc_state->dpll_hw_state.pll6 = + prop_coef | PORT_PLL_INT_COEFF(int_coef); + crtc_state->dpll_hw_state.pll6 |= + PORT_PLL_GAIN_CTL(gain_ctl); + + crtc_state->dpll_hw_state.pll8 = targ_cnt; + + crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT; + + crtc_state->dpll_hw_state.pll10 = + PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT) + | PORT_PLL_DCO_AMP_OVR_EN_H; + + crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE; + + crtc_state->dpll_hw_state.pcsdw12 = + LANESTAGGER_STRAP_OVRD | lanestagger; intel_dig_port = enc_to_dig_port(&encoder->base); + /* 1:1 mapping between ports and PLLs */ - i = (enum intel_dpll_id)intel_dig_port->port; - pll = &dev_priv->shared_dplls[i]; + i = (enum intel_dpll_id) intel_dig_port->port; + pll = intel_get_shared_dpll_by_id(dev_priv, i); + DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n", crtc->base.base.id, pll->name); intel_reference_shared_dpll(pll, crtc_state); + /* shared DPLL id 0 is DPLL A */ + crtc_state->ddi_pll_sel = pll->id; + return pll; } -- cgit v0.10.2 From 9d16da65bfda54dea0b9b10ec49a0e1d23b631eb Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:26 +0200 Subject: drm/i915: Manage HSW/BDW LCPLLs with the shared dpll interface Manage the LCPLLs used with DisplayPort, so that all the HSW/BDW DPLLs are managed by the shared dpll code. v2: Introduce INTEL_DPLL_ALWAYS_ON flag to please state checker. (Ander) v3: Initialize pll->flags in intel_shared_dpll_init(). (Ander) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-13-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 50cc264..31f9aa0 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -992,17 +992,13 @@ hsw_ddi_pll_select(struct intel_crtc *intel_crtc, { struct intel_shared_dpll *pll; - if (intel_encoder->type == INTEL_OUTPUT_HDMI || - intel_encoder->type == INTEL_OUTPUT_ANALOG) { - pll = intel_get_shared_dpll(intel_crtc, crtc_state, - intel_encoder); - if (!pll) - DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", - pipe_name(intel_crtc->pipe)); - return pll; - } else { - return true; - } + pll = intel_get_shared_dpll(intel_crtc, crtc_state, + intel_encoder); + if (!pll) + DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", + pipe_name(intel_crtc->pipe)); + + return pll; } static bool diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9d2f494..7e00ee5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9821,13 +9821,19 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, case PORT_CLK_SEL_SPLL: id = DPLL_ID_SPLL; break; + case PORT_CLK_SEL_LCPLL_810: + id = DPLL_ID_LCPLL_810; + break; + case PORT_CLK_SEL_LCPLL_1350: + id = DPLL_ID_LCPLL_1350; + break; + case PORT_CLK_SEL_LCPLL_2700: + id = DPLL_ID_LCPLL_2700; + break; default: MISSING_CASE(pipe_config->ddi_pll_sel); /* fall through */ case PORT_CLK_SEL_NONE: - case PORT_CLK_SEL_LCPLL_810: - case PORT_CLK_SEL_LCPLL_1350: - case PORT_CLK_SEL_LCPLL_2700: return; } @@ -12942,11 +12948,14 @@ check_shared_dpll_state(struct drm_device *dev) pll->active, hweight32(pll->config.crtc_mask)); I915_STATE_WARN(pll->active && !pll->on, "pll in active use but not on in sw tracking\n"); - I915_STATE_WARN(pll->on && !pll->active, - "pll in on but not on in use in sw tracking\n"); - I915_STATE_WARN(pll->on != active, - "pll on state mismatch (expected %i, found %i)\n", - pll->on, active); + + if (!(pll->flags & INTEL_DPLL_ALWAYS_ON)) { + I915_STATE_WARN(pll->on && !pll->active, + "pll in on but not on in use in sw tracking\n"); + I915_STATE_WARN(pll->on != active, + "pll on state mismatch (expected %i, found %i)\n", + pll->on, active); + } for_each_intel_crtc(dev, crtc) { if (crtc->base.state->enable && crtc->config->shared_dpll == pll) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 109ae61..4f0fad3 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1283,25 +1283,6 @@ skl_edp_set_pll_config(struct intel_crtc_state *pipe_config) pipe_config->dpll_hw_state.ctrl1 = ctrl1; } -void -hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config) -{ - memset(&pipe_config->dpll_hw_state, 0, - sizeof(pipe_config->dpll_hw_state)); - - switch (pipe_config->port_clock / 2) { - case 81000: - pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810; - break; - case 135000: - pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350; - break; - case 270000: - pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700; - break; - } -} - static int intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates) { @@ -1661,10 +1642,8 @@ found: if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && is_edp(intel_dp)) skl_edp_set_pll_config(pipe_config); - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) /* handled in ddi */; - else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) - hsw_dp_set_ddi_pll_sel(pipe_config); else intel_dp_set_clock(encoder, pipe_config); diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index a2bd698..8d1b703 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -33,7 +33,6 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { - struct drm_device *dev = encoder->base.dev; struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; struct intel_dp *intel_dp = &intel_dig_port->dp; @@ -92,9 +91,6 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, pipe_config->dp_m_n.tu = slots; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) - hsw_dp_set_ddi_pll_sel(pipe_config); - return true; } diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index a90ef34..a83af07 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -447,6 +447,12 @@ static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll) return PORT_CLK_SEL_WRPLL2; case DPLL_ID_SPLL: return PORT_CLK_SEL_SPLL; + case DPLL_ID_LCPLL_810: + return PORT_CLK_SEL_LCPLL_810; + case DPLL_ID_LCPLL_1350: + return PORT_CLK_SEL_LCPLL_1350; + case DPLL_ID_LCPLL_2700: + return PORT_CLK_SEL_LCPLL_2700; default: return PORT_CLK_SEL_NONE; } @@ -671,9 +677,13 @@ static struct intel_shared_dpll * hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct intel_shared_dpll *pll; int clock = crtc_state->port_clock; + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + if (encoder->type == INTEL_OUTPUT_HDMI) { uint32_t val; unsigned p, n2, r2; @@ -684,21 +694,37 @@ hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p); - memset(&crtc_state->dpll_hw_state, 0, - sizeof(crtc_state->dpll_hw_state)); - crtc_state->dpll_hw_state.wrpll = val; pll = intel_find_shared_dpll(crtc, crtc_state, DPLL_ID_WRPLL1, DPLL_ID_WRPLL2); + } else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT || + encoder->type == INTEL_OUTPUT_DP_MST || + encoder->type == INTEL_OUTPUT_EDP) { + enum intel_dpll_id pll_id; + + switch (clock / 2) { + case 81000: + pll_id = DPLL_ID_LCPLL_810; + break; + case 135000: + pll_id = DPLL_ID_LCPLL_1350; + break; + case 270000: + pll_id = DPLL_ID_LCPLL_2700; + break; + default: + DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock); + return NULL; + } + + pll = intel_get_shared_dpll_by_id(dev_priv, pll_id); + } else if (encoder->type == INTEL_OUTPUT_ANALOG) { if (WARN_ON(crtc_state->port_clock / 2 != 135000)) return NULL; - memset(&crtc_state->dpll_hw_state, 0, - sizeof(crtc_state->dpll_hw_state)); - crtc_state->dpll_hw_state.spll = SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC; @@ -731,6 +757,29 @@ static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = { .get_hw_state = hsw_ddi_spll_get_hw_state, }; +static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ +} + +static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ +} + +static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + return true; +} + +static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = { + .enable = hsw_ddi_lcpll_enable, + .disable = hsw_ddi_lcpll_disable, + .get_hw_state = hsw_ddi_lcpll_get_hw_state, +}; + struct skl_dpll_regs { i915_reg_t ctl, cfgcr1, cfgcr2; }; @@ -1537,6 +1586,7 @@ struct dpll_info { const char *name; const int id; const struct intel_shared_dpll_funcs *funcs; + uint32_t flags; }; struct intel_dpll_mgr { @@ -1548,9 +1598,9 @@ struct intel_dpll_mgr { }; static const struct dpll_info pch_plls[] = { - { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs }, - { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs }, - { NULL, -1, NULL }, + { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 }, + { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 }, + { NULL, -1, NULL, 0 }, }; static const struct intel_dpll_mgr pch_pll_mgr = { @@ -1559,9 +1609,12 @@ static const struct intel_dpll_mgr pch_pll_mgr = { }; static const struct dpll_info hsw_plls[] = { - { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs }, - { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs }, - { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs }, + { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 }, + { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 }, + { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 }, + { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON }, + { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON }, + { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON }, { NULL, -1, NULL, }, }; @@ -1571,9 +1624,9 @@ static const struct intel_dpll_mgr hsw_pll_mgr = { }; static const struct dpll_info skl_plls[] = { - { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs }, - { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs }, - { "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs }, + { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 }, + { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 }, + { "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 }, { NULL, -1, NULL, }, }; @@ -1583,9 +1636,9 @@ static const struct intel_dpll_mgr skl_pll_mgr = { }; static const struct dpll_info bxt_plls[] = { - { "PORT PLL A", 0, &bxt_ddi_pll_funcs }, - { "PORT PLL B", 1, &bxt_ddi_pll_funcs }, - { "PORT PLL C", 2, &bxt_ddi_pll_funcs }, + { "PORT PLL A", 0, &bxt_ddi_pll_funcs, 0 }, + { "PORT PLL B", 1, &bxt_ddi_pll_funcs, 0 }, + { "PORT PLL C", 2, &bxt_ddi_pll_funcs, 0 }, { NULL, -1, NULL, }, }; @@ -1623,6 +1676,7 @@ void intel_shared_dpll_init(struct drm_device *dev) dev_priv->shared_dplls[i].id = dpll_info[i].id; dev_priv->shared_dplls[i].name = dpll_info[i].name; dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs; + dev_priv->shared_dplls[i].flags = dpll_info[i].flags; } dev_priv->dpll_mgr = dpll_mgr; diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index 82e53f5..adf4706 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -49,13 +49,21 @@ enum intel_dpll_id { DPLL_ID_WRPLL1 = 0, DPLL_ID_WRPLL2 = 1, DPLL_ID_SPLL = 2, + DPLL_ID_LCPLL_810 = 3, + DPLL_ID_LCPLL_1350 = 4, + DPLL_ID_LCPLL_2700 = 5, /* skl */ DPLL_ID_SKL_DPLL1 = 0, DPLL_ID_SKL_DPLL2 = 1, DPLL_ID_SKL_DPLL3 = 2, }; -#define I915_NUM_PLLS 3 +#define I915_NUM_PLLS 6 + +/** Inform the state checker that the DPLL is kept enabled even if not + * in use by any crtc. + */ +#define INTEL_DPLL_ALWAYS_ON (1 << 0) struct intel_dpll_hw_state { /* i9xx, pch plls */ @@ -113,6 +121,8 @@ struct intel_shared_dpll { enum intel_dpll_id id; struct intel_shared_dpll_funcs funcs; + + uint32_t flags; }; #define SKL_DPLL0 0 diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1f62fba..1e39928 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1312,7 +1312,6 @@ void intel_edp_drrs_invalidate(struct drm_device *dev, 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); void intel_dp_program_link_training_pattern(struct intel_dp *intel_dp, -- cgit v0.10.2 From a3c988ea068c94f39a2e6bd37e0faf1c2606a55d Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 8 Mar 2016 17:46:27 +0200 Subject: drm/i915: Make SKL/KBL DPLL0 managed by the shared dpll code Include DPLL0 in the managed dplls for SKL/KBL. While it has to be kept enabled because of it driving CDCLK, it is better to special case that inside the DPLL code than in the higher level. v2: Use INTEL_DPLL_ALWAYS_ON flag. (Ander) v3: Remove extremely paranoid WARN_ONs. (Maarten) Handle DPLL0 in skylake_get_ddi_pll() properly. (Ander) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457451987-17466-14-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 31f9aa0..91654ff 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1008,9 +1008,6 @@ skl_ddi_pll_select(struct intel_crtc *intel_crtc, { struct intel_shared_dpll *pll; - if (intel_encoder->type == INTEL_OUTPUT_EDP) - return true; - pll = intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder); if (pll == NULL) { DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", @@ -1570,24 +1567,6 @@ void intel_ddi_clk_select(struct intel_encoder *encoder, uint32_t dpll = pipe_config->ddi_pll_sel; uint32_t val; - /* - * DPLL0 is used for eDP and is the only "private" DPLL (as - * opposed to shared) on SKL - */ - if (encoder->type == INTEL_OUTPUT_EDP) { - WARN_ON(dpll != SKL_DPLL0); - - val = I915_READ(DPLL_CTRL1); - - val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | - DPLL_CTRL1_SSC(dpll) | - DPLL_CTRL1_LINK_RATE_MASK(dpll)); - val |= pipe_config->dpll_hw_state.ctrl1 << (dpll * 6); - - I915_WRITE(DPLL_CTRL1, val); - POSTING_READ(DPLL_CTRL1); - } - /* DDI -> PLL mapping */ val = I915_READ(DPLL_CTRL2); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7e00ee5..28556a8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9771,21 +9771,15 @@ static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv, struct intel_crtc_state *pipe_config) { enum intel_dpll_id id; - u32 temp, dpll_ctl1; + u32 temp; temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port); pipe_config->ddi_pll_sel = temp >> (port * 3 + 1); switch (pipe_config->ddi_pll_sel) { case SKL_DPLL0: - /* - * On SKL the eDP DPLL (DPLL0 as we don't use SSC) is not part - * of the shared DPLL framework and thus needs to be read out - * separately - */ - dpll_ctl1 = I915_READ(DPLL_CTRL1); - pipe_config->dpll_hw_state.ctrl1 = dpll_ctl1 & 0x3f; - return; + id = DPLL_ID_SKL_DPLL0; + break; case SKL_DPLL1: id = DPLL_ID_SKL_DPLL1; break; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 4f0fad3..13e1cc8 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1237,52 +1237,6 @@ intel_dp_connector_unregister(struct intel_connector *intel_connector) intel_connector_unregister(intel_connector); } -static void -skl_edp_set_pll_config(struct intel_crtc_state *pipe_config) -{ - u32 ctrl1; - - memset(&pipe_config->dpll_hw_state, 0, - sizeof(pipe_config->dpll_hw_state)); - - pipe_config->ddi_pll_sel = SKL_DPLL0; - pipe_config->dpll_hw_state.cfgcr1 = 0; - pipe_config->dpll_hw_state.cfgcr2 = 0; - - ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0); - switch (pipe_config->port_clock / 2) { - case 81000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, - SKL_DPLL0); - break; - case 135000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, - SKL_DPLL0); - break; - case 270000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, - SKL_DPLL0); - break; - case 162000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, - SKL_DPLL0); - break; - /* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which - results in CDCLK change. Need to handle the change of CDCLK by - disabling pipes and re-enabling them */ - case 108000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, - SKL_DPLL0); - break; - case 216000: - ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, - SKL_DPLL0); - break; - - } - pipe_config->dpll_hw_state.ctrl1 = ctrl1; -} - static int intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates) { @@ -1640,11 +1594,7 @@ found: &pipe_config->dp_m2_n2); } - if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && is_edp(intel_dp)) - skl_edp_set_pll_config(pipe_config); - else if (IS_BROXTON(dev) || IS_HASWELL(dev) || IS_BROADWELL(dev)) - /* handled in ddi */; - else + if (!HAS_DDI(dev)) intel_dp_set_clock(encoder, pipe_config); return true; diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index a83af07..4b636c4 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -785,7 +785,12 @@ struct skl_dpll_regs { }; /* this array is indexed by the *shared* pll id */ -static const struct skl_dpll_regs skl_dpll_regs[3] = { +static const struct skl_dpll_regs skl_dpll_regs[4] = { + { + /* DPLL 0 */ + .ctl = LCPLL1_CTL, + /* DPLL 0 doesn't support HDMI mode */ + }, { /* DPLL 1 */ .ctl = LCPLL2_CTL, @@ -806,24 +811,27 @@ static const struct skl_dpll_regs skl_dpll_regs[3] = { }, }; -static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, - struct intel_shared_dpll *pll) +static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) { uint32_t val; - unsigned int dpll; - const struct skl_dpll_regs *regs = skl_dpll_regs; - - /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ - dpll = pll->id + 1; val = I915_READ(DPLL_CTRL1); - val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) | - DPLL_CTRL1_LINK_RATE_MASK(dpll)); - val |= pll->config.hw_state.ctrl1 << (dpll * 6); + val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) | + DPLL_CTRL1_LINK_RATE_MASK(pll->id)); + val |= pll->config.hw_state.ctrl1 << (pll->id * 6); I915_WRITE(DPLL_CTRL1, val); POSTING_READ(DPLL_CTRL1); +} + +static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + const struct skl_dpll_regs *regs = skl_dpll_regs; + + skl_ddi_pll_write_ctrl1(dev_priv, pll); I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1); I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2); @@ -834,8 +842,14 @@ static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, I915_WRITE(regs[pll->id].ctl, I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE); - if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5)) - DRM_ERROR("DPLL %d not locked\n", dpll); + if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(pll->id), 5)) + DRM_ERROR("DPLL %d not locked\n", pll->id); +} + +static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ + skl_ddi_pll_write_ctrl1(dev_priv, pll); } static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv, @@ -849,12 +863,16 @@ static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv, POSTING_READ(regs[pll->id].ctl); } +static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll) +{ +} + static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll, struct intel_dpll_hw_state *hw_state) { uint32_t val; - unsigned int dpll; const struct skl_dpll_regs *regs = skl_dpll_regs; bool ret; @@ -863,18 +881,15 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, ret = false; - /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */ - dpll = pll->id + 1; - val = I915_READ(regs[pll->id].ctl); if (!(val & LCPLL_PLL_ENABLE)) goto out; val = I915_READ(DPLL_CTRL1); - hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f; + hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f; /* avoid reading back stale values if HDMI mode is not enabled */ - if (val & DPLL_CTRL1_HDMI_MODE(dpll)) { + if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) { hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1); hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2); } @@ -886,6 +901,35 @@ out: return ret; } +static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv, + struct intel_shared_dpll *pll, + struct intel_dpll_hw_state *hw_state) +{ + uint32_t val; + const struct skl_dpll_regs *regs = skl_dpll_regs; + bool ret; + + if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS)) + return false; + + ret = false; + + /* DPLL0 is always enabled since it drives CDCLK */ + val = I915_READ(regs[pll->id].ctl); + if (WARN_ON(!(val & LCPLL_PLL_ENABLE))) + goto out; + + val = I915_READ(DPLL_CTRL1); + hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f; + + ret = true; + +out: + intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); + + return ret; +} + struct skl_wrpll_context { uint64_t min_deviation; /* current minimal deviation */ uint64_t central_freq; /* chosen central freq */ @@ -1165,7 +1209,8 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | wrpll_params.central_freq; } else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT || - encoder->type == INTEL_OUTPUT_DP_MST) { + encoder->type == INTEL_OUTPUT_DP_MST || + encoder->type == INTEL_OUTPUT_EDP) { switch (crtc_state->port_clock / 2) { case 81000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0); @@ -1176,6 +1221,19 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, case 270000: ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0); break; + /* eDP 1.4 rates */ + case 162000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0); + break; + /* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which + results in CDCLK change. Need to handle the change of CDCLK by + disabling pipes and re-enabling them */ + case 108000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0); + break; + case 216000: + ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0); + break; } cfgcr1 = cfgcr2 = 0; @@ -1190,13 +1248,18 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, crtc_state->dpll_hw_state.cfgcr1 = cfgcr1; crtc_state->dpll_hw_state.cfgcr2 = cfgcr2; - pll = intel_find_shared_dpll(crtc, crtc_state, - DPLL_ID_SKL_DPLL1, DPLL_ID_SKL_DPLL3); + if (encoder->type == INTEL_OUTPUT_EDP) + pll = intel_find_shared_dpll(crtc, crtc_state, + DPLL_ID_SKL_DPLL0, + DPLL_ID_SKL_DPLL0); + else + pll = intel_find_shared_dpll(crtc, crtc_state, + DPLL_ID_SKL_DPLL1, + DPLL_ID_SKL_DPLL3); if (!pll) return NULL; - /* shared DPLL id 0 is DPLL 1 */ - crtc_state->ddi_pll_sel = pll->id + 1; + crtc_state->ddi_pll_sel = pll->id; intel_reference_shared_dpll(pll, crtc_state); @@ -1209,6 +1272,12 @@ static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = { .get_hw_state = skl_ddi_pll_get_hw_state, }; +static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = { + .enable = skl_ddi_dpll0_enable, + .disable = skl_ddi_dpll0_disable, + .get_hw_state = skl_ddi_dpll0_get_hw_state, +}; + static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, struct intel_shared_dpll *pll) { @@ -1624,9 +1693,10 @@ static const struct intel_dpll_mgr hsw_pll_mgr = { }; static const struct dpll_info skl_plls[] = { - { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 }, - { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 }, - { "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 }, + { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON }, + { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 }, + { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 }, + { "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 }, { NULL, -1, NULL, }, }; diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index adf4706..1d34147 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -54,9 +54,10 @@ enum intel_dpll_id { DPLL_ID_LCPLL_2700 = 5, /* skl */ - DPLL_ID_SKL_DPLL1 = 0, - DPLL_ID_SKL_DPLL2 = 1, - DPLL_ID_SKL_DPLL3 = 2, + DPLL_ID_SKL_DPLL0 = 0, + DPLL_ID_SKL_DPLL1 = 1, + DPLL_ID_SKL_DPLL2 = 2, + DPLL_ID_SKL_DPLL3 = 3, }; #define I915_NUM_PLLS 6 -- cgit v0.10.2 From 8b1f165a4a8f64c28cf42d10e1f4d3b451dedc51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 7 Mar 2016 17:56:57 +0200 Subject: drm/i915: Actually retry with bit-banging after GMBUS timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the GMBUS transfer times out, we set force_bit=1 and return -EAGAIN expecting the i2c core to call the .master_xfer hook again so that we will retry the same transfer via bit-banging. This is in case the gmbus hardware is somehow faulty. Unfortunately we left adapter->retries to 0, meaning the i2c core didn't actually do the retry. Let's tell the core we want one retry when we return -EAGAIN. Note that i2c-algo-bit also uses this retry count for some internal retries, so we'll end up increasing those a bit as well. Cc: Jani Nikula Cc: drm-intel-fixes@lists.freedesktop.org Fixes: bffce907d640 ("drm/i915: abstract i2c bit banging fallback in gmbus xfer") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1457366220-29409-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index deb8282..52fbe53 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -664,6 +664,12 @@ int intel_setup_gmbus(struct drm_device *dev) bus->adapter.algo = &gmbus_algorithm; + /* + * We wish to retry with bit banging + * after a timed out GMBUS attempt. + */ + bus->adapter.retries = 1; + /* By default use a conservative clock rate */ bus->reg0 = pin | GMBUS_RATE_100KHZ; -- cgit v0.10.2 From dcb2e993f3c0cecc6c0d905cbf2e428640a957c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2016 19:07:23 +0200 Subject: Revert "drm/i915: Enable PSR by default on Valleyview and Cherryview." MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit a38c274faad0ec6aba692e294ec751d04dbba803. PSR causes all sorts of vblank wait timeouts and whanot on CHV. Disable it again. Cc: Rodrigo Vivi Fixes: a38c274faad0 ("drm/i915: Enable PSR by default on Valleyview and Cherryview.") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1457543247-13987-2-git-send-email-ville.syrjala@linux.intel.com Link: http://patchwork.freedesktop.org/patch/msgid/1457543247-13987-2-git-send-email-ville.syrjala@linux.intel.com Acked-by: Rodrigo Vivi Reviewed-by: Maarten Lankhorst diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index b1413be..38e9518 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -781,8 +781,7 @@ void intel_psr_init(struct drm_device *dev) /* Per platform default */ if (i915.enable_psr == -1) { - if (IS_HASWELL(dev) || IS_BROADWELL(dev) || - IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) i915.enable_psr = 1; else i915.enable_psr = 0; -- cgit v0.10.2 From 9f6151c9039084e18c118831779a99ac8f29e39c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2016 19:07:24 +0200 Subject: drm/i915: Pass the correct crtc state to .update_plane() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass the current crtc state, not the old crtc state, to the .update_plane() hook. Noticed on BSW when PRIMSIZE was getting programmed to a stale value which produced utter garbage on screen eg. wwhen going from 1920x1080 to 1024x768. Cc: Maarten Lankhorst Fixes: a758e6845825 ("drm/i915: Do not use commit_plane for sprite planes.") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1457543247-13987-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index e0b851a..7de7721 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -195,12 +195,10 @@ static void intel_plane_atomic_update(struct drm_plane *plane, struct intel_plane_state *intel_state = to_intel_plane_state(plane->state); struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc; - struct drm_crtc_state *crtc_state = - drm_atomic_get_existing_crtc_state(old_state->state, crtc); if (intel_state->visible) intel_plane->update_plane(plane, - to_intel_crtc_state(crtc_state), + to_intel_crtc_state(crtc->state), intel_state); else intel_plane->disable_plane(plane, crtc); -- cgit v0.10.2 From caed361d83b204b7766924b80463bf7502ee7986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2016 19:07:25 +0200 Subject: drm/i915: Fix watermarks for VLV/CHV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 92826fcdfc14 ("drm/i915: Calculate watermark related members in the crtc_state, v4.") broke thigns by removing the pre vs. post wm update distinction. We also lost the pre plane wm update entirely for VLV/CHV from the crtc enable path. This caused underruns on modeset and plane enable/disable on CHV, and often those can lead to a dead pipe. So let's bring back the pre vs. post thing, and let's toss in an explicit wm update to valleyview_crtc_enable() to avoid having to put it into the common code. This is more or less a partial revert of the offending commit. Cc: Maarten Lankhorst Cc: drm-intel-fixes@lists.freedesktop.org Fixes: 92826fcdfc14 ("drm/i915: Calculate watermark related members in the crtc_state, v4.") Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1457543247-13987-4-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 6a661e7..79448f1 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -96,7 +96,8 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state->update_pipe = false; crtc_state->disable_lp_wm = false; crtc_state->disable_cxsr = false; - crtc_state->wm_changed = false; + crtc_state->update_wm_pre = false; + crtc_state->update_wm_post = false; crtc_state->fb_changed = false; crtc_state->wm.need_postvbl_update = false; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 28556a8..860c530 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4677,7 +4677,7 @@ static void intel_post_plane_update(struct intel_crtc *crtc) crtc->wm.cxsr_allowed = true; - if (pipe_config->wm_changed && pipe_config->base.active) + if (pipe_config->update_wm_post && pipe_config->base.active) intel_update_watermarks(&crtc->base); if (atomic->update_fbc) @@ -4759,7 +4759,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) */ if (dev_priv->display.initial_watermarks != NULL) dev_priv->display.initial_watermarks(pipe_config); - else if (pipe_config->wm_changed) + else if (pipe_config->update_wm_pre) intel_update_watermarks(&crtc->base); } @@ -6130,6 +6130,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) intel_crtc_load_lut(crtc); + intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); assert_vblank_disabled(crtc); @@ -11776,19 +11777,27 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, plane->base.id, was_visible, visible, turn_off, turn_on, mode_changed); - if (turn_on || turn_off) { - pipe_config->wm_changed = true; + if (turn_on) { + pipe_config->update_wm_pre = true; + + /* must disable cxsr around plane enable/disable */ + if (plane->type != DRM_PLANE_TYPE_CURSOR) + pipe_config->disable_cxsr = true; + } else if (turn_off) { + pipe_config->update_wm_post = true; /* must disable cxsr around plane enable/disable */ if (plane->type != DRM_PLANE_TYPE_CURSOR) pipe_config->disable_cxsr = true; } else if (intel_wm_need_update(plane, plane_state)) { - pipe_config->wm_changed = true; + /* FIXME bollocks */ + pipe_config->update_wm_pre = true; + pipe_config->update_wm_post = true; } /* Pre-gen9 platforms need two-step watermark updates */ - if (pipe_config->wm_changed && INTEL_INFO(dev)->gen < 9 && - dev_priv->display.optimize_watermarks) + if ((pipe_config->update_wm_pre || pipe_config->update_wm_post) && + INTEL_INFO(dev)->gen < 9 && dev_priv->display.optimize_watermarks) to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true; if (visible || was_visible) @@ -11888,7 +11897,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, } if (mode_changed && !crtc_state->active) - pipe_config->wm_changed = true; + pipe_config->update_wm_post = true; if (mode_changed && crtc_state->enable && dev_priv->display.crtc_compute_clock && @@ -13442,12 +13451,12 @@ static bool needs_vblank_wait(struct intel_crtc_state *crtc_state) return true; /* wm changes, need vblank before final wm's */ - if (crtc_state->wm_changed) + if (crtc_state->update_wm_post) return true; /* * cxsr is re-enabled after vblank. - * This is already handled by crtc_state->wm_changed, + * This is already handled by crtc_state->update_wm_post, * but added for clarity. */ if (crtc_state->disable_cxsr) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1e39928..02b3d22 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -420,7 +420,7 @@ struct intel_crtc_state { bool update_pipe; /* can a fast modeset be performed? */ bool disable_cxsr; - bool wm_changed; /* watermarks are updated */ + bool update_wm_pre, update_wm_post; /* watermarks are updated */ bool fb_changed; /* fb on any of the planes is changed */ /* Pipe source size (ie. panel fitter input size) -- cgit v0.10.2 From 2622a08108b07fdb6ad74c46fc05e445e8be94bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2016 19:07:26 +0200 Subject: drm/i915: Wait for vblank after cxsr disable in pre_plane_update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We must wait for the hardware to exit cxsr before doing the plane update, so add the missing vblank wait to pre_plane_update after disabling cxsr. We have the wait for vblank in the pre_disable_primary hook, but not in the pre_plane_update hook. Just move the code from (and comment) from pre_disable_primary into pre_plane_update. Well, we still have to keep it in pre_disable_primary for these strange _noatomic codepaths, so let's do another version of pre_disable_primary for those. Also toss in some FIXMEs in the hope that someone will eventually clean up this pre_disable_primary mess. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1457543247-13987-5-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 860c530..6f8d7dd5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -116,7 +116,7 @@ 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); -static void intel_pre_disable_primary(struct drm_crtc *crtc); +static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc); typedef struct { int min, max; @@ -2619,7 +2619,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, */ to_intel_plane_state(plane_state)->visible = false; crtc_state->plane_mask &= ~(1 << drm_plane_index(primary)); - intel_pre_disable_primary(&intel_crtc->base); + intel_pre_disable_primary_noatomic(&intel_crtc->base); intel_plane->disable_plane(primary, &intel_crtc->base); return; @@ -4615,16 +4615,7 @@ intel_post_enable_primary(struct drm_crtc *crtc) intel_check_pch_fifo_underruns(dev_priv); } -/** - * intel_pre_disable_primary - Perform operations before disabling primary plane - * @crtc: the CRTC whose primary plane is to be disabled - * - * Performs potentially sleeping operations that must be done before the - * primary plane is disabled, such as updating FBC and IPS. Note that this may - * be called due to an explicit primary plane update, or due to an implicit - * disable that is caused when a sprite plane completely hides the primary - * plane. - */ +/* FIXME move all this to pre_plane_update() with proper state tracking */ static void intel_pre_disable_primary(struct drm_crtc *crtc) { @@ -4643,6 +4634,26 @@ intel_pre_disable_primary(struct drm_crtc *crtc) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); /* + * FIXME IPS should be fine as long as one plane is + * enabled, but in practice it seems to have problems + * when going from primary only to sprite only and vice + * versa. + */ + hsw_disable_ips(intel_crtc); +} + +/* FIXME get rid of this and use pre_plane_update */ +static void +intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + + intel_pre_disable_primary(crtc); + + /* * Vblank time updates from the shadow to live plane control register * are blocked if the memory self-refresh mode is active at that * moment. So to make sure the plane gets truly disabled, disable @@ -4656,14 +4667,6 @@ intel_pre_disable_primary(struct drm_crtc *crtc) dev_priv->wm.vlv.cxsr = false; intel_wait_for_vblank(dev, pipe); } - - /* - * FIXME IPS should be fine as long as one plane is - * enabled, but in practice it seems to have problems - * when going from primary only to sprite only and vice - * versa. - */ - hsw_disable_ips(intel_crtc); } static void intel_post_plane_update(struct intel_crtc *crtc) @@ -4720,8 +4723,20 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) if (pipe_config->disable_cxsr) { crtc->wm.cxsr_allowed = false; - if (old_crtc_state->base.active) + /* + * Vblank time updates from the shadow to live plane control register + * are blocked if the memory self-refresh mode is active at that + * moment. So to make sure the plane gets truly disabled, disable + * first the self-refresh mode. The self-refresh enable bit in turn + * will be checked/applied by the HW only at the next frame start + * event which is after the vblank start event, so we need to have a + * wait-for-vblank between disabling the plane and the pipe. + */ + if (old_crtc_state->base.active) { intel_set_memory_cxsr(dev_priv, false); + dev_priv->wm.vlv.cxsr = false; + intel_wait_for_vblank(dev, crtc->pipe); + } } /* @@ -6269,7 +6284,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) if (to_intel_plane_state(crtc->primary->state)->visible) { WARN_ON(intel_crtc->unpin_work); - intel_pre_disable_primary(crtc); + intel_pre_disable_primary_noatomic(crtc); intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary)); to_intel_plane_state(crtc->primary->state)->visible = false; -- cgit v0.10.2 From 29ceb0e6c896f9476c681bb15dd0763f2137c0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2016 19:07:27 +0200 Subject: drm/i915: s/crtc_state/old_crtc_state/ in intel_atomic_commit() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid some head spinning by renaming the crtc_state variable to old_crtc_state. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1457543247-13987-6-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6f8d7dd5..46a697c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13502,7 +13502,7 @@ static int intel_atomic_commit(struct drm_device *dev, { struct intel_atomic_state *intel_state = to_intel_atomic_state(state); struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc_state *crtc_state; + struct drm_crtc_state *old_crtc_state; struct drm_crtc *crtc; struct intel_crtc_state *intel_cstate; int ret = 0, i; @@ -13528,7 +13528,7 @@ static int intel_atomic_commit(struct drm_device *dev, intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET); } - for_each_crtc_in_state(state, crtc, crtc_state, i) { + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); if (needs_modeset(crtc->state) || @@ -13543,10 +13543,10 @@ static int intel_atomic_commit(struct drm_device *dev, if (!needs_modeset(crtc->state)) continue; - intel_pre_plane_update(to_intel_crtc_state(crtc_state)); + intel_pre_plane_update(to_intel_crtc_state(old_crtc_state)); - if (crtc_state->active) { - intel_crtc_disable_planes(crtc, crtc_state->plane_mask); + if (old_crtc_state->active) { + intel_crtc_disable_planes(crtc, old_crtc_state->plane_mask); dev_priv->display.crtc_disable(crtc); intel_crtc->active = false; intel_fbc_disable(intel_crtc); @@ -13579,7 +13579,7 @@ static int intel_atomic_commit(struct drm_device *dev, } /* Now enable the clocks, plane, pipe, and connectors that we set up. */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); bool modeset = needs_modeset(crtc->state); struct intel_crtc_state *pipe_config = @@ -13592,14 +13592,14 @@ static int intel_atomic_commit(struct drm_device *dev, } if (!modeset) - intel_pre_plane_update(to_intel_crtc_state(crtc_state)); + intel_pre_plane_update(to_intel_crtc_state(old_crtc_state)); if (crtc->state->active && intel_crtc->atomic.update_fbc) intel_fbc_enable(intel_crtc); if (crtc->state->active && (crtc->state->planes_changed || update_pipe)) - drm_atomic_helper_commit_planes_on_crtc(crtc_state); + drm_atomic_helper_commit_planes_on_crtc(old_crtc_state); if (pipe_config->base.active && needs_vblank_wait(pipe_config)) crtc_vblank_mask |= 1 << i; @@ -13610,7 +13610,7 @@ static int intel_atomic_commit(struct drm_device *dev, if (!state->legacy_cursor_update) intel_atomic_wait_for_vblanks(dev, dev_priv, crtc_vblank_mask); - for_each_crtc_in_state(state, crtc, crtc_state, i) { + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { intel_post_plane_update(to_intel_crtc(crtc)); if (put_domains[i]) @@ -13627,7 +13627,7 @@ static int intel_atomic_commit(struct drm_device *dev, * * TODO: Move this (and other cleanup) to an async worker eventually. */ - for_each_crtc_in_state(state, crtc, crtc_state, i) { + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { intel_cstate = to_intel_crtc_state(crtc->state); if (dev_priv->display.optimize_watermarks) -- cgit v0.10.2 From 842e03076ffb655e35c72f6c95fe216cc856f42b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 2 Mar 2016 15:48:01 +0100 Subject: drm/i915: Update state before setting watermarks, v2. When intel_update_watermarks is called on skylake from the hw state readout disable function it calls intel_update_watermarks. intel_update_watermarks inspects crtc->state, which should be set to disabled. This wasn't the case, and this resulted in a divide-by-zero in skl_update_wm when intel_update_watermarks got called. ------------[ cut here ]------------ WARNING: CPU: 1 PID: 295 at drivers/gpu/drm/i915/intel_pm.c:2834 skl_update_pipe_wm+0x102/0x8c0 [i915]() WARN_ON(!config->num_pipes_active) Modules linked in: coretemp i915(+) xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx CPU: 1 PID: 295 Comm: systemd-udevd Tainted: G U W 4.5.0-rc4 -xxxxxx #25 Hardware name: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 0000000000000000 ffff88003777f5a8 ffffffff813485c2 ffff88003777f5f0 ffffffffa0236240 ffff88003777f5e0 ffffffff81050fce ffff8800aa420000 ffff8800aba18000 ffff8800aba18000 ffff880037304c00 ffff8800aa420000 Call Trace: [] dump_stack+0x67/0x95 [] warn_slowpath_common+0x9e/0xc0 [] warn_slowpath_fmt+0x4c/0x50 [] ? flush_work+0x8e/0x280 [] ? flush_work+0x5/0x280 [] skl_update_pipe_wm+0x102/0x8c0 [i915] [] skl_update_wm+0xff/0x5f0 [i915] [] ? trace_hardirqs_on_caller+0x15e/0x1d0 [] ? trace_hardirqs_on+0xd/0x10 [] intel_update_watermarks+0x1e/0x30 [i915] [] intel_crtc_disable_noatomic+0xd2/0x150 [i915] [] intel_modeset_setup_hw_state+0xdd2/0xde0 [i915] [] intel_modeset_init+0x15a3/0x1950 [i915] [] i915_driver_load+0x13c6/0x1720 [i915] [] ? add_sysfs_fw_map_entry+0x9b/0x9b [] drm_dev_register+0x6f/0xb0 [drm] [] drm_get_pci_dev+0x10a/0x1d0 [drm] [] i915_pci_probe+0x49/0x50 [i915] [] pci_device_probe+0x80/0xf0 [] driver_probe_device+0x1bc/0x3d0 [] __driver_attach+0x66/0x90 [] ? driver_probe_device+0x3d0/0x3d0 [] bus_for_each_dev+0x5b/0xa0 [] driver_attach+0x1e/0x20 [] bus_add_driver+0x151/0x270 [] driver_register+0x8c/0xd0 [] __pci_register_driver+0x5d/0x60 [] drm_pci_init+0x58/0xf0 [drm] [] ? trace_hardirqs_on+0xd/0x10 [] ? 0xffffffffa02aa000 [] i915_init+0x94/0x9b [i915] [] do_one_initcall+0x113/0x1f0 [] ? rcu_read_lock_sched_held+0x61/0x90 [] ? kmem_cache_alloc_trace+0x1cc/0x280 [] do_init_module+0x60/0x1c8 [] load_module+0x1ceb/0x2410 [] ? store_uevent+0x40/0x40 [] ? kernel_read+0x41/0x60 [] SYSC_finit_module+0x8d/0xa0 [] SyS_finit_module+0xe/0x10 [] entry_SYSCALL_64_fastpath+0x12/0x6f ---[ end trace 1149e9ab3695a423 ]--- ------------[ cut here ]------------ Changes since v1: - Clear state before calling any function after .crtc_disable. Reported-by: Tvrtko Ursulin Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/56D6FD21.7020907@linux.intel.com Tested-by: Tvrtko Ursulin Reviewed-by: Ander Conselvan de Oliveira diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 46a697c..ce55f0b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6273,6 +6273,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) { + struct intel_encoder *encoder; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_i915_private *dev_priv = to_i915(crtc->dev); enum intel_display_power_domain domain; @@ -6291,7 +6292,20 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc) } dev_priv->display.crtc_disable(crtc); + + DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was enabled, now disabled\n", + crtc->base.id); + + WARN_ON(drm_atomic_set_mode_for_crtc(crtc->state, NULL) < 0); + crtc->state->active = false; intel_crtc->active = false; + crtc->enabled = false; + crtc->state->connector_mask = 0; + crtc->state->encoder_mask = 0; + + for_each_encoder_on_crtc(crtc->dev, crtc, encoder) + encoder->base.crtc = NULL; + intel_fbc_disable(intel_crtc); intel_update_watermarks(crtc); intel_disable_shared_dpll(intel_crtc); @@ -15513,38 +15527,9 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) /* Adjust the state of the output pipe according to whether we * have active connectors/encoders. */ - if (!intel_crtc_has_encoders(crtc)) + if (crtc->active && !intel_crtc_has_encoders(crtc)) intel_crtc_disable_noatomic(&crtc->base); - if (crtc->active != crtc->base.state->active) { - struct intel_encoder *encoder; - - /* This can happen either due to bugs in the get_hw_state - * functions or because of calls to intel_crtc_disable_noatomic, - * or because the pipe is force-enabled due to the - * pipe A quirk. */ - DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n", - crtc->base.base.id, - crtc->base.state->enable ? "enabled" : "disabled", - crtc->active ? "enabled" : "disabled"); - - WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, NULL) < 0); - crtc->base.state->active = crtc->active; - crtc->base.enabled = crtc->active; - crtc->base.state->connector_mask = 0; - crtc->base.state->encoder_mask = 0; - - /* Because we only establish the connector -> encoder -> - * crtc links if something is active, this means the - * crtc is now deactivated. Break the links. connector - * -> encoder links are only establish when things are - * actually up, hence no need to break them. */ - WARN_ON(crtc->active); - - for_each_encoder_on_crtc(dev, &crtc->base, encoder) - encoder->base.crtc = NULL; - } - if (crtc->active || HAS_GMCH_DISPLAY(dev)) { /* * We start out with underrun reporting disabled to avoid races. -- cgit v0.10.2 From 359d2243117a79599435141fda0047d01ef324e8 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 14 Mar 2016 08:16:51 +0100 Subject: drm/i915: Update DRIVER_DATE to 20160314 Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1557d65..80b14f1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -60,7 +60,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20160229" +#define DRIVER_DATE "20160314" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v0.10.2 From cd202f69d89c48a935d4763ff96c50e762ed2e0a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 9 Mar 2016 10:35:44 +0100 Subject: drm/i915: Remove some post-commit members from intel_crtc->atomic, v3. fb_bits is useful to have in the crtc_state for cs flips when the code is updated to use intel_frontbuffer_flip_prepare/complete. So calculate it in advance and move it to crtc_state. The other stuff can be calculated in post_plane_update, and aren't useful elsewhere. Changes since v1: - Changing wording, remove comment about loop. Changes since v2: - Rebase. Signed-off-by: Maarten Lankhorst Reviewed-by: Ander Conselvan de Oliveira Link: http://patchwork.freedesktop.org/patch/msgid/1457516145-32117-1-git-send-email-maarten.lankhorst@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c index 79448f1..50ff90a 100644 --- a/drivers/gpu/drm/i915/intel_atomic.c +++ b/drivers/gpu/drm/i915/intel_atomic.c @@ -100,6 +100,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state->update_wm_post = false; crtc_state->fb_changed = false; crtc_state->wm.need_postvbl_update = false; + crtc_state->fb_bits = 0; return &crtc_state->base; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ce55f0b..8a83426 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4669,14 +4669,20 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) } } -static void intel_post_plane_update(struct intel_crtc *crtc) +static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); + struct drm_atomic_state *old_state = old_crtc_state->base.state; struct intel_crtc_atomic_commit *atomic = &crtc->atomic; struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->base.state); struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_plane *primary = crtc->base.primary; + struct drm_plane_state *old_pri_state = + drm_atomic_get_existing_plane_state(old_state, primary); - intel_frontbuffer_flip(dev, atomic->fb_bits); + intel_frontbuffer_flip(dev, pipe_config->fb_bits); crtc->wm.cxsr_allowed = true; @@ -4686,8 +4692,17 @@ static void intel_post_plane_update(struct intel_crtc *crtc) if (atomic->update_fbc) intel_fbc_post_update(crtc); - if (atomic->post_enable_primary) - intel_post_enable_primary(&crtc->base); + if (old_pri_state) { + struct intel_plane_state *primary_state = + to_intel_plane_state(primary->state); + struct intel_plane_state *old_primary_state = + to_intel_plane_state(old_pri_state); + + if (primary_state->visible && + (needs_modeset(&pipe_config->base) || + !old_primary_state->visible)) + intel_post_enable_primary(&crtc->base); + } memset(atomic, 0, sizeof(*atomic)); } @@ -11830,12 +11845,10 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true; if (visible || was_visible) - intel_crtc->atomic.fb_bits |= - to_intel_plane(plane)->frontbuffer_bit; + pipe_config->fb_bits |= to_intel_plane(plane)->frontbuffer_bit; switch (plane->type) { case DRM_PLANE_TYPE_PRIMARY: - intel_crtc->atomic.post_enable_primary = turn_on; intel_crtc->atomic.update_fbc = true; break; @@ -13625,7 +13638,7 @@ static int intel_atomic_commit(struct drm_device *dev, intel_atomic_wait_for_vblanks(dev, dev_priv, crtc_vblank_mask); for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - intel_post_plane_update(to_intel_crtc(crtc)); + intel_post_plane_update(to_intel_crtc_state(old_crtc_state)); if (put_domains[i]) modeset_put_power_domains(dev_priv, put_domains[i]); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 02b3d22..09ab436 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -418,6 +418,7 @@ struct intel_crtc_state { #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS (1<<0) /* unreliable sync mode.flags */ unsigned long quirks; + unsigned fb_bits; /* framebuffers to flip */ bool update_pipe; /* can a fast modeset be performed? */ bool disable_cxsr; bool update_wm_pre, update_wm_post; /* watermarks are updated */ @@ -605,10 +606,6 @@ struct intel_crtc_atomic_commit { /* Sleepable operations to perform before commit */ /* Sleepable operations to perform after commit */ - unsigned fb_bits; - bool post_enable_primary; - - /* Sleepable operations to perform before and after commit */ bool update_fbc; }; -- cgit v0.10.2 From 31ae71fca7f91101613fac9deb8e858e1319b4f5 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 9 Mar 2016 10:35:45 +0100 Subject: drm/i915: Nuke fbc members from intel_crtc->atomic, v4. Whenever there's an update to the primary plane, fbc_pre_update and fbc_post_update are called. Kill off intel_crtc->atomic.update_fbc and now that intel_crtc->atomic is empty, kill it off too. Changes since v1: - Add a intel_fbc_supports_rotation helper. Changes since v2: - Remove intel_fbc_supports_rotation_helper. - Remove unrelated changes. Changes since v3: - Rebase Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457516145-32117-2-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Paulo Zanoni diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8a83426..ed650a4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4673,11 +4673,9 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); struct drm_atomic_state *old_state = old_crtc_state->base.state; - struct intel_crtc_atomic_commit *atomic = &crtc->atomic; struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->base.state); struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_plane *primary = crtc->base.primary; struct drm_plane_state *old_pri_state = drm_atomic_get_existing_plane_state(old_state, primary); @@ -4689,22 +4687,19 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state) if (pipe_config->update_wm_post && pipe_config->base.active) intel_update_watermarks(&crtc->base); - if (atomic->update_fbc) - intel_fbc_post_update(crtc); - if (old_pri_state) { struct intel_plane_state *primary_state = to_intel_plane_state(primary->state); struct intel_plane_state *old_primary_state = to_intel_plane_state(old_pri_state); + intel_fbc_post_update(crtc); + if (primary_state->visible && (needs_modeset(&pipe_config->base) || !old_primary_state->visible)) intel_post_enable_primary(&crtc->base); } - - memset(atomic, 0, sizeof(*atomic)); } static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) @@ -4712,7 +4707,6 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc); struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc_atomic_commit *atomic = &crtc->atomic; struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->base.state); struct drm_atomic_state *old_state = old_crtc_state->base.state; @@ -4721,15 +4715,14 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) drm_atomic_get_existing_plane_state(old_state, primary); bool modeset = needs_modeset(&pipe_config->base); - if (atomic->update_fbc) - intel_fbc_pre_update(crtc); - if (old_pri_state) { struct intel_plane_state *primary_state = to_intel_plane_state(primary->state); struct intel_plane_state *old_primary_state = to_intel_plane_state(old_pri_state); + intel_fbc_pre_update(crtc); + if (old_primary_state->visible && (modeset || !primary_state->visible)) intel_pre_disable_primary(&crtc->base); @@ -11847,27 +11840,17 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, if (visible || was_visible) pipe_config->fb_bits |= to_intel_plane(plane)->frontbuffer_bit; - switch (plane->type) { - case DRM_PLANE_TYPE_PRIMARY: - intel_crtc->atomic.update_fbc = true; - - break; - case DRM_PLANE_TYPE_CURSOR: - break; - case DRM_PLANE_TYPE_OVERLAY: - /* - * WaCxSRDisabledForSpriteScaling:ivb - * - * cstate->update_wm was already set above, so this flag will - * take effect when we commit and program watermarks. - */ - if (IS_IVYBRIDGE(dev) && - needs_scaling(to_intel_plane_state(plane_state)) && - !needs_scaling(old_plane_state)) - pipe_config->disable_lp_wm = true; + /* + * WaCxSRDisabledForSpriteScaling:ivb + * + * cstate->update_wm was already set above, so this flag will + * take effect when we commit and program watermarks. + */ + if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev) && + needs_scaling(to_intel_plane_state(plane_state)) && + !needs_scaling(old_plane_state)) + pipe_config->disable_lp_wm = true; - break; - } return 0; } @@ -13310,9 +13293,6 @@ static int intel_atomic_check(struct drm_device *dev, struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state); - memset(&to_intel_crtc(crtc)->atomic, 0, - sizeof(struct intel_crtc_atomic_commit)); - /* Catch I915_MODE_FLAG_INHERITED */ if (crtc_state->mode.private_flags != crtc->state->mode.private_flags) crtc_state->mode_changed = true; @@ -13621,7 +13601,8 @@ static int intel_atomic_commit(struct drm_device *dev, if (!modeset) intel_pre_plane_update(to_intel_crtc_state(old_crtc_state)); - if (crtc->state->active && intel_crtc->atomic.update_fbc) + if (crtc->state->active && + drm_atomic_get_existing_plane_state(state, crtc->primary)) intel_fbc_enable(intel_crtc); if (crtc->state->active && diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 09ab436..0786246 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -596,19 +596,6 @@ struct intel_mmio_flip { unsigned int rotation; }; -/* - * Tracking of operations that need to be performed at the beginning/end of an - * atomic commit, outside the atomic section where interrupts are disabled. - * These are generally operations that grab mutexes or might otherwise sleep - * and thus can't be run with interrupts disabled. - */ -struct intel_crtc_atomic_commit { - /* Sleepable operations to perform before commit */ - - /* Sleepable operations to perform after commit */ - bool update_fbc; -}; - struct intel_crtc { struct drm_crtc base; enum pipe pipe; @@ -669,8 +656,6 @@ struct intel_crtc { int scanline_start; } debug; - struct intel_crtc_atomic_commit atomic; - /* scalers available on this crtc */ int num_scalers; -- cgit v0.10.2 From 08250c4ba650a9d8453166b4c05962766798fe9b Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 14 Mar 2016 19:55:34 +0200 Subject: drm/i915/bxt: Fix off-by-one error in Broxton PLL IDs After the commit below the Broxton PLL IDs had an off-by-one error, so fix this up. Also add a missing brace at intel_shared_dpll_init(), it happened to compile only due to the way the IS_BROXTON macro is defined. v2: - remove debugging left-over Fixes: a3c988ea068c ("drm/i915: Make SKL/KBL DPLL0 managed by the shared dpll code") CC: Ander Conselvan de Oliveira CC: Maarten Lankhorst Signed-off-by: Imre Deak Reviewed-by: Ander Conselvan de Oliveira Link: http://patchwork.freedesktop.org/patch/msgid/1457978134-12362-1-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ed650a4..4c04dab 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9786,15 +9786,15 @@ static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv, switch (port) { case PORT_A: pipe_config->ddi_pll_sel = SKL_DPLL0; - id = DPLL_ID_SKL_DPLL1; + id = DPLL_ID_SKL_DPLL0; break; case PORT_B: pipe_config->ddi_pll_sel = SKL_DPLL1; - id = DPLL_ID_SKL_DPLL2; + id = DPLL_ID_SKL_DPLL1; break; case PORT_C: pipe_config->ddi_pll_sel = SKL_DPLL2; - id = DPLL_ID_SKL_DPLL3; + id = DPLL_ID_SKL_DPLL2; break; default: DRM_ERROR("Incorrect port type\n"); diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 4b636c4..74d5aec 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1706,9 +1706,9 @@ static const struct intel_dpll_mgr skl_pll_mgr = { }; static const struct dpll_info bxt_plls[] = { - { "PORT PLL A", 0, &bxt_ddi_pll_funcs, 0 }, - { "PORT PLL B", 1, &bxt_ddi_pll_funcs, 0 }, - { "PORT PLL C", 2, &bxt_ddi_pll_funcs, 0 }, + { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 }, + { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 }, + { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 }, { NULL, -1, NULL, }, }; @@ -1726,7 +1726,7 @@ void intel_shared_dpll_init(struct drm_device *dev) if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) dpll_mgr = &skl_pll_mgr; - else if IS_BROXTON(dev) + else if (IS_BROXTON(dev)) dpll_mgr = &bxt_pll_mgr; else if (HAS_DDI(dev)) dpll_mgr = &hsw_pll_mgr; -- cgit v0.10.2 From e2f80391478af71bbbc91686fe0efc580b907caa Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 16 Mar 2016 11:00:36 +0000 Subject: drm/i915: Rename local struct intel_engine_cs variables Done by the Coccinelle script below plus a manual intervention to GEN8_RING_SEMAPHORE_INIT. @@ expression E; @@ - struct intel_engine_cs *ring = E; + struct intel_engine_cs *engine = E; <+... - ring + engine ...+> @@ @@ - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; <+... - ring + engine ...+> Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 15aacd0..5037ccb 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -129,7 +129,7 @@ static void describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) { struct drm_i915_private *dev_priv = to_i915(obj->base.dev); - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct i915_vma *vma; int pin_count = 0; int i; @@ -143,7 +143,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) obj->base.size / 1024, obj->base.read_domains, obj->base.write_domain); - for_each_ring(ring, dev_priv, i) + for_each_ring(engine, dev_priv, i) seq_printf(m, "%x ", i915_gem_request_get_seqno(obj->last_read_req[i])); seq_printf(m, "] %x %x%s%s%s", @@ -397,15 +397,15 @@ static void print_batch_pool_stats(struct seq_file *m, { struct drm_i915_gem_object *obj; struct file_stats stats; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i, j; memset(&stats, 0, sizeof(stats)); - for_each_ring(ring, dev_priv, i) { - for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) { + for_each_ring(engine, dev_priv, i) { + for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { list_for_each_entry(obj, - &ring->batch_pool.cache_list[j], + &engine->batch_pool.cache_list[j], batch_pool_link) per_file_stats(0, obj, &stats); } @@ -591,14 +591,13 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) pipe, plane); } if (work->flip_queued_req) { - struct intel_engine_cs *ring = - i915_gem_request_get_ring(work->flip_queued_req); + struct intel_engine_cs *engine = i915_gem_request_get_ring(work->flip_queued_req); seq_printf(m, "Flip queued on %s at seqno %x, next seqno %x [current breadcrumb %x], completed? %d\n", - ring->name, + engine->name, i915_gem_request_get_seqno(work->flip_queued_req), dev_priv->next_seqno, - ring->get_seqno(ring, true), + engine->get_seqno(engine, true), i915_gem_request_completed(work->flip_queued_req, true)); } else seq_printf(m, "Flip not associated with any ring\n"); @@ -637,7 +636,7 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int total = 0; int ret, i, j; @@ -645,20 +644,20 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) if (ret) return ret; - for_each_ring(ring, dev_priv, i) { - for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) { + for_each_ring(engine, dev_priv, i) { + for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { int count; count = 0; list_for_each_entry(obj, - &ring->batch_pool.cache_list[j], + &engine->batch_pool.cache_list[j], batch_pool_link) count++; seq_printf(m, "%s cache[%d]: %d objects\n", - ring->name, j, count); + engine->name, j, count); list_for_each_entry(obj, - &ring->batch_pool.cache_list[j], + &engine->batch_pool.cache_list[j], batch_pool_link) { seq_puts(m, " "); describe_obj(m, obj); @@ -681,7 +680,7 @@ static int i915_gem_request_info(struct seq_file *m, void *data) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct drm_i915_gem_request *req; int ret, any, i; @@ -690,17 +689,17 @@ static int i915_gem_request_info(struct seq_file *m, void *data) return ret; any = 0; - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { int count; count = 0; - list_for_each_entry(req, &ring->request_list, list) + list_for_each_entry(req, &engine->request_list, list) count++; if (count == 0) continue; - seq_printf(m, "%s requests: %d\n", ring->name, count); - list_for_each_entry(req, &ring->request_list, list) { + seq_printf(m, "%s requests: %d\n", engine->name, count); + list_for_each_entry(req, &engine->request_list, list) { struct task_struct *task; rcu_read_lock(); @@ -739,7 +738,7 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int ret, i; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -747,8 +746,8 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) return ret; intel_runtime_pm_get(dev_priv); - for_each_ring(ring, dev_priv, i) - i915_ring_seqno_info(m, ring); + for_each_ring(engine, dev_priv, i) + i915_ring_seqno_info(m, engine); intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); @@ -762,7 +761,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int ret, i, pipe; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -934,13 +933,13 @@ static int i915_interrupt_info(struct seq_file *m, void *data) seq_printf(m, "Graphics Interrupt mask: %08x\n", I915_READ(GTIMR)); } - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { if (INTEL_INFO(dev)->gen >= 6) { seq_printf(m, "Graphics Interrupt mask (%s): %08x\n", - ring->name, I915_READ_IMR(ring)); + engine->name, I915_READ_IMR(engine)); } - i915_ring_seqno_info(m, ring); + i915_ring_seqno_info(m, engine); } intel_runtime_pm_put(dev_priv); mutex_unlock(&dev->struct_mutex); @@ -981,12 +980,12 @@ static int i915_hws_info(struct seq_file *m, void *data) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; const u32 *hws; int i; - ring = &dev_priv->ring[(uintptr_t)node->info_ent->data]; - hws = ring->status_page.page_addr; + engine = &dev_priv->ring[(uintptr_t)node->info_ent->data]; + hws = engine->status_page.page_addr; if (hws == NULL) return 0; @@ -1331,7 +1330,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; u64 acthd[I915_NUM_RINGS]; u32 seqno[I915_NUM_RINGS]; u32 instdone[I915_NUM_INSTDONE_REG]; @@ -1344,9 +1343,9 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); - for_each_ring(ring, dev_priv, i) { - seqno[i] = ring->get_seqno(ring, false); - acthd[i] = intel_ring_get_active_head(ring); + for_each_ring(engine, dev_priv, i) { + seqno[i] = engine->get_seqno(engine, false); + acthd[i] = intel_ring_get_active_head(engine); } i915_get_extra_instdone(dev, instdone); @@ -1360,17 +1359,17 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) } else seq_printf(m, "Hangcheck inactive\n"); - for_each_ring(ring, dev_priv, i) { - seq_printf(m, "%s:\n", ring->name); + for_each_ring(engine, dev_priv, i) { + seq_printf(m, "%s:\n", engine->name); seq_printf(m, "\tseqno = %x [current %x]\n", - ring->hangcheck.seqno, seqno[i]); + engine->hangcheck.seqno, seqno[i]); seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n", - (long long)ring->hangcheck.acthd, + (long long)engine->hangcheck.acthd, (long long)acthd[i]); - seq_printf(m, "\tscore = %d\n", ring->hangcheck.score); - seq_printf(m, "\taction = %d\n", ring->hangcheck.action); + seq_printf(m, "\tscore = %d\n", engine->hangcheck.score); + seq_printf(m, "\taction = %d\n", engine->hangcheck.action); - if (ring->id == RCS) { + if (engine->id == RCS) { seq_puts(m, "\tinstdone read ="); for (j = 0; j < I915_NUM_INSTDONE_REG; j++) @@ -1380,7 +1379,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) for (j = 0; j < I915_NUM_INSTDONE_REG; j++) seq_printf(m, " 0x%08x", - ring->hangcheck.instdone[j]); + engine->hangcheck.instdone[j]); seq_puts(m, "\n"); } @@ -1946,7 +1945,7 @@ static int i915_context_status(struct seq_file *m, void *unused) struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct intel_context *ctx; int ret, i; @@ -1966,13 +1965,13 @@ static int i915_context_status(struct seq_file *m, void *unused) if (i915.enable_execlists) { seq_putc(m, '\n'); - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state; struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf; - seq_printf(m, "%s: ", ring->name); + seq_printf(m, "%s: ", engine->name); if (ctx_obj) describe_obj(m, ctx_obj); if (ringbuf) @@ -2041,7 +2040,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct intel_context *ctx; int ret, i; @@ -2056,8 +2055,8 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) list_for_each_entry(ctx, &dev_priv->context_list, link) if (ctx != dev_priv->kernel_context) - for_each_ring(ring, dev_priv, i) - i915_dump_lrc_obj(m, ctx, ring); + for_each_ring(engine, dev_priv, i) + i915_dump_lrc_obj(m, ctx, engine); mutex_unlock(&dev->struct_mutex); @@ -2069,7 +2068,7 @@ static int i915_execlists(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; u32 status_pointer; u8 read_pointer; u8 write_pointer; @@ -2090,22 +2089,22 @@ static int i915_execlists(struct seq_file *m, void *data) intel_runtime_pm_get(dev_priv); - for_each_ring(ring, dev_priv, ring_id) { + for_each_ring(engine, dev_priv, ring_id) { struct drm_i915_gem_request *head_req = NULL; int count = 0; unsigned long flags; - seq_printf(m, "%s\n", ring->name); + seq_printf(m, "%s\n", engine->name); - status = I915_READ(RING_EXECLIST_STATUS_LO(ring)); - ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(ring)); + status = I915_READ(RING_EXECLIST_STATUS_LO(engine)); + ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(engine)); seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n", status, ctx_id); - status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring)); + status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); seq_printf(m, "\tStatus pointer: 0x%08X\n", status_pointer); - read_pointer = ring->next_context_status_buffer; + read_pointer = engine->next_context_status_buffer; write_pointer = GEN8_CSB_WRITE_PTR(status_pointer); if (read_pointer > write_pointer) write_pointer += GEN8_CSB_ENTRIES; @@ -2113,24 +2112,25 @@ static int i915_execlists(struct seq_file *m, void *data) read_pointer, write_pointer); for (i = 0; i < GEN8_CSB_ENTRIES; i++) { - status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, i)); - ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, i)); + status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, i)); + ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, i)); seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n", i, status, ctx_id); } - spin_lock_irqsave(&ring->execlist_lock, flags); - list_for_each(cursor, &ring->execlist_queue) + spin_lock_irqsave(&engine->execlist_lock, flags); + list_for_each(cursor, &engine->execlist_queue) count++; - head_req = list_first_entry_or_null(&ring->execlist_queue, - struct drm_i915_gem_request, execlist_link); - spin_unlock_irqrestore(&ring->execlist_lock, flags); + head_req = list_first_entry_or_null(&engine->execlist_queue, + struct drm_i915_gem_request, + execlist_link); + spin_unlock_irqrestore(&engine->execlist_lock, flags); seq_printf(m, "\t%d requests in queue\n", count); if (head_req) { seq_printf(m, "\tHead request id: %u\n", - intel_execlists_ctx_id(head_req->ctx, ring)); + intel_execlists_ctx_id(head_req->ctx, engine)); seq_printf(m, "\tHead request tail: %u\n", head_req->tail); } @@ -2246,19 +2246,19 @@ static int per_file_ctx(int id, void *ptr, void *data) static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; int unused, i; if (!ppgtt) return; - for_each_ring(ring, dev_priv, unused) { - seq_printf(m, "%s\n", ring->name); + for_each_ring(engine, dev_priv, unused) { + seq_printf(m, "%s\n", engine->name); for (i = 0; i < 4; i++) { - u64 pdp = I915_READ(GEN8_RING_PDP_UDW(ring, i)); + u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i)); pdp <<= 32; - pdp |= I915_READ(GEN8_RING_PDP_LDW(ring, i)); + pdp |= I915_READ(GEN8_RING_PDP_LDW(engine, i)); seq_printf(m, "\tPDP%d 0x%016llx\n", i, pdp); } } @@ -2267,19 +2267,23 @@ static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev) static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; if (INTEL_INFO(dev)->gen == 6) seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE)); - for_each_ring(ring, dev_priv, i) { - seq_printf(m, "%s\n", ring->name); + for_each_ring(engine, dev_priv, i) { + seq_printf(m, "%s\n", engine->name); if (INTEL_INFO(dev)->gen == 7) - seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(RING_MODE_GEN7(ring))); - seq_printf(m, "PP_DIR_BASE: 0x%08x\n", I915_READ(RING_PP_DIR_BASE(ring))); - seq_printf(m, "PP_DIR_BASE_READ: 0x%08x\n", I915_READ(RING_PP_DIR_BASE_READ(ring))); - seq_printf(m, "PP_DIR_DCLV: 0x%08x\n", I915_READ(RING_PP_DIR_DCLV(ring))); + seq_printf(m, "GFX_MODE: 0x%08x\n", + I915_READ(RING_MODE_GEN7(engine))); + seq_printf(m, "PP_DIR_BASE: 0x%08x\n", + I915_READ(RING_PP_DIR_BASE(engine))); + seq_printf(m, "PP_DIR_BASE_READ: 0x%08x\n", + I915_READ(RING_PP_DIR_BASE_READ(engine))); + seq_printf(m, "PP_DIR_DCLV: 0x%08x\n", + I915_READ(RING_PP_DIR_DCLV(engine))); } if (dev_priv->mm.aliasing_ppgtt) { struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; @@ -2334,12 +2338,12 @@ out_put: static int count_irq_waiters(struct drm_i915_private *i915) { - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int count = 0; int i; - for_each_ring(ring, i915, i) - count += ring->irq_refcount; + for_each_ring(engine, i915, i) + count += engine->irq_refcount; return count; } @@ -2447,7 +2451,7 @@ static void i915_guc_client_info(struct seq_file *m, struct drm_i915_private *dev_priv, struct i915_guc_client *client) { - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; uint64_t tot = 0; uint32_t i; @@ -2462,11 +2466,11 @@ static void i915_guc_client_info(struct seq_file *m, seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail); seq_printf(m, "\tLast submission result: %d\n", client->retcode); - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { seq_printf(m, "\tSubmissions: %llu %s\n", - client->submissions[ring->guc_id], - ring->name); - tot += client->submissions[ring->guc_id]; + client->submissions[engine->guc_id], + engine->name); + tot += client->submissions[engine->guc_id]; } seq_printf(m, "\tTotal: %llu\n", tot); } @@ -2478,7 +2482,7 @@ static int i915_guc_info(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_guc guc; struct i915_guc_client client = {}; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; enum intel_ring_id i; u64 total = 0; @@ -2502,11 +2506,11 @@ static int i915_guc_info(struct seq_file *m, void *data) seq_printf(m, "GuC last action error code: %d\n", guc.action_err); seq_printf(m, "\nGuC submissions:\n"); - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n", - ring->name, guc.submissions[ring->guc_id], - guc.last_seqno[ring->guc_id]); - total += guc.submissions[ring->guc_id]; + engine->name, guc.submissions[engine->guc_id], + guc.last_seqno[engine->guc_id]); + total += guc.submissions[engine->guc_id]; } seq_printf(m, "\t%s: %llu\n", "Total", total); @@ -3128,7 +3132,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int num_rings = hweight32(INTEL_INFO(dev)->ring_mask); int i, j, ret; @@ -3149,10 +3153,10 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) page = i915_gem_object_get_page(dev_priv->semaphore_obj, 0); seqno = (uint64_t *)kmap_atomic(page); - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { uint64_t offset; - seq_printf(m, "%s\n", ring->name); + seq_printf(m, "%s\n", engine->name); seq_puts(m, " Last signal:"); for (j = 0; j < num_rings; j++) { @@ -3174,17 +3178,18 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) kunmap_atomic(seqno); } else { seq_puts(m, " Last signal:"); - for_each_ring(ring, dev_priv, i) + for_each_ring(engine, dev_priv, i) for (j = 0; j < num_rings; j++) seq_printf(m, "0x%08x\n", - I915_READ(ring->semaphore.mbox.signal[j])); + I915_READ(engine->semaphore.mbox.signal[j])); seq_putc(m, '\n'); } seq_puts(m, "\nSync seqno:\n"); - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { for (j = 0; j < num_rings; j++) { - seq_printf(m, " 0x%08x ", ring->semaphore.sync_seqno[j]); + seq_printf(m, " 0x%08x ", + engine->semaphore.sync_seqno[j]); } seq_putc(m, '\n'); } @@ -3226,7 +3231,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused) { int i; int ret; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -3239,9 +3244,9 @@ static int i915_wa_registers(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); seq_printf(m, "Workarounds applied: %d\n", workarounds->count); - for_each_ring(ring, dev_priv, i) + for_each_ring(engine, dev_priv, i) seq_printf(m, "HW whitelist count for %s: %d\n", - ring->name, workarounds->hw_whitelist_count[i]); + engine->name, workarounds->hw_whitelist_count[i]); for (i = 0; i < workarounds->count; ++i) { i915_reg_t addr; u32 mask, value, read; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b854af2..5a7f603 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1243,11 +1243,11 @@ int __i915_wait_request(struct drm_i915_gem_request *req, s64 *timeout, struct intel_rps_client *rps) { - struct intel_engine_cs *ring = i915_gem_request_get_ring(req); - struct drm_device *dev = ring->dev; + struct intel_engine_cs *engine = i915_gem_request_get_ring(req); + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; const bool irq_test_in_progress = - ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring); + ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(engine); int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; DEFINE_WAIT(wait); unsigned long timeout_expire; @@ -1288,7 +1288,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, if (ret == 0) goto out; - if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring))) { + if (!irq_test_in_progress && WARN_ON(!engine->irq_get(engine))) { ret = -ENODEV; goto out; } @@ -1296,7 +1296,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req, for (;;) { struct timer_list timer; - prepare_to_wait(&ring->irq_queue, &wait, state); + prepare_to_wait(&engine->irq_queue, &wait, state); /* We need to check whether any gpu reset happened in between * the caller grabbing the seqno and now ... */ @@ -1325,11 +1325,11 @@ int __i915_wait_request(struct drm_i915_gem_request *req, } timer.function = NULL; - if (timeout || missed_irq(dev_priv, ring)) { + if (timeout || missed_irq(dev_priv, engine)) { unsigned long expire; setup_timer_on_stack(&timer, fake_irq, (unsigned long)current); - expire = missed_irq(dev_priv, ring) ? jiffies + 1 : timeout_expire; + expire = missed_irq(dev_priv, engine) ? jiffies + 1 : timeout_expire; mod_timer(&timer, expire); } @@ -1341,9 +1341,9 @@ int __i915_wait_request(struct drm_i915_gem_request *req, } } if (!irq_test_in_progress) - ring->irq_put(ring); + engine->irq_put(engine); - finish_wait(&ring->irq_queue, &wait); + finish_wait(&engine->irq_queue, &wait); out: trace_i915_gem_request_wait_end(req); @@ -2404,17 +2404,17 @@ void i915_vma_move_to_active(struct i915_vma *vma, struct drm_i915_gem_request *req) { struct drm_i915_gem_object *obj = vma->obj; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; - ring = i915_gem_request_get_ring(req); + engine = i915_gem_request_get_ring(req); /* Add a reference if we're newly entering the active list. */ if (obj->active == 0) drm_gem_object_reference(&obj->base); - obj->active |= intel_ring_flag(ring); + obj->active |= intel_ring_flag(engine); - list_move_tail(&obj->ring_list[ring->id], &ring->active_list); - i915_gem_request_assign(&obj->last_read_req[ring->id], req); + list_move_tail(&obj->ring_list[engine->id], &engine->active_list); + i915_gem_request_assign(&obj->last_read_req[engine->id], req); list_move_tail(&vma->vm_link, &vma->vm->active_list); } @@ -2467,23 +2467,23 @@ static int i915_gem_init_seqno(struct drm_device *dev, u32 seqno) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int ret, i, j; /* Carefully retire all requests without writing to the rings */ - for_each_ring(ring, dev_priv, i) { - ret = intel_ring_idle(ring); + for_each_ring(engine, dev_priv, i) { + ret = intel_ring_idle(engine); if (ret) return ret; } i915_gem_retire_requests(dev); /* Finally reset hw state */ - for_each_ring(ring, dev_priv, i) { - intel_ring_init_seqno(ring, seqno); + for_each_ring(engine, dev_priv, i) { + intel_ring_init_seqno(engine, seqno); - for (j = 0; j < ARRAY_SIZE(ring->semaphore.sync_seqno); j++) - ring->semaphore.sync_seqno[j] = 0; + for (j = 0; j < ARRAY_SIZE(engine->semaphore.sync_seqno); j++) + engine->semaphore.sync_seqno[j] = 0; } return 0; @@ -2542,7 +2542,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, struct drm_i915_gem_object *obj, bool flush_caches) { - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct drm_i915_private *dev_priv; struct intel_ringbuffer *ringbuf; u32 request_start; @@ -2551,8 +2551,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, if (WARN_ON(request == NULL)) return; - ring = request->ring; - dev_priv = ring->dev->dev_private; + engine = request->ring; + dev_priv = engine->dev->dev_private; ringbuf = request->ringbuf; /* @@ -2587,9 +2587,9 @@ void __i915_add_request(struct drm_i915_gem_request *request, request->postfix = intel_ring_get_tail(ringbuf); if (i915.enable_execlists) - ret = ring->emit_request(request); + ret = engine->emit_request(request); else { - ret = ring->add_request(request); + ret = engine->add_request(request); request->tail = intel_ring_get_tail(ringbuf); } @@ -2607,13 +2607,13 @@ void __i915_add_request(struct drm_i915_gem_request *request, request->batch_obj = obj; request->emitted_jiffies = jiffies; - request->previous_seqno = ring->last_submitted_seqno; - ring->last_submitted_seqno = request->seqno; - list_add_tail(&request->list, &ring->request_list); + request->previous_seqno = engine->last_submitted_seqno; + engine->last_submitted_seqno = request->seqno; + list_add_tail(&request->list, &engine->request_list); trace_i915_gem_request_add(request); - i915_queue_hangcheck(ring->dev); + i915_queue_hangcheck(engine->dev); queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, @@ -2885,7 +2885,7 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, void i915_gem_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; /* @@ -2893,11 +2893,11 @@ void i915_gem_reset(struct drm_device *dev) * them for finding the guilty party. As the requests only borrow * their reference to the objects, the inspection must be done first. */ - for_each_ring(ring, dev_priv, i) - i915_gem_reset_ring_status(dev_priv, ring); + for_each_ring(engine, dev_priv, i) + i915_gem_reset_ring_status(dev_priv, engine); - for_each_ring(ring, dev_priv, i) - i915_gem_reset_ring_cleanup(dev_priv, ring); + for_each_ring(engine, dev_priv, i) + i915_gem_reset_ring_cleanup(dev_priv, engine); i915_gem_context_reset(dev); @@ -2962,19 +2962,19 @@ bool i915_gem_retire_requests(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; bool idle = true; int i; - for_each_ring(ring, dev_priv, i) { - i915_gem_retire_requests_ring(ring); - idle &= list_empty(&ring->request_list); + for_each_ring(engine, dev_priv, i) { + i915_gem_retire_requests_ring(engine); + idle &= list_empty(&engine->request_list); if (i915.enable_execlists) { - spin_lock_irq(&ring->execlist_lock); - idle &= list_empty(&ring->execlist_queue); - spin_unlock_irq(&ring->execlist_lock); + spin_lock_irq(&engine->execlist_lock); + idle &= list_empty(&engine->execlist_queue); + spin_unlock_irq(&engine->execlist_lock); - intel_execlists_retire_requests(ring); + intel_execlists_retire_requests(engine); } } @@ -3025,11 +3025,11 @@ i915_gem_idle_work_handler(struct work_struct *work) intel_mark_idle(dev); if (mutex_trylock(&dev->struct_mutex)) { - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; - for_each_ring(ring, dev_priv, i) - i915_gem_batch_pool_fini(&ring->batch_pool); + for_each_ring(engine, dev_priv, i) + i915_gem_batch_pool_fini(&engine->batch_pool); mutex_unlock(&dev->struct_mutex); } @@ -3391,15 +3391,15 @@ int __i915_vma_unbind_no_wait(struct i915_vma *vma) int i915_gpu_idle(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int ret, i; /* Flush everything onto the inactive list. */ - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { if (!i915.enable_execlists) { struct drm_i915_gem_request *req; - req = i915_gem_request_alloc(ring, NULL); + req = i915_gem_request_alloc(engine, NULL); if (IS_ERR(req)) return PTR_ERR(req); @@ -3412,7 +3412,7 @@ int i915_gpu_idle(struct drm_device *dev) i915_add_request_no_flush(req); } - ret = intel_ring_idle(ring); + ret = intel_ring_idle(engine); if (ret) return ret; } @@ -4656,11 +4656,11 @@ static void i915_gem_stop_ringbuffers(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; - for_each_ring(ring, dev_priv, i) - dev_priv->gt.stop_ring(ring); + for_each_ring(engine, dev_priv, i) + dev_priv->gt.stop_ring(engine); } int @@ -4697,8 +4697,8 @@ err: int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice) { - struct intel_engine_cs *ring = req->ring; - struct drm_device *dev = ring->dev; + struct intel_engine_cs *engine = req->ring; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 *remap_info = dev_priv->l3_parity.remap_info[slice]; int i, ret; @@ -4716,12 +4716,12 @@ int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice) * at initialization time. */ for (i = 0; i < GEN7_L3LOG_SIZE / 4; i++) { - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit_reg(ring, GEN7_L3LOG(slice, i)); - intel_ring_emit(ring, remap_info[i]); + intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit_reg(engine, GEN7_L3LOG(slice, i)); + intel_ring_emit(engine, remap_info[i]); } - intel_ring_advance(ring); + intel_ring_advance(engine); return ret; } @@ -4829,7 +4829,7 @@ int i915_gem_init_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int ret, i, j; if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt()) @@ -4876,8 +4876,8 @@ i915_gem_init_hw(struct drm_device *dev) } /* Need to do basic initialisation of all rings first: */ - for_each_ring(ring, dev_priv, i) { - ret = ring->init_hw(ring); + for_each_ring(engine, dev_priv, i) { + ret = engine->init_hw(engine); if (ret) goto out; } @@ -4901,17 +4901,17 @@ i915_gem_init_hw(struct drm_device *dev) goto out; /* Now it is safe to go back round and do everything else: */ - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { struct drm_i915_gem_request *req; - req = i915_gem_request_alloc(ring, NULL); + req = i915_gem_request_alloc(engine, NULL); if (IS_ERR(req)) { ret = PTR_ERR(req); i915_gem_cleanup_ringbuffer(dev); goto out; } - if (ring->id == RCS) { + if (engine->id == RCS) { for (j = 0; j < NUM_L3_SLICES(dev); j++) i915_gem_l3_remap(req, j); } @@ -5006,11 +5006,11 @@ void i915_gem_cleanup_ringbuffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; - for_each_ring(ring, dev_priv, i) - dev_priv->gt.cleanup_ring(ring); + for_each_ring(engine, dev_priv, i) + dev_priv->gt.cleanup_ring(engine); if (i915.enable_execlists) /* diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 5dd84e1..cc07666 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -346,11 +346,11 @@ void i915_gem_context_reset(struct drm_device *dev) } for (i = 0; i < I915_NUM_RINGS; i++) { - struct intel_engine_cs *ring = &dev_priv->ring[i]; + struct intel_engine_cs *engine = &dev_priv->ring[i]; - if (ring->last_context) { - i915_gem_context_unpin(ring->last_context, ring); - ring->last_context = NULL; + if (engine->last_context) { + i915_gem_context_unpin(engine->last_context, engine); + engine->last_context = NULL; } } @@ -427,11 +427,11 @@ void i915_gem_context_fini(struct drm_device *dev) } for (i = I915_NUM_RINGS; --i >= 0;) { - struct intel_engine_cs *ring = &dev_priv->ring[i]; + struct intel_engine_cs *engine = &dev_priv->ring[i]; - if (ring->last_context) { - i915_gem_context_unpin(ring->last_context, ring); - ring->last_context = NULL; + if (engine->last_context) { + i915_gem_context_unpin(engine->last_context, engine); + engine->last_context = NULL; } } @@ -441,14 +441,14 @@ void i915_gem_context_fini(struct drm_device *dev) int i915_gem_context_enable(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; if (i915.enable_execlists) { - if (ring->init_context == NULL) + if (engine->init_context == NULL) return 0; - ret = ring->init_context(req); + ret = engine->init_context(req); } else ret = i915_switch_context(req); @@ -510,12 +510,12 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) static inline int mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; u32 flags = hw_flags | MI_MM_SPACE_GTT; const int num_rings = /* Use an extended w/a on ivb+ if signalling from other rings */ - i915_semaphore_is_enabled(ring->dev) ? - hweight32(INTEL_INFO(ring->dev)->ring_mask) - 1 : + i915_semaphore_is_enabled(engine->dev) ? + hweight32(INTEL_INFO(engine->dev)->ring_mask) - 1 : 0; int len, i, ret; @@ -524,21 +524,21 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) * explicitly, so we rely on the value at ring init, stored in * itlb_before_ctx_switch. */ - if (IS_GEN6(ring->dev)) { - ret = ring->flush(req, I915_GEM_GPU_DOMAINS, 0); + if (IS_GEN6(engine->dev)) { + ret = engine->flush(req, I915_GEM_GPU_DOMAINS, 0); if (ret) return ret; } /* These flags are for resource streamer on HSW+ */ - if (IS_HASWELL(ring->dev) || INTEL_INFO(ring->dev)->gen >= 8) + if (IS_HASWELL(engine->dev) || INTEL_INFO(engine->dev)->gen >= 8) flags |= (HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN); - else if (INTEL_INFO(ring->dev)->gen < 8) + else if (INTEL_INFO(engine->dev)->gen < 8) flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN); len = 4; - if (INTEL_INFO(ring->dev)->gen >= 7) + if (INTEL_INFO(engine->dev)->gen >= 7) len += 2 + (num_rings ? 4*num_rings + 2 : 0); ret = intel_ring_begin(req, len); @@ -546,49 +546,56 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) return ret; /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ - if (INTEL_INFO(ring->dev)->gen >= 7) { - intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); + if (INTEL_INFO(engine->dev)->gen >= 7) { + intel_ring_emit(engine, MI_ARB_ON_OFF | MI_ARB_DISABLE); if (num_rings) { struct intel_engine_cs *signaller; - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); - for_each_ring(signaller, to_i915(ring->dev), i) { - if (signaller == ring) + intel_ring_emit(engine, + MI_LOAD_REGISTER_IMM(num_rings)); + for_each_ring(signaller, to_i915(engine->dev), i) { + if (signaller == engine) continue; - intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base)); - intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); + intel_ring_emit_reg(engine, + RING_PSMI_CTL(signaller->mmio_base)); + intel_ring_emit(engine, + _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); } } } - intel_ring_emit(ring, MI_NOOP); - intel_ring_emit(ring, MI_SET_CONTEXT); - intel_ring_emit(ring, i915_gem_obj_ggtt_offset(req->ctx->legacy_hw_ctx.rcs_state) | + intel_ring_emit(engine, MI_NOOP); + intel_ring_emit(engine, MI_SET_CONTEXT); + intel_ring_emit(engine, + i915_gem_obj_ggtt_offset(req->ctx->legacy_hw_ctx.rcs_state) | flags); /* * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP * WaMiSetContext_Hang:snb,ivb,vlv */ - intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(engine, MI_NOOP); - if (INTEL_INFO(ring->dev)->gen >= 7) { + if (INTEL_INFO(engine->dev)->gen >= 7) { if (num_rings) { struct intel_engine_cs *signaller; - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); - for_each_ring(signaller, to_i915(ring->dev), i) { - if (signaller == ring) + intel_ring_emit(engine, + MI_LOAD_REGISTER_IMM(num_rings)); + for_each_ring(signaller, to_i915(engine->dev), i) { + if (signaller == engine) continue; - intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base)); - intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); + intel_ring_emit_reg(engine, + RING_PSMI_CTL(signaller->mmio_base)); + intel_ring_emit(engine, + _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); } } - intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); + intel_ring_emit(engine, MI_ARB_ON_OFF | MI_ARB_ENABLE); } - intel_ring_advance(ring); + intel_ring_advance(engine); return ret; } @@ -648,25 +655,26 @@ needs_pd_load_post(struct intel_engine_cs *ring, struct intel_context *to, static int do_switch(struct drm_i915_gem_request *req) { struct intel_context *to = req->ctx; - struct intel_engine_cs *ring = req->ring; - struct drm_i915_private *dev_priv = ring->dev->dev_private; - struct intel_context *from = ring->last_context; + struct intel_engine_cs *engine = req->ring; + struct drm_i915_private *dev_priv = engine->dev->dev_private; + struct intel_context *from = engine->last_context; u32 hw_flags = 0; bool uninitialized = false; int ret, i; - if (from != NULL && ring == &dev_priv->ring[RCS]) { + if (from != NULL && engine == &dev_priv->ring[RCS]) { BUG_ON(from->legacy_hw_ctx.rcs_state == NULL); BUG_ON(!i915_gem_obj_is_pinned(from->legacy_hw_ctx.rcs_state)); } - if (should_skip_switch(ring, from, to)) + if (should_skip_switch(engine, from, to)) return 0; /* Trying to pin first makes error handling easier. */ - if (ring == &dev_priv->ring[RCS]) { + if (engine == &dev_priv->ring[RCS]) { ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state, - get_context_alignment(ring->dev), 0); + get_context_alignment(engine->dev), + 0); if (ret) return ret; } @@ -676,23 +684,23 @@ static int do_switch(struct drm_i915_gem_request *req) * evict_everything - as a last ditch gtt defrag effort that also * switches to the default context. Hence we need to reload from here. */ - from = ring->last_context; + from = engine->last_context; - if (needs_pd_load_pre(ring, to)) { + if (needs_pd_load_pre(engine, to)) { /* Older GENs and non render rings still want the load first, * "PP_DCLV followed by PP_DIR_BASE register through Load * Register Immediate commands in Ring Buffer before submitting * a context."*/ - trace_switch_mm(ring, to); + trace_switch_mm(engine, to); ret = to->ppgtt->switch_mm(to->ppgtt, req); if (ret) goto unpin_out; /* Doing a PD load always reloads the page dirs */ - to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(ring); + to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(engine); } - if (ring != &dev_priv->ring[RCS]) { + if (engine != &dev_priv->ring[RCS]) { if (from) i915_gem_context_unreference(from); goto done; @@ -717,14 +725,14 @@ static int do_switch(struct drm_i915_gem_request *req) * space. This means we must enforce that a page table load * occur when this occurs. */ } else if (to->ppgtt && - (intel_ring_flag(ring) & to->ppgtt->pd_dirty_rings)) { + (intel_ring_flag(engine) & to->ppgtt->pd_dirty_rings)) { hw_flags |= MI_FORCE_RESTORE; - to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(ring); + to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(engine); } /* We should never emit switch_mm more than once */ - WARN_ON(needs_pd_load_pre(ring, to) && - needs_pd_load_post(ring, to, hw_flags)); + WARN_ON(needs_pd_load_pre(engine, to) && + needs_pd_load_post(engine, to, hw_flags)); ret = mi_set_context(req, hw_flags); if (ret) @@ -733,8 +741,8 @@ static int do_switch(struct drm_i915_gem_request *req) /* GEN8 does *not* require an explicit reload if the PDPs have been * setup, and we do not wish to move them. */ - if (needs_pd_load_post(ring, to, hw_flags)) { - trace_switch_mm(ring, to); + if (needs_pd_load_post(engine, to, hw_flags)) { + trace_switch_mm(engine, to); ret = to->ppgtt->switch_mm(to->ppgtt, req); /* The hardware context switch is emitted, but we haven't * actually changed the state - so it's probably safe to bail @@ -787,11 +795,11 @@ static int do_switch(struct drm_i915_gem_request *req) done: i915_gem_context_reference(to); - ring->last_context = to; + engine->last_context = to; if (uninitialized) { - if (ring->init_context) { - ret = ring->init_context(req); + if (engine->init_context) { + ret = engine->init_context(req); if (ret) DRM_ERROR("ring init context: %d\n", ret); } @@ -800,7 +808,7 @@ done: return 0; unpin_out: - if (ring->id == RCS) + if (engine->id == RCS) i915_gem_object_ggtt_unpin(to->legacy_hw_ctx.rcs_state); return ret; } @@ -820,18 +828,18 @@ unpin_out: */ int i915_switch_context(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct intel_engine_cs *engine = req->ring; + struct drm_i915_private *dev_priv = engine->dev->dev_private; WARN_ON(i915.enable_execlists); WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); if (req->ctx->legacy_hw_ctx.rcs_state == NULL) { /* We have the fake context */ - if (req->ctx != ring->last_context) { + if (req->ctx != engine->last_context) { i915_gem_context_reference(req->ctx); - if (ring->last_context) - i915_gem_context_unreference(ring->last_context); - ring->last_context = req->ctx; + if (engine->last_context) + i915_gem_context_unreference(engine->last_context); + engine->last_context = req->ctx; } return 0; } diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index 17299d0..202a7e6 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c @@ -36,29 +36,30 @@ i915_verify_lists(struct drm_device *dev) static int warned; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_object *obj; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int err = 0; int i; if (warned) return 0; - for_each_ring(ring, dev_priv, i) { - list_for_each_entry(obj, &ring->active_list, ring_list[ring->id]) { + for_each_ring(engine, dev_priv, i) { + list_for_each_entry(obj, &engine->active_list, + ring_list[engine->id]) { if (obj->base.dev != dev || !atomic_read(&obj->base.refcount.refcount)) { DRM_ERROR("%s: freed active obj %p\n", - ring->name, obj); + engine->name, obj); err++; break; } else if (!obj->active || - obj->last_read_req[ring->id] == NULL) { + obj->last_read_req[engine->id] == NULL) { DRM_ERROR("%s: invalid active obj %p\n", - ring->name, obj); + engine->name, obj); err++; } else if (obj->base.write_domain) { DRM_ERROR("%s: invalid write obj %p (w %x)\n", - ring->name, + engine->name, obj, obj->base.write_domain); err++; } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 1328bc5..b73496e 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1095,7 +1095,7 @@ void i915_gem_execbuffer_move_to_active(struct list_head *vmas, struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = i915_gem_request_get_ring(req); + struct intel_engine_cs *engine = i915_gem_request_get_ring(req); struct i915_vma *vma; list_for_each_entry(vma, vmas, exec_list) { @@ -1122,7 +1122,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas, if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) { i915_gem_request_assign(&obj->last_fenced_req, req); if (entry->flags & __EXEC_OBJECT_HAS_FENCE) { - struct drm_i915_private *dev_priv = to_i915(ring->dev); + struct drm_i915_private *dev_priv = to_i915(engine->dev); list_move_tail(&dev_priv->fence_regs[obj->fence_reg].lru_list, &dev_priv->mm.fence_list); } @@ -1146,11 +1146,11 @@ static int i915_reset_gen7_sol_offsets(struct drm_device *dev, struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct drm_i915_private *dev_priv = dev->dev_private; int ret, i; - if (!IS_GEN7(dev) || ring != &dev_priv->ring[RCS]) { + if (!IS_GEN7(dev) || engine != &dev_priv->ring[RCS]) { DRM_DEBUG("sol reset is gen7/rcs only\n"); return -EINVAL; } @@ -1160,12 +1160,12 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev, return ret; for (i = 0; i < 4; i++) { - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit_reg(ring, GEN7_SO_WRITE_OFFSET(i)); - intel_ring_emit(ring, 0); + intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit_reg(engine, GEN7_SO_WRITE_OFFSET(i)); + intel_ring_emit(engine, 0); } - intel_ring_advance(ring); + intel_ring_advance(engine); return 0; } @@ -1229,7 +1229,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, struct list_head *vmas) { struct drm_device *dev = params->dev; - struct intel_engine_cs *ring = params->ring; + struct intel_engine_cs *engine = params->ring; struct drm_i915_private *dev_priv = dev->dev_private; u64 exec_start, exec_len; int instp_mode; @@ -1244,8 +1244,8 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, if (ret) return ret; - WARN(params->ctx->ppgtt && params->ctx->ppgtt->pd_dirty_rings & (1<id), - "%s didn't clear reload\n", ring->name); + WARN(params->ctx->ppgtt && params->ctx->ppgtt->pd_dirty_rings & (1<id), + "%s didn't clear reload\n", engine->name); instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK; instp_mask = I915_EXEC_CONSTANTS_MASK; @@ -1253,7 +1253,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, case I915_EXEC_CONSTANTS_REL_GENERAL: case I915_EXEC_CONSTANTS_ABSOLUTE: case I915_EXEC_CONSTANTS_REL_SURFACE: - if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) { + if (instp_mode != 0 && engine != &dev_priv->ring[RCS]) { DRM_DEBUG("non-0 rel constants mode on non-RCS\n"); return -EINVAL; } @@ -1280,17 +1280,17 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, return -EINVAL; } - if (ring == &dev_priv->ring[RCS] && + if (engine == &dev_priv->ring[RCS] && instp_mode != dev_priv->relative_constants_mode) { ret = intel_ring_begin(params->request, 4); if (ret) return ret; - intel_ring_emit(ring, MI_NOOP); - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit_reg(ring, INSTPM); - intel_ring_emit(ring, instp_mask << 16 | instp_mode); - intel_ring_advance(ring); + intel_ring_emit(engine, MI_NOOP); + intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit_reg(engine, INSTPM); + intel_ring_emit(engine, instp_mask << 16 | instp_mode); + intel_ring_advance(engine); dev_priv->relative_constants_mode = instp_mode; } @@ -1308,7 +1308,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, if (exec_len == 0) exec_len = params->batch_obj->base.size; - ret = ring->dispatch_execbuffer(params->request, + ret = engine->dispatch_execbuffer(params->request, exec_start, exec_len, params->dispatch_flags); if (ret) @@ -1432,7 +1432,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct eb_vmas *eb; struct drm_i915_gem_object *batch_obj; struct drm_i915_gem_exec_object2 shadow_exec_entry; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct intel_context *ctx; struct i915_address_space *vm; struct i915_execbuffer_params params_master; /* XXX: will be removed later */ @@ -1459,7 +1459,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (args->flags & I915_EXEC_IS_PINNED) dispatch_flags |= I915_DISPATCH_PINNED; - ret = eb_select_ring(dev_priv, file, args, &ring); + ret = eb_select_ring(dev_priv, file, args, &engine); if (ret) return ret; @@ -1473,9 +1473,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, DRM_DEBUG("RS is only allowed for Haswell, Gen8 and above\n"); return -EINVAL; } - if (ring->id != RCS) { + if (engine->id != RCS) { DRM_DEBUG("RS is not available on %s\n", - ring->name); + engine->name); return -EINVAL; } @@ -1488,7 +1488,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (ret) goto pre_mutex_err; - ctx = i915_gem_validate_context(dev, file, ring, ctx_id); + ctx = i915_gem_validate_context(dev, file, engine, ctx_id); if (IS_ERR(ctx)) { mutex_unlock(&dev->struct_mutex); ret = PTR_ERR(ctx); @@ -1522,7 +1522,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, /* Move the objects en-masse into the GTT, evicting if necessary. */ need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0; - ret = i915_gem_execbuffer_reserve(ring, &eb->vmas, ctx, &need_relocs); + ret = i915_gem_execbuffer_reserve(engine, &eb->vmas, ctx, + &need_relocs); if (ret) goto err; @@ -1531,7 +1532,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, ret = i915_gem_execbuffer_relocate(eb); if (ret) { if (ret == -EFAULT) { - ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring, + ret = i915_gem_execbuffer_relocate_slow(dev, args, file, + engine, eb, exec, ctx); BUG_ON(!mutex_is_locked(&dev->struct_mutex)); } @@ -1547,16 +1549,16 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, } params->args_batch_start_offset = args->batch_start_offset; - if (i915_needs_cmd_parser(ring) && args->batch_len) { + if (i915_needs_cmd_parser(engine) && args->batch_len) { struct drm_i915_gem_object *parsed_batch_obj; - parsed_batch_obj = i915_gem_execbuffer_parse(ring, - &shadow_exec_entry, - eb, - batch_obj, - args->batch_start_offset, - args->batch_len, - file->is_master); + parsed_batch_obj = i915_gem_execbuffer_parse(engine, + &shadow_exec_entry, + eb, + batch_obj, + args->batch_start_offset, + args->batch_len, + file->is_master); if (IS_ERR(parsed_batch_obj)) { ret = PTR_ERR(parsed_batch_obj); goto err; @@ -1608,7 +1610,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, params->batch_obj_vm_offset = i915_gem_obj_offset(batch_obj, vm); /* Allocate a request for this batch buffer nice and early. */ - req = i915_gem_request_alloc(ring, ctx); + req = i915_gem_request_alloc(engine, ctx); if (IS_ERR(req)) { ret = PTR_ERR(req); goto err_batch_unpin; @@ -1626,7 +1628,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, */ params->dev = dev; params->file = file; - params->ring = ring; + params->ring = engine; params->dispatch_flags = dispatch_flags; params->batch_obj = batch_obj; params->ctx = ctx; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 7b8de85..1bc7779 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -658,7 +658,7 @@ static int gen8_write_pdp(struct drm_i915_gem_request *req, unsigned entry, dma_addr_t addr) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; BUG_ON(entry >= 4); @@ -667,13 +667,13 @@ static int gen8_write_pdp(struct drm_i915_gem_request *req, if (ret) return ret; - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit_reg(ring, GEN8_RING_PDP_UDW(ring, entry)); - intel_ring_emit(ring, upper_32_bits(addr)); - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit_reg(ring, GEN8_RING_PDP_LDW(ring, entry)); - intel_ring_emit(ring, lower_32_bits(addr)); - intel_ring_advance(ring); + intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit_reg(engine, GEN8_RING_PDP_UDW(engine, entry)); + intel_ring_emit(engine, upper_32_bits(addr)); + intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit_reg(engine, GEN8_RING_PDP_LDW(engine, entry)); + intel_ring_emit(engine, lower_32_bits(addr)); + intel_ring_advance(engine); return 0; } @@ -1650,11 +1650,11 @@ static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt) static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt, struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; /* NB: TLBs must be flushed and invalidated before a switch */ - ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); + ret = engine->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); if (ret) return ret; @@ -1662,13 +1662,13 @@ static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt, if (ret) return ret; - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2)); - intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring)); - intel_ring_emit(ring, PP_DIR_DCLV_2G); - intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring)); - intel_ring_emit(ring, get_pd_offset(ppgtt)); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(2)); + intel_ring_emit_reg(engine, RING_PP_DIR_DCLV(engine)); + intel_ring_emit(engine, PP_DIR_DCLV_2G); + intel_ring_emit_reg(engine, RING_PP_DIR_BASE(engine)); + intel_ring_emit(engine, get_pd_offset(ppgtt)); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); return 0; } @@ -1676,22 +1676,22 @@ static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt, static int vgpu_mm_switch(struct i915_hw_ppgtt *ppgtt, struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev); - I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); - I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt)); + I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G); + I915_WRITE(RING_PP_DIR_BASE(engine), get_pd_offset(ppgtt)); return 0; } static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt, struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; /* NB: TLBs must be flushed and invalidated before a switch */ - ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); + ret = engine->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); if (ret) return ret; @@ -1699,17 +1699,17 @@ static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt, if (ret) return ret; - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2)); - intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring)); - intel_ring_emit(ring, PP_DIR_DCLV_2G); - intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring)); - intel_ring_emit(ring, get_pd_offset(ppgtt)); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(2)); + intel_ring_emit_reg(engine, RING_PP_DIR_DCLV(engine)); + intel_ring_emit(engine, PP_DIR_DCLV_2G); + intel_ring_emit_reg(engine, RING_PP_DIR_BASE(engine)); + intel_ring_emit(engine, get_pd_offset(ppgtt)); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); /* XXX: RCS is the only one to auto invalidate the TLBs? */ - if (ring->id != RCS) { - ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); + if (engine->id != RCS) { + ret = engine->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); if (ret) return ret; } @@ -1720,15 +1720,15 @@ static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt, static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt, struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct drm_device *dev = ppgtt->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G); - I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt)); + I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G); + I915_WRITE(RING_PP_DIR_BASE(engine), get_pd_offset(ppgtt)); - POSTING_READ(RING_PP_DIR_DCLV(ring)); + POSTING_READ(RING_PP_DIR_DCLV(engine)); return 0; } @@ -1736,12 +1736,12 @@ static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt, static void gen8_ppgtt_enable(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int j; - for_each_ring(ring, dev_priv, j) { + for_each_ring(engine, dev_priv, j) { u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0; - I915_WRITE(RING_MODE_GEN7(ring), + I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level)); } } @@ -1749,7 +1749,7 @@ static void gen8_ppgtt_enable(struct drm_device *dev) static void gen7_ppgtt_enable(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; uint32_t ecochk, ecobits; int i; @@ -1765,9 +1765,9 @@ static void gen7_ppgtt_enable(struct drm_device *dev) } I915_WRITE(GAM_ECOCHK, ecochk); - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { /* GFX_MODE is per-ring on gen7+ */ - I915_WRITE(RING_MODE_GEN7(ring), + I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); } } @@ -2286,15 +2286,15 @@ static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) void i915_check_and_clear_faults(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; if (INTEL_INFO(dev)->gen < 6) return; - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { u32 fault_reg; - fault_reg = I915_READ(RING_FAULT_REG(ring)); + fault_reg = I915_READ(RING_FAULT_REG(engine)); if (fault_reg & RING_FAULT_VALID) { DRM_DEBUG_DRIVER("Unexpected fault\n" "\tAddr: 0x%08lx\n" @@ -2305,7 +2305,7 @@ void i915_check_and_clear_faults(struct drm_device *dev) fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT", RING_FAULT_SRCID(fault_reg), RING_FAULT_FAULT_TYPE(fault_reg)); - I915_WRITE(RING_FAULT_REG(ring), + I915_WRITE(RING_FAULT_REG(engine), fault_reg & ~RING_FAULT_VALID); } } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 13b5f3a..d97cadc 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -495,9 +495,9 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if (obj) { u64 wa_ctx_offset = obj->gtt_offset; u32 *wa_ctx_page = &obj->pages[0][0]; - struct intel_engine_cs *ring = &dev_priv->ring[RCS]; - u32 wa_ctx_size = (ring->wa_ctx.indirect_ctx.size + - ring->wa_ctx.per_ctx.size); + struct intel_engine_cs *engine = &dev_priv->ring[RCS]; + u32 wa_ctx_size = (engine->wa_ctx.indirect_ctx.size + + engine->wa_ctx.per_ctx.size); err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n", dev_priv->ring[i].name, wa_ctx_offset); @@ -1019,19 +1019,19 @@ static void i915_gem_record_rings(struct drm_device *dev, int i, count; for (i = 0; i < I915_NUM_RINGS; i++) { - struct intel_engine_cs *ring = &dev_priv->ring[i]; + struct intel_engine_cs *engine = &dev_priv->ring[i]; struct intel_ringbuffer *rbuf; error->ring[i].pid = -1; - if (ring->dev == NULL) + if (engine->dev == NULL) continue; error->ring[i].valid = true; - i915_record_ring_state(dev, error, ring, &error->ring[i]); + i915_record_ring_state(dev, error, engine, &error->ring[i]); - request = i915_gem_find_active_request(ring); + request = i915_gem_find_active_request(engine); if (request) { struct i915_address_space *vm; @@ -1051,7 +1051,7 @@ static void i915_gem_record_rings(struct drm_device *dev, if (HAS_BROKEN_CS_TLB(dev_priv->dev)) error->ring[i].wa_batchbuffer = i915_error_ggtt_object_create(dev_priv, - ring->scratch.obj); + engine->scratch.obj); if (request->pid) { struct task_struct *task; @@ -1073,11 +1073,11 @@ static void i915_gem_record_rings(struct drm_device *dev, * executed). */ if (request) - rbuf = request->ctx->engine[ring->id].ringbuf; + rbuf = request->ctx->engine[engine->id].ringbuf; else - rbuf = dev_priv->kernel_context->engine[ring->id].ringbuf; + rbuf = dev_priv->kernel_context->engine[engine->id].ringbuf; } else - rbuf = ring->buffer; + rbuf = engine->buffer; error->ring[i].cpu_ring_head = rbuf->head; error->ring[i].cpu_ring_tail = rbuf->tail; @@ -1086,18 +1086,19 @@ static void i915_gem_record_rings(struct drm_device *dev, i915_error_ggtt_object_create(dev_priv, rbuf->obj); error->ring[i].hws_page = - i915_error_ggtt_object_create(dev_priv, ring->status_page.obj); + i915_error_ggtt_object_create(dev_priv, + engine->status_page.obj); - if (ring->wa_ctx.obj) { + if (engine->wa_ctx.obj) { error->ring[i].wa_ctx = i915_error_ggtt_object_create(dev_priv, - ring->wa_ctx.obj); + engine->wa_ctx.obj); } - i915_gem_record_active_context(ring, error, &error->ring[i]); + i915_gem_record_active_context(engine, error, &error->ring[i]); count = 0; - list_for_each_entry(request, &ring->request_list, list) + list_for_each_entry(request, &engine->request_list, list) count++; error->ring[i].num_requests = count; @@ -1110,7 +1111,7 @@ static void i915_gem_record_rings(struct drm_device *dev, } count = 0; - list_for_each_entry(request, &ring->request_list, list) { + list_for_each_entry(request, &engine->request_list, list) { struct drm_i915_error_request *erq; if (count >= error->ring[i].num_requests) { diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index d7543ef..15a4beb 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -377,7 +377,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc, struct i915_guc_client *client) { struct drm_i915_private *dev_priv = guc_to_i915(guc); - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct intel_context *ctx = client->owner; struct guc_context_desc desc; struct sg_table *sg; @@ -390,8 +390,8 @@ static void guc_init_ctx_desc(struct intel_guc *guc, desc.priority = client->priority; desc.db_id = client->doorbell_id; - for_each_ring(ring, dev_priv, i) { - struct guc_execlist_context *lrc = &desc.lrc[ring->guc_id]; + for_each_ring(engine, dev_priv, i) { + struct guc_execlist_context *lrc = &desc.lrc[engine->guc_id]; struct drm_i915_gem_object *obj; uint64_t ctx_desc; @@ -406,14 +406,14 @@ static void guc_init_ctx_desc(struct intel_guc *guc, if (!obj) break; /* XXX: continue? */ - ctx_desc = intel_lr_context_descriptor(ctx, ring); + ctx_desc = intel_lr_context_descriptor(ctx, engine); lrc->context_desc = (u32)ctx_desc; /* The state page is after PPHWSP */ lrc->ring_lcra = i915_gem_obj_ggtt_offset(obj) + LRC_STATE_PN * PAGE_SIZE; lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) | - (ring->guc_id << GUC_ELC_ENGINE_OFFSET); + (engine->guc_id << GUC_ELC_ENGINE_OFFSET); obj = ctx->engine[i].ringbuf->obj; @@ -422,7 +422,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc, lrc->ring_next_free_location = lrc->ring_begin; lrc->ring_current_tail_pointer_value = 0; - desc.engines_used |= (1 << ring->guc_id); + desc.engines_used |= (1 << engine->guc_id); } WARN_ON(desc.engines_used == 0); @@ -839,7 +839,7 @@ static void guc_create_ads(struct intel_guc *guc) struct guc_ads *ads; struct guc_policies *policies; struct guc_mmio_reg_state *reg_state; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct page *page; u32 size, i; @@ -867,11 +867,11 @@ static void guc_create_ads(struct intel_guc *guc) * so its address won't change after we've told the GuC where * to find it. */ - ring = &dev_priv->ring[RCS]; - ads->golden_context_lrca = ring->status_page.gfx_addr; + engine = &dev_priv->ring[RCS]; + ads->golden_context_lrca = engine->status_page.gfx_addr; - for_each_ring(ring, dev_priv, i) - ads->eng_state_size[ring->guc_id] = intel_lr_context_size(ring); + for_each_ring(engine, dev_priv, i) + ads->eng_state_size[engine->guc_id] = intel_lr_context_size(engine); /* GuC scheduling policies */ policies = (void *)ads + sizeof(struct guc_ads); @@ -883,12 +883,12 @@ static void guc_create_ads(struct intel_guc *guc) /* MMIO reg state */ reg_state = (void *)policies + sizeof(struct guc_policies); - for_each_ring(ring, dev_priv, i) { - reg_state->mmio_white_list[ring->guc_id].mmio_start = - ring->mmio_base + GUC_MMIO_WHITE_LIST_START; + for_each_ring(engine, dev_priv, i) { + reg_state->mmio_white_list[engine->guc_id].mmio_start = + engine->mmio_base + GUC_MMIO_WHITE_LIST_START; /* Nothing to be saved or restored for now. */ - reg_state->mmio_white_list[ring->guc_id].count = 0; + reg_state->mmio_white_list[engine->guc_id].count = 0; } ads->reg_state_addr = ads->scheduler_policies + diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 53e5104..f172de0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1079,11 +1079,11 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) static bool any_waiters(struct drm_i915_private *dev_priv) { - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; - for_each_ring(ring, dev_priv, i) - if (ring->irq_refcount) + for_each_ring(engine, dev_priv, i) + if (engine->irq_refcount) return true; return false; @@ -2449,7 +2449,7 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg) static void i915_error_wake_up(struct drm_i915_private *dev_priv, bool reset_completed) { - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; /* @@ -2460,8 +2460,8 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv, */ /* Wake up __wait_seqno, potentially holding dev->struct_mutex. */ - for_each_ring(ring, dev_priv, i) - wake_up_all(&ring->irq_queue); + for_each_ring(engine, dev_priv, i) + wake_up_all(&engine->irq_queue); /* Wake up intel_crtc_wait_for_pending_flips, holding crtc->mutex. */ wake_up_all(&dev_priv->pending_flip_queue); @@ -2956,11 +2956,11 @@ static int semaphore_passed(struct intel_engine_cs *ring) static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) { - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; - for_each_ring(ring, dev_priv, i) - ring->hangcheck.deadlock = 0; + for_each_ring(engine, dev_priv, i) + engine->hangcheck.deadlock = 0; } static bool subunits_stuck(struct intel_engine_cs *ring) @@ -3071,7 +3071,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) container_of(work, typeof(*dev_priv), gpu_error.hangcheck_work.work); struct drm_device *dev = dev_priv->dev; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; int busy_count = 0, rings_hung = 0; bool stuck[I915_NUM_RINGS] = { 0 }; @@ -3096,33 +3096,33 @@ static void i915_hangcheck_elapsed(struct work_struct *work) */ intel_uncore_arm_unclaimed_mmio_detection(dev_priv); - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { u64 acthd; u32 seqno; bool busy = true; semaphore_clear_deadlocks(dev_priv); - seqno = ring->get_seqno(ring, false); - acthd = intel_ring_get_active_head(ring); + seqno = engine->get_seqno(engine, false); + acthd = intel_ring_get_active_head(engine); - if (ring->hangcheck.seqno == seqno) { - if (ring_idle(ring, seqno)) { - ring->hangcheck.action = HANGCHECK_IDLE; + if (engine->hangcheck.seqno == seqno) { + if (ring_idle(engine, seqno)) { + engine->hangcheck.action = HANGCHECK_IDLE; - if (waitqueue_active(&ring->irq_queue)) { + if (waitqueue_active(&engine->irq_queue)) { /* Issue a wake-up to catch stuck h/w. */ - if (!test_and_set_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings)) { - if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring))) + if (!test_and_set_bit(engine->id, &dev_priv->gpu_error.missed_irq_rings)) { + if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(engine))) DRM_ERROR("Hangcheck timer elapsed... %s idle\n", - ring->name); + engine->name); else DRM_INFO("Fake missed irq on %s\n", - ring->name); - wake_up_all(&ring->irq_queue); + engine->name); + wake_up_all(&engine->irq_queue); } /* Safeguard against driver failure */ - ring->hangcheck.score += BUSY; + engine->hangcheck.score += BUSY; } else busy = false; } else { @@ -3141,53 +3141,53 @@ static void i915_hangcheck_elapsed(struct work_struct *work) * being repeatedly kicked and so responsible * for stalling the machine. */ - ring->hangcheck.action = ring_stuck(ring, - acthd); + engine->hangcheck.action = ring_stuck(engine, + acthd); - switch (ring->hangcheck.action) { + switch (engine->hangcheck.action) { case HANGCHECK_IDLE: case HANGCHECK_WAIT: break; case HANGCHECK_ACTIVE: - ring->hangcheck.score += BUSY; + engine->hangcheck.score += BUSY; break; case HANGCHECK_KICK: - ring->hangcheck.score += KICK; + engine->hangcheck.score += KICK; break; case HANGCHECK_HUNG: - ring->hangcheck.score += HUNG; + engine->hangcheck.score += HUNG; stuck[i] = true; break; } } } else { - ring->hangcheck.action = HANGCHECK_ACTIVE; + engine->hangcheck.action = HANGCHECK_ACTIVE; /* Gradually reduce the count so that we catch DoS * attempts across multiple batches. */ - if (ring->hangcheck.score > 0) - ring->hangcheck.score -= ACTIVE_DECAY; - if (ring->hangcheck.score < 0) - ring->hangcheck.score = 0; + if (engine->hangcheck.score > 0) + engine->hangcheck.score -= ACTIVE_DECAY; + if (engine->hangcheck.score < 0) + engine->hangcheck.score = 0; /* Clear head and subunit states on seqno movement */ - ring->hangcheck.acthd = 0; + engine->hangcheck.acthd = 0; - memset(ring->hangcheck.instdone, 0, - sizeof(ring->hangcheck.instdone)); + memset(engine->hangcheck.instdone, 0, + sizeof(engine->hangcheck.instdone)); } - ring->hangcheck.seqno = seqno; - ring->hangcheck.acthd = acthd; + engine->hangcheck.seqno = seqno; + engine->hangcheck.acthd = acthd; busy_count += busy; } - for_each_ring(ring, dev_priv, i) { - if (ring->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) { + for_each_ring(engine, dev_priv, i) { + if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) { DRM_INFO("%s on %s\n", stuck[i] ? "stuck" : "no progress", - ring->name); + engine->name); rings_hung++; } } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4c04dab..e95f2b7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10984,7 +10984,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); u32 flip_mask; int ret; @@ -11000,13 +11000,13 @@ static int intel_gen2_queue_flip(struct drm_device *dev, flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; else flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; - intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask); - intel_ring_emit(ring, MI_NOOP); - intel_ring_emit(ring, MI_DISPLAY_FLIP | + intel_ring_emit(engine, MI_WAIT_FOR_EVENT | flip_mask); + intel_ring_emit(engine, MI_NOOP); + intel_ring_emit(engine, MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - intel_ring_emit(ring, fb->pitches[0]); - intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset); - intel_ring_emit(ring, 0); /* aux display base address, unused */ + intel_ring_emit(engine, fb->pitches[0]); + intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset); + intel_ring_emit(engine, 0); /* aux display base address, unused */ intel_mark_page_flip_active(intel_crtc->unpin_work); return 0; @@ -11019,7 +11019,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); u32 flip_mask; int ret; @@ -11032,13 +11032,13 @@ static int intel_gen3_queue_flip(struct drm_device *dev, flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; else flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; - intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask); - intel_ring_emit(ring, MI_NOOP); - intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | + intel_ring_emit(engine, MI_WAIT_FOR_EVENT | flip_mask); + intel_ring_emit(engine, MI_NOOP); + intel_ring_emit(engine, MI_DISPLAY_FLIP_I915 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - intel_ring_emit(ring, fb->pitches[0]); - intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset); - intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(engine, fb->pitches[0]); + intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset); + intel_ring_emit(engine, MI_NOOP); intel_mark_page_flip_active(intel_crtc->unpin_work); return 0; @@ -11051,7 +11051,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t pf, pipesrc; @@ -11065,10 +11065,10 @@ static int intel_gen4_queue_flip(struct drm_device *dev, * Display Registers (which do not change across a page-flip) * so we need only reprogram the base address. */ - intel_ring_emit(ring, MI_DISPLAY_FLIP | + intel_ring_emit(engine, MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - intel_ring_emit(ring, fb->pitches[0]); - intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset | + intel_ring_emit(engine, fb->pitches[0]); + intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset | obj->tiling_mode); /* XXX Enabling the panel-fitter across page-flip is so far @@ -11077,7 +11077,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev, */ pf = 0; pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; - intel_ring_emit(ring, pf | pipesrc); + intel_ring_emit(engine, pf | pipesrc); intel_mark_page_flip_active(intel_crtc->unpin_work); return 0; @@ -11090,7 +11090,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t pf, pipesrc; @@ -11100,10 +11100,10 @@ static int intel_gen6_queue_flip(struct drm_device *dev, if (ret) return ret; - intel_ring_emit(ring, MI_DISPLAY_FLIP | + intel_ring_emit(engine, MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode); - intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset); + intel_ring_emit(engine, fb->pitches[0] | obj->tiling_mode); + intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset); /* Contrary to the suggestions in the documentation, * "Enable Panel Fitter" does not seem to be required when page @@ -11113,7 +11113,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev, */ pf = 0; pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; - intel_ring_emit(ring, pf | pipesrc); + intel_ring_emit(engine, pf | pipesrc); intel_mark_page_flip_active(intel_crtc->unpin_work); return 0; @@ -11126,7 +11126,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t plane_bit = 0; int len, ret; @@ -11147,7 +11147,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, } len = 4; - if (ring->id == RCS) { + if (engine->id == RCS) { len += 6; /* * On Gen 8, SRM is now taking an extra dword to accommodate @@ -11185,30 +11185,30 @@ static int intel_gen7_queue_flip(struct drm_device *dev, * for the RCS also doesn't appear to drop events. Setting the DERRMR * to zero does lead to lockups within MI_DISPLAY_FLIP. */ - if (ring->id == RCS) { - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); - intel_ring_emit_reg(ring, DERRMR); - intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE | - DERRMR_PIPEB_PRI_FLIP_DONE | - DERRMR_PIPEC_PRI_FLIP_DONE)); + if (engine->id == RCS) { + intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit_reg(engine, DERRMR); + intel_ring_emit(engine, ~(DERRMR_PIPEA_PRI_FLIP_DONE | + DERRMR_PIPEB_PRI_FLIP_DONE | + DERRMR_PIPEC_PRI_FLIP_DONE)); if (IS_GEN8(dev)) - intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 | + intel_ring_emit(engine, MI_STORE_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT); else - intel_ring_emit(ring, MI_STORE_REGISTER_MEM | + intel_ring_emit(engine, MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT); - intel_ring_emit_reg(ring, DERRMR); - intel_ring_emit(ring, ring->scratch.gtt_offset + 256); + intel_ring_emit_reg(engine, DERRMR); + intel_ring_emit(engine, engine->scratch.gtt_offset + 256); if (IS_GEN8(dev)) { - intel_ring_emit(ring, 0); - intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(engine, 0); + intel_ring_emit(engine, MI_NOOP); } } - intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); - intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); - intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset); - intel_ring_emit(ring, (MI_NOOP)); + intel_ring_emit(engine, MI_DISPLAY_FLIP_I915 | plane_bit); + intel_ring_emit(engine, (fb->pitches[0] | obj->tiling_mode)); + intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset); + intel_ring_emit(engine, (MI_NOOP)); intel_mark_page_flip_active(intel_crtc->unpin_work); return 0; @@ -11488,7 +11488,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, struct drm_plane *primary = crtc->primary; enum pipe pipe = intel_crtc->pipe; struct intel_unpin_work *work; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; bool mmio_flip; struct drm_i915_gem_request *request = NULL; int ret; @@ -11575,21 +11575,21 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1; if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { - ring = &dev_priv->ring[BCS]; + engine = &dev_priv->ring[BCS]; if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode) /* vlv: DISPLAY_FLIP fails to change tiling */ - ring = NULL; + engine = NULL; } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { - ring = &dev_priv->ring[BCS]; + engine = &dev_priv->ring[BCS]; } else if (INTEL_INFO(dev)->gen >= 7) { - ring = i915_gem_request_get_ring(obj->last_write_req); - if (ring == NULL || ring->id != RCS) - ring = &dev_priv->ring[BCS]; + engine = i915_gem_request_get_ring(obj->last_write_req); + if (engine == NULL || engine->id != RCS) + engine = &dev_priv->ring[BCS]; } else { - ring = &dev_priv->ring[RCS]; + engine = &dev_priv->ring[RCS]; } - mmio_flip = use_mmio_flip(ring, obj); + mmio_flip = use_mmio_flip(engine, obj); /* When using CS flips, we want to emit semaphores between rings. * However, when using mmio flips we will create a task to do the @@ -11597,7 +11597,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, * into the display plane and skip any waits. */ if (!mmio_flip) { - ret = i915_gem_object_sync(obj, ring, &request); + ret = i915_gem_object_sync(obj, engine, &request); if (ret) goto cleanup_pending; } @@ -11619,7 +11619,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, obj->last_write_req); } else { if (!request) { - request = i915_gem_request_alloc(ring, NULL); + request = i915_gem_request_alloc(engine, NULL); if (IS_ERR(request)) { ret = PTR_ERR(request); goto cleanup_unpin; diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 82a3c03..fc2c518 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -81,14 +81,14 @@ const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status) static void direct_interrupts_to_host(struct drm_i915_private *dev_priv) { - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i, irqs; /* tell all command streamers NOT to forward interrupts and vblank to GuC */ irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER); irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING); - for_each_ring(ring, dev_priv, i) - I915_WRITE(RING_MODE_GEN7(ring), irqs); + for_each_ring(engine, dev_priv, i) + I915_WRITE(RING_MODE_GEN7(engine), irqs); /* route all GT interrupts to the host */ I915_WRITE(GUC_BCS_RCS_IER, 0); @@ -98,14 +98,14 @@ static void direct_interrupts_to_host(struct drm_i915_private *dev_priv) static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv) { - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i, irqs; /* tell all command streamers to forward interrupts and vblank to GuC */ irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_ALWAYS); irqs |= _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); - for_each_ring(ring, dev_priv, i) - I915_WRITE(RING_MODE_GEN7(ring), irqs); + for_each_ring(engine, dev_priv, i) + I915_WRITE(RING_MODE_GEN7(engine), irqs); /* route USER_INTERRUPT to Host, all others are sent to GuC. */ irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT | diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 6fcbf6b..448c68e 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -360,8 +360,8 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0, struct drm_i915_gem_request *rq1) { - struct intel_engine_cs *ring = rq0->ring; - struct drm_device *dev = ring->dev; + struct intel_engine_cs *engine = rq0->ring; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; uint64_t desc[2]; @@ -376,15 +376,15 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0, rq0->elsp_submitted++; /* You must always write both descriptors in the order below. */ - I915_WRITE_FW(RING_ELSP(ring), upper_32_bits(desc[1])); - I915_WRITE_FW(RING_ELSP(ring), lower_32_bits(desc[1])); + I915_WRITE_FW(RING_ELSP(engine), upper_32_bits(desc[1])); + I915_WRITE_FW(RING_ELSP(engine), lower_32_bits(desc[1])); - I915_WRITE_FW(RING_ELSP(ring), upper_32_bits(desc[0])); + I915_WRITE_FW(RING_ELSP(engine), upper_32_bits(desc[0])); /* The context is automatically loaded after the following */ - I915_WRITE_FW(RING_ELSP(ring), lower_32_bits(desc[0])); + I915_WRITE_FW(RING_ELSP(engine), lower_32_bits(desc[0])); /* ELSP is a wo register, use another nearby reg for posting */ - POSTING_READ_FW(RING_EXECLIST_STATUS_LO(ring)); + POSTING_READ_FW(RING_EXECLIST_STATUS_LO(engine)); } static void @@ -398,9 +398,9 @@ execlists_update_context_pdps(struct i915_hw_ppgtt *ppgtt, u32 *reg_state) static void execlists_update_context(struct drm_i915_gem_request *rq) { - struct intel_engine_cs *ring = rq->ring; + struct intel_engine_cs *engine = rq->ring; struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt; - uint32_t *reg_state = rq->ctx->engine[ring->id].lrc_reg_state; + uint32_t *reg_state = rq->ctx->engine[engine->id].lrc_reg_state; reg_state[CTX_RING_TAIL+1] = rq->tail; @@ -609,25 +609,25 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) static void execlists_context_queue(struct drm_i915_gem_request *request) { - struct intel_engine_cs *ring = request->ring; + struct intel_engine_cs *engine = request->ring; struct drm_i915_gem_request *cursor; int num_elements = 0; if (request->ctx != request->i915->kernel_context) - intel_lr_context_pin(request->ctx, ring); + intel_lr_context_pin(request->ctx, engine); i915_gem_request_reference(request); - spin_lock_irq(&ring->execlist_lock); + spin_lock_irq(&engine->execlist_lock); - list_for_each_entry(cursor, &ring->execlist_queue, execlist_link) + list_for_each_entry(cursor, &engine->execlist_queue, execlist_link) if (++num_elements > 2) break; if (num_elements > 2) { struct drm_i915_gem_request *tail_req; - tail_req = list_last_entry(&ring->execlist_queue, + tail_req = list_last_entry(&engine->execlist_queue, struct drm_i915_gem_request, execlist_link); @@ -635,32 +635,32 @@ static void execlists_context_queue(struct drm_i915_gem_request *request) WARN(tail_req->elsp_submitted != 0, "More than 2 already-submitted reqs queued\n"); list_move_tail(&tail_req->execlist_link, - &ring->execlist_retired_req_list); + &engine->execlist_retired_req_list); } } - list_add_tail(&request->execlist_link, &ring->execlist_queue); + list_add_tail(&request->execlist_link, &engine->execlist_queue); if (num_elements == 0) - execlists_context_unqueue(ring); + execlists_context_unqueue(engine); - spin_unlock_irq(&ring->execlist_lock); + spin_unlock_irq(&engine->execlist_lock); } static int logical_ring_invalidate_all_caches(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; uint32_t flush_domains; int ret; flush_domains = 0; - if (ring->gpu_caches_dirty) + if (engine->gpu_caches_dirty) flush_domains = I915_GEM_GPU_DOMAINS; - ret = ring->emit_flush(req, I915_GEM_GPU_DOMAINS, flush_domains); + ret = engine->emit_flush(req, I915_GEM_GPU_DOMAINS, flush_domains); if (ret) return ret; - ring->gpu_caches_dirty = false; + engine->gpu_caches_dirty = false; return 0; } @@ -726,7 +726,7 @@ static int logical_ring_wait_for_space(struct drm_i915_gem_request *req, int bytes) { struct intel_ringbuffer *ringbuf = req->ringbuf; - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct drm_i915_gem_request *target; unsigned space; int ret; @@ -737,7 +737,7 @@ static int logical_ring_wait_for_space(struct drm_i915_gem_request *req, /* The whole point of reserving space is to not wait! */ WARN_ON(ringbuf->reserved_in_use); - list_for_each_entry(target, &ring->request_list, list) { + list_for_each_entry(target, &engine->request_list, list) { /* * The request queue is per-engine, so can contain requests * from multiple ringbuffers. Here, we must ignore any that @@ -753,7 +753,7 @@ static int logical_ring_wait_for_space(struct drm_i915_gem_request *req, break; } - if (WARN_ON(&target->list == &ring->request_list)) + if (WARN_ON(&target->list == &engine->request_list)) return -ENOSPC; ret = i915_wait_request(target); @@ -947,9 +947,9 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, struct list_head *vmas) { struct drm_device *dev = params->dev; - struct intel_engine_cs *ring = params->ring; + struct intel_engine_cs *engine = params->ring; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ringbuffer *ringbuf = params->ctx->engine[ring->id].ringbuf; + struct intel_ringbuffer *ringbuf = params->ctx->engine[engine->id].ringbuf; u64 exec_start; int instp_mode; u32 instp_mask; @@ -961,7 +961,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, case I915_EXEC_CONSTANTS_REL_GENERAL: case I915_EXEC_CONSTANTS_ABSOLUTE: case I915_EXEC_CONSTANTS_REL_SURFACE: - if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) { + if (instp_mode != 0 && engine != &dev_priv->ring[RCS]) { DRM_DEBUG("non-0 rel constants mode on non-RCS\n"); return -EINVAL; } @@ -990,7 +990,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, if (ret) return ret; - if (ring == &dev_priv->ring[RCS] && + if (engine == &dev_priv->ring[RCS] && instp_mode != dev_priv->relative_constants_mode) { ret = intel_logical_ring_begin(params->request, 4); if (ret) @@ -1008,7 +1008,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, exec_start = params->batch_obj_vm_offset + args->batch_start_offset; - ret = ring->emit_bb_start(params->request, exec_start, params->dispatch_flags); + ret = engine->emit_bb_start(params->request, exec_start, params->dispatch_flags); if (ret) return ret; @@ -1071,17 +1071,17 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring) int logical_ring_flush_all_caches(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; - if (!ring->gpu_caches_dirty) + if (!engine->gpu_caches_dirty) return 0; - ret = ring->emit_flush(req, 0, I915_GEM_GPU_DOMAINS); + ret = engine->emit_flush(req, 0, I915_GEM_GPU_DOMAINS); if (ret) return ret; - ring->gpu_caches_dirty = false; + engine->gpu_caches_dirty = false; return 0; } @@ -1172,16 +1172,16 @@ void intel_lr_context_unpin(struct intel_context *ctx, static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req) { int ret, i; - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct intel_ringbuffer *ringbuf = req->ringbuf; - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct i915_workarounds *w = &dev_priv->workarounds; if (w->count == 0) return 0; - ring->gpu_caches_dirty = true; + engine->gpu_caches_dirty = true; ret = logical_ring_flush_all_caches(req); if (ret) return ret; @@ -1199,7 +1199,7 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req) intel_logical_ring_advance(ringbuf); - ring->gpu_caches_dirty = true; + engine->gpu_caches_dirty = true; ret = logical_ring_flush_all_caches(req); if (ret) return ret; @@ -1643,7 +1643,7 @@ static int gen9_init_render_ring(struct intel_engine_cs *ring) static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) { struct i915_hw_ppgtt *ppgtt = req->ctx->ppgtt; - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; struct intel_ringbuffer *ringbuf = req->ringbuf; const int num_lri_cmds = GEN8_LEGACY_PDPES * 2; int i, ret; @@ -1656,9 +1656,11 @@ static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) { const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i); - intel_logical_ring_emit_reg(ringbuf, GEN8_RING_PDP_UDW(ring, i)); + intel_logical_ring_emit_reg(ringbuf, + GEN8_RING_PDP_UDW(engine, i)); intel_logical_ring_emit(ringbuf, upper_32_bits(pd_daddr)); - intel_logical_ring_emit_reg(ringbuf, GEN8_RING_PDP_LDW(ring, i)); + intel_logical_ring_emit_reg(ringbuf, + GEN8_RING_PDP_LDW(engine, i)); intel_logical_ring_emit(ringbuf, lower_32_bits(pd_daddr)); } @@ -1748,8 +1750,8 @@ static int gen8_emit_flush(struct drm_i915_gem_request *request, u32 unused) { struct intel_ringbuffer *ringbuf = request->ringbuf; - struct intel_engine_cs *ring = ringbuf->ring; - struct drm_device *dev = ring->dev; + struct intel_engine_cs *engine = ringbuf->ring; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; uint32_t cmd; int ret; @@ -1769,7 +1771,7 @@ static int gen8_emit_flush(struct drm_i915_gem_request *request, if (invalidate_domains & I915_GEM_GPU_DOMAINS) { cmd |= MI_INVALIDATE_TLB; - if (ring == &dev_priv->ring[VCS]) + if (engine == &dev_priv->ring[VCS]) cmd |= MI_INVALIDATE_BSD; } @@ -1789,8 +1791,8 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, u32 flush_domains) { struct intel_ringbuffer *ringbuf = request->ringbuf; - struct intel_engine_cs *ring = ringbuf->ring; - u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; + struct intel_engine_cs *engine = ringbuf->ring; + u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; bool vf_flush_wa = false; u32 flags = 0; int ret; @@ -1818,7 +1820,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, * On GEN9: before VF_CACHE_INVALIDATE we need to emit a NULL * pipe control. */ - if (IS_GEN9(ring->dev)) + if (IS_GEN9(engine->dev)) vf_flush_wa = true; } @@ -2109,38 +2111,38 @@ error: static int logical_render_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->ring[RCS]; int ret; - ring->name = "render ring"; - ring->id = RCS; - ring->exec_id = I915_EXEC_RENDER; - ring->guc_id = GUC_RENDER_ENGINE; - ring->mmio_base = RENDER_RING_BASE; + engine->name = "render ring"; + engine->id = RCS; + engine->exec_id = I915_EXEC_RENDER; + engine->guc_id = GUC_RENDER_ENGINE; + engine->mmio_base = RENDER_RING_BASE; - logical_ring_default_irqs(ring, GEN8_RCS_IRQ_SHIFT); + logical_ring_default_irqs(engine, GEN8_RCS_IRQ_SHIFT); if (HAS_L3_DPF(dev)) - ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; + engine->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT; - logical_ring_default_vfuncs(dev, ring); + logical_ring_default_vfuncs(dev, engine); /* Override some for render ring. */ if (INTEL_INFO(dev)->gen >= 9) - ring->init_hw = gen9_init_render_ring; + engine->init_hw = gen9_init_render_ring; else - ring->init_hw = gen8_init_render_ring; - ring->init_context = gen8_init_rcs_context; - ring->cleanup = intel_fini_pipe_control; - ring->emit_flush = gen8_emit_flush_render; - ring->emit_request = gen8_emit_request_render; + engine->init_hw = gen8_init_render_ring; + engine->init_context = gen8_init_rcs_context; + engine->cleanup = intel_fini_pipe_control; + engine->emit_flush = gen8_emit_flush_render; + engine->emit_request = gen8_emit_request_render; - ring->dev = dev; + engine->dev = dev; - ret = intel_init_pipe_control(ring); + ret = intel_init_pipe_control(engine); if (ret) return ret; - ret = intel_init_workaround_bb(ring); + ret = intel_init_workaround_bb(engine); if (ret) { /* * We continue even if we fail to initialize WA batch @@ -2151,9 +2153,9 @@ static int logical_render_ring_init(struct drm_device *dev) ret); } - ret = logical_ring_init(dev, ring); + ret = logical_ring_init(dev, engine); if (ret) { - lrc_destroy_wa_ctx_obj(ring); + lrc_destroy_wa_ctx_obj(engine); } return ret; @@ -2162,69 +2164,69 @@ static int logical_render_ring_init(struct drm_device *dev) static int logical_bsd_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[VCS]; + struct intel_engine_cs *engine = &dev_priv->ring[VCS]; - ring->name = "bsd ring"; - ring->id = VCS; - ring->exec_id = I915_EXEC_BSD; - ring->guc_id = GUC_VIDEO_ENGINE; - ring->mmio_base = GEN6_BSD_RING_BASE; + engine->name = "bsd ring"; + engine->id = VCS; + engine->exec_id = I915_EXEC_BSD; + engine->guc_id = GUC_VIDEO_ENGINE; + engine->mmio_base = GEN6_BSD_RING_BASE; - logical_ring_default_irqs(ring, GEN8_VCS1_IRQ_SHIFT); - logical_ring_default_vfuncs(dev, ring); + logical_ring_default_irqs(engine, GEN8_VCS1_IRQ_SHIFT); + logical_ring_default_vfuncs(dev, engine); - return logical_ring_init(dev, ring); + return logical_ring_init(dev, engine); } static int logical_bsd2_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[VCS2]; + struct intel_engine_cs *engine = &dev_priv->ring[VCS2]; - ring->name = "bsd2 ring"; - ring->id = VCS2; - ring->exec_id = I915_EXEC_BSD; - ring->guc_id = GUC_VIDEO_ENGINE2; - ring->mmio_base = GEN8_BSD2_RING_BASE; + engine->name = "bsd2 ring"; + engine->id = VCS2; + engine->exec_id = I915_EXEC_BSD; + engine->guc_id = GUC_VIDEO_ENGINE2; + engine->mmio_base = GEN8_BSD2_RING_BASE; - logical_ring_default_irqs(ring, GEN8_VCS2_IRQ_SHIFT); - logical_ring_default_vfuncs(dev, ring); + logical_ring_default_irqs(engine, GEN8_VCS2_IRQ_SHIFT); + logical_ring_default_vfuncs(dev, engine); - return logical_ring_init(dev, ring); + return logical_ring_init(dev, engine); } static int logical_blt_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[BCS]; + struct intel_engine_cs *engine = &dev_priv->ring[BCS]; - ring->name = "blitter ring"; - ring->id = BCS; - ring->exec_id = I915_EXEC_BLT; - ring->guc_id = GUC_BLITTER_ENGINE; - ring->mmio_base = BLT_RING_BASE; + engine->name = "blitter ring"; + engine->id = BCS; + engine->exec_id = I915_EXEC_BLT; + engine->guc_id = GUC_BLITTER_ENGINE; + engine->mmio_base = BLT_RING_BASE; - logical_ring_default_irqs(ring, GEN8_BCS_IRQ_SHIFT); - logical_ring_default_vfuncs(dev, ring); + logical_ring_default_irqs(engine, GEN8_BCS_IRQ_SHIFT); + logical_ring_default_vfuncs(dev, engine); - return logical_ring_init(dev, ring); + return logical_ring_init(dev, engine); } static int logical_vebox_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[VECS]; + struct intel_engine_cs *engine = &dev_priv->ring[VECS]; - ring->name = "video enhancement ring"; - ring->id = VECS; - ring->exec_id = I915_EXEC_VEBOX; - ring->guc_id = GUC_VIDEOENHANCE_ENGINE; - ring->mmio_base = VEBOX_RING_BASE; + engine->name = "video enhancement ring"; + engine->id = VECS; + engine->exec_id = I915_EXEC_VEBOX; + engine->guc_id = GUC_VIDEOENHANCE_ENGINE; + engine->mmio_base = VEBOX_RING_BASE; - logical_ring_default_irqs(ring, GEN8_VECS_IRQ_SHIFT); - logical_ring_default_vfuncs(dev, ring); + logical_ring_default_irqs(engine, GEN8_VECS_IRQ_SHIFT); + logical_ring_default_vfuncs(dev, engine); - return logical_ring_init(dev, ring); + return logical_ring_init(dev, engine); } /** @@ -2639,14 +2641,14 @@ void intel_lr_context_reset(struct drm_device *dev, struct intel_context *ctx) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; int i; - for_each_ring(ring, dev_priv, i) { + for_each_ring(engine, dev_priv, i) { struct drm_i915_gem_object *ctx_obj = - ctx->engine[ring->id].state; + ctx->engine[engine->id].state; struct intel_ringbuffer *ringbuf = - ctx->engine[ring->id].ringbuf; + ctx->engine[engine->id].ringbuf; uint32_t *reg_state; struct page *page; diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c index fed7bea..d559259 100644 --- a/drivers/gpu/drm/i915/intel_mocs.c +++ b/drivers/gpu/drm/i915/intel_mocs.c @@ -324,11 +324,11 @@ int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req) if (get_mocs_settings(req->ring->dev, &t)) { struct drm_i915_private *dev_priv = req->i915; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; enum intel_ring_id ring_id; /* Program the control registers */ - for_each_ring(ring, dev_priv, ring_id) { + for_each_ring(engine, dev_priv, ring_id) { ret = emit_mocs_control_table(req, &t, ring_id); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 9168413..13b2763 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -233,14 +233,14 @@ static int intel_overlay_on(struct intel_overlay *overlay) { struct drm_device *dev = overlay->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->ring[RCS]; struct drm_i915_gem_request *req; int ret; WARN_ON(overlay->active); WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE)); - req = i915_gem_request_alloc(ring, NULL); + req = i915_gem_request_alloc(engine, NULL); if (IS_ERR(req)) return PTR_ERR(req); @@ -252,11 +252,11 @@ static int intel_overlay_on(struct intel_overlay *overlay) overlay->active = true; - intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON); - intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE); - intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_ON); + intel_ring_emit(engine, overlay->flip_addr | OFC_UPDATE); + intel_ring_emit(engine, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); return intel_overlay_do_wait_request(overlay, req, NULL); } @@ -267,7 +267,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay, { struct drm_device *dev = overlay->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->ring[RCS]; struct drm_i915_gem_request *req; u32 flip_addr = overlay->flip_addr; u32 tmp; @@ -283,7 +283,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay, if (tmp & (1 << 17)) DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); - req = i915_gem_request_alloc(ring, NULL); + req = i915_gem_request_alloc(engine, NULL); if (IS_ERR(req)) return PTR_ERR(req); @@ -293,9 +293,9 @@ static int intel_overlay_continue(struct intel_overlay *overlay, return ret; } - intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); - intel_ring_emit(ring, flip_addr); - intel_ring_advance(ring); + intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); + intel_ring_emit(engine, flip_addr); + intel_ring_advance(engine); WARN_ON(overlay->last_flip_req); i915_gem_request_assign(&overlay->last_flip_req, req); @@ -336,7 +336,7 @@ static int intel_overlay_off(struct intel_overlay *overlay) { struct drm_device *dev = overlay->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->ring[RCS]; struct drm_i915_gem_request *req; u32 flip_addr = overlay->flip_addr; int ret; @@ -349,7 +349,7 @@ static int intel_overlay_off(struct intel_overlay *overlay) * of the hw. Do it in both cases */ flip_addr |= OFC_UPDATE; - req = i915_gem_request_alloc(ring, NULL); + req = i915_gem_request_alloc(engine, NULL); if (IS_ERR(req)) return PTR_ERR(req); @@ -360,22 +360,23 @@ static int intel_overlay_off(struct intel_overlay *overlay) } /* wait for overlay to go idle */ - intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); - intel_ring_emit(ring, flip_addr); - intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); + intel_ring_emit(engine, flip_addr); + intel_ring_emit(engine, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); /* turn overlay off */ if (IS_I830(dev)) { /* Workaround: Don't disable the overlay fully, since otherwise * it dies on the next OVERLAY_ON cmd. */ - intel_ring_emit(ring, MI_NOOP); - intel_ring_emit(ring, MI_NOOP); - intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(engine, MI_NOOP); + intel_ring_emit(engine, MI_NOOP); + intel_ring_emit(engine, MI_NOOP); } else { - intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); - intel_ring_emit(ring, flip_addr); - intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); + intel_ring_emit(engine, flip_addr); + intel_ring_emit(engine, + MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); } - intel_ring_advance(ring); + intel_ring_advance(engine); return intel_overlay_do_wait_request(overlay, req, intel_overlay_off_tail); } @@ -408,7 +409,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) { struct drm_device *dev = overlay->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->ring[RCS]; int ret; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); @@ -423,7 +424,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) /* synchronous slowpath */ struct drm_i915_gem_request *req; - req = i915_gem_request_alloc(ring, NULL); + req = i915_gem_request_alloc(engine, NULL); if (IS_ERR(req)) return PTR_ERR(req); @@ -433,9 +434,10 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) return ret; } - intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, + MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); ret = intel_overlay_do_wait_request(overlay, req, intel_overlay_release_old_vid_tail); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d7aef17..c54a7df 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4815,7 +4815,7 @@ static void gen9_enable_rps(struct drm_device *dev) static void gen9_enable_rc6(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; uint32_t rc6_mask = 0; int unused; @@ -4838,8 +4838,8 @@ static void gen9_enable_rc6(struct drm_device *dev) 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) - I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + for_each_ring(engine, dev_priv, unused) + I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); if (HAS_GUC_UCODE(dev)) I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA); @@ -4885,7 +4885,7 @@ static void gen9_enable_rc6(struct drm_device *dev) static void gen8_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; uint32_t rc6_mask = 0; int unused; @@ -4906,8 +4906,8 @@ static void gen8_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 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) - I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + for_each_ring(engine, dev_priv, unused) + I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); if (IS_BROADWELL(dev)) I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */ @@ -4967,7 +4967,7 @@ static void gen8_enable_rps(struct drm_device *dev) static void gen6_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; u32 rc6vids, pcu_mbox = 0, rc6_mask = 0; u32 gtfifodbg; int rc6_mode; @@ -5003,8 +5003,8 @@ static void gen6_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); - for_each_ring(ring, dev_priv, i) - I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + for_each_ring(engine, dev_priv, i) + I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); @@ -5495,7 +5495,7 @@ static void valleyview_cleanup_gt_powersave(struct drm_device *dev) static void cherryview_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; u32 gtfifodbg, val, rc6_mode = 0, pcbr; int i; @@ -5522,8 +5522,8 @@ static void cherryview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ - for_each_ring(ring, dev_priv, i) - I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + for_each_ring(engine, dev_priv, i) + I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); /* TO threshold set to 500 us ( 0x186 * 1.28 us) */ @@ -5593,7 +5593,7 @@ static void cherryview_enable_rps(struct drm_device *dev) static void valleyview_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; u32 gtfifodbg, val, rc6_mode = 0; int i; @@ -5633,8 +5633,8 @@ static void valleyview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); - for_each_ring(ring, dev_priv, i) - I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + for_each_ring(engine, dev_priv, i) + I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); @@ -6010,7 +6010,7 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower); bool i915_gpu_busy(void) { struct drm_i915_private *dev_priv; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; bool ret = false; int i; @@ -6019,8 +6019,8 @@ bool i915_gpu_busy(void) goto out_unlock; dev_priv = i915_mch_dev; - for_each_ring(ring, dev_priv, i) - ret |= !list_empty(&ring->request_list); + for_each_ring(engine, dev_priv, i) + ret |= !list_empty(&engine->request_list); out_unlock: spin_unlock_irq(&mchdev_lock); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 45ce45a..688773a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -79,7 +79,7 @@ gen2_render_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; u32 cmd; int ret; @@ -94,9 +94,9 @@ gen2_render_ring_flush(struct drm_i915_gem_request *req, if (ret) return ret; - intel_ring_emit(ring, cmd); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, cmd); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); return 0; } @@ -106,8 +106,8 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { - struct intel_engine_cs *ring = req->ring; - struct drm_device *dev = ring->dev; + struct intel_engine_cs *engine = req->ring; + struct drm_device *dev = engine->dev; u32 cmd; int ret; @@ -153,9 +153,9 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req, if (ret) return ret; - intel_ring_emit(ring, cmd); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, cmd); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); return 0; } @@ -200,34 +200,34 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req, static int intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; - u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; + struct intel_engine_cs *engine = req->ring; + u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; int ret; ret = intel_ring_begin(req, 6); if (ret) return ret; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); - intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | + intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5)); + intel_ring_emit(engine, PIPE_CONTROL_CS_STALL | PIPE_CONTROL_STALL_AT_SCOREBOARD); - intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ - intel_ring_emit(ring, 0); /* low dword */ - intel_ring_emit(ring, 0); /* high dword */ - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ + intel_ring_emit(engine, 0); /* low dword */ + intel_ring_emit(engine, 0); /* high dword */ + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); ret = intel_ring_begin(req, 6); if (ret) return ret; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); - intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE); - intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ - intel_ring_emit(ring, 0); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5)); + intel_ring_emit(engine, PIPE_CONTROL_QW_WRITE); + intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */ + intel_ring_emit(engine, 0); + intel_ring_emit(engine, 0); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); return 0; } @@ -236,9 +236,9 @@ static int gen6_render_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; u32 flags = 0; - u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; + u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; int ret; /* Force SNB workarounds for PIPE_CONTROL flushes */ @@ -276,11 +276,11 @@ gen6_render_ring_flush(struct drm_i915_gem_request *req, if (ret) return ret; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); - intel_ring_emit(ring, flags); - intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); - intel_ring_emit(ring, 0); - intel_ring_advance(ring); + intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); + intel_ring_emit(engine, flags); + intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); + intel_ring_emit(engine, 0); + intel_ring_advance(engine); return 0; } @@ -288,19 +288,19 @@ gen6_render_ring_flush(struct drm_i915_gem_request *req, static int gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; ret = intel_ring_begin(req, 4); if (ret) return ret; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); - intel_ring_emit(ring, PIPE_CONTROL_CS_STALL | + intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); + intel_ring_emit(engine, PIPE_CONTROL_CS_STALL | PIPE_CONTROL_STALL_AT_SCOREBOARD); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, 0); - intel_ring_advance(ring); + intel_ring_emit(engine, 0); + intel_ring_emit(engine, 0); + intel_ring_advance(engine); return 0; } @@ -309,9 +309,9 @@ static int gen7_render_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; u32 flags = 0; - u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; + u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; int ret; /* @@ -360,11 +360,11 @@ gen7_render_ring_flush(struct drm_i915_gem_request *req, if (ret) return ret; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4)); - intel_ring_emit(ring, flags); - intel_ring_emit(ring, scratch_addr); - intel_ring_emit(ring, 0); - intel_ring_advance(ring); + intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4)); + intel_ring_emit(engine, flags); + intel_ring_emit(engine, scratch_addr); + intel_ring_emit(engine, 0); + intel_ring_advance(engine); return 0; } @@ -373,20 +373,20 @@ static int gen8_emit_pipe_control(struct drm_i915_gem_request *req, u32 flags, u32 scratch_addr) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; ret = intel_ring_begin(req, 6); if (ret) return ret; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6)); - intel_ring_emit(ring, flags); - intel_ring_emit(ring, scratch_addr); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, 0); - intel_ring_emit(ring, 0); - intel_ring_advance(ring); + intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6)); + intel_ring_emit(engine, flags); + intel_ring_emit(engine, scratch_addr); + intel_ring_emit(engine, 0); + intel_ring_emit(engine, 0); + intel_ring_emit(engine, 0); + intel_ring_advance(engine); return 0; } @@ -700,15 +700,15 @@ err: static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) { int ret, i; - struct intel_engine_cs *ring = req->ring; - struct drm_device *dev = ring->dev; + struct intel_engine_cs *engine = req->ring; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct i915_workarounds *w = &dev_priv->workarounds; if (w->count == 0) return 0; - ring->gpu_caches_dirty = true; + engine->gpu_caches_dirty = true; ret = intel_ring_flush_all_caches(req); if (ret) return ret; @@ -717,16 +717,16 @@ static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) if (ret) return ret; - intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count)); + intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(w->count)); for (i = 0; i < w->count; i++) { - intel_ring_emit_reg(ring, w->reg[i].addr); - intel_ring_emit(ring, w->reg[i].value); + intel_ring_emit_reg(engine, w->reg[i].addr); + intel_ring_emit(engine, w->reg[i].value); } - intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(engine, MI_NOOP); - intel_ring_advance(ring); + intel_ring_advance(engine); - ring->gpu_caches_dirty = true; + engine->gpu_caches_dirty = true; ret = intel_ring_flush_all_caches(req); if (ret) return ret; @@ -1388,22 +1388,23 @@ static int gen6_signal(struct drm_i915_gem_request *signaller_req, static int gen6_add_request(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; - if (ring->semaphore.signal) - ret = ring->semaphore.signal(req, 4); + if (engine->semaphore.signal) + ret = engine->semaphore.signal(req, 4); else ret = intel_ring_begin(req, 4); if (ret) return ret; - intel_ring_emit(ring, MI_STORE_DWORD_INDEX); - intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - intel_ring_emit(ring, i915_gem_request_get_seqno(req)); - intel_ring_emit(ring, MI_USER_INTERRUPT); - __intel_ring_advance(ring); + intel_ring_emit(engine, MI_STORE_DWORD_INDEX); + intel_ring_emit(engine, + I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); + intel_ring_emit(engine, i915_gem_request_get_seqno(req)); + intel_ring_emit(engine, MI_USER_INTERRUPT); + __intel_ring_advance(engine); return 0; } @@ -1502,8 +1503,8 @@ do { \ static int pc_render_add_request(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; - u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; + struct intel_engine_cs *engine = req->ring; + u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; int ret; /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently @@ -1518,32 +1519,36 @@ pc_render_add_request(struct drm_i915_gem_request *req) if (ret) return ret; - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | + intel_ring_emit(engine, + GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_WRITE_FLUSH | PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE); - intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); - intel_ring_emit(ring, i915_gem_request_get_seqno(req)); - intel_ring_emit(ring, 0); - PIPE_CONTROL_FLUSH(ring, scratch_addr); + intel_ring_emit(engine, + engine->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); + intel_ring_emit(engine, i915_gem_request_get_seqno(req)); + intel_ring_emit(engine, 0); + PIPE_CONTROL_FLUSH(engine, scratch_addr); scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */ - PIPE_CONTROL_FLUSH(ring, scratch_addr); + PIPE_CONTROL_FLUSH(engine, scratch_addr); scratch_addr += 2 * CACHELINE_BYTES; - PIPE_CONTROL_FLUSH(ring, scratch_addr); + PIPE_CONTROL_FLUSH(engine, scratch_addr); scratch_addr += 2 * CACHELINE_BYTES; - PIPE_CONTROL_FLUSH(ring, scratch_addr); + PIPE_CONTROL_FLUSH(engine, scratch_addr); scratch_addr += 2 * CACHELINE_BYTES; - PIPE_CONTROL_FLUSH(ring, scratch_addr); + PIPE_CONTROL_FLUSH(engine, scratch_addr); scratch_addr += 2 * CACHELINE_BYTES; - PIPE_CONTROL_FLUSH(ring, scratch_addr); + PIPE_CONTROL_FLUSH(engine, scratch_addr); - intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | + intel_ring_emit(engine, + GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE | PIPE_CONTROL_WRITE_FLUSH | PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | PIPE_CONTROL_NOTIFY); - intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); - intel_ring_emit(ring, i915_gem_request_get_seqno(req)); - intel_ring_emit(ring, 0); - __intel_ring_advance(ring); + intel_ring_emit(engine, + engine->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT); + intel_ring_emit(engine, i915_gem_request_get_seqno(req)); + intel_ring_emit(engine, 0); + __intel_ring_advance(engine); return 0; } @@ -1696,34 +1701,35 @@ bsd_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; ret = intel_ring_begin(req, 2); if (ret) return ret; - intel_ring_emit(ring, MI_FLUSH); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, MI_FLUSH); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); return 0; } static int i9xx_add_request(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; ret = intel_ring_begin(req, 4); if (ret) return ret; - intel_ring_emit(ring, MI_STORE_DWORD_INDEX); - intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - intel_ring_emit(ring, i915_gem_request_get_seqno(req)); - intel_ring_emit(ring, MI_USER_INTERRUPT); - __intel_ring_advance(ring); + intel_ring_emit(engine, MI_STORE_DWORD_INDEX); + intel_ring_emit(engine, + I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); + intel_ring_emit(engine, i915_gem_request_get_seqno(req)); + intel_ring_emit(engine, MI_USER_INTERRUPT); + __intel_ring_advance(engine); return 0; } @@ -1857,20 +1863,20 @@ i965_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 length, unsigned dispatch_flags) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; ret = intel_ring_begin(req, 2); if (ret) return ret; - intel_ring_emit(ring, + intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT | (dispatch_flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); - intel_ring_emit(ring, offset); - intel_ring_advance(ring); + intel_ring_emit(engine, offset); + intel_ring_advance(engine); return 0; } @@ -1884,8 +1890,8 @@ i830_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 len, unsigned dispatch_flags) { - struct intel_engine_cs *ring = req->ring; - u32 cs_offset = ring->scratch.gtt_offset; + struct intel_engine_cs *engine = req->ring; + u32 cs_offset = engine->scratch.gtt_offset; int ret; ret = intel_ring_begin(req, 6); @@ -1893,13 +1899,13 @@ i830_dispatch_execbuffer(struct drm_i915_gem_request *req, return ret; /* Evict the invalid PTE TLBs */ - intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA); - intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); - intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */ - intel_ring_emit(ring, cs_offset); - intel_ring_emit(ring, 0xdeadbeef); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, COLOR_BLT_CMD | BLT_WRITE_RGBA); + intel_ring_emit(engine, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096); + intel_ring_emit(engine, I830_TLB_ENTRIES << 16 | 4); /* load each page */ + intel_ring_emit(engine, cs_offset); + intel_ring_emit(engine, 0xdeadbeef); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) { if (len > I830_BATCH_LIMIT) @@ -1913,16 +1919,17 @@ i830_dispatch_execbuffer(struct drm_i915_gem_request *req, * stable batch scratch bo area (so that the CS never * stumbles over its tlb invalidation bug) ... */ - intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); - intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); - intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096); - intel_ring_emit(ring, cs_offset); - intel_ring_emit(ring, 4096); - intel_ring_emit(ring, offset); - - intel_ring_emit(ring, MI_FLUSH); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA); + intel_ring_emit(engine, + BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096); + intel_ring_emit(engine, DIV_ROUND_UP(len, 4096) << 16 | 4096); + intel_ring_emit(engine, cs_offset); + intel_ring_emit(engine, 4096); + intel_ring_emit(engine, offset); + + intel_ring_emit(engine, MI_FLUSH); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); /* ... and execute it. */ offset = cs_offset; @@ -1932,10 +1939,10 @@ i830_dispatch_execbuffer(struct drm_i915_gem_request *req, if (ret) return ret; - intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); - intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? - 0 : MI_BATCH_NON_SECURE)); - intel_ring_advance(ring); + intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT); + intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ? + 0 : MI_BATCH_NON_SECURE)); + intel_ring_advance(engine); return 0; } @@ -1945,17 +1952,17 @@ i915_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 len, unsigned dispatch_flags) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; ret = intel_ring_begin(req, 2); if (ret) return ret; - intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT); - intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ? - 0 : MI_BATCH_NON_SECURE)); - intel_ring_advance(ring); + intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT); + intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ? + 0 : MI_BATCH_NON_SECURE)); + intel_ring_advance(engine); return 0; } @@ -2480,32 +2487,32 @@ static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes) int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords) { - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct drm_i915_private *dev_priv; int ret; WARN_ON(req == NULL); - ring = req->ring; - dev_priv = ring->dev->dev_private; + engine = req->ring; + dev_priv = engine->dev->dev_private; ret = i915_gem_check_wedge(&dev_priv->gpu_error, dev_priv->mm.interruptible); if (ret) return ret; - ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t)); + ret = __intel_ring_prepare(engine, num_dwords * sizeof(uint32_t)); if (ret) return ret; - ring->buffer->space -= num_dwords * sizeof(uint32_t); + engine->buffer->space -= num_dwords * sizeof(uint32_t); return 0; } /* Align the ring tail to a cacheline boundary */ int intel_ring_cacheline_align(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; - int num_dwords = (ring->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); + struct intel_engine_cs *engine = req->ring; + int num_dwords = (engine->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); int ret; if (num_dwords == 0) @@ -2517,9 +2524,9 @@ int intel_ring_cacheline_align(struct drm_i915_gem_request *req) return ret; while (num_dwords--) - intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(engine, MI_NOOP); - intel_ring_advance(ring); + intel_ring_advance(engine); return 0; } @@ -2576,7 +2583,7 @@ static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring, static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, u32 invalidate, u32 flush) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; uint32_t cmd; int ret; @@ -2585,7 +2592,7 @@ static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, return ret; cmd = MI_FLUSH_DW; - if (INTEL_INFO(ring->dev)->gen >= 8) + if (INTEL_INFO(engine->dev)->gen >= 8) cmd += 1; /* We always require a command barrier so that subsequent @@ -2604,16 +2611,17 @@ static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, if (invalidate & I915_GEM_GPU_DOMAINS) cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD; - intel_ring_emit(ring, cmd); - intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); - if (INTEL_INFO(ring->dev)->gen >= 8) { - intel_ring_emit(ring, 0); /* upper addr */ - intel_ring_emit(ring, 0); /* value */ + intel_ring_emit(engine, cmd); + intel_ring_emit(engine, + I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); + if (INTEL_INFO(engine->dev)->gen >= 8) { + intel_ring_emit(engine, 0); /* upper addr */ + intel_ring_emit(engine, 0); /* value */ } else { - intel_ring_emit(ring, 0); - intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(engine, 0); + intel_ring_emit(engine, MI_NOOP); } - intel_ring_advance(ring); + intel_ring_advance(engine); return 0; } @@ -2622,8 +2630,8 @@ gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 len, unsigned dispatch_flags) { - struct intel_engine_cs *ring = req->ring; - bool ppgtt = USES_PPGTT(ring->dev) && + struct intel_engine_cs *engine = req->ring; + bool ppgtt = USES_PPGTT(engine->dev) && !(dispatch_flags & I915_DISPATCH_SECURE); int ret; @@ -2632,13 +2640,13 @@ gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, return ret; /* FIXME(BDW): Address space and security selectors. */ - intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) | + intel_ring_emit(engine, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) | (dispatch_flags & I915_DISPATCH_RS ? MI_BATCH_RESOURCE_STREAMER : 0)); - intel_ring_emit(ring, lower_32_bits(offset)); - intel_ring_emit(ring, upper_32_bits(offset)); - intel_ring_emit(ring, MI_NOOP); - intel_ring_advance(ring); + intel_ring_emit(engine, lower_32_bits(offset)); + intel_ring_emit(engine, upper_32_bits(offset)); + intel_ring_emit(engine, MI_NOOP); + intel_ring_advance(engine); return 0; } @@ -2648,22 +2656,22 @@ hsw_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 len, unsigned dispatch_flags) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; ret = intel_ring_begin(req, 2); if (ret) return ret; - intel_ring_emit(ring, + intel_ring_emit(engine, MI_BATCH_BUFFER_START | (dispatch_flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) | (dispatch_flags & I915_DISPATCH_RS ? MI_BATCH_RESOURCE_STREAMER : 0)); /* bit0-7 is the length on GEN6+ */ - intel_ring_emit(ring, offset); - intel_ring_advance(ring); + intel_ring_emit(engine, offset); + intel_ring_advance(engine); return 0; } @@ -2673,20 +2681,20 @@ gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 len, unsigned dispatch_flags) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; ret = intel_ring_begin(req, 2); if (ret) return ret; - intel_ring_emit(ring, + intel_ring_emit(engine, MI_BATCH_BUFFER_START | (dispatch_flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE_I965)); /* bit0-7 is the length on GEN6+ */ - intel_ring_emit(ring, offset); - intel_ring_advance(ring); + intel_ring_emit(engine, offset); + intel_ring_advance(engine); return 0; } @@ -2696,8 +2704,8 @@ gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 invalidate, u32 flush) { - struct intel_engine_cs *ring = req->ring; - struct drm_device *dev = ring->dev; + struct intel_engine_cs *engine = req->ring; + struct drm_device *dev = engine->dev; uint32_t cmd; int ret; @@ -2724,16 +2732,17 @@ static int gen6_ring_flush(struct drm_i915_gem_request *req, */ if (invalidate & I915_GEM_DOMAIN_RENDER) cmd |= MI_INVALIDATE_TLB; - intel_ring_emit(ring, cmd); - intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); + intel_ring_emit(engine, cmd); + intel_ring_emit(engine, + I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT); if (INTEL_INFO(dev)->gen >= 8) { - intel_ring_emit(ring, 0); /* upper addr */ - intel_ring_emit(ring, 0); /* value */ + intel_ring_emit(engine, 0); /* upper addr */ + intel_ring_emit(engine, 0); /* value */ } else { - intel_ring_emit(ring, 0); - intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(engine, 0); + intel_ring_emit(engine, MI_NOOP); } - intel_ring_advance(ring); + intel_ring_advance(engine); return 0; } @@ -2741,14 +2750,14 @@ static int gen6_ring_flush(struct drm_i915_gem_request *req, int intel_init_render_ring_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->ring[RCS]; struct drm_i915_gem_object *obj; int ret; - ring->name = "render ring"; - ring->id = RCS; - ring->exec_id = I915_EXEC_RENDER; - ring->mmio_base = RENDER_RING_BASE; + engine->name = "render ring"; + engine->id = RCS; + engine->exec_id = I915_EXEC_RENDER; + engine->mmio_base = RENDER_RING_BASE; if (INTEL_INFO(dev)->gen >= 8) { if (i915_semaphore_is_enabled(dev)) { @@ -2768,34 +2777,34 @@ int intel_init_render_ring_buffer(struct drm_device *dev) } } - ring->init_context = intel_rcs_ctx_init; - ring->add_request = gen6_add_request; - ring->flush = gen8_render_ring_flush; - ring->irq_get = gen8_ring_get_irq; - ring->irq_put = gen8_ring_put_irq; - ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; - ring->get_seqno = gen6_ring_get_seqno; - ring->set_seqno = ring_set_seqno; + engine->init_context = intel_rcs_ctx_init; + engine->add_request = gen6_add_request; + engine->flush = gen8_render_ring_flush; + engine->irq_get = gen8_ring_get_irq; + engine->irq_put = gen8_ring_put_irq; + engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT; + engine->get_seqno = gen6_ring_get_seqno; + engine->set_seqno = ring_set_seqno; if (i915_semaphore_is_enabled(dev)) { WARN_ON(!dev_priv->semaphore_obj); - ring->semaphore.sync_to = gen8_ring_sync; - ring->semaphore.signal = gen8_rcs_signal; - GEN8_RING_SEMAPHORE_INIT; + engine->semaphore.sync_to = gen8_ring_sync; + engine->semaphore.signal = gen8_rcs_signal; + GEN8_RING_SEMAPHORE_INIT(engine); } } else if (INTEL_INFO(dev)->gen >= 6) { - ring->init_context = intel_rcs_ctx_init; - ring->add_request = gen6_add_request; - ring->flush = gen7_render_ring_flush; + engine->init_context = intel_rcs_ctx_init; + engine->add_request = gen6_add_request; + engine->flush = gen7_render_ring_flush; if (INTEL_INFO(dev)->gen == 6) - ring->flush = gen6_render_ring_flush; - ring->irq_get = gen6_ring_get_irq; - ring->irq_put = gen6_ring_put_irq; - ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT; - ring->get_seqno = gen6_ring_get_seqno; - ring->set_seqno = ring_set_seqno; + engine->flush = gen6_render_ring_flush; + engine->irq_get = gen6_ring_get_irq; + engine->irq_put = gen6_ring_put_irq; + engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT; + engine->get_seqno = gen6_ring_get_seqno; + engine->set_seqno = ring_set_seqno; if (i915_semaphore_is_enabled(dev)) { - ring->semaphore.sync_to = gen6_ring_sync; - ring->semaphore.signal = gen6_signal; + engine->semaphore.sync_to = gen6_ring_sync; + engine->semaphore.signal = gen6_signal; /* * The current semaphore is only applied on pre-gen8 * platform. And there is no VCS2 ring on the pre-gen8 @@ -2803,59 +2812,59 @@ int intel_init_render_ring_buffer(struct drm_device *dev) * initialized as INVALID. Gen8 will initialize the * sema between VCS2 and RCS later. */ - ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV; - ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB; - ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE; - ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC; - ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC; - ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC; - ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC; - ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; + engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID; + engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV; + engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB; + engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE; + engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; + engine->semaphore.mbox.signal[RCS] = GEN6_NOSYNC; + engine->semaphore.mbox.signal[VCS] = GEN6_VRSYNC; + engine->semaphore.mbox.signal[BCS] = GEN6_BRSYNC; + engine->semaphore.mbox.signal[VECS] = GEN6_VERSYNC; + engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; } } else if (IS_GEN5(dev)) { - ring->add_request = pc_render_add_request; - ring->flush = gen4_render_ring_flush; - ring->get_seqno = pc_render_get_seqno; - ring->set_seqno = pc_render_set_seqno; - ring->irq_get = gen5_ring_get_irq; - ring->irq_put = gen5_ring_put_irq; - ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT | + engine->add_request = pc_render_add_request; + engine->flush = gen4_render_ring_flush; + engine->get_seqno = pc_render_get_seqno; + engine->set_seqno = pc_render_set_seqno; + engine->irq_get = gen5_ring_get_irq; + engine->irq_put = gen5_ring_put_irq; + engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT; } else { - ring->add_request = i9xx_add_request; + engine->add_request = i9xx_add_request; if (INTEL_INFO(dev)->gen < 4) - ring->flush = gen2_render_ring_flush; + engine->flush = gen2_render_ring_flush; else - ring->flush = gen4_render_ring_flush; - ring->get_seqno = ring_get_seqno; - ring->set_seqno = ring_set_seqno; + engine->flush = gen4_render_ring_flush; + engine->get_seqno = ring_get_seqno; + engine->set_seqno = ring_set_seqno; if (IS_GEN2(dev)) { - ring->irq_get = i8xx_ring_get_irq; - ring->irq_put = i8xx_ring_put_irq; + engine->irq_get = i8xx_ring_get_irq; + engine->irq_put = i8xx_ring_put_irq; } else { - ring->irq_get = i9xx_ring_get_irq; - ring->irq_put = i9xx_ring_put_irq; + engine->irq_get = i9xx_ring_get_irq; + engine->irq_put = i9xx_ring_put_irq; } - ring->irq_enable_mask = I915_USER_INTERRUPT; + engine->irq_enable_mask = I915_USER_INTERRUPT; } - ring->write_tail = ring_write_tail; + engine->write_tail = ring_write_tail; if (IS_HASWELL(dev)) - ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; + engine->dispatch_execbuffer = hsw_ring_dispatch_execbuffer; else if (IS_GEN8(dev)) - ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; + engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; else if (INTEL_INFO(dev)->gen >= 6) - ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; + engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; else if (INTEL_INFO(dev)->gen >= 4) - ring->dispatch_execbuffer = i965_dispatch_execbuffer; + engine->dispatch_execbuffer = i965_dispatch_execbuffer; else if (IS_I830(dev) || IS_845G(dev)) - ring->dispatch_execbuffer = i830_dispatch_execbuffer; + engine->dispatch_execbuffer = i830_dispatch_execbuffer; else - ring->dispatch_execbuffer = i915_dispatch_execbuffer; - ring->init_hw = init_render_ring; - ring->cleanup = render_ring_cleanup; + engine->dispatch_execbuffer = i915_dispatch_execbuffer; + engine->init_hw = init_render_ring; + engine->cleanup = render_ring_cleanup; /* Workaround batchbuffer to combat CS tlb bug. */ if (HAS_BROKEN_CS_TLB(dev)) { @@ -2872,16 +2881,16 @@ int intel_init_render_ring_buffer(struct drm_device *dev) return ret; } - ring->scratch.obj = obj; - ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); + engine->scratch.obj = obj; + engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj); } - ret = intel_init_ring_buffer(dev, ring); + ret = intel_init_ring_buffer(dev, engine); if (ret) return ret; if (INTEL_INFO(dev)->gen >= 5) { - ret = intel_init_pipe_control(ring); + ret = intel_init_pipe_control(engine); if (ret) return ret; } @@ -2892,75 +2901,75 @@ int intel_init_render_ring_buffer(struct drm_device *dev) int intel_init_bsd_ring_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[VCS]; + struct intel_engine_cs *engine = &dev_priv->ring[VCS]; - ring->name = "bsd ring"; - ring->id = VCS; - ring->exec_id = I915_EXEC_BSD; + engine->name = "bsd ring"; + engine->id = VCS; + engine->exec_id = I915_EXEC_BSD; - ring->write_tail = ring_write_tail; + engine->write_tail = ring_write_tail; if (INTEL_INFO(dev)->gen >= 6) { - ring->mmio_base = GEN6_BSD_RING_BASE; + engine->mmio_base = GEN6_BSD_RING_BASE; /* gen6 bsd needs a special wa for tail updates */ if (IS_GEN6(dev)) - ring->write_tail = gen6_bsd_ring_write_tail; - ring->flush = gen6_bsd_ring_flush; - ring->add_request = gen6_add_request; - ring->get_seqno = gen6_ring_get_seqno; - ring->set_seqno = ring_set_seqno; + engine->write_tail = gen6_bsd_ring_write_tail; + engine->flush = gen6_bsd_ring_flush; + engine->add_request = gen6_add_request; + engine->get_seqno = gen6_ring_get_seqno; + engine->set_seqno = ring_set_seqno; if (INTEL_INFO(dev)->gen >= 8) { - ring->irq_enable_mask = + engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT; - ring->irq_get = gen8_ring_get_irq; - ring->irq_put = gen8_ring_put_irq; - ring->dispatch_execbuffer = + engine->irq_get = gen8_ring_get_irq; + engine->irq_put = gen8_ring_put_irq; + engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; if (i915_semaphore_is_enabled(dev)) { - ring->semaphore.sync_to = gen8_ring_sync; - ring->semaphore.signal = gen8_xcs_signal; - GEN8_RING_SEMAPHORE_INIT; + engine->semaphore.sync_to = gen8_ring_sync; + engine->semaphore.signal = gen8_xcs_signal; + GEN8_RING_SEMAPHORE_INIT(engine); } } else { - ring->irq_enable_mask = GT_BSD_USER_INTERRUPT; - ring->irq_get = gen6_ring_get_irq; - ring->irq_put = gen6_ring_put_irq; - ring->dispatch_execbuffer = + engine->irq_enable_mask = GT_BSD_USER_INTERRUPT; + engine->irq_get = gen6_ring_get_irq; + engine->irq_put = gen6_ring_put_irq; + engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; if (i915_semaphore_is_enabled(dev)) { - ring->semaphore.sync_to = gen6_ring_sync; - ring->semaphore.signal = gen6_signal; - ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR; - ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB; - ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE; - ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC; - ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC; - ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC; - ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC; - ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; + engine->semaphore.sync_to = gen6_ring_sync; + engine->semaphore.signal = gen6_signal; + engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR; + engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID; + engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB; + engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE; + engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; + engine->semaphore.mbox.signal[RCS] = GEN6_RVSYNC; + engine->semaphore.mbox.signal[VCS] = GEN6_NOSYNC; + engine->semaphore.mbox.signal[BCS] = GEN6_BVSYNC; + engine->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC; + engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; } } } else { - ring->mmio_base = BSD_RING_BASE; - ring->flush = bsd_ring_flush; - ring->add_request = i9xx_add_request; - ring->get_seqno = ring_get_seqno; - ring->set_seqno = ring_set_seqno; + engine->mmio_base = BSD_RING_BASE; + engine->flush = bsd_ring_flush; + engine->add_request = i9xx_add_request; + engine->get_seqno = ring_get_seqno; + engine->set_seqno = ring_set_seqno; if (IS_GEN5(dev)) { - ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT; - ring->irq_get = gen5_ring_get_irq; - ring->irq_put = gen5_ring_put_irq; + engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT; + engine->irq_get = gen5_ring_get_irq; + engine->irq_put = gen5_ring_put_irq; } else { - ring->irq_enable_mask = I915_BSD_USER_INTERRUPT; - ring->irq_get = i9xx_ring_get_irq; - ring->irq_put = i9xx_ring_put_irq; + engine->irq_enable_mask = I915_BSD_USER_INTERRUPT; + engine->irq_get = i9xx_ring_get_irq; + engine->irq_put = i9xx_ring_put_irq; } - ring->dispatch_execbuffer = i965_dispatch_execbuffer; + engine->dispatch_execbuffer = i965_dispatch_execbuffer; } - ring->init_hw = init_ring_common; + engine->init_hw = init_ring_common; - return intel_init_ring_buffer(dev, ring); + return intel_init_ring_buffer(dev, engine); } /** @@ -2969,68 +2978,68 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) int intel_init_bsd2_ring_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[VCS2]; - - ring->name = "bsd2 ring"; - ring->id = VCS2; - ring->exec_id = I915_EXEC_BSD; - - ring->write_tail = ring_write_tail; - ring->mmio_base = GEN8_BSD2_RING_BASE; - ring->flush = gen6_bsd_ring_flush; - ring->add_request = gen6_add_request; - ring->get_seqno = gen6_ring_get_seqno; - ring->set_seqno = ring_set_seqno; - ring->irq_enable_mask = + struct intel_engine_cs *engine = &dev_priv->ring[VCS2]; + + engine->name = "bsd2 ring"; + engine->id = VCS2; + engine->exec_id = I915_EXEC_BSD; + + engine->write_tail = ring_write_tail; + engine->mmio_base = GEN8_BSD2_RING_BASE; + engine->flush = gen6_bsd_ring_flush; + engine->add_request = gen6_add_request; + engine->get_seqno = gen6_ring_get_seqno; + engine->set_seqno = ring_set_seqno; + engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT; - ring->irq_get = gen8_ring_get_irq; - ring->irq_put = gen8_ring_put_irq; - ring->dispatch_execbuffer = + engine->irq_get = gen8_ring_get_irq; + engine->irq_put = gen8_ring_put_irq; + engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; if (i915_semaphore_is_enabled(dev)) { - ring->semaphore.sync_to = gen8_ring_sync; - ring->semaphore.signal = gen8_xcs_signal; - GEN8_RING_SEMAPHORE_INIT; + engine->semaphore.sync_to = gen8_ring_sync; + engine->semaphore.signal = gen8_xcs_signal; + GEN8_RING_SEMAPHORE_INIT(engine); } - ring->init_hw = init_ring_common; + engine->init_hw = init_ring_common; - return intel_init_ring_buffer(dev, ring); + return intel_init_ring_buffer(dev, engine); } int intel_init_blt_ring_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[BCS]; - - ring->name = "blitter ring"; - ring->id = BCS; - ring->exec_id = I915_EXEC_BLT; - - ring->mmio_base = BLT_RING_BASE; - ring->write_tail = ring_write_tail; - ring->flush = gen6_ring_flush; - ring->add_request = gen6_add_request; - ring->get_seqno = gen6_ring_get_seqno; - ring->set_seqno = ring_set_seqno; + struct intel_engine_cs *engine = &dev_priv->ring[BCS]; + + engine->name = "blitter ring"; + engine->id = BCS; + engine->exec_id = I915_EXEC_BLT; + + engine->mmio_base = BLT_RING_BASE; + engine->write_tail = ring_write_tail; + engine->flush = gen6_ring_flush; + engine->add_request = gen6_add_request; + engine->get_seqno = gen6_ring_get_seqno; + engine->set_seqno = ring_set_seqno; if (INTEL_INFO(dev)->gen >= 8) { - ring->irq_enable_mask = + engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT; - ring->irq_get = gen8_ring_get_irq; - ring->irq_put = gen8_ring_put_irq; - ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; + engine->irq_get = gen8_ring_get_irq; + engine->irq_put = gen8_ring_put_irq; + engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; if (i915_semaphore_is_enabled(dev)) { - ring->semaphore.sync_to = gen8_ring_sync; - ring->semaphore.signal = gen8_xcs_signal; - GEN8_RING_SEMAPHORE_INIT; + engine->semaphore.sync_to = gen8_ring_sync; + engine->semaphore.signal = gen8_xcs_signal; + GEN8_RING_SEMAPHORE_INIT(engine); } } else { - ring->irq_enable_mask = GT_BLT_USER_INTERRUPT; - ring->irq_get = gen6_ring_get_irq; - ring->irq_put = gen6_ring_put_irq; - ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; + engine->irq_enable_mask = GT_BLT_USER_INTERRUPT; + engine->irq_get = gen6_ring_get_irq; + engine->irq_put = gen6_ring_put_irq; + engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; if (i915_semaphore_is_enabled(dev)) { - ring->semaphore.signal = gen6_signal; - ring->semaphore.sync_to = gen6_ring_sync; + engine->semaphore.signal = gen6_signal; + engine->semaphore.sync_to = gen6_ring_sync; /* * The current semaphore is only applied on pre-gen8 * platform. And there is no VCS2 ring on the pre-gen8 @@ -3038,112 +3047,112 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) * initialized as INVALID. Gen8 will initialize the * sema between BCS and VCS2 later. */ - ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR; - ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV; - ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE; - ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC; - ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC; - ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC; - ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC; - ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; + engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR; + engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV; + engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID; + engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE; + engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; + engine->semaphore.mbox.signal[RCS] = GEN6_RBSYNC; + engine->semaphore.mbox.signal[VCS] = GEN6_VBSYNC; + engine->semaphore.mbox.signal[BCS] = GEN6_NOSYNC; + engine->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC; + engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; } } - ring->init_hw = init_ring_common; + engine->init_hw = init_ring_common; - return intel_init_ring_buffer(dev, ring); + return intel_init_ring_buffer(dev, engine); } int intel_init_vebox_ring_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *ring = &dev_priv->ring[VECS]; + struct intel_engine_cs *engine = &dev_priv->ring[VECS]; - ring->name = "video enhancement ring"; - ring->id = VECS; - ring->exec_id = I915_EXEC_VEBOX; + engine->name = "video enhancement ring"; + engine->id = VECS; + engine->exec_id = I915_EXEC_VEBOX; - ring->mmio_base = VEBOX_RING_BASE; - ring->write_tail = ring_write_tail; - ring->flush = gen6_ring_flush; - ring->add_request = gen6_add_request; - ring->get_seqno = gen6_ring_get_seqno; - ring->set_seqno = ring_set_seqno; + engine->mmio_base = VEBOX_RING_BASE; + engine->write_tail = ring_write_tail; + engine->flush = gen6_ring_flush; + engine->add_request = gen6_add_request; + engine->get_seqno = gen6_ring_get_seqno; + engine->set_seqno = ring_set_seqno; if (INTEL_INFO(dev)->gen >= 8) { - ring->irq_enable_mask = + engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT; - ring->irq_get = gen8_ring_get_irq; - ring->irq_put = gen8_ring_put_irq; - ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; + engine->irq_get = gen8_ring_get_irq; + engine->irq_put = gen8_ring_put_irq; + engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer; if (i915_semaphore_is_enabled(dev)) { - ring->semaphore.sync_to = gen8_ring_sync; - ring->semaphore.signal = gen8_xcs_signal; - GEN8_RING_SEMAPHORE_INIT; + engine->semaphore.sync_to = gen8_ring_sync; + engine->semaphore.signal = gen8_xcs_signal; + GEN8_RING_SEMAPHORE_INIT(engine); } } else { - ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; - ring->irq_get = hsw_vebox_get_irq; - ring->irq_put = hsw_vebox_put_irq; - ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; + engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT; + engine->irq_get = hsw_vebox_get_irq; + engine->irq_put = hsw_vebox_put_irq; + engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer; if (i915_semaphore_is_enabled(dev)) { - ring->semaphore.sync_to = gen6_ring_sync; - ring->semaphore.signal = gen6_signal; - ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER; - ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV; - ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB; - ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; - ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC; - ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC; - ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC; - ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC; - ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; + engine->semaphore.sync_to = gen6_ring_sync; + engine->semaphore.signal = gen6_signal; + engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER; + engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV; + engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB; + engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID; + engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID; + engine->semaphore.mbox.signal[RCS] = GEN6_RVESYNC; + engine->semaphore.mbox.signal[VCS] = GEN6_VVESYNC; + engine->semaphore.mbox.signal[BCS] = GEN6_BVESYNC; + engine->semaphore.mbox.signal[VECS] = GEN6_NOSYNC; + engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC; } } - ring->init_hw = init_ring_common; + engine->init_hw = init_ring_common; - return intel_init_ring_buffer(dev, ring); + return intel_init_ring_buffer(dev, engine); } int intel_ring_flush_all_caches(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; int ret; - if (!ring->gpu_caches_dirty) + if (!engine->gpu_caches_dirty) return 0; - ret = ring->flush(req, 0, I915_GEM_GPU_DOMAINS); + ret = engine->flush(req, 0, I915_GEM_GPU_DOMAINS); if (ret) return ret; trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS); - ring->gpu_caches_dirty = false; + engine->gpu_caches_dirty = false; return 0; } int intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) { - struct intel_engine_cs *ring = req->ring; + struct intel_engine_cs *engine = req->ring; uint32_t flush_domains; int ret; flush_domains = 0; - if (ring->gpu_caches_dirty) + if (engine->gpu_caches_dirty) flush_domains = I915_GEM_GPU_DOMAINS; - ret = ring->flush(req, I915_GEM_GPU_DOMAINS, flush_domains); + ret = engine->flush(req, I915_GEM_GPU_DOMAINS, flush_domains); if (ret) return ret; trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains); - ring->gpu_caches_dirty = false; + engine->gpu_caches_dirty = false; return 0; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 4b1439d..24efb57 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -63,16 +63,16 @@ struct intel_hw_status_page { ((from) * I915_NUM_RINGS * i915_semaphore_seqno_size) + \ (i915_semaphore_seqno_size * (__ring)->id)) -#define GEN8_RING_SEMAPHORE_INIT do { \ +#define GEN8_RING_SEMAPHORE_INIT(e) do { \ if (!dev_priv->semaphore_obj) { \ break; \ } \ - ring->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET(ring, RCS); \ - ring->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET(ring, VCS); \ - ring->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET(ring, BCS); \ - ring->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET(ring, VECS); \ - ring->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET(ring, VCS2); \ - ring->semaphore.signal_ggtt[ring->id] = MI_SEMAPHORE_SYNC_INVALID; \ + (e)->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET((e), RCS); \ + (e)->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET((e), VCS); \ + (e)->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET((e), BCS); \ + (e)->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET((e), VECS); \ + (e)->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET((e), VCS2); \ + (e)->semaphore.signal_ggtt[(e)->id] = MI_SEMAPHORE_SYNC_INVALID; \ } while(0) enum intel_ring_hangcheck_action { -- cgit v0.10.2 From 0bc40be85f33ca1795253a5f8674efb430f83cce Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 16 Mar 2016 11:00:37 +0000 Subject: drm/i915: Rename intel_engine_cs function parameters @@ identifier func; @@ func(..., struct intel_engine_cs * - ring + engine , ...) { <... - ring + engine ...> } @@ identifier func; type T; @@ T func(..., struct intel_engine_cs * - ring + engine , ...); Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 814d894..2c50142 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -555,7 +555,7 @@ static u32 gen7_blt_get_cmd_length_mask(u32 cmd_header) return 0; } -static bool validate_cmds_sorted(struct intel_engine_cs *ring, +static bool validate_cmds_sorted(struct intel_engine_cs *engine, const struct drm_i915_cmd_table *cmd_tables, int cmd_table_count) { @@ -577,7 +577,7 @@ static bool validate_cmds_sorted(struct intel_engine_cs *ring, if (curr < previous) { DRM_ERROR("CMD: table not sorted ring=%d table=%d entry=%d cmd=0x%08X prev=0x%08X\n", - ring->id, i, j, curr, previous); + engine->id, i, j, curr, previous); ret = false; } @@ -611,11 +611,11 @@ static bool check_sorted(int ring_id, return ret; } -static bool validate_regs_sorted(struct intel_engine_cs *ring) +static bool validate_regs_sorted(struct intel_engine_cs *engine) { - return check_sorted(ring->id, ring->reg_table, ring->reg_count) && - check_sorted(ring->id, ring->master_reg_table, - ring->master_reg_count); + return check_sorted(engine->id, engine->reg_table, engine->reg_count) && + check_sorted(engine->id, engine->master_reg_table, + engine->master_reg_count); } struct cmd_node { @@ -639,13 +639,13 @@ struct cmd_node { */ #define CMD_HASH_MASK STD_MI_OPCODE_MASK -static int init_hash_table(struct intel_engine_cs *ring, +static int init_hash_table(struct intel_engine_cs *engine, const struct drm_i915_cmd_table *cmd_tables, int cmd_table_count) { int i, j; - hash_init(ring->cmd_hash); + hash_init(engine->cmd_hash); for (i = 0; i < cmd_table_count; i++) { const struct drm_i915_cmd_table *table = &cmd_tables[i]; @@ -660,7 +660,7 @@ static int init_hash_table(struct intel_engine_cs *ring, return -ENOMEM; desc_node->desc = desc; - hash_add(ring->cmd_hash, &desc_node->node, + hash_add(engine->cmd_hash, &desc_node->node, desc->cmd.value & CMD_HASH_MASK); } } @@ -668,13 +668,13 @@ static int init_hash_table(struct intel_engine_cs *ring, return 0; } -static void fini_hash_table(struct intel_engine_cs *ring) +static void fini_hash_table(struct intel_engine_cs *engine) { struct hlist_node *tmp; struct cmd_node *desc_node; int i; - hash_for_each_safe(ring->cmd_hash, i, tmp, desc_node, node) { + hash_for_each_safe(engine->cmd_hash, i, tmp, desc_node, node) { hash_del(&desc_node->node); kfree(desc_node); } @@ -690,18 +690,18 @@ static void fini_hash_table(struct intel_engine_cs *ring) * * Return: non-zero if initialization fails */ -int i915_cmd_parser_init_ring(struct intel_engine_cs *ring) +int i915_cmd_parser_init_ring(struct intel_engine_cs *engine) { const struct drm_i915_cmd_table *cmd_tables; int cmd_table_count; int ret; - if (!IS_GEN7(ring->dev)) + if (!IS_GEN7(engine->dev)) return 0; - switch (ring->id) { + switch (engine->id) { case RCS: - if (IS_HASWELL(ring->dev)) { + if (IS_HASWELL(engine->dev)) { cmd_tables = hsw_render_ring_cmds; cmd_table_count = ARRAY_SIZE(hsw_render_ring_cmds); @@ -710,26 +710,26 @@ int i915_cmd_parser_init_ring(struct intel_engine_cs *ring) cmd_table_count = ARRAY_SIZE(gen7_render_cmds); } - ring->reg_table = gen7_render_regs; - ring->reg_count = ARRAY_SIZE(gen7_render_regs); + engine->reg_table = gen7_render_regs; + engine->reg_count = ARRAY_SIZE(gen7_render_regs); - if (IS_HASWELL(ring->dev)) { - ring->master_reg_table = hsw_master_regs; - ring->master_reg_count = ARRAY_SIZE(hsw_master_regs); + if (IS_HASWELL(engine->dev)) { + engine->master_reg_table = hsw_master_regs; + engine->master_reg_count = ARRAY_SIZE(hsw_master_regs); } else { - ring->master_reg_table = ivb_master_regs; - ring->master_reg_count = ARRAY_SIZE(ivb_master_regs); + engine->master_reg_table = ivb_master_regs; + engine->master_reg_count = ARRAY_SIZE(ivb_master_regs); } - ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask; + engine->get_cmd_length_mask = gen7_render_get_cmd_length_mask; break; case VCS: cmd_tables = gen7_video_cmds; cmd_table_count = ARRAY_SIZE(gen7_video_cmds); - ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask; + engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask; break; case BCS: - if (IS_HASWELL(ring->dev)) { + if (IS_HASWELL(engine->dev)) { cmd_tables = hsw_blt_ring_cmds; cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmds); } else { @@ -737,44 +737,44 @@ int i915_cmd_parser_init_ring(struct intel_engine_cs *ring) cmd_table_count = ARRAY_SIZE(gen7_blt_cmds); } - ring->reg_table = gen7_blt_regs; - ring->reg_count = ARRAY_SIZE(gen7_blt_regs); + engine->reg_table = gen7_blt_regs; + engine->reg_count = ARRAY_SIZE(gen7_blt_regs); - if (IS_HASWELL(ring->dev)) { - ring->master_reg_table = hsw_master_regs; - ring->master_reg_count = ARRAY_SIZE(hsw_master_regs); + if (IS_HASWELL(engine->dev)) { + engine->master_reg_table = hsw_master_regs; + engine->master_reg_count = ARRAY_SIZE(hsw_master_regs); } else { - ring->master_reg_table = ivb_master_regs; - ring->master_reg_count = ARRAY_SIZE(ivb_master_regs); + engine->master_reg_table = ivb_master_regs; + engine->master_reg_count = ARRAY_SIZE(ivb_master_regs); } - ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask; + engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask; break; case VECS: cmd_tables = hsw_vebox_cmds; cmd_table_count = ARRAY_SIZE(hsw_vebox_cmds); /* VECS can use the same length_mask function as VCS */ - ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask; + engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask; break; default: DRM_ERROR("CMD: cmd_parser_init with unknown ring: %d\n", - ring->id); + engine->id); BUG(); } - BUG_ON(!validate_cmds_sorted(ring, cmd_tables, cmd_table_count)); - BUG_ON(!validate_regs_sorted(ring)); + BUG_ON(!validate_cmds_sorted(engine, cmd_tables, cmd_table_count)); + BUG_ON(!validate_regs_sorted(engine)); - WARN_ON(!hash_empty(ring->cmd_hash)); + WARN_ON(!hash_empty(engine->cmd_hash)); - ret = init_hash_table(ring, cmd_tables, cmd_table_count); + ret = init_hash_table(engine, cmd_tables, cmd_table_count); if (ret) { DRM_ERROR("CMD: cmd_parser_init failed!\n"); - fini_hash_table(ring); + fini_hash_table(engine); return ret; } - ring->needs_cmd_parser = true; + engine->needs_cmd_parser = true; return 0; } @@ -786,21 +786,21 @@ int i915_cmd_parser_init_ring(struct intel_engine_cs *ring) * Releases any resources related to command parsing that may have been * initialized for the specified ring. */ -void i915_cmd_parser_fini_ring(struct intel_engine_cs *ring) +void i915_cmd_parser_fini_ring(struct intel_engine_cs *engine) { - if (!ring->needs_cmd_parser) + if (!engine->needs_cmd_parser) return; - fini_hash_table(ring); + fini_hash_table(engine); } static const struct drm_i915_cmd_descriptor* -find_cmd_in_table(struct intel_engine_cs *ring, +find_cmd_in_table(struct intel_engine_cs *engine, u32 cmd_header) { struct cmd_node *desc_node; - hash_for_each_possible(ring->cmd_hash, desc_node, node, + hash_for_each_possible(engine->cmd_hash, desc_node, node, cmd_header & CMD_HASH_MASK) { const struct drm_i915_cmd_descriptor *desc = desc_node->desc; u32 masked_cmd = desc->cmd.mask & cmd_header; @@ -822,18 +822,18 @@ find_cmd_in_table(struct intel_engine_cs *ring, * ring's default length encoding and returns default_desc. */ static const struct drm_i915_cmd_descriptor* -find_cmd(struct intel_engine_cs *ring, +find_cmd(struct intel_engine_cs *engine, u32 cmd_header, struct drm_i915_cmd_descriptor *default_desc) { const struct drm_i915_cmd_descriptor *desc; u32 mask; - desc = find_cmd_in_table(ring, cmd_header); + desc = find_cmd_in_table(engine, cmd_header); if (desc) return desc; - mask = ring->get_cmd_length_mask(cmd_header); + mask = engine->get_cmd_length_mask(cmd_header); if (!mask) return NULL; @@ -963,18 +963,18 @@ unpin_src: * * Return: true if the ring requires software command parsing */ -bool i915_needs_cmd_parser(struct intel_engine_cs *ring) +bool i915_needs_cmd_parser(struct intel_engine_cs *engine) { - if (!ring->needs_cmd_parser) + if (!engine->needs_cmd_parser) return false; - if (!USES_PPGTT(ring->dev)) + if (!USES_PPGTT(engine->dev)) return false; return (i915.enable_cmd_parser == 1); } -static bool check_cmd(const struct intel_engine_cs *ring, +static bool check_cmd(const struct intel_engine_cs *engine, const struct drm_i915_cmd_descriptor *desc, const u32 *cmd, u32 length, const bool is_master, @@ -1004,17 +1004,17 @@ static bool check_cmd(const struct intel_engine_cs *ring, offset += step) { const u32 reg_addr = cmd[offset] & desc->reg.mask; const struct drm_i915_reg_descriptor *reg = - find_reg(ring->reg_table, ring->reg_count, + find_reg(engine->reg_table, engine->reg_count, reg_addr); if (!reg && is_master) - reg = find_reg(ring->master_reg_table, - ring->master_reg_count, + reg = find_reg(engine->master_reg_table, + engine->master_reg_count, reg_addr); if (!reg) { DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n", - reg_addr, *cmd, ring->id); + reg_addr, *cmd, engine->id); return false; } @@ -1087,7 +1087,7 @@ static bool check_cmd(const struct intel_engine_cs *ring, *cmd, desc->bits[i].mask, desc->bits[i].expected, - dword, ring->id); + dword, engine->id); return false; } } @@ -1113,7 +1113,7 @@ static bool check_cmd(const struct intel_engine_cs *ring, * Return: non-zero if the parser finds violations or otherwise fails; -EACCES * if the batch appears legal but should use hardware parsing */ -int i915_parse_cmds(struct intel_engine_cs *ring, +int i915_parse_cmds(struct intel_engine_cs *engine, struct drm_i915_gem_object *batch_obj, struct drm_i915_gem_object *shadow_batch_obj, u32 batch_start_offset, @@ -1147,7 +1147,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring, if (*cmd == MI_BATCH_BUFFER_END) break; - desc = find_cmd(ring, *cmd, &default_desc); + desc = find_cmd(engine, *cmd, &default_desc); if (!desc) { DRM_DEBUG_DRIVER("CMD: Unrecognized command: 0x%08X\n", *cmd); @@ -1179,7 +1179,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring, break; } - if (!check_cmd(ring, desc, cmd, length, is_master, + if (!check_cmd(engine, desc, cmd, length, is_master, &oacontrol_set)) { ret = -EINVAL; break; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5037ccb..164e143 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -725,11 +725,11 @@ static int i915_gem_request_info(struct seq_file *m, void *data) } static void i915_ring_seqno_info(struct seq_file *m, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { - if (ring->get_seqno) { + if (engine->get_seqno) { seq_printf(m, "Current sequence (%s): %x\n", - ring->name, ring->get_seqno(ring, false)); + engine->name, engine->get_seqno(engine, false)); } } @@ -1992,22 +1992,22 @@ static int i915_context_status(struct seq_file *m, void *unused) static void i915_dump_lrc_obj(struct seq_file *m, struct intel_context *ctx, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { struct page *page; uint32_t *reg_state; int j; - struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; + struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state; unsigned long ggtt_offset = 0; if (ctx_obj == NULL) { seq_printf(m, "Context on %s with no gem object\n", - ring->name); + engine->name); return; } - seq_printf(m, "CONTEXT: %s %u\n", ring->name, - intel_execlists_ctx_id(ctx, ring)); + seq_printf(m, "CONTEXT: %s %u\n", engine->name, + intel_execlists_ctx_id(ctx, engine)); if (!i915_gem_obj_ggtt_bound(ctx_obj)) seq_puts(m, "\tNot bound in GGTT\n"); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 80b14f1..8d87242 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2964,10 +2964,10 @@ int __must_check i915_gem_get_seqno(struct drm_device *dev, u32 *seqno); int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno); struct drm_i915_gem_request * -i915_gem_find_active_request(struct intel_engine_cs *ring); +i915_gem_find_active_request(struct intel_engine_cs *engine); bool i915_gem_retire_requests(struct drm_device *dev); -void i915_gem_retire_requests_ring(struct intel_engine_cs *ring); +void i915_gem_retire_requests_ring(struct intel_engine_cs *engine); int __must_check i915_gem_check_wedge(struct i915_gpu_error *error, bool interruptible); @@ -3297,10 +3297,10 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type); /* i915_cmd_parser.c */ int i915_cmd_parser_get_version(void); -int i915_cmd_parser_init_ring(struct intel_engine_cs *ring); -void i915_cmd_parser_fini_ring(struct intel_engine_cs *ring); -bool i915_needs_cmd_parser(struct intel_engine_cs *ring); -int i915_parse_cmds(struct intel_engine_cs *ring, +int i915_cmd_parser_init_ring(struct intel_engine_cs *engine); +void i915_cmd_parser_fini_ring(struct intel_engine_cs *engine); +bool i915_needs_cmd_parser(struct intel_engine_cs *engine); +int i915_parse_cmds(struct intel_engine_cs *engine, struct drm_i915_gem_object *batch_obj, struct drm_i915_gem_object *shadow_batch_obj, u32 batch_start_offset, @@ -3571,11 +3571,11 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) } } -static inline void i915_trace_irq_get(struct intel_engine_cs *ring, +static inline void i915_trace_irq_get(struct intel_engine_cs *engine, struct drm_i915_gem_request *req) { - if (ring->trace_irq_req == NULL && ring->irq_get(ring)) - i915_gem_request_assign(&ring->trace_irq_req, req); + if (engine->trace_irq_req == NULL && engine->irq_get(engine)) + i915_gem_request_assign(&engine->trace_irq_req, req); } #endif diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5a7f603..1119b8f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1141,9 +1141,9 @@ static void fake_irq(unsigned long data) } static bool missed_irq(struct drm_i915_private *dev_priv, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { - return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings); + return test_bit(engine->id, &dev_priv->gpu_error.missed_irq_rings); } static unsigned long local_clock_us(unsigned *cpu) @@ -2689,11 +2689,11 @@ void i915_gem_request_free(struct kref *req_ref) } static inline int -__i915_gem_request_alloc(struct intel_engine_cs *ring, +__i915_gem_request_alloc(struct intel_engine_cs *engine, struct intel_context *ctx, struct drm_i915_gem_request **req_out) { - struct drm_i915_private *dev_priv = to_i915(ring->dev); + struct drm_i915_private *dev_priv = to_i915(engine->dev); struct drm_i915_gem_request *req; int ret; @@ -2706,13 +2706,13 @@ __i915_gem_request_alloc(struct intel_engine_cs *ring, if (req == NULL) return -ENOMEM; - ret = i915_gem_get_seqno(ring->dev, &req->seqno); + ret = i915_gem_get_seqno(engine->dev, &req->seqno); if (ret) goto err; kref_init(&req->ref); req->i915 = dev_priv; - req->ring = ring; + req->ring = engine; req->ctx = ctx; i915_gem_context_reference(req->ctx); @@ -2787,11 +2787,11 @@ void i915_gem_request_cancel(struct drm_i915_gem_request *req) } struct drm_i915_gem_request * -i915_gem_find_active_request(struct intel_engine_cs *ring) +i915_gem_find_active_request(struct intel_engine_cs *engine) { struct drm_i915_gem_request *request; - list_for_each_entry(request, &ring->request_list, list) { + list_for_each_entry(request, &engine->request_list, list) { if (i915_gem_request_completed(request, false)) continue; @@ -2802,37 +2802,37 @@ i915_gem_find_active_request(struct intel_engine_cs *ring) } static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { struct drm_i915_gem_request *request; bool ring_hung; - request = i915_gem_find_active_request(ring); + request = i915_gem_find_active_request(engine); if (request == NULL) return; - ring_hung = ring->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG; + ring_hung = engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG; i915_set_reset_status(dev_priv, request->ctx, ring_hung); - list_for_each_entry_continue(request, &ring->request_list, list) + list_for_each_entry_continue(request, &engine->request_list, list) i915_set_reset_status(dev_priv, request->ctx, false); } static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { struct intel_ringbuffer *buffer; - while (!list_empty(&ring->active_list)) { + while (!list_empty(&engine->active_list)) { struct drm_i915_gem_object *obj; - obj = list_first_entry(&ring->active_list, + obj = list_first_entry(&engine->active_list, struct drm_i915_gem_object, - ring_list[ring->id]); + ring_list[engine->id]); - i915_gem_object_retire__read(obj, ring->id); + i915_gem_object_retire__read(obj, engine->id); } /* @@ -2842,14 +2842,14 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, */ if (i915.enable_execlists) { - spin_lock_irq(&ring->execlist_lock); + spin_lock_irq(&engine->execlist_lock); /* list_splice_tail_init checks for empty lists */ - list_splice_tail_init(&ring->execlist_queue, - &ring->execlist_retired_req_list); + list_splice_tail_init(&engine->execlist_queue, + &engine->execlist_retired_req_list); - spin_unlock_irq(&ring->execlist_lock); - intel_execlists_retire_requests(ring); + spin_unlock_irq(&engine->execlist_lock); + intel_execlists_retire_requests(engine); } /* @@ -2859,10 +2859,10 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, * implicit references on things like e.g. ppgtt address spaces through * the request. */ - while (!list_empty(&ring->request_list)) { + while (!list_empty(&engine->request_list)) { struct drm_i915_gem_request *request; - request = list_first_entry(&ring->request_list, + request = list_first_entry(&engine->request_list, struct drm_i915_gem_request, list); @@ -2876,7 +2876,7 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, * upon reset is less than when we start. Do one more pass over * all the ringbuffers to reset last_retired_head. */ - list_for_each_entry(buffer, &ring->buffers, link) { + list_for_each_entry(buffer, &engine->buffers, link) { buffer->last_retired_head = buffer->tail; intel_ring_update_space(buffer); } @@ -2910,19 +2910,19 @@ void i915_gem_reset(struct drm_device *dev) * This function clears the request list as sequence numbers are passed. */ void -i915_gem_retire_requests_ring(struct intel_engine_cs *ring) +i915_gem_retire_requests_ring(struct intel_engine_cs *engine) { - WARN_ON(i915_verify_lists(ring->dev)); + WARN_ON(i915_verify_lists(engine->dev)); /* Retire requests first as we use it above for the early return. * If we retire requests last, we may use a later seqno and so clear * the requests lists without clearing the active list, leading to * confusion. */ - while (!list_empty(&ring->request_list)) { + while (!list_empty(&engine->request_list)) { struct drm_i915_gem_request *request; - request = list_first_entry(&ring->request_list, + request = list_first_entry(&engine->request_list, struct drm_i915_gem_request, list); @@ -2936,26 +2936,26 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring) * by the ringbuffer to the flushing/inactive lists as appropriate, * before we free the context associated with the requests. */ - while (!list_empty(&ring->active_list)) { + while (!list_empty(&engine->active_list)) { struct drm_i915_gem_object *obj; - obj = list_first_entry(&ring->active_list, - struct drm_i915_gem_object, - ring_list[ring->id]); + obj = list_first_entry(&engine->active_list, + struct drm_i915_gem_object, + ring_list[engine->id]); - if (!list_empty(&obj->last_read_req[ring->id]->list)) + if (!list_empty(&obj->last_read_req[engine->id]->list)) break; - i915_gem_object_retire__read(obj, ring->id); + i915_gem_object_retire__read(obj, engine->id); } - if (unlikely(ring->trace_irq_req && - i915_gem_request_completed(ring->trace_irq_req, true))) { - ring->irq_put(ring); - i915_gem_request_assign(&ring->trace_irq_req, NULL); + if (unlikely(engine->trace_irq_req && + i915_gem_request_completed(engine->trace_irq_req, true))) { + engine->irq_put(engine); + i915_gem_request_assign(&engine->trace_irq_req, NULL); } - WARN_ON(i915_verify_lists(ring->dev)); + WARN_ON(i915_verify_lists(engine->dev)); } bool @@ -5022,10 +5022,10 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) } static void -init_ring_lists(struct intel_engine_cs *ring) +init_ring_lists(struct intel_engine_cs *engine) { - INIT_LIST_HEAD(&ring->active_list); - INIT_LIST_HEAD(&ring->request_list); + INIT_LIST_HEAD(&engine->active_list); + INIT_LIST_HEAD(&engine->request_list); } void diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index cc07666..44f5829 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -600,7 +600,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) return ret; } -static inline bool should_skip_switch(struct intel_engine_cs *ring, +static inline bool should_skip_switch(struct intel_engine_cs *engine, struct intel_context *from, struct intel_context *to) { @@ -608,42 +608,42 @@ static inline bool should_skip_switch(struct intel_engine_cs *ring, return false; if (to->ppgtt && from == to && - !(intel_ring_flag(ring) & to->ppgtt->pd_dirty_rings)) + !(intel_ring_flag(engine) & to->ppgtt->pd_dirty_rings)) return true; return false; } static bool -needs_pd_load_pre(struct intel_engine_cs *ring, struct intel_context *to) +needs_pd_load_pre(struct intel_engine_cs *engine, struct intel_context *to) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; if (!to->ppgtt) return false; - if (INTEL_INFO(ring->dev)->gen < 8) + if (INTEL_INFO(engine->dev)->gen < 8) return true; - if (ring != &dev_priv->ring[RCS]) + if (engine != &dev_priv->ring[RCS]) return true; return false; } static bool -needs_pd_load_post(struct intel_engine_cs *ring, struct intel_context *to, - u32 hw_flags) +needs_pd_load_post(struct intel_engine_cs *engine, struct intel_context *to, + u32 hw_flags) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; if (!to->ppgtt) return false; - if (!IS_GEN8(ring->dev)) + if (!IS_GEN8(engine->dev)) return false; - if (ring != &dev_priv->ring[RCS]) + if (engine != &dev_priv->ring[RCS]) return false; if (hw_flags & MI_RESTORE_INHIBIT) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index b73496e..f94d756 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -599,7 +599,7 @@ static bool only_mappable_for_reloc(unsigned int flags) static int i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, - struct intel_engine_cs *ring, + struct intel_engine_cs *engine, bool *need_reloc) { struct drm_i915_gem_object *obj = vma->obj; @@ -713,7 +713,7 @@ eb_vma_misplaced(struct i915_vma *vma) } static int -i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, +i915_gem_execbuffer_reserve(struct intel_engine_cs *engine, struct list_head *vmas, struct intel_context *ctx, bool *need_relocs) @@ -723,10 +723,10 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, struct i915_address_space *vm; struct list_head ordered_vmas; struct list_head pinned_vmas; - bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; + bool has_fenced_gpu_access = INTEL_INFO(engine->dev)->gen < 4; int retry; - i915_gem_retire_requests_ring(ring); + i915_gem_retire_requests_ring(engine); vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm; @@ -788,7 +788,9 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, if (eb_vma_misplaced(vma)) ret = i915_vma_unbind(vma); else - ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); + ret = i915_gem_execbuffer_reserve_vma(vma, + engine, + need_relocs); if (ret) goto err; } @@ -798,7 +800,8 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring, if (drm_mm_node_allocated(&vma->node)) continue; - ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs); + ret = i915_gem_execbuffer_reserve_vma(vma, engine, + need_relocs); if (ret) goto err; } @@ -821,7 +824,7 @@ static int i915_gem_execbuffer_relocate_slow(struct drm_device *dev, struct drm_i915_gem_execbuffer2 *args, struct drm_file *file, - struct intel_engine_cs *ring, + struct intel_engine_cs *engine, struct eb_vmas *eb, struct drm_i915_gem_exec_object2 *exec, struct intel_context *ctx) @@ -910,7 +913,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, goto err; need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0; - ret = i915_gem_execbuffer_reserve(ring, &eb->vmas, ctx, &need_relocs); + ret = i915_gem_execbuffer_reserve(engine, &eb->vmas, ctx, + &need_relocs); if (ret) goto err; @@ -1062,12 +1066,12 @@ validate_exec_list(struct drm_device *dev, static struct intel_context * i915_gem_validate_context(struct drm_device *dev, struct drm_file *file, - struct intel_engine_cs *ring, const u32 ctx_id) + struct intel_engine_cs *engine, const u32 ctx_id) { struct intel_context *ctx = NULL; struct i915_ctx_hang_stats *hs; - if (ring->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE) + if (engine->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE) return ERR_PTR(-EINVAL); ctx = i915_gem_context_get(file->driver_priv, ctx_id); @@ -1080,8 +1084,8 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file, return ERR_PTR(-EIO); } - if (i915.enable_execlists && !ctx->engine[ring->id].state) { - int ret = intel_lr_context_deferred_alloc(ctx, ring); + if (i915.enable_execlists && !ctx->engine[engine->id].state) { + int ret = intel_lr_context_deferred_alloc(ctx, engine); if (ret) { DRM_DEBUG("Could not create LRC %u: %d\n", ctx_id, ret); return ERR_PTR(ret); @@ -1171,7 +1175,7 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev, } static struct drm_i915_gem_object* -i915_gem_execbuffer_parse(struct intel_engine_cs *ring, +i915_gem_execbuffer_parse(struct intel_engine_cs *engine, struct drm_i915_gem_exec_object2 *shadow_exec_entry, struct eb_vmas *eb, struct drm_i915_gem_object *batch_obj, @@ -1183,12 +1187,12 @@ i915_gem_execbuffer_parse(struct intel_engine_cs *ring, struct i915_vma *vma; int ret; - shadow_batch_obj = i915_gem_batch_pool_get(&ring->batch_pool, + shadow_batch_obj = i915_gem_batch_pool_get(&engine->batch_pool, PAGE_ALIGN(batch_len)); if (IS_ERR(shadow_batch_obj)) return shadow_batch_obj; - ret = i915_parse_cmds(ring, + ret = i915_parse_cmds(engine, batch_obj, shadow_batch_obj, batch_start_offset, diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index fc7e6d5..b21f72e 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -169,15 +169,15 @@ void i915_gem_render_state_fini(struct render_state *so) drm_gem_object_unreference(&so->obj->base); } -int i915_gem_render_state_prepare(struct intel_engine_cs *ring, +int i915_gem_render_state_prepare(struct intel_engine_cs *engine, struct render_state *so) { int ret; - if (WARN_ON(ring->id != RCS)) + if (WARN_ON(engine->id != RCS)) return -ENOENT; - ret = render_state_init(so, ring->dev); + ret = render_state_init(so, engine->dev); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.h b/drivers/gpu/drm/i915/i915_gem_render_state.h index e641bb0..6aaa3a1 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.h +++ b/drivers/gpu/drm/i915/i915_gem_render_state.h @@ -43,7 +43,7 @@ struct render_state { int i915_gem_render_state_init(struct drm_i915_gem_request *req); void i915_gem_render_state_fini(struct render_state *so); -int i915_gem_render_state_prepare(struct intel_engine_cs *ring, +int i915_gem_render_state_prepare(struct intel_engine_cs *engine, struct render_state *so); #endif /* _I915_GEM_RENDER_STATE_H_ */ diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index d97cadc..029ed40 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -842,7 +842,7 @@ static void i915_gem_record_fences(struct drm_device *dev, static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv, struct drm_i915_error_state *error, - struct intel_engine_cs *ring, + struct intel_engine_cs *engine, struct drm_i915_error_ring *ering) { struct intel_engine_cs *to; @@ -861,63 +861,64 @@ static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv, u16 signal_offset; u32 *tmp; - if (ring == to) + if (engine == to) continue; - signal_offset = (GEN8_SIGNAL_OFFSET(ring, i) & (PAGE_SIZE - 1)) + signal_offset = (GEN8_SIGNAL_OFFSET(engine, i) & (PAGE_SIZE - 1)) / 4; tmp = error->semaphore_obj->pages[0]; - idx = intel_ring_sync_index(ring, to); + idx = intel_ring_sync_index(engine, to); ering->semaphore_mboxes[idx] = tmp[signal_offset]; - ering->semaphore_seqno[idx] = ring->semaphore.sync_seqno[idx]; + ering->semaphore_seqno[idx] = engine->semaphore.sync_seqno[idx]; } } static void gen6_record_semaphore_state(struct drm_i915_private *dev_priv, - struct intel_engine_cs *ring, + struct intel_engine_cs *engine, struct drm_i915_error_ring *ering) { - ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(ring->mmio_base)); - ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(ring->mmio_base)); - ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0]; - ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1]; + ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(engine->mmio_base)); + ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(engine->mmio_base)); + ering->semaphore_seqno[0] = engine->semaphore.sync_seqno[0]; + ering->semaphore_seqno[1] = engine->semaphore.sync_seqno[1]; if (HAS_VEBOX(dev_priv->dev)) { ering->semaphore_mboxes[2] = - I915_READ(RING_SYNC_2(ring->mmio_base)); - ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2]; + I915_READ(RING_SYNC_2(engine->mmio_base)); + ering->semaphore_seqno[2] = engine->semaphore.sync_seqno[2]; } } static void i915_record_ring_state(struct drm_device *dev, struct drm_i915_error_state *error, - struct intel_engine_cs *ring, + struct intel_engine_cs *engine, struct drm_i915_error_ring *ering) { struct drm_i915_private *dev_priv = dev->dev_private; if (INTEL_INFO(dev)->gen >= 6) { - ering->rc_psmi = I915_READ(RING_PSMI_CTL(ring->mmio_base)); - ering->fault_reg = I915_READ(RING_FAULT_REG(ring)); + ering->rc_psmi = I915_READ(RING_PSMI_CTL(engine->mmio_base)); + ering->fault_reg = I915_READ(RING_FAULT_REG(engine)); if (INTEL_INFO(dev)->gen >= 8) - gen8_record_semaphore_state(dev_priv, error, ring, ering); + gen8_record_semaphore_state(dev_priv, error, engine, + ering); else - gen6_record_semaphore_state(dev_priv, ring, ering); + gen6_record_semaphore_state(dev_priv, engine, ering); } if (INTEL_INFO(dev)->gen >= 4) { - ering->faddr = I915_READ(RING_DMA_FADD(ring->mmio_base)); - ering->ipeir = I915_READ(RING_IPEIR(ring->mmio_base)); - ering->ipehr = I915_READ(RING_IPEHR(ring->mmio_base)); - ering->instdone = I915_READ(RING_INSTDONE(ring->mmio_base)); - ering->instps = I915_READ(RING_INSTPS(ring->mmio_base)); - ering->bbaddr = I915_READ(RING_BBADDR(ring->mmio_base)); + ering->faddr = I915_READ(RING_DMA_FADD(engine->mmio_base)); + ering->ipeir = I915_READ(RING_IPEIR(engine->mmio_base)); + ering->ipehr = I915_READ(RING_IPEHR(engine->mmio_base)); + ering->instdone = I915_READ(RING_INSTDONE(engine->mmio_base)); + ering->instps = I915_READ(RING_INSTPS(engine->mmio_base)); + ering->bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); if (INTEL_INFO(dev)->gen >= 8) { - ering->faddr |= (u64) I915_READ(RING_DMA_FADD_UDW(ring->mmio_base)) << 32; - ering->bbaddr |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32; + ering->faddr |= (u64) I915_READ(RING_DMA_FADD_UDW(engine->mmio_base)) << 32; + ering->bbaddr |= (u64) I915_READ(RING_BBADDR_UDW(engine->mmio_base)) << 32; } - ering->bbstate = I915_READ(RING_BBSTATE(ring->mmio_base)); + ering->bbstate = I915_READ(RING_BBSTATE(engine->mmio_base)); } else { ering->faddr = I915_READ(DMA_FADD_I8XX); ering->ipeir = I915_READ(IPEIR); @@ -925,20 +926,20 @@ static void i915_record_ring_state(struct drm_device *dev, ering->instdone = I915_READ(GEN2_INSTDONE); } - ering->waiting = waitqueue_active(&ring->irq_queue); - ering->instpm = I915_READ(RING_INSTPM(ring->mmio_base)); - ering->seqno = ring->get_seqno(ring, false); - ering->acthd = intel_ring_get_active_head(ring); - ering->start = I915_READ_START(ring); - ering->head = I915_READ_HEAD(ring); - ering->tail = I915_READ_TAIL(ring); - ering->ctl = I915_READ_CTL(ring); + ering->waiting = waitqueue_active(&engine->irq_queue); + ering->instpm = I915_READ(RING_INSTPM(engine->mmio_base)); + ering->seqno = engine->get_seqno(engine, false); + ering->acthd = intel_ring_get_active_head(engine); + ering->start = I915_READ_START(engine); + ering->head = I915_READ_HEAD(engine); + ering->tail = I915_READ_TAIL(engine); + ering->ctl = I915_READ_CTL(engine); if (I915_NEED_GFX_HWS(dev)) { i915_reg_t mmio; if (IS_GEN7(dev)) { - switch (ring->id) { + switch (engine->id) { default: case RCS: mmio = RENDER_HWS_PGA_GEN7; @@ -953,51 +954,51 @@ static void i915_record_ring_state(struct drm_device *dev, mmio = VEBOX_HWS_PGA_GEN7; break; } - } else if (IS_GEN6(ring->dev)) { - mmio = RING_HWS_PGA_GEN6(ring->mmio_base); + } else if (IS_GEN6(engine->dev)) { + mmio = RING_HWS_PGA_GEN6(engine->mmio_base); } else { /* XXX: gen8 returns to sanity */ - mmio = RING_HWS_PGA(ring->mmio_base); + mmio = RING_HWS_PGA(engine->mmio_base); } ering->hws = I915_READ(mmio); } - ering->hangcheck_score = ring->hangcheck.score; - ering->hangcheck_action = ring->hangcheck.action; + ering->hangcheck_score = engine->hangcheck.score; + ering->hangcheck_action = engine->hangcheck.action; if (USES_PPGTT(dev)) { int i; - ering->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(ring)); + ering->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(engine)); if (IS_GEN6(dev)) ering->vm_info.pp_dir_base = - I915_READ(RING_PP_DIR_BASE_READ(ring)); + I915_READ(RING_PP_DIR_BASE_READ(engine)); else if (IS_GEN7(dev)) ering->vm_info.pp_dir_base = - I915_READ(RING_PP_DIR_BASE(ring)); + I915_READ(RING_PP_DIR_BASE(engine)); else if (INTEL_INFO(dev)->gen >= 8) for (i = 0; i < 4; i++) { ering->vm_info.pdp[i] = - I915_READ(GEN8_RING_PDP_UDW(ring, i)); + I915_READ(GEN8_RING_PDP_UDW(engine, i)); ering->vm_info.pdp[i] <<= 32; ering->vm_info.pdp[i] |= - I915_READ(GEN8_RING_PDP_LDW(ring, i)); + I915_READ(GEN8_RING_PDP_LDW(engine, i)); } } } -static void i915_gem_record_active_context(struct intel_engine_cs *ring, +static void i915_gem_record_active_context(struct intel_engine_cs *engine, struct drm_i915_error_state *error, struct drm_i915_error_ring *ering) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; struct drm_i915_gem_object *obj; /* Currently render ring is the only HW context user */ - if (ring->id != RCS || !error->ccid) + if (engine->id != RCS || !error->ccid) return; list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index f172de0..6465896 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -994,14 +994,14 @@ static void ironlake_rps_change_irq_handler(struct drm_device *dev) return; } -static void notify_ring(struct intel_engine_cs *ring) +static void notify_ring(struct intel_engine_cs *engine) { - if (!intel_ring_initialized(ring)) + if (!intel_ring_initialized(engine)) return; - trace_i915_gem_request_notify(ring); + trace_i915_gem_request_notify(engine); - wake_up_all(&ring->irq_queue); + wake_up_all(&engine->irq_queue); } static void vlv_c0_read(struct drm_i915_private *dev_priv, @@ -1319,12 +1319,12 @@ static void snb_gt_irq_handler(struct drm_device *dev, } static __always_inline void -gen8_cs_irq_handler(struct intel_engine_cs *ring, u32 iir, int test_shift) +gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) { if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) - notify_ring(ring); + notify_ring(engine); if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift)) - intel_lrc_irq_handler(ring); + intel_lrc_irq_handler(engine); } static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv, @@ -2805,10 +2805,10 @@ static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe) } static bool -ring_idle(struct intel_engine_cs *ring, u32 seqno) +ring_idle(struct intel_engine_cs *engine, u32 seqno) { - return (list_empty(&ring->request_list) || - i915_seqno_passed(seqno, ring->last_submitted_seqno)); + return (list_empty(&engine->request_list) || + i915_seqno_passed(seqno, engine->last_submitted_seqno)); } static bool @@ -2824,42 +2824,43 @@ ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr) } static struct intel_engine_cs * -semaphore_wait_to_signaller_ring(struct intel_engine_cs *ring, u32 ipehr, u64 offset) +semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, + u64 offset) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; struct intel_engine_cs *signaller; int i; if (INTEL_INFO(dev_priv->dev)->gen >= 8) { for_each_ring(signaller, dev_priv, i) { - if (ring == signaller) + if (engine == signaller) continue; - if (offset == signaller->semaphore.signal_ggtt[ring->id]) + if (offset == signaller->semaphore.signal_ggtt[engine->id]) return signaller; } } else { u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK; for_each_ring(signaller, dev_priv, i) { - if(ring == signaller) + if(engine == signaller) continue; - if (sync_bits == signaller->semaphore.mbox.wait[ring->id]) + if (sync_bits == signaller->semaphore.mbox.wait[engine->id]) return signaller; } } DRM_ERROR("No signaller ring found for ring %i, ipehr 0x%08x, offset 0x%016llx\n", - ring->id, ipehr, offset); + engine->id, ipehr, offset); return NULL; } static struct intel_engine_cs * -semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno) +semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; u32 cmd, ipehr, head; u64 offset = 0; int i, backwards; @@ -2881,11 +2882,11 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno) * Therefore, this function does not support execlist mode in its * current form. Just return NULL and move on. */ - if (ring->buffer == NULL) + if (engine->buffer == NULL) return NULL; - ipehr = I915_READ(RING_IPEHR(ring->mmio_base)); - if (!ipehr_is_semaphore_wait(ring->dev, ipehr)) + ipehr = I915_READ(RING_IPEHR(engine->mmio_base)); + if (!ipehr_is_semaphore_wait(engine->dev, ipehr)) return NULL; /* @@ -2896,8 +2897,8 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno) * point at at batch, and semaphores are always emitted into the * ringbuffer itself. */ - head = I915_READ_HEAD(ring) & HEAD_ADDR; - backwards = (INTEL_INFO(ring->dev)->gen >= 8) ? 5 : 4; + head = I915_READ_HEAD(engine) & HEAD_ADDR; + backwards = (INTEL_INFO(engine->dev)->gen >= 8) ? 5 : 4; for (i = backwards; i; --i) { /* @@ -2905,10 +2906,10 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno) * our ring is smaller than what the hardware (and hence * HEAD_ADDR) allows. Also handles wrap-around. */ - head &= ring->buffer->size - 1; + head &= engine->buffer->size - 1; /* This here seems to blow up */ - cmd = ioread32(ring->buffer->virtual_start + head); + cmd = ioread32(engine->buffer->virtual_start + head); if (cmd == ipehr) break; @@ -2918,24 +2919,24 @@ semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno) if (!i) return NULL; - *seqno = ioread32(ring->buffer->virtual_start + head + 4) + 1; - if (INTEL_INFO(ring->dev)->gen >= 8) { - offset = ioread32(ring->buffer->virtual_start + head + 12); + *seqno = ioread32(engine->buffer->virtual_start + head + 4) + 1; + if (INTEL_INFO(engine->dev)->gen >= 8) { + offset = ioread32(engine->buffer->virtual_start + head + 12); offset <<= 32; - offset = ioread32(ring->buffer->virtual_start + head + 8); + offset = ioread32(engine->buffer->virtual_start + head + 8); } - return semaphore_wait_to_signaller_ring(ring, ipehr, offset); + return semaphore_wait_to_signaller_ring(engine, ipehr, offset); } -static int semaphore_passed(struct intel_engine_cs *ring) +static int semaphore_passed(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; struct intel_engine_cs *signaller; u32 seqno; - ring->hangcheck.deadlock++; + engine->hangcheck.deadlock++; - signaller = semaphore_waits_for(ring, &seqno); + signaller = semaphore_waits_for(engine, &seqno); if (signaller == NULL) return -1; @@ -2963,16 +2964,16 @@ static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) engine->hangcheck.deadlock = 0; } -static bool subunits_stuck(struct intel_engine_cs *ring) +static bool subunits_stuck(struct intel_engine_cs *engine) { u32 instdone[I915_NUM_INSTDONE_REG]; bool stuck; int i; - if (ring->id != RCS) + if (engine->id != RCS) return true; - i915_get_extra_instdone(ring->dev, instdone); + i915_get_extra_instdone(engine->dev, instdone); /* There might be unstable subunit states even when * actual head is not moving. Filter out the unstable ones by @@ -2981,44 +2982,44 @@ static bool subunits_stuck(struct intel_engine_cs *ring) */ stuck = true; for (i = 0; i < I915_NUM_INSTDONE_REG; i++) { - const u32 tmp = instdone[i] | ring->hangcheck.instdone[i]; + const u32 tmp = instdone[i] | engine->hangcheck.instdone[i]; - if (tmp != ring->hangcheck.instdone[i]) + if (tmp != engine->hangcheck.instdone[i]) stuck = false; - ring->hangcheck.instdone[i] |= tmp; + engine->hangcheck.instdone[i] |= tmp; } return stuck; } static enum intel_ring_hangcheck_action -head_stuck(struct intel_engine_cs *ring, u64 acthd) +head_stuck(struct intel_engine_cs *engine, u64 acthd) { - if (acthd != ring->hangcheck.acthd) { + if (acthd != engine->hangcheck.acthd) { /* Clear subunit states on head movement */ - memset(ring->hangcheck.instdone, 0, - sizeof(ring->hangcheck.instdone)); + memset(engine->hangcheck.instdone, 0, + sizeof(engine->hangcheck.instdone)); return HANGCHECK_ACTIVE; } - if (!subunits_stuck(ring)) + if (!subunits_stuck(engine)) return HANGCHECK_ACTIVE; return HANGCHECK_HUNG; } static enum intel_ring_hangcheck_action -ring_stuck(struct intel_engine_cs *ring, u64 acthd) +ring_stuck(struct intel_engine_cs *engine, u64 acthd) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; enum intel_ring_hangcheck_action ha; u32 tmp; - ha = head_stuck(ring, acthd); + ha = head_stuck(engine, acthd); if (ha != HANGCHECK_HUNG) return ha; @@ -3030,24 +3031,24 @@ ring_stuck(struct intel_engine_cs *ring, u64 acthd) * and break the hang. This should work on * all but the second generation chipsets. */ - tmp = I915_READ_CTL(ring); + tmp = I915_READ_CTL(engine); if (tmp & RING_WAIT) { i915_handle_error(dev, false, "Kicking stuck wait on %s", - ring->name); - I915_WRITE_CTL(ring, tmp); + engine->name); + I915_WRITE_CTL(engine, tmp); return HANGCHECK_KICK; } if (INTEL_INFO(dev)->gen >= 6 && tmp & RING_WAIT_SEMAPHORE) { - switch (semaphore_passed(ring)) { + switch (semaphore_passed(engine)) { default: return HANGCHECK_HUNG; case 1: i915_handle_error(dev, false, "Kicking stuck semaphore on %s", - ring->name); - I915_WRITE_CTL(ring, tmp); + engine->name); + I915_WRITE_CTL(engine, tmp); return HANGCHECK_KICK; case 0: return HANGCHECK_WAIT; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e95f2b7..317b55b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11214,7 +11214,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, return 0; } -static bool use_mmio_flip(struct intel_engine_cs *ring, +static bool use_mmio_flip(struct intel_engine_cs *engine, struct drm_i915_gem_object *obj) { /* @@ -11225,10 +11225,10 @@ static bool use_mmio_flip(struct intel_engine_cs *ring, * So using MMIO flips there would disrupt this mechanism. */ - if (ring == NULL) + if (engine == NULL) return true; - if (INTEL_INFO(ring->dev)->gen < 5) + if (INTEL_INFO(engine->dev)->gen < 5) return false; if (i915.use_mmio_flip < 0) @@ -11242,7 +11242,7 @@ static bool use_mmio_flip(struct intel_engine_cs *ring, false)) return true; else - return ring != i915_gem_request_get_ring(obj->last_write_req); + return engine != i915_gem_request_get_ring(obj->last_write_req); } static void skl_do_mmio_flip(struct intel_crtc *intel_crtc, diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 448c68e..25514e9 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -228,8 +228,8 @@ enum { static int intel_lr_context_pin(struct intel_context *ctx, struct intel_engine_cs *engine); -static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, - struct drm_i915_gem_object *default_ctx_obj); +static void lrc_setup_hardware_status_page(struct intel_engine_cs *engine, + struct drm_i915_gem_object *default_ctx_obj); /** @@ -266,23 +266,23 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists } static void -logical_ring_init_platform_invariants(struct intel_engine_cs *ring) +logical_ring_init_platform_invariants(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; if (IS_GEN8(dev) || IS_GEN9(dev)) - ring->idle_lite_restore_wa = ~0; + engine->idle_lite_restore_wa = ~0; - ring->disable_lite_restore_wa = (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || + engine->disable_lite_restore_wa = (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || IS_BXT_REVID(dev, 0, BXT_REVID_A1)) && - (ring->id == VCS || ring->id == VCS2); + (engine->id == VCS || engine->id == VCS2); - ring->ctx_desc_template = GEN8_CTX_VALID; - ring->ctx_desc_template |= GEN8_CTX_ADDRESSING_MODE(dev) << + engine->ctx_desc_template = GEN8_CTX_VALID; + engine->ctx_desc_template |= GEN8_CTX_ADDRESSING_MODE(dev) << GEN8_CTX_ADDRESSING_MODE_SHIFT; if (IS_GEN8(dev)) - ring->ctx_desc_template |= GEN8_CTX_L3LLC_COHERENT; - ring->ctx_desc_template |= GEN8_CTX_PRIVILEGE; + engine->ctx_desc_template |= GEN8_CTX_L3LLC_COHERENT; + engine->ctx_desc_template |= GEN8_CTX_PRIVILEGE; /* TODO: WaDisableLiteRestore when we start using semaphore * signalling between Command Streamers */ @@ -290,8 +290,8 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *ring) /* WaEnableForceRestoreInCtxtDescForVCS:skl */ /* WaEnableForceRestoreInCtxtDescForVCS:bxt */ - if (ring->disable_lite_restore_wa) - ring->ctx_desc_template |= GEN8_CTX_FORCE_RESTORE; + if (engine->disable_lite_restore_wa) + engine->ctx_desc_template |= GEN8_CTX_FORCE_RESTORE; } /** @@ -314,24 +314,24 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *ring) */ static void intel_lr_context_descriptor_update(struct intel_context *ctx, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { uint64_t lrca, desc; - lrca = ctx->engine[ring->id].lrc_vma->node.start + + lrca = ctx->engine[engine->id].lrc_vma->node.start + LRC_PPHWSP_PN * PAGE_SIZE; - desc = ring->ctx_desc_template; /* bits 0-11 */ + desc = engine->ctx_desc_template; /* bits 0-11 */ desc |= lrca; /* bits 12-31 */ desc |= (lrca >> PAGE_SHIFT) << GEN8_CTX_ID_SHIFT; /* bits 32-51 */ - ctx->engine[ring->id].lrc_desc = desc; + ctx->engine[engine->id].lrc_desc = desc; } uint64_t intel_lr_context_descriptor(struct intel_context *ctx, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { - return ctx->engine[ring->id].lrc_desc; + return ctx->engine[engine->id].lrc_desc; } /** @@ -351,9 +351,9 @@ uint64_t intel_lr_context_descriptor(struct intel_context *ctx, * Return: 20-bits globally unique context ID. */ u32 intel_execlists_ctx_id(struct intel_context *ctx, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { - return intel_lr_context_descriptor(ctx, ring) >> GEN8_CTX_ID_SHIFT; + return intel_lr_context_descriptor(ctx, engine) >> GEN8_CTX_ID_SHIFT; } static void execlists_elsp_write(struct drm_i915_gem_request *rq0, @@ -424,21 +424,21 @@ static void execlists_submit_requests(struct drm_i915_gem_request *rq0, execlists_elsp_write(rq0, rq1); } -static void execlists_context_unqueue__locked(struct intel_engine_cs *ring) +static void execlists_context_unqueue__locked(struct intel_engine_cs *engine) { struct drm_i915_gem_request *req0 = NULL, *req1 = NULL; struct drm_i915_gem_request *cursor, *tmp; - assert_spin_locked(&ring->execlist_lock); + assert_spin_locked(&engine->execlist_lock); /* * If irqs are not active generate a warning as batches that finish * without the irqs may get lost and a GPU Hang may occur. */ - WARN_ON(!intel_irqs_enabled(ring->dev->dev_private)); + WARN_ON(!intel_irqs_enabled(engine->dev->dev_private)); /* Try to read in pairs */ - list_for_each_entry_safe(cursor, tmp, &ring->execlist_queue, + list_for_each_entry_safe(cursor, tmp, &engine->execlist_queue, execlist_link) { if (!req0) { req0 = cursor; @@ -447,7 +447,7 @@ static void execlists_context_unqueue__locked(struct intel_engine_cs *ring) * will update tail past first request's workload */ cursor->elsp_submitted = req0->elsp_submitted; list_move_tail(&req0->execlist_link, - &ring->execlist_retired_req_list); + &engine->execlist_retired_req_list); req0 = cursor; } else { req1 = cursor; @@ -459,7 +459,7 @@ static void execlists_context_unqueue__locked(struct intel_engine_cs *ring) if (unlikely(!req0)) return; - if (req0->elsp_submitted & ring->idle_lite_restore_wa) { + if (req0->elsp_submitted & engine->idle_lite_restore_wa) { /* * WaIdleLiteRestore: make sure we never cause a lite restore * with HEAD==TAIL. @@ -470,7 +470,7 @@ static void execlists_context_unqueue__locked(struct intel_engine_cs *ring) */ struct intel_ringbuffer *ringbuf; - ringbuf = req0->ctx->engine[ring->id].ringbuf; + ringbuf = req0->ctx->engine[engine->id].ringbuf; req0->tail += 8; req0->tail &= ringbuf->size - 1; } @@ -478,34 +478,34 @@ static void execlists_context_unqueue__locked(struct intel_engine_cs *ring) execlists_submit_requests(req0, req1); } -static void execlists_context_unqueue(struct intel_engine_cs *ring) +static void execlists_context_unqueue(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; spin_lock(&dev_priv->uncore.lock); intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); - execlists_context_unqueue__locked(ring); + execlists_context_unqueue__locked(engine); intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); spin_unlock(&dev_priv->uncore.lock); } static unsigned int -execlists_check_remove_request(struct intel_engine_cs *ring, u32 request_id) +execlists_check_remove_request(struct intel_engine_cs *engine, u32 request_id) { struct drm_i915_gem_request *head_req; - assert_spin_locked(&ring->execlist_lock); + assert_spin_locked(&engine->execlist_lock); - head_req = list_first_entry_or_null(&ring->execlist_queue, + head_req = list_first_entry_or_null(&engine->execlist_queue, struct drm_i915_gem_request, execlist_link); if (!head_req) return 0; - if (unlikely(intel_execlists_ctx_id(head_req->ctx, ring) != request_id)) + if (unlikely(intel_execlists_ctx_id(head_req->ctx, engine) != request_id)) return 0; WARN(head_req->elsp_submitted == 0, "Never submitted head request\n"); @@ -514,26 +514,26 @@ execlists_check_remove_request(struct intel_engine_cs *ring, u32 request_id) return 0; list_move_tail(&head_req->execlist_link, - &ring->execlist_retired_req_list); + &engine->execlist_retired_req_list); return 1; } static u32 -get_context_status(struct intel_engine_cs *ring, unsigned int read_pointer, +get_context_status(struct intel_engine_cs *engine, unsigned int read_pointer, u32 *context_id) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; u32 status; read_pointer %= GEN8_CSB_ENTRIES; - status = I915_READ_FW(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer)); + status = I915_READ_FW(RING_CONTEXT_STATUS_BUF_LO(engine, read_pointer)); if (status & GEN8_CTX_STATUS_IDLE_ACTIVE) return 0; - *context_id = I915_READ_FW(RING_CONTEXT_STATUS_BUF_HI(ring, + *context_id = I915_READ_FW(RING_CONTEXT_STATUS_BUF_HI(engine, read_pointer)); return status; @@ -546,33 +546,34 @@ get_context_status(struct intel_engine_cs *ring, unsigned int read_pointer, * Check the unread Context Status Buffers and manage the submission of new * contexts to the ELSP accordingly. */ -void intel_lrc_irq_handler(struct intel_engine_cs *ring) +void intel_lrc_irq_handler(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; u32 status_pointer; unsigned int read_pointer, write_pointer; u32 status = 0; u32 status_id; unsigned int submit_contexts = 0; - spin_lock(&ring->execlist_lock); + spin_lock(&engine->execlist_lock); spin_lock(&dev_priv->uncore.lock); intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); - status_pointer = I915_READ_FW(RING_CONTEXT_STATUS_PTR(ring)); + status_pointer = I915_READ_FW(RING_CONTEXT_STATUS_PTR(engine)); - read_pointer = ring->next_context_status_buffer; + read_pointer = engine->next_context_status_buffer; write_pointer = GEN8_CSB_WRITE_PTR(status_pointer); if (read_pointer > write_pointer) write_pointer += GEN8_CSB_ENTRIES; while (read_pointer < write_pointer) { - status = get_context_status(ring, ++read_pointer, &status_id); + status = get_context_status(engine, ++read_pointer, + &status_id); if (unlikely(status & GEN8_CTX_STATUS_PREEMPTED)) { if (status & GEN8_CTX_STATUS_LITE_RESTORE) { - if (execlists_check_remove_request(ring, status_id)) + if (execlists_check_remove_request(engine, status_id)) WARN(1, "Lite Restored request removed from queue\n"); } else WARN(1, "Preemption without Lite Restore\n"); @@ -581,27 +582,28 @@ void intel_lrc_irq_handler(struct intel_engine_cs *ring) if (status & (GEN8_CTX_STATUS_ACTIVE_IDLE | GEN8_CTX_STATUS_ELEMENT_SWITCH)) submit_contexts += - execlists_check_remove_request(ring, status_id); + execlists_check_remove_request(engine, + status_id); } if (submit_contexts) { - if (!ring->disable_lite_restore_wa || + if (!engine->disable_lite_restore_wa || (status & GEN8_CTX_STATUS_ACTIVE_IDLE)) - execlists_context_unqueue__locked(ring); + execlists_context_unqueue__locked(engine); } - ring->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES; + engine->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES; /* Update the read pointer to the old write pointer. Manual ringbuffer * management ftw */ - I915_WRITE_FW(RING_CONTEXT_STATUS_PTR(ring), + I915_WRITE_FW(RING_CONTEXT_STATUS_PTR(engine), _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, - ring->next_context_status_buffer << 8)); + engine->next_context_status_buffer << 8)); intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); spin_unlock(&dev_priv->uncore.lock); - spin_unlock(&ring->execlist_lock); + spin_unlock(&engine->execlist_lock); if (unlikely(submit_contexts > 2)) DRM_ERROR("More than two context complete events?\n"); @@ -1020,53 +1022,53 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, return 0; } -void intel_execlists_retire_requests(struct intel_engine_cs *ring) +void intel_execlists_retire_requests(struct intel_engine_cs *engine) { struct drm_i915_gem_request *req, *tmp; struct list_head retired_list; - WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); - if (list_empty(&ring->execlist_retired_req_list)) + WARN_ON(!mutex_is_locked(&engine->dev->struct_mutex)); + if (list_empty(&engine->execlist_retired_req_list)) return; INIT_LIST_HEAD(&retired_list); - spin_lock_irq(&ring->execlist_lock); - list_replace_init(&ring->execlist_retired_req_list, &retired_list); - spin_unlock_irq(&ring->execlist_lock); + spin_lock_irq(&engine->execlist_lock); + list_replace_init(&engine->execlist_retired_req_list, &retired_list); + spin_unlock_irq(&engine->execlist_lock); list_for_each_entry_safe(req, tmp, &retired_list, execlist_link) { struct intel_context *ctx = req->ctx; struct drm_i915_gem_object *ctx_obj = - ctx->engine[ring->id].state; + ctx->engine[engine->id].state; if (ctx_obj && (ctx != req->i915->kernel_context)) - intel_lr_context_unpin(ctx, ring); + intel_lr_context_unpin(ctx, engine); list_del(&req->execlist_link); i915_gem_request_unreference(req); } } -void intel_logical_ring_stop(struct intel_engine_cs *ring) +void intel_logical_ring_stop(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; int ret; - if (!intel_ring_initialized(ring)) + if (!intel_ring_initialized(engine)) return; - ret = intel_ring_idle(ring); - if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error)) + ret = intel_ring_idle(engine); + if (ret && !i915_reset_in_progress(&to_i915(engine->dev)->gpu_error)) DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", - ring->name, ret); + engine->name, ret); /* TODO: Is this correct with Execlists enabled? */ - I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); - if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { - DRM_ERROR("%s :timed out trying to stop ring\n", ring->name); + I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING)); + if (wait_for((I915_READ_MODE(engine) & MODE_IDLE) != 0, 1000)) { + DRM_ERROR("%s :timed out trying to stop ring\n", engine->name); return; } - I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING)); + I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING)); } int logical_ring_flush_all_caches(struct drm_i915_gem_request *req) @@ -1086,17 +1088,17 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req) } static int intel_lr_context_do_pin(struct intel_context *ctx, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state; - struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf; + struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state; + struct intel_ringbuffer *ringbuf = ctx->engine[engine->id].ringbuf; struct page *lrc_state_page; uint32_t *lrc_reg_state; int ret; - WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex)); + WARN_ON(!mutex_is_locked(&engine->dev->struct_mutex)); ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, PIN_OFFSET_BIAS | GUC_WOPCM_TOP); @@ -1109,15 +1111,15 @@ static int intel_lr_context_do_pin(struct intel_context *ctx, goto unpin_ctx_obj; } - ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf); + ret = intel_pin_and_map_ringbuffer_obj(engine->dev, ringbuf); if (ret) goto unpin_ctx_obj; - ctx->engine[ring->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj); - intel_lr_context_descriptor_update(ctx, ring); + ctx->engine[engine->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj); + intel_lr_context_descriptor_update(ctx, engine); lrc_reg_state = kmap(lrc_state_page); lrc_reg_state[CTX_RING_BUFFER_START+1] = ringbuf->vma->node.start; - ctx->engine[ring->id].lrc_reg_state = lrc_reg_state; + ctx->engine[engine->id].lrc_reg_state = lrc_reg_state; ctx_obj->dirty = true; /* Invalidate GuC TLB. */ @@ -1235,7 +1237,7 @@ static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req) * This WA is also required for Gen9 so extracting as a function avoids * code duplication. */ -static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring, +static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine, uint32_t *const batch, uint32_t index) { @@ -1247,13 +1249,13 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring, * this batch updates GEN8_L3SQCREG4 with default value we need to * set this bit here to retain the WA during flush. */ - if (IS_SKL_REVID(ring->dev, 0, SKL_REVID_E0)) + if (IS_SKL_REVID(engine->dev, 0, SKL_REVID_E0)) l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS; wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT)); wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4); - wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256); + wa_ctx_emit(batch, index, engine->scratch.gtt_offset + 256); wa_ctx_emit(batch, index, 0); wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1)); @@ -1271,7 +1273,7 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring, wa_ctx_emit(batch, index, (MI_LOAD_REGISTER_MEM_GEN8 | MI_SRM_LRM_GLOBAL_GTT)); wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4); - wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256); + wa_ctx_emit(batch, index, engine->scratch.gtt_offset + 256); wa_ctx_emit(batch, index, 0); return index; @@ -1324,7 +1326,7 @@ static inline int wa_ctx_end(struct i915_wa_ctx_bb *wa_ctx, * Return: non-zero if we exceed the PAGE_SIZE limit. */ -static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring, +static int gen8_init_indirectctx_bb(struct intel_engine_cs *engine, struct i915_wa_ctx_bb *wa_ctx, uint32_t *const batch, uint32_t *offset) @@ -1336,8 +1338,8 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring, wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE); /* WaFlushCoherentL3CacheLinesAtContextSwitch:bdw */ - if (IS_BROADWELL(ring->dev)) { - int rc = gen8_emit_flush_coherentl3_wa(ring, batch, index); + if (IS_BROADWELL(engine->dev)) { + int rc = gen8_emit_flush_coherentl3_wa(engine, batch, index); if (rc < 0) return rc; index = rc; @@ -1345,7 +1347,7 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring, /* WaClearSlmSpaceAtContextSwitch:bdw,chv */ /* Actual scratch location is at 128 bytes offset */ - scratch_addr = ring->scratch.gtt_offset + 2*CACHELINE_BYTES; + scratch_addr = engine->scratch.gtt_offset + 2*CACHELINE_BYTES; wa_ctx_emit(batch, index, GFX_OP_PIPE_CONTROL(6)); wa_ctx_emit(batch, index, (PIPE_CONTROL_FLUSH_L3 | @@ -1387,7 +1389,7 @@ static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring, * This batch is terminated with MI_BATCH_BUFFER_END and so we need not add padding * to align it with cacheline as padding after MI_BATCH_BUFFER_END is redundant. */ -static int gen8_init_perctx_bb(struct intel_engine_cs *ring, +static int gen8_init_perctx_bb(struct intel_engine_cs *engine, struct i915_wa_ctx_bb *wa_ctx, uint32_t *const batch, uint32_t *offset) @@ -1402,13 +1404,13 @@ static int gen8_init_perctx_bb(struct intel_engine_cs *ring, return wa_ctx_end(wa_ctx, *offset = index, 1); } -static int gen9_init_indirectctx_bb(struct intel_engine_cs *ring, +static int gen9_init_indirectctx_bb(struct intel_engine_cs *engine, struct i915_wa_ctx_bb *wa_ctx, uint32_t *const batch, uint32_t *offset) { int ret; - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); /* WaDisableCtxRestoreArbitration:skl,bxt */ @@ -1417,7 +1419,7 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *ring, wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE); /* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */ - ret = gen8_emit_flush_coherentl3_wa(ring, batch, index); + ret = gen8_emit_flush_coherentl3_wa(engine, batch, index); if (ret < 0) return ret; index = ret; @@ -1429,12 +1431,12 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *ring, return wa_ctx_end(wa_ctx, *offset = index, CACHELINE_DWORDS); } -static int gen9_init_perctx_bb(struct intel_engine_cs *ring, +static int gen9_init_perctx_bb(struct intel_engine_cs *engine, struct i915_wa_ctx_bb *wa_ctx, uint32_t *const batch, uint32_t *offset) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ @@ -1457,60 +1459,61 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *ring, return wa_ctx_end(wa_ctx, *offset = index, 1); } -static int lrc_setup_wa_ctx_obj(struct intel_engine_cs *ring, u32 size) +static int lrc_setup_wa_ctx_obj(struct intel_engine_cs *engine, u32 size) { int ret; - ring->wa_ctx.obj = i915_gem_alloc_object(ring->dev, PAGE_ALIGN(size)); - if (!ring->wa_ctx.obj) { + engine->wa_ctx.obj = i915_gem_alloc_object(engine->dev, + PAGE_ALIGN(size)); + if (!engine->wa_ctx.obj) { DRM_DEBUG_DRIVER("alloc LRC WA ctx backing obj failed.\n"); return -ENOMEM; } - ret = i915_gem_obj_ggtt_pin(ring->wa_ctx.obj, PAGE_SIZE, 0); + ret = i915_gem_obj_ggtt_pin(engine->wa_ctx.obj, PAGE_SIZE, 0); if (ret) { DRM_DEBUG_DRIVER("pin LRC WA ctx backing obj failed: %d\n", ret); - drm_gem_object_unreference(&ring->wa_ctx.obj->base); + drm_gem_object_unreference(&engine->wa_ctx.obj->base); return ret; } return 0; } -static void lrc_destroy_wa_ctx_obj(struct intel_engine_cs *ring) +static void lrc_destroy_wa_ctx_obj(struct intel_engine_cs *engine) { - if (ring->wa_ctx.obj) { - i915_gem_object_ggtt_unpin(ring->wa_ctx.obj); - drm_gem_object_unreference(&ring->wa_ctx.obj->base); - ring->wa_ctx.obj = NULL; + if (engine->wa_ctx.obj) { + i915_gem_object_ggtt_unpin(engine->wa_ctx.obj); + drm_gem_object_unreference(&engine->wa_ctx.obj->base); + engine->wa_ctx.obj = NULL; } } -static int intel_init_workaround_bb(struct intel_engine_cs *ring) +static int intel_init_workaround_bb(struct intel_engine_cs *engine) { int ret; uint32_t *batch; uint32_t offset; struct page *page; - struct i915_ctx_workarounds *wa_ctx = &ring->wa_ctx; + struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx; - WARN_ON(ring->id != RCS); + WARN_ON(engine->id != RCS); /* update this when WA for higher Gen are added */ - if (INTEL_INFO(ring->dev)->gen > 9) { + if (INTEL_INFO(engine->dev)->gen > 9) { DRM_ERROR("WA batch buffer is not initialized for Gen%d\n", - INTEL_INFO(ring->dev)->gen); + INTEL_INFO(engine->dev)->gen); return 0; } /* some WA perform writes to scratch page, ensure it is valid */ - if (ring->scratch.obj == NULL) { - DRM_ERROR("scratch page not allocated for %s\n", ring->name); + if (engine->scratch.obj == NULL) { + DRM_ERROR("scratch page not allocated for %s\n", engine->name); return -EINVAL; } - ret = lrc_setup_wa_ctx_obj(ring, PAGE_SIZE); + ret = lrc_setup_wa_ctx_obj(engine, PAGE_SIZE); if (ret) { DRM_DEBUG_DRIVER("Failed to setup context WA page: %d\n", ret); return ret; @@ -1520,29 +1523,29 @@ static int intel_init_workaround_bb(struct intel_engine_cs *ring) batch = kmap_atomic(page); offset = 0; - if (INTEL_INFO(ring->dev)->gen == 8) { - ret = gen8_init_indirectctx_bb(ring, + if (INTEL_INFO(engine->dev)->gen == 8) { + ret = gen8_init_indirectctx_bb(engine, &wa_ctx->indirect_ctx, batch, &offset); if (ret) goto out; - ret = gen8_init_perctx_bb(ring, + ret = gen8_init_perctx_bb(engine, &wa_ctx->per_ctx, batch, &offset); if (ret) goto out; - } else if (INTEL_INFO(ring->dev)->gen == 9) { - ret = gen9_init_indirectctx_bb(ring, + } else if (INTEL_INFO(engine->dev)->gen == 9) { + ret = gen9_init_indirectctx_bb(engine, &wa_ctx->indirect_ctx, batch, &offset); if (ret) goto out; - ret = gen9_init_perctx_bb(ring, + ret = gen9_init_perctx_bb(engine, &wa_ctx->per_ctx, batch, &offset); @@ -1553,27 +1556,28 @@ static int intel_init_workaround_bb(struct intel_engine_cs *ring) out: kunmap_atomic(batch); if (ret) - lrc_destroy_wa_ctx_obj(ring); + lrc_destroy_wa_ctx_obj(engine); return ret; } -static int gen8_init_common_ring(struct intel_engine_cs *ring) +static int gen8_init_common_ring(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned int next_context_status_buffer_hw; - lrc_setup_hardware_status_page(ring, - dev_priv->kernel_context->engine[ring->id].state); + lrc_setup_hardware_status_page(engine, + dev_priv->kernel_context->engine[engine->id].state); - I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); - I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff); + I915_WRITE_IMR(engine, + ~(engine->irq_enable_mask | engine->irq_keep_mask)); + I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff); - I915_WRITE(RING_MODE_GEN7(ring), + I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) | _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE)); - POSTING_READ(RING_MODE_GEN7(ring)); + POSTING_READ(RING_MODE_GEN7(engine)); /* * Instead of resetting the Context Status Buffer (CSB) read pointer to @@ -1588,7 +1592,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring) * BXT | ? | ? | */ next_context_status_buffer_hw = - GEN8_CSB_WRITE_PTR(I915_READ(RING_CONTEXT_STATUS_PTR(ring))); + GEN8_CSB_WRITE_PTR(I915_READ(RING_CONTEXT_STATUS_PTR(engine))); /* * When the CSB registers are reset (also after power-up / gpu reset), @@ -1598,21 +1602,21 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring) if (next_context_status_buffer_hw == GEN8_CSB_PTR_MASK) next_context_status_buffer_hw = (GEN8_CSB_ENTRIES - 1); - ring->next_context_status_buffer = next_context_status_buffer_hw; - DRM_DEBUG_DRIVER("Execlists enabled for %s\n", ring->name); + engine->next_context_status_buffer = next_context_status_buffer_hw; + DRM_DEBUG_DRIVER("Execlists enabled for %s\n", engine->name); - memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); + memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); return 0; } -static int gen8_init_render_ring(struct intel_engine_cs *ring) +static int gen8_init_render_ring(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; int ret; - ret = gen8_init_common_ring(ring); + ret = gen8_init_common_ring(engine); if (ret) return ret; @@ -1626,18 +1630,18 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); - return init_workarounds_ring(ring); + return init_workarounds_ring(engine); } -static int gen9_init_render_ring(struct intel_engine_cs *ring) +static int gen9_init_render_ring(struct intel_engine_cs *engine) { int ret; - ret = gen8_init_common_ring(ring); + ret = gen8_init_common_ring(engine); if (ret) return ret; - return init_workarounds_ring(ring); + return init_workarounds_ring(engine); } static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) @@ -1712,9 +1716,9 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req, return 0; } -static bool gen8_logical_ring_get_irq(struct intel_engine_cs *ring) +static bool gen8_logical_ring_get_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; @@ -1722,25 +1726,26 @@ static bool gen8_logical_ring_get_irq(struct intel_engine_cs *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { - I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); - POSTING_READ(RING_IMR(ring->mmio_base)); + if (engine->irq_refcount++ == 0) { + I915_WRITE_IMR(engine, + ~(engine->irq_enable_mask | engine->irq_keep_mask)); + POSTING_READ(RING_IMR(engine->mmio_base)); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); return true; } -static void gen8_logical_ring_put_irq(struct intel_engine_cs *ring) +static void gen8_logical_ring_put_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { - I915_WRITE_IMR(ring, ~ring->irq_keep_mask); - POSTING_READ(RING_IMR(ring->mmio_base)); + if (--engine->irq_refcount == 0) { + I915_WRITE_IMR(engine, ~engine->irq_keep_mask); + POSTING_READ(RING_IMR(engine->mmio_base)); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); } @@ -1848,17 +1853,18 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, return 0; } -static u32 gen8_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) +static u32 gen8_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency) { - return intel_read_status_page(ring, I915_GEM_HWS_INDEX); + return intel_read_status_page(engine, I915_GEM_HWS_INDEX); } -static void gen8_set_seqno(struct intel_engine_cs *ring, u32 seqno) +static void gen8_set_seqno(struct intel_engine_cs *engine, u32 seqno) { - intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); + intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); } -static u32 bxt_a_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) +static u32 bxt_a_get_seqno(struct intel_engine_cs *engine, + bool lazy_coherency) { /* @@ -1873,17 +1879,17 @@ static u32 bxt_a_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) */ if (!lazy_coherency) - intel_flush_status_page(ring, I915_GEM_HWS_INDEX); + intel_flush_status_page(engine, I915_GEM_HWS_INDEX); - return intel_read_status_page(ring, I915_GEM_HWS_INDEX); + return intel_read_status_page(engine, I915_GEM_HWS_INDEX); } -static void bxt_a_set_seqno(struct intel_engine_cs *ring, u32 seqno) +static void bxt_a_set_seqno(struct intel_engine_cs *engine, u32 seqno) { - intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); + intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); /* See bxt_a_get_seqno() explaining the reason for the clflush. */ - intel_flush_status_page(ring, I915_GEM_HWS_INDEX); + intel_flush_status_page(engine, I915_GEM_HWS_INDEX); } /* @@ -2002,109 +2008,109 @@ static int gen8_init_rcs_context(struct drm_i915_gem_request *req) * @ring: Engine Command Streamer. * */ -void intel_logical_ring_cleanup(struct intel_engine_cs *ring) +void intel_logical_ring_cleanup(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv; - if (!intel_ring_initialized(ring)) + if (!intel_ring_initialized(engine)) return; - dev_priv = ring->dev->dev_private; + dev_priv = engine->dev->dev_private; - if (ring->buffer) { - intel_logical_ring_stop(ring); - WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); + if (engine->buffer) { + intel_logical_ring_stop(engine); + WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0); } - if (ring->cleanup) - ring->cleanup(ring); + if (engine->cleanup) + engine->cleanup(engine); - i915_cmd_parser_fini_ring(ring); - i915_gem_batch_pool_fini(&ring->batch_pool); + i915_cmd_parser_fini_ring(engine); + i915_gem_batch_pool_fini(&engine->batch_pool); - if (ring->status_page.obj) { - kunmap(sg_page(ring->status_page.obj->pages->sgl)); - ring->status_page.obj = NULL; + if (engine->status_page.obj) { + kunmap(sg_page(engine->status_page.obj->pages->sgl)); + engine->status_page.obj = NULL; } - ring->idle_lite_restore_wa = 0; - ring->disable_lite_restore_wa = false; - ring->ctx_desc_template = 0; + engine->idle_lite_restore_wa = 0; + engine->disable_lite_restore_wa = false; + engine->ctx_desc_template = 0; - lrc_destroy_wa_ctx_obj(ring); - ring->dev = NULL; + lrc_destroy_wa_ctx_obj(engine); + engine->dev = NULL; } static void logical_ring_default_vfuncs(struct drm_device *dev, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { /* Default vfuncs which can be overriden by each engine. */ - ring->init_hw = gen8_init_common_ring; - ring->emit_request = gen8_emit_request; - ring->emit_flush = gen8_emit_flush; - ring->irq_get = gen8_logical_ring_get_irq; - ring->irq_put = gen8_logical_ring_put_irq; - ring->emit_bb_start = gen8_emit_bb_start; + engine->init_hw = gen8_init_common_ring; + engine->emit_request = gen8_emit_request; + engine->emit_flush = gen8_emit_flush; + engine->irq_get = gen8_logical_ring_get_irq; + engine->irq_put = gen8_logical_ring_put_irq; + engine->emit_bb_start = gen8_emit_bb_start; if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { - ring->get_seqno = bxt_a_get_seqno; - ring->set_seqno = bxt_a_set_seqno; + engine->get_seqno = bxt_a_get_seqno; + engine->set_seqno = bxt_a_set_seqno; } else { - ring->get_seqno = gen8_get_seqno; - ring->set_seqno = gen8_set_seqno; + engine->get_seqno = gen8_get_seqno; + engine->set_seqno = gen8_set_seqno; } } static inline void -logical_ring_default_irqs(struct intel_engine_cs *ring, unsigned shift) +logical_ring_default_irqs(struct intel_engine_cs *engine, unsigned shift) { - ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift; - ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift; + engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift; + engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift; } static int -logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring) +logical_ring_init(struct drm_device *dev, struct intel_engine_cs *engine) { struct intel_context *dctx = to_i915(dev)->kernel_context; int ret; /* Intentionally left blank. */ - ring->buffer = NULL; + engine->buffer = NULL; - ring->dev = dev; - INIT_LIST_HEAD(&ring->active_list); - INIT_LIST_HEAD(&ring->request_list); - i915_gem_batch_pool_init(dev, &ring->batch_pool); - init_waitqueue_head(&ring->irq_queue); + engine->dev = dev; + INIT_LIST_HEAD(&engine->active_list); + INIT_LIST_HEAD(&engine->request_list); + i915_gem_batch_pool_init(dev, &engine->batch_pool); + init_waitqueue_head(&engine->irq_queue); - INIT_LIST_HEAD(&ring->buffers); - INIT_LIST_HEAD(&ring->execlist_queue); - INIT_LIST_HEAD(&ring->execlist_retired_req_list); - spin_lock_init(&ring->execlist_lock); + INIT_LIST_HEAD(&engine->buffers); + INIT_LIST_HEAD(&engine->execlist_queue); + INIT_LIST_HEAD(&engine->execlist_retired_req_list); + spin_lock_init(&engine->execlist_lock); - logical_ring_init_platform_invariants(ring); + logical_ring_init_platform_invariants(engine); - ret = i915_cmd_parser_init_ring(ring); + ret = i915_cmd_parser_init_ring(engine); if (ret) goto error; - ret = intel_lr_context_deferred_alloc(dctx, ring); + ret = intel_lr_context_deferred_alloc(dctx, engine); if (ret) goto error; /* As this is the default context, always pin it */ - ret = intel_lr_context_do_pin(dctx, ring); + ret = intel_lr_context_do_pin(dctx, engine); if (ret) { DRM_ERROR( "Failed to pin and map ringbuffer %s: %d\n", - ring->name, ret); + engine->name, ret); goto error; } return 0; error: - intel_logical_ring_cleanup(ring); + intel_logical_ring_cleanup(engine); return ret; } @@ -2329,13 +2335,13 @@ make_rpcs(struct drm_device *dev) return rpcs; } -static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *ring) +static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *engine) { u32 indirect_ctx_offset; - switch (INTEL_INFO(ring->dev)->gen) { + switch (INTEL_INFO(engine->dev)->gen) { default: - MISSING_CASE(INTEL_INFO(ring->dev)->gen); + MISSING_CASE(INTEL_INFO(engine->dev)->gen); /* fall through */ case 9: indirect_ctx_offset = @@ -2352,9 +2358,10 @@ static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *ring) static int populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_obj, - struct intel_engine_cs *ring, struct intel_ringbuffer *ringbuf) + struct intel_engine_cs *engine, + struct intel_ringbuffer *ringbuf) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct i915_hw_ppgtt *ppgtt = ctx->ppgtt; struct page *page; @@ -2389,33 +2396,47 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o * recreate this batchbuffer with new values (including all the missing * MI_LOAD_REGISTER_IMM commands that we are not initializing here). */ reg_state[CTX_LRI_HEADER_0] = - MI_LOAD_REGISTER_IMM(ring->id == RCS ? 14 : 11) | MI_LRI_FORCE_POSTED; - ASSIGN_CTX_REG(reg_state, CTX_CONTEXT_CONTROL, RING_CONTEXT_CONTROL(ring), + MI_LOAD_REGISTER_IMM(engine->id == RCS ? 14 : 11) | MI_LRI_FORCE_POSTED; + ASSIGN_CTX_REG(reg_state, CTX_CONTEXT_CONTROL, + RING_CONTEXT_CONTROL(engine), _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH | CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | (HAS_RESOURCE_STREAMER(dev) ? CTX_CTRL_RS_CTX_ENABLE : 0))); - ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(ring->mmio_base), 0); - ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(ring->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(engine->mmio_base), + 0); + ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(engine->mmio_base), + 0); /* Ring buffer start address is not known until the buffer is pinned. * It is written to the context image in execlists_update_context() */ - ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START, RING_START(ring->mmio_base), 0); - ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL, RING_CTL(ring->mmio_base), + ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START, + RING_START(engine->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL, + RING_CTL(engine->mmio_base), ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); - ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U, RING_BBADDR_UDW(ring->mmio_base), 0); - ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L, RING_BBADDR(ring->mmio_base), 0); - ASSIGN_CTX_REG(reg_state, CTX_BB_STATE, RING_BBSTATE(ring->mmio_base), + ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U, + RING_BBADDR_UDW(engine->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L, + RING_BBADDR(engine->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_BB_STATE, + RING_BBSTATE(engine->mmio_base), RING_BB_PPGTT); - ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_U, RING_SBBADDR_UDW(ring->mmio_base), 0); - ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_L, RING_SBBADDR(ring->mmio_base), 0); - ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_STATE, RING_SBBSTATE(ring->mmio_base), 0); - if (ring->id == RCS) { - ASSIGN_CTX_REG(reg_state, CTX_BB_PER_CTX_PTR, RING_BB_PER_CTX_PTR(ring->mmio_base), 0); - ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX, RING_INDIRECT_CTX(ring->mmio_base), 0); - ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX_OFFSET, RING_INDIRECT_CTX_OFFSET(ring->mmio_base), 0); - if (ring->wa_ctx.obj) { - struct i915_ctx_workarounds *wa_ctx = &ring->wa_ctx; + ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_U, + RING_SBBADDR_UDW(engine->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_L, + RING_SBBADDR(engine->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_STATE, + RING_SBBSTATE(engine->mmio_base), 0); + if (engine->id == RCS) { + ASSIGN_CTX_REG(reg_state, CTX_BB_PER_CTX_PTR, + RING_BB_PER_CTX_PTR(engine->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX, + RING_INDIRECT_CTX(engine->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX_OFFSET, + RING_INDIRECT_CTX_OFFSET(engine->mmio_base), 0); + if (engine->wa_ctx.obj) { + struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx; uint32_t ggtt_offset = i915_gem_obj_ggtt_offset(wa_ctx->obj); reg_state[CTX_RCS_INDIRECT_CTX+1] = @@ -2423,7 +2444,7 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o (wa_ctx->indirect_ctx.size / CACHELINE_DWORDS); reg_state[CTX_RCS_INDIRECT_CTX_OFFSET+1] = - intel_lr_indirect_ctx_offset(ring) << 6; + intel_lr_indirect_ctx_offset(engine) << 6; reg_state[CTX_BB_PER_CTX_PTR+1] = (ggtt_offset + wa_ctx->per_ctx.offset * sizeof(uint32_t)) | @@ -2431,16 +2452,25 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o } } reg_state[CTX_LRI_HEADER_1] = MI_LOAD_REGISTER_IMM(9) | MI_LRI_FORCE_POSTED; - ASSIGN_CTX_REG(reg_state, CTX_CTX_TIMESTAMP, RING_CTX_TIMESTAMP(ring->mmio_base), 0); + ASSIGN_CTX_REG(reg_state, CTX_CTX_TIMESTAMP, + RING_CTX_TIMESTAMP(engine->mmio_base), 0); /* PDP values well be assigned later if needed */ - ASSIGN_CTX_REG(reg_state, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(ring, 3), 0); - ASSIGN_CTX_REG(reg_state, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(ring, 3), 0); - ASSIGN_CTX_REG(reg_state, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(ring, 2), 0); - ASSIGN_CTX_REG(reg_state, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(ring, 2), 0); - ASSIGN_CTX_REG(reg_state, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(ring, 1), 0); - ASSIGN_CTX_REG(reg_state, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(ring, 1), 0); - ASSIGN_CTX_REG(reg_state, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(ring, 0), 0); - ASSIGN_CTX_REG(reg_state, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(ring, 0), 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(engine, 3), + 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(engine, 3), + 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(engine, 2), + 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(engine, 2), + 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(engine, 1), + 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(engine, 1), + 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(engine, 0), + 0); + ASSIGN_CTX_REG(reg_state, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(engine, 0), + 0); if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) { /* 64b PPGTT (48bit canonical) @@ -2457,7 +2487,7 @@ populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_o execlists_update_context_pdps(ppgtt, reg_state); } - if (ring->id == RCS) { + if (engine->id == RCS) { reg_state[CTX_LRI_HEADER_2] = MI_LOAD_REGISTER_IMM(1); ASSIGN_CTX_REG(reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE, make_rpcs(dev)); @@ -2513,15 +2543,15 @@ void intel_lr_context_free(struct intel_context *ctx) * in LRC mode, but does not include the "shared data page" used with * GuC submission. The caller should account for this if using the GuC. */ -uint32_t intel_lr_context_size(struct intel_engine_cs *ring) +uint32_t intel_lr_context_size(struct intel_engine_cs *engine) { int ret = 0; - WARN_ON(INTEL_INFO(ring->dev)->gen < 8); + WARN_ON(INTEL_INFO(engine->dev)->gen < 8); - switch (ring->id) { + switch (engine->id) { case RCS: - if (INTEL_INFO(ring->dev)->gen >= 9) + if (INTEL_INFO(engine->dev)->gen >= 9) ret = GEN9_LR_CONTEXT_RENDER_SIZE; else ret = GEN8_LR_CONTEXT_RENDER_SIZE; @@ -2537,22 +2567,22 @@ uint32_t intel_lr_context_size(struct intel_engine_cs *ring) return ret; } -static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, - struct drm_i915_gem_object *default_ctx_obj) +static void lrc_setup_hardware_status_page(struct intel_engine_cs *engine, + struct drm_i915_gem_object *default_ctx_obj) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; struct page *page; /* The HWSP is part of the default context object in LRC mode. */ - ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj) + engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj) + LRC_PPHWSP_PN * PAGE_SIZE; page = i915_gem_object_get_page(default_ctx_obj, LRC_PPHWSP_PN); - ring->status_page.page_addr = kmap(page); - ring->status_page.obj = default_ctx_obj; + engine->status_page.page_addr = kmap(page); + engine->status_page.obj = default_ctx_obj; - I915_WRITE(RING_HWS_PGA(ring->mmio_base), - (u32)ring->status_page.gfx_addr); - POSTING_READ(RING_HWS_PGA(ring->mmio_base)); + I915_WRITE(RING_HWS_PGA(engine->mmio_base), + (u32)engine->status_page.gfx_addr); + POSTING_READ(RING_HWS_PGA(engine->mmio_base)); } /** @@ -2570,18 +2600,18 @@ static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring, */ int intel_lr_context_deferred_alloc(struct intel_context *ctx, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_gem_object *ctx_obj; uint32_t context_size; struct intel_ringbuffer *ringbuf; int ret; WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL); - WARN_ON(ctx->engine[ring->id].state); + WARN_ON(ctx->engine[engine->id].state); - context_size = round_up(intel_lr_context_size(ring), 4096); + context_size = round_up(intel_lr_context_size(engine), 4096); /* One extra page as the sharing data between driver and GuC */ context_size += PAGE_SIZE * LRC_PPHWSP_PN; @@ -2592,32 +2622,32 @@ int intel_lr_context_deferred_alloc(struct intel_context *ctx, return -ENOMEM; } - ringbuf = intel_engine_create_ringbuffer(ring, 4 * PAGE_SIZE); + ringbuf = intel_engine_create_ringbuffer(engine, 4 * PAGE_SIZE); if (IS_ERR(ringbuf)) { ret = PTR_ERR(ringbuf); goto error_deref_obj; } - ret = populate_lr_context(ctx, ctx_obj, ring, ringbuf); + ret = populate_lr_context(ctx, ctx_obj, engine, ringbuf); if (ret) { DRM_DEBUG_DRIVER("Failed to populate LRC: %d\n", ret); goto error_ringbuf; } - ctx->engine[ring->id].ringbuf = ringbuf; - ctx->engine[ring->id].state = ctx_obj; + ctx->engine[engine->id].ringbuf = ringbuf; + ctx->engine[engine->id].state = ctx_obj; - if (ctx != ctx->i915->kernel_context && ring->init_context) { + if (ctx != ctx->i915->kernel_context && engine->init_context) { struct drm_i915_gem_request *req; - req = i915_gem_request_alloc(ring, ctx); + req = i915_gem_request_alloc(engine, ctx); if (IS_ERR(req)) { ret = PTR_ERR(req); DRM_ERROR("ring create req: %d\n", ret); goto error_ringbuf; } - ret = ring->init_context(req); + ret = engine->init_context(req); if (ret) { DRM_ERROR("ring init context: %d\n", ret); @@ -2632,8 +2662,8 @@ error_ringbuf: intel_ringbuffer_free(ringbuf); error_deref_obj: drm_gem_object_unreference(&ctx_obj->base); - ctx->engine[ring->id].ringbuf = NULL; - ctx->engine[ring->id].state = NULL; + ctx->engine[engine->id].ringbuf = NULL; + ctx->engine[engine->id].state = NULL; return ret; } diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index e6cda3e..a17cb12 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -57,8 +57,8 @@ /* Logical Rings */ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request); int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request); -void intel_logical_ring_stop(struct intel_engine_cs *ring); -void intel_logical_ring_cleanup(struct intel_engine_cs *ring); +void intel_logical_ring_stop(struct intel_engine_cs *engine); +void intel_logical_ring_cleanup(struct intel_engine_cs *engine); int intel_logical_rings_init(struct drm_device *dev); int intel_logical_ring_begin(struct drm_i915_gem_request *req, int num_dwords); @@ -98,18 +98,18 @@ static inline void intel_logical_ring_emit_reg(struct intel_ringbuffer *ringbuf, #define LRC_STATE_PN (LRC_PPHWSP_PN + 1) void intel_lr_context_free(struct intel_context *ctx); -uint32_t intel_lr_context_size(struct intel_engine_cs *ring); +uint32_t intel_lr_context_size(struct intel_engine_cs *engine); int intel_lr_context_deferred_alloc(struct intel_context *ctx, - struct intel_engine_cs *ring); + struct intel_engine_cs *engine); void intel_lr_context_unpin(struct intel_context *ctx, struct intel_engine_cs *engine); void intel_lr_context_reset(struct drm_device *dev, struct intel_context *ctx); uint64_t intel_lr_context_descriptor(struct intel_context *ctx, - struct intel_engine_cs *ring); + struct intel_engine_cs *engine); u32 intel_execlists_ctx_id(struct intel_context *ctx, - struct intel_engine_cs *ring); + struct intel_engine_cs *engine); /* Execlists */ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists); @@ -118,7 +118,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, struct drm_i915_gem_execbuffer2 *args, struct list_head *vmas); -void intel_lrc_irq_handler(struct intel_engine_cs *ring); -void intel_execlists_retire_requests(struct intel_engine_cs *ring); +void intel_lrc_irq_handler(struct intel_engine_cs *engine); +void intel_execlists_retire_requests(struct intel_engine_cs *engine); #endif /* _INTEL_LRC_H_ */ diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 688773a..5323761 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -59,19 +59,19 @@ int intel_ring_space(struct intel_ringbuffer *ringbuf) return ringbuf->space; } -bool intel_ring_stopped(struct intel_engine_cs *ring) +bool intel_ring_stopped(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; - return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring); + struct drm_i915_private *dev_priv = engine->dev->dev_private; + return dev_priv->gpu_error.stop_rings & intel_ring_flag(engine); } -static void __intel_ring_advance(struct intel_engine_cs *ring) +static void __intel_ring_advance(struct intel_engine_cs *engine) { - struct intel_ringbuffer *ringbuf = ring->buffer; + struct intel_ringbuffer *ringbuf = engine->buffer; ringbuf->tail &= ringbuf->size - 1; - if (intel_ring_stopped(ring)) + if (intel_ring_stopped(engine)) return; - ring->write_tail(ring, ringbuf->tail); + engine->write_tail(engine, ringbuf->tail); } static int @@ -429,51 +429,51 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req, return gen8_emit_pipe_control(req, flags, scratch_addr); } -static void ring_write_tail(struct intel_engine_cs *ring, +static void ring_write_tail(struct intel_engine_cs *engine, u32 value) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; - I915_WRITE_TAIL(ring, value); + struct drm_i915_private *dev_priv = engine->dev->dev_private; + I915_WRITE_TAIL(engine, value); } -u64 intel_ring_get_active_head(struct intel_engine_cs *ring) +u64 intel_ring_get_active_head(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; u64 acthd; - if (INTEL_INFO(ring->dev)->gen >= 8) - acthd = I915_READ64_2x32(RING_ACTHD(ring->mmio_base), - RING_ACTHD_UDW(ring->mmio_base)); - else if (INTEL_INFO(ring->dev)->gen >= 4) - acthd = I915_READ(RING_ACTHD(ring->mmio_base)); + if (INTEL_INFO(engine->dev)->gen >= 8) + acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), + RING_ACTHD_UDW(engine->mmio_base)); + else if (INTEL_INFO(engine->dev)->gen >= 4) + acthd = I915_READ(RING_ACTHD(engine->mmio_base)); else acthd = I915_READ(ACTHD); return acthd; } -static void ring_setup_phys_status_page(struct intel_engine_cs *ring) +static void ring_setup_phys_status_page(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; u32 addr; addr = dev_priv->status_page_dmah->busaddr; - if (INTEL_INFO(ring->dev)->gen >= 4) + if (INTEL_INFO(engine->dev)->gen >= 4) addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0; I915_WRITE(HWS_PGA, addr); } -static void intel_ring_setup_status_page(struct intel_engine_cs *ring) +static void intel_ring_setup_status_page(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_device *dev = engine->dev; + struct drm_i915_private *dev_priv = engine->dev->dev_private; i915_reg_t mmio; /* The ring status page addresses are no longer next to the rest of * the ring registers as of gen7. */ if (IS_GEN7(dev)) { - switch (ring->id) { + switch (engine->id) { case RCS: mmio = RENDER_HWS_PGA_GEN7; break; @@ -492,14 +492,14 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring) mmio = VEBOX_HWS_PGA_GEN7; break; } - } else if (IS_GEN6(ring->dev)) { - mmio = RING_HWS_PGA_GEN6(ring->mmio_base); + } else if (IS_GEN6(engine->dev)) { + mmio = RING_HWS_PGA_GEN6(engine->mmio_base); } else { /* XXX: gen8 returns to sanity */ - mmio = RING_HWS_PGA(ring->mmio_base); + mmio = RING_HWS_PGA(engine->mmio_base); } - I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); + I915_WRITE(mmio, (u32)engine->status_page.gfx_addr); POSTING_READ(mmio); /* @@ -510,10 +510,10 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring) * invalidating the TLB? */ if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) { - i915_reg_t reg = RING_INSTPM(ring->mmio_base); + i915_reg_t reg = RING_INSTPM(engine->mmio_base); /* ring should be idle before issuing a sync flush*/ - WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0); + WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0); I915_WRITE(reg, _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | @@ -521,117 +521,120 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *ring) if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, 1000)) DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", - ring->name); + engine->name); } } -static bool stop_ring(struct intel_engine_cs *ring) +static bool stop_ring(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = to_i915(ring->dev); + struct drm_i915_private *dev_priv = to_i915(engine->dev); - if (!IS_GEN2(ring->dev)) { - I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING)); - if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) { - DRM_ERROR("%s : timed out trying to stop ring\n", ring->name); + if (!IS_GEN2(engine->dev)) { + I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING)); + if (wait_for((I915_READ_MODE(engine) & MODE_IDLE) != 0, 1000)) { + DRM_ERROR("%s : timed out trying to stop ring\n", + engine->name); /* Sometimes we observe that the idle flag is not * set even though the ring is empty. So double * check before giving up. */ - if (I915_READ_HEAD(ring) != I915_READ_TAIL(ring)) + if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine)) return false; } } - I915_WRITE_CTL(ring, 0); - I915_WRITE_HEAD(ring, 0); - ring->write_tail(ring, 0); + I915_WRITE_CTL(engine, 0); + I915_WRITE_HEAD(engine, 0); + engine->write_tail(engine, 0); - if (!IS_GEN2(ring->dev)) { - (void)I915_READ_CTL(ring); - I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING)); + if (!IS_GEN2(engine->dev)) { + (void)I915_READ_CTL(engine); + I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING)); } - return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0; + return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0; } -static int init_ring_common(struct intel_engine_cs *ring) +static int init_ring_common(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ringbuffer *ringbuf = ring->buffer; + struct intel_ringbuffer *ringbuf = engine->buffer; struct drm_i915_gem_object *obj = ringbuf->obj; int ret = 0; intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); - if (!stop_ring(ring)) { + if (!stop_ring(engine)) { /* G45 ring initialization often fails to reset head to zero */ DRM_DEBUG_KMS("%s head not reset to zero " "ctl %08x head %08x tail %08x start %08x\n", - ring->name, - I915_READ_CTL(ring), - I915_READ_HEAD(ring), - I915_READ_TAIL(ring), - I915_READ_START(ring)); + engine->name, + I915_READ_CTL(engine), + I915_READ_HEAD(engine), + I915_READ_TAIL(engine), + I915_READ_START(engine)); - if (!stop_ring(ring)) { + if (!stop_ring(engine)) { DRM_ERROR("failed to set %s head to zero " "ctl %08x head %08x tail %08x start %08x\n", - ring->name, - I915_READ_CTL(ring), - I915_READ_HEAD(ring), - I915_READ_TAIL(ring), - I915_READ_START(ring)); + engine->name, + I915_READ_CTL(engine), + I915_READ_HEAD(engine), + I915_READ_TAIL(engine), + I915_READ_START(engine)); ret = -EIO; goto out; } } if (I915_NEED_GFX_HWS(dev)) - intel_ring_setup_status_page(ring); + intel_ring_setup_status_page(engine); else - ring_setup_phys_status_page(ring); + ring_setup_phys_status_page(engine); /* Enforce ordering by reading HEAD register back */ - I915_READ_HEAD(ring); + I915_READ_HEAD(engine); /* Initialize the ring. This must happen _after_ we've cleared the ring * registers with the above sequence (the readback of the HEAD registers * also enforces ordering), otherwise the hw might lose the new ring * register values. */ - I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj)); + I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj)); /* WaClearRingBufHeadRegAtInit:ctg,elk */ - if (I915_READ_HEAD(ring)) + if (I915_READ_HEAD(engine)) DRM_DEBUG("%s initialization failed [head=%08x], fudging\n", - ring->name, I915_READ_HEAD(ring)); - I915_WRITE_HEAD(ring, 0); - (void)I915_READ_HEAD(ring); + engine->name, I915_READ_HEAD(engine)); + I915_WRITE_HEAD(engine, 0); + (void)I915_READ_HEAD(engine); - I915_WRITE_CTL(ring, + I915_WRITE_CTL(engine, ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); /* If the head is still not zero, the ring is dead */ - if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && - I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) && - (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { + if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 && + I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) && + (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) { DRM_ERROR("%s initialization failed " "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n", - ring->name, - I915_READ_CTL(ring), I915_READ_CTL(ring) & RING_VALID, - I915_READ_HEAD(ring), I915_READ_TAIL(ring), - I915_READ_START(ring), (unsigned long)i915_gem_obj_ggtt_offset(obj)); + engine->name, + I915_READ_CTL(engine), + I915_READ_CTL(engine) & RING_VALID, + I915_READ_HEAD(engine), I915_READ_TAIL(engine), + I915_READ_START(engine), + (unsigned long)i915_gem_obj_ggtt_offset(obj)); ret = -EIO; goto out; } ringbuf->last_retired_head = -1; - ringbuf->head = I915_READ_HEAD(ring); - ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR; + ringbuf->head = I915_READ_HEAD(engine); + ringbuf->tail = I915_READ_TAIL(engine) & TAIL_ADDR; intel_ring_update_space(ringbuf); - memset(&ring->hangcheck, 0, sizeof(ring->hangcheck)); + memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); out: intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); @@ -640,59 +643,60 @@ out: } void -intel_fini_pipe_control(struct intel_engine_cs *ring) +intel_fini_pipe_control(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; - if (ring->scratch.obj == NULL) + if (engine->scratch.obj == NULL) return; if (INTEL_INFO(dev)->gen >= 5) { - kunmap(sg_page(ring->scratch.obj->pages->sgl)); - i915_gem_object_ggtt_unpin(ring->scratch.obj); + kunmap(sg_page(engine->scratch.obj->pages->sgl)); + i915_gem_object_ggtt_unpin(engine->scratch.obj); } - drm_gem_object_unreference(&ring->scratch.obj->base); - ring->scratch.obj = NULL; + drm_gem_object_unreference(&engine->scratch.obj->base); + engine->scratch.obj = NULL; } int -intel_init_pipe_control(struct intel_engine_cs *ring) +intel_init_pipe_control(struct intel_engine_cs *engine) { int ret; - WARN_ON(ring->scratch.obj); + WARN_ON(engine->scratch.obj); - ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096); - if (ring->scratch.obj == NULL) { + engine->scratch.obj = i915_gem_alloc_object(engine->dev, 4096); + if (engine->scratch.obj == NULL) { DRM_ERROR("Failed to allocate seqno page\n"); ret = -ENOMEM; goto err; } - ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC); + ret = i915_gem_object_set_cache_level(engine->scratch.obj, + I915_CACHE_LLC); if (ret) goto err_unref; - ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0); + ret = i915_gem_obj_ggtt_pin(engine->scratch.obj, 4096, 0); if (ret) goto err_unref; - ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj); - ring->scratch.cpu_page = kmap(sg_page(ring->scratch.obj->pages->sgl)); - if (ring->scratch.cpu_page == NULL) { + engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(engine->scratch.obj); + engine->scratch.cpu_page = kmap(sg_page(engine->scratch.obj->pages->sgl)); + if (engine->scratch.cpu_page == NULL) { ret = -ENOMEM; goto err_unpin; } DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", - ring->name, ring->scratch.gtt_offset); + engine->name, engine->scratch.gtt_offset); return 0; err_unpin: - i915_gem_object_ggtt_unpin(ring->scratch.obj); + i915_gem_object_ggtt_unpin(engine->scratch.obj); err_unref: - drm_gem_object_unreference(&ring->scratch.obj->base); + drm_gem_object_unreference(&engine->scratch.obj->base); err: return ret; } @@ -789,25 +793,26 @@ static int wa_add(struct drm_i915_private *dev_priv, #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) -static int wa_ring_whitelist_reg(struct intel_engine_cs *ring, i915_reg_t reg) +static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, + i915_reg_t reg) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; struct i915_workarounds *wa = &dev_priv->workarounds; - const uint32_t index = wa->hw_whitelist_count[ring->id]; + const uint32_t index = wa->hw_whitelist_count[engine->id]; if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) return -EINVAL; - WA_WRITE(RING_FORCE_TO_NONPRIV(ring->mmio_base, index), + WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), i915_mmio_reg_offset(reg)); - wa->hw_whitelist_count[ring->id]++; + wa->hw_whitelist_count[engine->id]++; return 0; } -static int gen8_init_workarounds(struct intel_engine_cs *ring) +static int gen8_init_workarounds(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); @@ -857,13 +862,13 @@ static int gen8_init_workarounds(struct intel_engine_cs *ring) return 0; } -static int bdw_init_workarounds(struct intel_engine_cs *ring) +static int bdw_init_workarounds(struct intel_engine_cs *engine) { int ret; - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; - ret = gen8_init_workarounds(ring); + ret = gen8_init_workarounds(engine); if (ret) return ret; @@ -886,13 +891,13 @@ static int bdw_init_workarounds(struct intel_engine_cs *ring) return 0; } -static int chv_init_workarounds(struct intel_engine_cs *ring) +static int chv_init_workarounds(struct intel_engine_cs *engine) { int ret; - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; - ret = gen8_init_workarounds(ring); + ret = gen8_init_workarounds(engine); if (ret) return ret; @@ -905,9 +910,9 @@ static int chv_init_workarounds(struct intel_engine_cs *ring) return 0; } -static int gen9_init_workarounds(struct intel_engine_cs *ring) +static int gen9_init_workarounds(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; uint32_t tmp; int ret; @@ -986,21 +991,21 @@ static int gen9_init_workarounds(struct intel_engine_cs *ring) GEN8_LQSC_FLUSH_COHERENT_LINES)); /* WaEnablePreemptionGranularityControlByUMD:skl,bxt */ - ret= wa_ring_whitelist_reg(ring, GEN8_CS_CHICKEN1); + ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); if (ret) return ret; /* WaAllowUMDToModifyHDCChicken1:skl,bxt */ - ret = wa_ring_whitelist_reg(ring, GEN8_HDC_CHICKEN1); + ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1); if (ret) return ret; return 0; } -static int skl_tune_iz_hashing(struct intel_engine_cs *ring) +static int skl_tune_iz_hashing(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; u8 vals[3] = { 0, 0, 0 }; unsigned int i; @@ -1040,13 +1045,13 @@ static int skl_tune_iz_hashing(struct intel_engine_cs *ring) return 0; } -static int skl_init_workarounds(struct intel_engine_cs *ring) +static int skl_init_workarounds(struct intel_engine_cs *engine) { int ret; - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; - ret = gen9_init_workarounds(ring); + ret = gen9_init_workarounds(engine); if (ret) return ret; @@ -1113,20 +1118,20 @@ static int skl_init_workarounds(struct intel_engine_cs *ring) GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); /* WaDisableLSQCROPERFforOCL:skl */ - ret = wa_ring_whitelist_reg(ring, GEN8_L3SQCREG4); + ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); if (ret) return ret; - return skl_tune_iz_hashing(ring); + return skl_tune_iz_hashing(engine); } -static int bxt_init_workarounds(struct intel_engine_cs *ring) +static int bxt_init_workarounds(struct intel_engine_cs *engine) { int ret; - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; - ret = gen9_init_workarounds(ring); + ret = gen9_init_workarounds(engine); if (ret) return ret; @@ -1157,11 +1162,11 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring) /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ /* WaDisableLSQCROPERFforOCL:bxt */ if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { - ret = wa_ring_whitelist_reg(ring, GEN9_CS_DEBUG_MODE1); + ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1); if (ret) return ret; - ret = wa_ring_whitelist_reg(ring, GEN8_L3SQCREG4); + ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); if (ret) return ret; } @@ -1169,36 +1174,36 @@ static int bxt_init_workarounds(struct intel_engine_cs *ring) return 0; } -int init_workarounds_ring(struct intel_engine_cs *ring) +int init_workarounds_ring(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; - WARN_ON(ring->id != RCS); + WARN_ON(engine->id != RCS); dev_priv->workarounds.count = 0; dev_priv->workarounds.hw_whitelist_count[RCS] = 0; if (IS_BROADWELL(dev)) - return bdw_init_workarounds(ring); + return bdw_init_workarounds(engine); if (IS_CHERRYVIEW(dev)) - return chv_init_workarounds(ring); + return chv_init_workarounds(engine); if (IS_SKYLAKE(dev)) - return skl_init_workarounds(ring); + return skl_init_workarounds(engine); if (IS_BROXTON(dev)) - return bxt_init_workarounds(ring); + return bxt_init_workarounds(engine); return 0; } -static int init_render_ring(struct intel_engine_cs *ring) +static int init_render_ring(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; - int ret = init_ring_common(ring); + int ret = init_ring_common(engine); if (ret) return ret; @@ -1241,14 +1246,14 @@ static int init_render_ring(struct intel_engine_cs *ring) I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING)); if (HAS_L3_DPF(dev)) - I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); + I915_WRITE_IMR(engine, ~GT_PARITY_ERROR(dev)); - return init_workarounds_ring(ring); + return init_workarounds_ring(engine); } -static void render_ring_cleanup(struct intel_engine_cs *ring) +static void render_ring_cleanup(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; if (dev_priv->semaphore_obj) { @@ -1257,7 +1262,7 @@ static void render_ring_cleanup(struct intel_engine_cs *ring) dev_priv->semaphore_obj = NULL; } - intel_fini_pipe_control(ring); + intel_fini_pipe_control(engine); } static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, @@ -1554,47 +1559,47 @@ pc_render_add_request(struct drm_i915_gem_request *req) } static u32 -gen6_ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) +gen6_ring_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency) { /* Workaround to force correct ordering between irq and seqno writes on * ivb (and maybe also on snb) by reading from a CS register (like * ACTHD) before reading the status page. */ if (!lazy_coherency) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; - POSTING_READ(RING_ACTHD(ring->mmio_base)); + struct drm_i915_private *dev_priv = engine->dev->dev_private; + POSTING_READ(RING_ACTHD(engine->mmio_base)); } - return intel_read_status_page(ring, I915_GEM_HWS_INDEX); + return intel_read_status_page(engine, I915_GEM_HWS_INDEX); } static u32 -ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) +ring_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency) { - return intel_read_status_page(ring, I915_GEM_HWS_INDEX); + return intel_read_status_page(engine, I915_GEM_HWS_INDEX); } static void -ring_set_seqno(struct intel_engine_cs *ring, u32 seqno) +ring_set_seqno(struct intel_engine_cs *engine, u32 seqno) { - intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); + intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); } static u32 -pc_render_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency) +pc_render_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency) { - return ring->scratch.cpu_page[0]; + return engine->scratch.cpu_page[0]; } static void -pc_render_set_seqno(struct intel_engine_cs *ring, u32 seqno) +pc_render_set_seqno(struct intel_engine_cs *engine, u32 seqno) { - ring->scratch.cpu_page[0] = seqno; + engine->scratch.cpu_page[0] = seqno; } static bool -gen5_ring_get_irq(struct intel_engine_cs *ring) +gen5_ring_get_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; @@ -1602,30 +1607,30 @@ gen5_ring_get_irq(struct intel_engine_cs *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) - gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); + if (engine->irq_refcount++ == 0) + gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); spin_unlock_irqrestore(&dev_priv->irq_lock, flags); return true; } static void -gen5_ring_put_irq(struct intel_engine_cs *ring) +gen5_ring_put_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) - gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); + if (--engine->irq_refcount == 0) + gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); spin_unlock_irqrestore(&dev_priv->irq_lock, flags); } static bool -i9xx_ring_get_irq(struct intel_engine_cs *ring) +i9xx_ring_get_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; @@ -1633,8 +1638,8 @@ i9xx_ring_get_irq(struct intel_engine_cs *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { - dev_priv->irq_mask &= ~ring->irq_enable_mask; + if (engine->irq_refcount++ == 0) { + dev_priv->irq_mask &= ~engine->irq_enable_mask; I915_WRITE(IMR, dev_priv->irq_mask); POSTING_READ(IMR); } @@ -1644,15 +1649,15 @@ i9xx_ring_get_irq(struct intel_engine_cs *ring) } static void -i9xx_ring_put_irq(struct intel_engine_cs *ring) +i9xx_ring_put_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { - dev_priv->irq_mask |= ring->irq_enable_mask; + if (--engine->irq_refcount == 0) { + dev_priv->irq_mask |= engine->irq_enable_mask; I915_WRITE(IMR, dev_priv->irq_mask); POSTING_READ(IMR); } @@ -1660,9 +1665,9 @@ i9xx_ring_put_irq(struct intel_engine_cs *ring) } static bool -i8xx_ring_get_irq(struct intel_engine_cs *ring) +i8xx_ring_get_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; @@ -1670,8 +1675,8 @@ i8xx_ring_get_irq(struct intel_engine_cs *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { - dev_priv->irq_mask &= ~ring->irq_enable_mask; + if (engine->irq_refcount++ == 0) { + dev_priv->irq_mask &= ~engine->irq_enable_mask; I915_WRITE16(IMR, dev_priv->irq_mask); POSTING_READ16(IMR); } @@ -1681,15 +1686,15 @@ i8xx_ring_get_irq(struct intel_engine_cs *ring) } static void -i8xx_ring_put_irq(struct intel_engine_cs *ring) +i8xx_ring_put_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { - dev_priv->irq_mask |= ring->irq_enable_mask; + if (--engine->irq_refcount == 0) { + dev_priv->irq_mask |= engine->irq_enable_mask; I915_WRITE16(IMR, dev_priv->irq_mask); POSTING_READ16(IMR); } @@ -1735,9 +1740,9 @@ i9xx_add_request(struct drm_i915_gem_request *req) } static bool -gen6_ring_get_irq(struct intel_engine_cs *ring) +gen6_ring_get_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; @@ -1745,14 +1750,14 @@ gen6_ring_get_irq(struct intel_engine_cs *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { - if (HAS_L3_DPF(dev) && ring->id == RCS) - I915_WRITE_IMR(ring, - ~(ring->irq_enable_mask | + if (engine->irq_refcount++ == 0) { + if (HAS_L3_DPF(dev) && engine->id == RCS) + I915_WRITE_IMR(engine, + ~(engine->irq_enable_mask | GT_PARITY_ERROR(dev))); else - I915_WRITE_IMR(ring, ~ring->irq_enable_mask); - gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask); + I915_WRITE_IMR(engine, ~engine->irq_enable_mask); + gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); @@ -1760,27 +1765,27 @@ gen6_ring_get_irq(struct intel_engine_cs *ring) } static void -gen6_ring_put_irq(struct intel_engine_cs *ring) +gen6_ring_put_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { - if (HAS_L3_DPF(dev) && ring->id == RCS) - I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev)); + if (--engine->irq_refcount == 0) { + if (HAS_L3_DPF(dev) && engine->id == RCS) + I915_WRITE_IMR(engine, ~GT_PARITY_ERROR(dev)); else - I915_WRITE_IMR(ring, ~0); - gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask); + I915_WRITE_IMR(engine, ~0); + gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); } static bool -hsw_vebox_get_irq(struct intel_engine_cs *ring) +hsw_vebox_get_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; @@ -1788,9 +1793,9 @@ hsw_vebox_get_irq(struct intel_engine_cs *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { - I915_WRITE_IMR(ring, ~ring->irq_enable_mask); - gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask); + if (engine->irq_refcount++ == 0) { + I915_WRITE_IMR(engine, ~engine->irq_enable_mask); + gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); @@ -1798,24 +1803,24 @@ hsw_vebox_get_irq(struct intel_engine_cs *ring) } static void -hsw_vebox_put_irq(struct intel_engine_cs *ring) +hsw_vebox_put_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { - I915_WRITE_IMR(ring, ~0); - gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask); + if (--engine->irq_refcount == 0) { + I915_WRITE_IMR(engine, ~0); + gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); } static bool -gen8_ring_get_irq(struct intel_engine_cs *ring) +gen8_ring_get_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; @@ -1823,15 +1828,15 @@ gen8_ring_get_irq(struct intel_engine_cs *ring) return false; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (ring->irq_refcount++ == 0) { - if (HAS_L3_DPF(dev) && ring->id == RCS) { - I915_WRITE_IMR(ring, - ~(ring->irq_enable_mask | + if (engine->irq_refcount++ == 0) { + if (HAS_L3_DPF(dev) && engine->id == RCS) { + I915_WRITE_IMR(engine, + ~(engine->irq_enable_mask | GT_RENDER_L3_PARITY_ERROR_INTERRUPT)); } else { - I915_WRITE_IMR(ring, ~ring->irq_enable_mask); + I915_WRITE_IMR(engine, ~engine->irq_enable_mask); } - POSTING_READ(RING_IMR(ring->mmio_base)); + POSTING_READ(RING_IMR(engine->mmio_base)); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); @@ -1839,21 +1844,21 @@ gen8_ring_get_irq(struct intel_engine_cs *ring) } static void -gen8_ring_put_irq(struct intel_engine_cs *ring) +gen8_ring_put_irq(struct intel_engine_cs *engine) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; unsigned long flags; spin_lock_irqsave(&dev_priv->irq_lock, flags); - if (--ring->irq_refcount == 0) { - if (HAS_L3_DPF(dev) && ring->id == RCS) { - I915_WRITE_IMR(ring, + if (--engine->irq_refcount == 0) { + if (HAS_L3_DPF(dev) && engine->id == RCS) { + I915_WRITE_IMR(engine, ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT); } else { - I915_WRITE_IMR(ring, ~0); + I915_WRITE_IMR(engine, ~0); } - POSTING_READ(RING_IMR(ring->mmio_base)); + POSTING_READ(RING_IMR(engine->mmio_base)); } spin_unlock_irqrestore(&dev_priv->irq_lock, flags); } @@ -1967,40 +1972,40 @@ i915_dispatch_execbuffer(struct drm_i915_gem_request *req, return 0; } -static void cleanup_phys_status_page(struct intel_engine_cs *ring) +static void cleanup_phys_status_page(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = to_i915(ring->dev); + struct drm_i915_private *dev_priv = to_i915(engine->dev); if (!dev_priv->status_page_dmah) return; - drm_pci_free(ring->dev, dev_priv->status_page_dmah); - ring->status_page.page_addr = NULL; + drm_pci_free(engine->dev, dev_priv->status_page_dmah); + engine->status_page.page_addr = NULL; } -static void cleanup_status_page(struct intel_engine_cs *ring) +static void cleanup_status_page(struct intel_engine_cs *engine) { struct drm_i915_gem_object *obj; - obj = ring->status_page.obj; + obj = engine->status_page.obj; if (obj == NULL) return; kunmap(sg_page(obj->pages->sgl)); i915_gem_object_ggtt_unpin(obj); drm_gem_object_unreference(&obj->base); - ring->status_page.obj = NULL; + engine->status_page.obj = NULL; } -static int init_status_page(struct intel_engine_cs *ring) +static int init_status_page(struct intel_engine_cs *engine) { - struct drm_i915_gem_object *obj = ring->status_page.obj; + struct drm_i915_gem_object *obj = engine->status_page.obj; if (obj == NULL) { unsigned flags; int ret; - obj = i915_gem_alloc_object(ring->dev, 4096); + obj = i915_gem_alloc_object(engine->dev, 4096); if (obj == NULL) { DRM_ERROR("Failed to allocate status page\n"); return -ENOMEM; @@ -2011,7 +2016,7 @@ static int init_status_page(struct intel_engine_cs *ring) goto err_unref; flags = 0; - if (!HAS_LLC(ring->dev)) + if (!HAS_LLC(engine->dev)) /* On g33, we cannot place HWS above 256MiB, so * restrict its pinning to the low mappable arena. * Though this restriction is not documented for @@ -2030,32 +2035,32 @@ err_unref: return ret; } - ring->status_page.obj = obj; + engine->status_page.obj = obj; } - ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); - ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); - memset(ring->status_page.page_addr, 0, PAGE_SIZE); + engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj); + engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl)); + memset(engine->status_page.page_addr, 0, PAGE_SIZE); DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", - ring->name, ring->status_page.gfx_addr); + engine->name, engine->status_page.gfx_addr); return 0; } -static int init_phys_status_page(struct intel_engine_cs *ring) +static int init_phys_status_page(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; if (!dev_priv->status_page_dmah) { dev_priv->status_page_dmah = - drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE); + drm_pci_alloc(engine->dev, PAGE_SIZE, PAGE_SIZE); if (!dev_priv->status_page_dmah) return -ENOMEM; } - ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; - memset(ring->status_page.page_addr, 0, PAGE_SIZE); + engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; + memset(engine->status_page.page_addr, 0, PAGE_SIZE); return 0; } @@ -2218,37 +2223,38 @@ intel_ringbuffer_free(struct intel_ringbuffer *ring) } static int intel_init_ring_buffer(struct drm_device *dev, - struct intel_engine_cs *ring) + struct intel_engine_cs *engine) { struct intel_ringbuffer *ringbuf; int ret; - WARN_ON(ring->buffer); + WARN_ON(engine->buffer); - ring->dev = dev; - INIT_LIST_HEAD(&ring->active_list); - INIT_LIST_HEAD(&ring->request_list); - INIT_LIST_HEAD(&ring->execlist_queue); - INIT_LIST_HEAD(&ring->buffers); - i915_gem_batch_pool_init(dev, &ring->batch_pool); - memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno)); + engine->dev = dev; + INIT_LIST_HEAD(&engine->active_list); + INIT_LIST_HEAD(&engine->request_list); + INIT_LIST_HEAD(&engine->execlist_queue); + INIT_LIST_HEAD(&engine->buffers); + i915_gem_batch_pool_init(dev, &engine->batch_pool); + memset(engine->semaphore.sync_seqno, 0, + sizeof(engine->semaphore.sync_seqno)); - init_waitqueue_head(&ring->irq_queue); + init_waitqueue_head(&engine->irq_queue); - ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE); + ringbuf = intel_engine_create_ringbuffer(engine, 32 * PAGE_SIZE); if (IS_ERR(ringbuf)) { ret = PTR_ERR(ringbuf); goto error; } - ring->buffer = ringbuf; + engine->buffer = ringbuf; if (I915_NEED_GFX_HWS(dev)) { - ret = init_status_page(ring); + ret = init_status_page(engine); if (ret) goto error; } else { - WARN_ON(ring->id != RCS); - ret = init_phys_status_page(ring); + WARN_ON(engine->id != RCS); + ret = init_phys_status_page(engine); if (ret) goto error; } @@ -2256,58 +2262,58 @@ static int intel_init_ring_buffer(struct drm_device *dev, 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); + engine->name, ret); intel_destroy_ringbuffer_obj(ringbuf); goto error; } - ret = i915_cmd_parser_init_ring(ring); + ret = i915_cmd_parser_init_ring(engine); if (ret) goto error; return 0; error: - intel_cleanup_ring_buffer(ring); + intel_cleanup_ring_buffer(engine); return ret; } -void intel_cleanup_ring_buffer(struct intel_engine_cs *ring) +void intel_cleanup_ring_buffer(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv; - if (!intel_ring_initialized(ring)) + if (!intel_ring_initialized(engine)) return; - dev_priv = to_i915(ring->dev); + dev_priv = to_i915(engine->dev); - if (ring->buffer) { - intel_stop_ring_buffer(ring); - WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); + if (engine->buffer) { + intel_stop_ring_buffer(engine); + WARN_ON(!IS_GEN2(engine->dev) && (I915_READ_MODE(engine) & MODE_IDLE) == 0); - intel_unpin_ringbuffer_obj(ring->buffer); - intel_ringbuffer_free(ring->buffer); - ring->buffer = NULL; + intel_unpin_ringbuffer_obj(engine->buffer); + intel_ringbuffer_free(engine->buffer); + engine->buffer = NULL; } - if (ring->cleanup) - ring->cleanup(ring); + if (engine->cleanup) + engine->cleanup(engine); - if (I915_NEED_GFX_HWS(ring->dev)) { - cleanup_status_page(ring); + if (I915_NEED_GFX_HWS(engine->dev)) { + cleanup_status_page(engine); } else { - WARN_ON(ring->id != RCS); - cleanup_phys_status_page(ring); + WARN_ON(engine->id != RCS); + cleanup_phys_status_page(engine); } - i915_cmd_parser_fini_ring(ring); - i915_gem_batch_pool_fini(&ring->batch_pool); - ring->dev = NULL; + i915_cmd_parser_fini_ring(engine); + i915_gem_batch_pool_fini(&engine->batch_pool); + engine->dev = NULL; } -static int ring_wait_for_space(struct intel_engine_cs *ring, int n) +static int ring_wait_for_space(struct intel_engine_cs *engine, int n) { - struct intel_ringbuffer *ringbuf = ring->buffer; + struct intel_ringbuffer *ringbuf = engine->buffer; struct drm_i915_gem_request *request; unsigned space; int ret; @@ -2318,14 +2324,14 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n) /* The whole point of reserving space is to not wait! */ WARN_ON(ringbuf->reserved_in_use); - list_for_each_entry(request, &ring->request_list, list) { + list_for_each_entry(request, &engine->request_list, list) { space = __intel_ring_space(request->postfix, ringbuf->tail, ringbuf->size); if (space >= n) break; } - if (WARN_ON(&request->list == &ring->request_list)) + if (WARN_ON(&request->list == &engine->request_list)) return -ENOSPC; ret = i915_wait_request(request); @@ -2350,22 +2356,22 @@ static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf) intel_ring_update_space(ringbuf); } -int intel_ring_idle(struct intel_engine_cs *ring) +int intel_ring_idle(struct intel_engine_cs *engine) { struct drm_i915_gem_request *req; /* Wait upon the last request to be completed */ - if (list_empty(&ring->request_list)) + if (list_empty(&engine->request_list)) return 0; - req = list_entry(ring->request_list.prev, - struct drm_i915_gem_request, - list); + req = list_entry(engine->request_list.prev, + struct drm_i915_gem_request, + list); /* Make sure we do not trigger any retires */ return __i915_wait_request(req, - atomic_read(&to_i915(ring->dev)->gpu_error.reset_counter), - to_i915(ring->dev)->mm.interruptible, + atomic_read(&to_i915(engine->dev)->gpu_error.reset_counter), + to_i915(engine->dev)->mm.interruptible, NULL, NULL); } @@ -2437,9 +2443,9 @@ void intel_ring_reserved_space_end(struct intel_ringbuffer *ringbuf) ringbuf->reserved_in_use = false; } -static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes) +static int __intel_ring_prepare(struct intel_engine_cs *engine, int bytes) { - struct intel_ringbuffer *ringbuf = ring->buffer; + struct intel_ringbuffer *ringbuf = engine->buffer; int remain_usable = ringbuf->effective_size - ringbuf->tail; int remain_actual = ringbuf->size - ringbuf->tail; int ret, total_bytes, wait_bytes = 0; @@ -2473,7 +2479,7 @@ static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes) } if (wait_bytes) { - ret = ring_wait_for_space(ring, wait_bytes); + ret = ring_wait_for_space(engine, wait_bytes); if (unlikely(ret)) return ret; @@ -2531,26 +2537,26 @@ int intel_ring_cacheline_align(struct drm_i915_gem_request *req) return 0; } -void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno) +void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno) { - struct drm_device *dev = ring->dev; + struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) { - I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); - I915_WRITE(RING_SYNC_1(ring->mmio_base), 0); + I915_WRITE(RING_SYNC_0(engine->mmio_base), 0); + I915_WRITE(RING_SYNC_1(engine->mmio_base), 0); if (HAS_VEBOX(dev)) - I915_WRITE(RING_SYNC_2(ring->mmio_base), 0); + I915_WRITE(RING_SYNC_2(engine->mmio_base), 0); } - ring->set_seqno(ring, seqno); - ring->hangcheck.seqno = seqno; + engine->set_seqno(engine, seqno); + engine->hangcheck.seqno = seqno; } -static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring, +static void gen6_bsd_ring_write_tail(struct intel_engine_cs *engine, u32 value) { - struct drm_i915_private *dev_priv = ring->dev->dev_private; + struct drm_i915_private *dev_priv = engine->dev->dev_private; /* Every tail move must follow the sequence below */ @@ -2570,8 +2576,8 @@ static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring, DRM_ERROR("timed out waiting for the BSD ring to wake up\n"); /* Now that the ring is fully powered up, update the tail */ - I915_WRITE_TAIL(ring, value); - POSTING_READ(RING_TAIL(ring->mmio_base)); + I915_WRITE_TAIL(engine, value); + POSTING_READ(RING_TAIL(engine->mmio_base)); /* Let the ring send IDLE messages to the GT again, * and so let it sleep to conserve power when idle. @@ -3157,17 +3163,17 @@ intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) } void -intel_stop_ring_buffer(struct intel_engine_cs *ring) +intel_stop_ring_buffer(struct intel_engine_cs *engine) { int ret; - if (!intel_ring_initialized(ring)) + if (!intel_ring_initialized(engine)) return; - ret = intel_ring_idle(ring); - if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error)) + ret = intel_ring_idle(engine); + if (ret && !i915_reset_in_progress(&to_i915(engine->dev)->gpu_error)) DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", - ring->name, ret); + engine->name, ret); - stop_ring(ring); + stop_ring(engine); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 24efb57..4848463 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -355,19 +355,19 @@ struct intel_engine_cs { }; static inline bool -intel_ring_initialized(struct intel_engine_cs *ring) +intel_ring_initialized(struct intel_engine_cs *engine) { - return ring->dev != NULL; + return engine->dev != NULL; } static inline unsigned -intel_ring_flag(struct intel_engine_cs *ring) +intel_ring_flag(struct intel_engine_cs *engine) { - return 1 << ring->id; + return 1 << engine->id; } static inline u32 -intel_ring_sync_index(struct intel_engine_cs *ring, +intel_ring_sync_index(struct intel_engine_cs *engine, struct intel_engine_cs *other) { int idx; @@ -380,7 +380,7 @@ intel_ring_sync_index(struct intel_engine_cs *ring, * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs; */ - idx = (other - ring) - 1; + idx = (other - engine) - 1; if (idx < 0) idx += I915_NUM_RINGS; @@ -388,26 +388,26 @@ intel_ring_sync_index(struct intel_engine_cs *ring, } static inline void -intel_flush_status_page(struct intel_engine_cs *ring, int reg) +intel_flush_status_page(struct intel_engine_cs *engine, int reg) { - drm_clflush_virt_range(&ring->status_page.page_addr[reg], + drm_clflush_virt_range(&engine->status_page.page_addr[reg], sizeof(uint32_t)); } static inline u32 -intel_read_status_page(struct intel_engine_cs *ring, +intel_read_status_page(struct intel_engine_cs *engine, int reg) { /* Ensure that the compiler doesn't optimize away the load. */ barrier(); - return ring->status_page.page_addr[reg]; + return engine->status_page.page_addr[reg]; } static inline void -intel_write_status_page(struct intel_engine_cs *ring, +intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value) { - ring->status_page.page_addr[reg] = value; + engine->status_page.page_addr[reg] = value; } /* @@ -438,42 +438,42 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf); void intel_ringbuffer_free(struct intel_ringbuffer *ring); -void intel_stop_ring_buffer(struct intel_engine_cs *ring); -void intel_cleanup_ring_buffer(struct intel_engine_cs *ring); +void intel_stop_ring_buffer(struct intel_engine_cs *engine); +void intel_cleanup_ring_buffer(struct intel_engine_cs *engine); int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request); int __must_check intel_ring_begin(struct drm_i915_gem_request *req, int n); int __must_check intel_ring_cacheline_align(struct drm_i915_gem_request *req); -static inline void intel_ring_emit(struct intel_engine_cs *ring, +static inline void intel_ring_emit(struct intel_engine_cs *engine, u32 data) { - struct intel_ringbuffer *ringbuf = ring->buffer; + struct intel_ringbuffer *ringbuf = engine->buffer; iowrite32(data, ringbuf->virtual_start + ringbuf->tail); ringbuf->tail += 4; } -static inline void intel_ring_emit_reg(struct intel_engine_cs *ring, +static inline void intel_ring_emit_reg(struct intel_engine_cs *engine, i915_reg_t reg) { - intel_ring_emit(ring, i915_mmio_reg_offset(reg)); + intel_ring_emit(engine, i915_mmio_reg_offset(reg)); } -static inline void intel_ring_advance(struct intel_engine_cs *ring) +static inline void intel_ring_advance(struct intel_engine_cs *engine) { - struct intel_ringbuffer *ringbuf = ring->buffer; + struct intel_ringbuffer *ringbuf = engine->buffer; ringbuf->tail &= ringbuf->size - 1; } int __intel_ring_space(int head, int tail, int size); void intel_ring_update_space(struct intel_ringbuffer *ringbuf); int intel_ring_space(struct intel_ringbuffer *ringbuf); -bool intel_ring_stopped(struct intel_engine_cs *ring); +bool intel_ring_stopped(struct intel_engine_cs *engine); -int __must_check intel_ring_idle(struct intel_engine_cs *ring); -void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno); +int __must_check intel_ring_idle(struct intel_engine_cs *engine); +void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno); int intel_ring_flush_all_caches(struct drm_i915_gem_request *req); int intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req); -void intel_fini_pipe_control(struct intel_engine_cs *ring); -int intel_init_pipe_control(struct intel_engine_cs *ring); +void intel_fini_pipe_control(struct intel_engine_cs *engine); +int intel_init_pipe_control(struct intel_engine_cs *engine); int intel_init_render_ring_buffer(struct drm_device *dev); int intel_init_bsd_ring_buffer(struct drm_device *dev); @@ -481,9 +481,9 @@ int intel_init_bsd2_ring_buffer(struct drm_device *dev); int intel_init_blt_ring_buffer(struct drm_device *dev); int intel_init_vebox_ring_buffer(struct drm_device *dev); -u64 intel_ring_get_active_head(struct intel_engine_cs *ring); +u64 intel_ring_get_active_head(struct intel_engine_cs *engine); -int init_workarounds_ring(struct intel_engine_cs *ring); +int init_workarounds_ring(struct intel_engine_cs *engine); static inline u32 intel_ring_get_tail(struct intel_ringbuffer *ringbuf) { -- cgit v0.10.2 From 4a570db57c051644093c20eea934ee02b6ea84fd Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 16 Mar 2016 11:00:38 +0000 Subject: drm/i915: Rename intel_engine_cs struct members below and a couple manual fixups. @@ identifier I, J; @@ struct I { ... - struct intel_engine_cs *J; + struct intel_engine_cs *engine; ... } @@ identifier I, J; @@ struct I { ... - struct intel_engine_cs J; + struct intel_engine_cs engine; ... } @@ struct drm_i915_private *d; @@ ( - d->ring + d->engine ) @@ struct i915_execbuffer_params *p; @@ ( - p->ring + p->engine ) @@ struct intel_ringbuffer *r; @@ ( - r->ring + r->engine ) @@ struct drm_i915_gem_request *req; @@ ( - req->ring + req->engine ) v2: Script missed the tracepoint code - fixed up by hand. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 164e143..a71ffaa 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -984,7 +984,7 @@ static int i915_hws_info(struct seq_file *m, void *data) const u32 *hws; int i; - engine = &dev_priv->ring[(uintptr_t)node->info_ent->data]; + engine = &dev_priv->engine[(uintptr_t)node->info_ent->data]; hws = engine->status_page.page_addr; if (hws == NULL) return 0; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 4aa3db6..19f605b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -87,16 +87,16 @@ static int i915_getparam(struct drm_device *dev, void *data, value = 1; break; case I915_PARAM_HAS_BSD: - value = intel_ring_initialized(&dev_priv->ring[VCS]); + value = intel_ring_initialized(&dev_priv->engine[VCS]); break; case I915_PARAM_HAS_BLT: - value = intel_ring_initialized(&dev_priv->ring[BCS]); + value = intel_ring_initialized(&dev_priv->engine[BCS]); break; case I915_PARAM_HAS_VEBOX: - value = intel_ring_initialized(&dev_priv->ring[VECS]); + value = intel_ring_initialized(&dev_priv->engine[VECS]); break; case I915_PARAM_HAS_BSD2: - value = intel_ring_initialized(&dev_priv->ring[VCS2]); + value = intel_ring_initialized(&dev_priv->engine[VCS2]); break; case I915_PARAM_HAS_RELAXED_FENCING: value = 1; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8d87242..0187a56 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1652,7 +1652,7 @@ struct i915_execbuffer_params { uint32_t dispatch_flags; uint32_t args_batch_start_offset; uint64_t batch_obj_vm_offset; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct drm_i915_gem_object *batch_obj; struct intel_context *ctx; struct drm_i915_gem_request *request; @@ -1704,7 +1704,7 @@ struct drm_i915_private { wait_queue_head_t gmbus_wait_queue; struct pci_dev *bridge_dev; - struct intel_engine_cs ring[I915_NUM_RINGS]; + struct intel_engine_cs engine[I915_NUM_RINGS]; struct drm_i915_gem_object *semaphore_obj; uint32_t last_seqno, next_seqno; @@ -1969,7 +1969,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) /* Iterate over initialised rings */ #define for_each_ring(ring__, dev_priv__, i__) \ for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \ - for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))) + for_each_if ((((ring__) = &(dev_priv__)->engine[(i__)]), intel_ring_initialized((ring__)))) enum hdmi_force_audio { HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ @@ -2184,7 +2184,7 @@ struct drm_i915_gem_request { /** On Which ring this request was generated */ struct drm_i915_private *i915; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; /** GEM sequence number associated with the previous request, * when the HWS breadcrumb is equal to this the GPU is processing @@ -2279,7 +2279,7 @@ i915_gem_request_get_seqno(struct drm_i915_gem_request *req) static inline struct intel_engine_cs * i915_gem_request_get_ring(struct drm_i915_gem_request *req) { - return req ? req->ring : NULL; + return req ? req->engine : NULL; } static inline struct drm_i915_gem_request * @@ -2293,7 +2293,7 @@ i915_gem_request_reference(struct drm_i915_gem_request *req) static inline void i915_gem_request_unreference(struct drm_i915_gem_request *req) { - WARN_ON(!mutex_is_locked(&req->ring->dev->struct_mutex)); + WARN_ON(!mutex_is_locked(&req->engine->dev->struct_mutex)); kref_put(&req->ref, i915_gem_request_free); } @@ -2305,7 +2305,7 @@ i915_gem_request_unreference__unlocked(struct drm_i915_gem_request *req) if (!req) return; - dev = req->ring->dev; + dev = req->engine->dev; if (kref_put_mutex(&req->ref, i915_gem_request_free, &dev->struct_mutex)) mutex_unlock(&dev->struct_mutex); } @@ -2949,14 +2949,14 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2) static inline bool i915_gem_request_started(struct drm_i915_gem_request *req, bool lazy_coherency) { - u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency); + u32 seqno = req->engine->get_seqno(req->engine, lazy_coherency); return i915_seqno_passed(seqno, req->previous_seqno); } static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req, bool lazy_coherency) { - u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency); + u32 seqno = req->engine->get_seqno(req->engine, lazy_coherency); return i915_seqno_passed(seqno, req->seqno); } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1119b8f..cd68a86 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1193,7 +1193,7 @@ static int __i915_spin_request(struct drm_i915_gem_request *req, int state) * takes to sleep on a request, on the order of a microsecond. */ - if (req->ring->irq_refcount) + if (req->engine->irq_refcount) return -EBUSY; /* Only spin if we know the GPU is processing this request */ @@ -1381,7 +1381,7 @@ int i915_gem_request_add_to_client(struct drm_i915_gem_request *req, if (req->file_priv) return -EINVAL; - dev_private = req->ring->dev->dev_private; + dev_private = req->engine->dev->dev_private; file_priv = file->driver_priv; spin_lock(&file_priv->mm.lock); @@ -1434,7 +1434,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) static void __i915_gem_request_retire__upto(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_i915_gem_request *tmp; lockdep_assert_held(&engine->dev->struct_mutex); @@ -1466,7 +1466,7 @@ i915_wait_request(struct drm_i915_gem_request *req) BUG_ON(req == NULL); - dev = req->ring->dev; + dev = req->engine->dev; dev_priv = dev->dev_private; interruptible = dev_priv->mm.interruptible; @@ -1505,7 +1505,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, if (ret) return ret; - i = obj->last_write_req->ring->id; + i = obj->last_write_req->engine->id; if (obj->last_read_req[i] == obj->last_write_req) i915_gem_object_retire__read(obj, i); else @@ -1532,7 +1532,7 @@ static void i915_gem_object_retire_request(struct drm_i915_gem_object *obj, struct drm_i915_gem_request *req) { - int ring = req->ring->id; + int ring = req->engine->id; if (obj->last_read_req[ring] == req) i915_gem_object_retire__read(obj, ring); @@ -2423,7 +2423,7 @@ static void i915_gem_object_retire__write(struct drm_i915_gem_object *obj) { RQ_BUG_ON(obj->last_write_req == NULL); - RQ_BUG_ON(!(obj->active & intel_ring_flag(obj->last_write_req->ring))); + RQ_BUG_ON(!(obj->active & intel_ring_flag(obj->last_write_req->engine))); i915_gem_request_assign(&obj->last_write_req, NULL); intel_fb_obj_flush(obj, true, ORIGIN_CS); @@ -2440,7 +2440,7 @@ i915_gem_object_retire__read(struct drm_i915_gem_object *obj, int ring) list_del_init(&obj->ring_list[ring]); i915_gem_request_assign(&obj->last_read_req[ring], NULL); - if (obj->last_write_req && obj->last_write_req->ring->id == ring) + if (obj->last_write_req && obj->last_write_req->engine->id == ring) i915_gem_object_retire__write(obj); obj->active &= ~(1 << ring); @@ -2551,7 +2551,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, if (WARN_ON(request == NULL)) return; - engine = request->ring; + engine = request->engine; dev_priv = engine->dev->dev_private; ringbuf = request->ringbuf; @@ -2680,7 +2680,7 @@ void i915_gem_request_free(struct kref *req_ref) if (ctx) { if (i915.enable_execlists && ctx != req->i915->kernel_context) - intel_lr_context_unpin(ctx, req->ring); + intel_lr_context_unpin(ctx, req->engine); i915_gem_context_unreference(ctx); } @@ -2712,7 +2712,7 @@ __i915_gem_request_alloc(struct intel_engine_cs *engine, kref_init(&req->ref); req->i915 = dev_priv; - req->ring = engine; + req->engine = engine; req->ctx = ctx; i915_gem_context_reference(req->ctx); @@ -4364,10 +4364,10 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, req = obj->last_read_req[i]; if (req) - args->busy |= 1 << (16 + req->ring->exec_id); + args->busy |= 1 << (16 + req->engine->exec_id); } if (obj->last_write_req) - args->busy |= obj->last_write_req->ring->exec_id; + args->busy |= obj->last_write_req->engine->exec_id; } unref: @@ -4697,7 +4697,7 @@ err: int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; u32 *remap_info = dev_priv->l3_parity.remap_info[slice]; @@ -4814,13 +4814,13 @@ int i915_gem_init_rings(struct drm_device *dev) return 0; cleanup_vebox_ring: - intel_cleanup_ring_buffer(&dev_priv->ring[VECS]); + intel_cleanup_ring_buffer(&dev_priv->engine[VECS]); cleanup_blt_ring: - intel_cleanup_ring_buffer(&dev_priv->ring[BCS]); + intel_cleanup_ring_buffer(&dev_priv->engine[BCS]); cleanup_bsd_ring: - intel_cleanup_ring_buffer(&dev_priv->ring[VCS]); + intel_cleanup_ring_buffer(&dev_priv->engine[VCS]); cleanup_render_ring: - intel_cleanup_ring_buffer(&dev_priv->ring[RCS]); + intel_cleanup_ring_buffer(&dev_priv->engine[RCS]); return ret; } @@ -5056,7 +5056,7 @@ i915_gem_load_init(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->mm.bound_list); INIT_LIST_HEAD(&dev_priv->mm.fence_list); for (i = 0; i < I915_NUM_RINGS; i++) - init_ring_lists(&dev_priv->ring[i]); + init_ring_lists(&dev_priv->engine[i]); for (i = 0; i < I915_MAX_NUM_FENCES; i++) INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); INIT_DELAYED_WORK(&dev_priv->mm.retire_work, diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 44f5829..6c325e4 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -346,7 +346,7 @@ void i915_gem_context_reset(struct drm_device *dev) } for (i = 0; i < I915_NUM_RINGS; i++) { - struct intel_engine_cs *engine = &dev_priv->ring[i]; + struct intel_engine_cs *engine = &dev_priv->engine[i]; if (engine->last_context) { i915_gem_context_unpin(engine->last_context, engine); @@ -421,13 +421,13 @@ void i915_gem_context_fini(struct drm_device *dev) * to default context. So we need to unreference the base object once * to offset the do_switch part, so that i915_gem_context_unreference() * can then free the base object correctly. */ - WARN_ON(!dev_priv->ring[RCS].last_context); + WARN_ON(!dev_priv->engine[RCS].last_context); i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state); } for (i = I915_NUM_RINGS; --i >= 0;) { - struct intel_engine_cs *engine = &dev_priv->ring[i]; + struct intel_engine_cs *engine = &dev_priv->engine[i]; if (engine->last_context) { i915_gem_context_unpin(engine->last_context, engine); @@ -441,7 +441,7 @@ void i915_gem_context_fini(struct drm_device *dev) int i915_gem_context_enable(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; if (i915.enable_execlists) { @@ -510,7 +510,7 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) static inline int mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; u32 flags = hw_flags | MI_MM_SPACE_GTT; const int num_rings = /* Use an extended w/a on ivb+ if signalling from other rings */ @@ -625,7 +625,7 @@ needs_pd_load_pre(struct intel_engine_cs *engine, struct intel_context *to) if (INTEL_INFO(engine->dev)->gen < 8) return true; - if (engine != &dev_priv->ring[RCS]) + if (engine != &dev_priv->engine[RCS]) return true; return false; @@ -643,7 +643,7 @@ needs_pd_load_post(struct intel_engine_cs *engine, struct intel_context *to, if (!IS_GEN8(engine->dev)) return false; - if (engine != &dev_priv->ring[RCS]) + if (engine != &dev_priv->engine[RCS]) return false; if (hw_flags & MI_RESTORE_INHIBIT) @@ -655,14 +655,14 @@ needs_pd_load_post(struct intel_engine_cs *engine, struct intel_context *to, static int do_switch(struct drm_i915_gem_request *req) { struct intel_context *to = req->ctx; - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_i915_private *dev_priv = engine->dev->dev_private; struct intel_context *from = engine->last_context; u32 hw_flags = 0; bool uninitialized = false; int ret, i; - if (from != NULL && engine == &dev_priv->ring[RCS]) { + if (from != NULL && engine == &dev_priv->engine[RCS]) { BUG_ON(from->legacy_hw_ctx.rcs_state == NULL); BUG_ON(!i915_gem_obj_is_pinned(from->legacy_hw_ctx.rcs_state)); } @@ -671,7 +671,7 @@ static int do_switch(struct drm_i915_gem_request *req) return 0; /* Trying to pin first makes error handling easier. */ - if (engine == &dev_priv->ring[RCS]) { + if (engine == &dev_priv->engine[RCS]) { ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state, get_context_alignment(engine->dev), 0); @@ -700,7 +700,7 @@ static int do_switch(struct drm_i915_gem_request *req) to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(engine); } - if (engine != &dev_priv->ring[RCS]) { + if (engine != &dev_priv->engine[RCS]) { if (from) i915_gem_context_unreference(from); goto done; @@ -828,7 +828,7 @@ unpin_out: */ int i915_switch_context(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_i915_private *dev_priv = engine->dev->dev_private; WARN_ON(i915.enable_execlists); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index f94d756..bb1ed8c 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -942,7 +942,7 @@ static int i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req, struct list_head *vmas) { - const unsigned other_rings = ~intel_ring_flag(req->ring); + const unsigned other_rings = ~intel_ring_flag(req->engine); struct i915_vma *vma; uint32_t flush_domains = 0; bool flush_chipset = false; @@ -952,7 +952,7 @@ i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req, struct drm_i915_gem_object *obj = vma->obj; if (obj->active & other_rings) { - ret = i915_gem_object_sync(obj, req->ring, &req); + ret = i915_gem_object_sync(obj, req->engine, &req); if (ret) return ret; } @@ -964,7 +964,7 @@ i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req, } if (flush_chipset) - i915_gem_chipset_flush(req->ring->dev); + i915_gem_chipset_flush(req->engine->dev); if (flush_domains & I915_GEM_DOMAIN_GTT) wmb(); @@ -1140,7 +1140,7 @@ void i915_gem_execbuffer_retire_commands(struct i915_execbuffer_params *params) { /* Unconditionally force add_request to emit a full flush. */ - params->ring->gpu_caches_dirty = true; + params->engine->gpu_caches_dirty = true; /* Add a breadcrumb for the completion of the batch buffer */ __i915_add_request(params->request, params->batch_obj, true); @@ -1150,11 +1150,11 @@ static int i915_reset_gen7_sol_offsets(struct drm_device *dev, struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_i915_private *dev_priv = dev->dev_private; int ret, i; - if (!IS_GEN7(dev) || engine != &dev_priv->ring[RCS]) { + if (!IS_GEN7(dev) || engine != &dev_priv->engine[RCS]) { DRM_DEBUG("sol reset is gen7/rcs only\n"); return -EINVAL; } @@ -1233,7 +1233,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, struct list_head *vmas) { struct drm_device *dev = params->dev; - struct intel_engine_cs *engine = params->ring; + struct intel_engine_cs *engine = params->engine; struct drm_i915_private *dev_priv = dev->dev_private; u64 exec_start, exec_len; int instp_mode; @@ -1257,7 +1257,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, case I915_EXEC_CONSTANTS_REL_GENERAL: case I915_EXEC_CONSTANTS_ABSOLUTE: case I915_EXEC_CONSTANTS_REL_SURFACE: - if (instp_mode != 0 && engine != &dev_priv->ring[RCS]) { + if (instp_mode != 0 && engine != &dev_priv->engine[RCS]) { DRM_DEBUG("non-0 rel constants mode on non-RCS\n"); return -EINVAL; } @@ -1284,7 +1284,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params, return -EINVAL; } - if (engine == &dev_priv->ring[RCS] && + if (engine == &dev_priv->engine[RCS] && instp_mode != dev_priv->relative_constants_mode) { ret = intel_ring_begin(params->request, 4); if (ret) @@ -1412,9 +1412,9 @@ eb_select_ring(struct drm_i915_private *dev_priv, return -EINVAL; } - *ring = &dev_priv->ring[_VCS(bsd_idx)]; + *ring = &dev_priv->engine[_VCS(bsd_idx)]; } else { - *ring = &dev_priv->ring[user_ring_map[user_ring_id]]; + *ring = &dev_priv->engine[user_ring_map[user_ring_id]]; } if (!intel_ring_initialized(*ring)) { @@ -1632,7 +1632,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, */ params->dev = dev; params->file = file; - params->ring = engine; + params->engine = engine; params->dispatch_flags = dispatch_flags; params->batch_obj = batch_obj; params->ctx = ctx; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 1bc7779..ab54396 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -658,7 +658,7 @@ static int gen8_write_pdp(struct drm_i915_gem_request *req, unsigned entry, dma_addr_t addr) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; BUG_ON(entry >= 4); @@ -1650,7 +1650,7 @@ static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt) static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt, struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; /* NB: TLBs must be flushed and invalidated before a switch */ @@ -1676,7 +1676,7 @@ static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt, static int vgpu_mm_switch(struct i915_hw_ppgtt *ppgtt, struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev); I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G); @@ -1687,7 +1687,7 @@ static int vgpu_mm_switch(struct i915_hw_ppgtt *ppgtt, static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt, struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; /* NB: TLBs must be flushed and invalidated before a switch */ @@ -1720,7 +1720,7 @@ static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt, static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt, struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_device *dev = ppgtt->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -2192,7 +2192,7 @@ int i915_ppgtt_init_hw(struct drm_device *dev) int i915_ppgtt_init_ring(struct drm_i915_gem_request *req) { - struct drm_i915_private *dev_priv = req->ring->dev->dev_private; + struct drm_i915_private *dev_priv = req->engine->dev->dev_private; struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; if (i915.enable_execlists) @@ -2309,7 +2309,7 @@ void i915_check_and_clear_faults(struct drm_device *dev) fault_reg & ~RING_FAULT_VALID); } } - POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS])); + POSTING_READ(RING_FAULT_REG(&dev_priv->engine[RCS])); } static void i915_ggtt_flush(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index b21f72e..71611bf 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -198,21 +198,21 @@ int i915_gem_render_state_init(struct drm_i915_gem_request *req) struct render_state so; int ret; - ret = i915_gem_render_state_prepare(req->ring, &so); + ret = i915_gem_render_state_prepare(req->engine, &so); if (ret) return ret; if (so.rodata == NULL) return 0; - ret = req->ring->dispatch_execbuffer(req, so.ggtt_offset, + ret = req->engine->dispatch_execbuffer(req, so.ggtt_offset, so.rodata->batch_items * 4, I915_DISPATCH_SECURE); if (ret) goto out; if (so.aux_batch_size > 8) { - ret = req->ring->dispatch_execbuffer(req, + ret = req->engine->dispatch_execbuffer(req, (so.ggtt_offset + so.aux_batch_offset), so.aux_batch_size, diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 029ed40..a73f705 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -431,7 +431,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, for (i = 0; i < ARRAY_SIZE(error->ring); i++) { obj = error->ring[i].batchbuffer; if (obj) { - err_puts(m, dev_priv->ring[i].name); + err_puts(m, dev_priv->engine[i].name); if (error->ring[i].pid != -1) err_printf(m, " (submitted by %s [%d])", error->ring[i].comm, @@ -445,14 +445,14 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, obj = error->ring[i].wa_batchbuffer; if (obj) { err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n", - dev_priv->ring[i].name, + dev_priv->engine[i].name, lower_32_bits(obj->gtt_offset)); print_error_obj(m, obj); } if (error->ring[i].num_requests) { err_printf(m, "%s --- %d requests\n", - dev_priv->ring[i].name, + dev_priv->engine[i].name, error->ring[i].num_requests); for (j = 0; j < error->ring[i].num_requests; j++) { err_printf(m, " seqno 0x%08x, emitted %ld, tail 0x%08x\n", @@ -464,7 +464,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if ((obj = error->ring[i].ringbuffer)) { err_printf(m, "%s --- ringbuffer = 0x%08x\n", - dev_priv->ring[i].name, + dev_priv->engine[i].name, lower_32_bits(obj->gtt_offset)); print_error_obj(m, obj); } @@ -478,7 +478,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, hws_page = &obj->pages[LRC_PPHWSP_PN][0]; } err_printf(m, "%s --- HW Status = 0x%08llx\n", - dev_priv->ring[i].name, hws_offset); + dev_priv->engine[i].name, hws_offset); offset = 0; for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { err_printf(m, "[%04x] %08x %08x %08x %08x\n", @@ -495,12 +495,12 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if (obj) { u64 wa_ctx_offset = obj->gtt_offset; u32 *wa_ctx_page = &obj->pages[0][0]; - struct intel_engine_cs *engine = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->engine[RCS]; u32 wa_ctx_size = (engine->wa_ctx.indirect_ctx.size + engine->wa_ctx.per_ctx.size); err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n", - dev_priv->ring[i].name, wa_ctx_offset); + dev_priv->engine[i].name, wa_ctx_offset); offset = 0; for (elt = 0; elt < wa_ctx_size; elt += 4) { err_printf(m, "[%04x] %08x %08x %08x %08x\n", @@ -515,7 +515,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, if ((obj = error->ring[i].ctx)) { err_printf(m, "%s --- HW Context = 0x%08x\n", - dev_priv->ring[i].name, + dev_priv->engine[i].name, lower_32_bits(obj->gtt_offset)); print_error_obj(m, obj); } @@ -1020,7 +1020,7 @@ static void i915_gem_record_rings(struct drm_device *dev, int i, count; for (i = 0; i < I915_NUM_RINGS; i++) { - struct intel_engine_cs *engine = &dev_priv->ring[i]; + struct intel_engine_cs *engine = &dev_priv->engine[i]; struct intel_ringbuffer *rbuf; error->ring[i].pid = -1; diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 15a4beb..ed4f076 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -542,11 +542,12 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc, wq_len = sizeof(struct guc_wq_item) / sizeof(u32) - 1; wqi->header = WQ_TYPE_INORDER | (wq_len << WQ_LEN_SHIFT) | - (rq->ring->guc_id << WQ_TARGET_SHIFT) | + (rq->engine->guc_id << WQ_TARGET_SHIFT) | WQ_NO_WCFLUSH_WAIT; /* The GuC wants only the low-order word of the context descriptor */ - wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, rq->ring); + wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, + rq->engine); /* The GuC firmware wants the tail index in QWords, not bytes */ tail = rq->ringbuf->tail >> 3; @@ -569,7 +570,7 @@ int i915_guc_submit(struct i915_guc_client *client, struct drm_i915_gem_request *rq) { struct intel_guc *guc = client->guc; - unsigned int engine_id = rq->ring->guc_id; + unsigned int engine_id = rq->engine->guc_id; int q_ret, b_ret; q_ret = guc_add_workqueue_item(client, rq); @@ -867,7 +868,7 @@ static void guc_create_ads(struct intel_guc *guc) * so its address won't change after we've told the GuC where * to find it. */ - engine = &dev_priv->ring[RCS]; + engine = &dev_priv->engine[RCS]; ads->golden_context_lrca = engine->status_page.gfx_addr; for_each_ring(engine, dev_priv, i) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 6465896..6b7bee5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1291,9 +1291,9 @@ static void ilk_gt_irq_handler(struct drm_device *dev, { if (gt_iir & (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)) - notify_ring(&dev_priv->ring[RCS]); + notify_ring(&dev_priv->engine[RCS]); if (gt_iir & ILK_BSD_USER_INTERRUPT) - notify_ring(&dev_priv->ring[VCS]); + notify_ring(&dev_priv->engine[VCS]); } static void snb_gt_irq_handler(struct drm_device *dev, @@ -1303,11 +1303,11 @@ static void snb_gt_irq_handler(struct drm_device *dev, if (gt_iir & (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)) - notify_ring(&dev_priv->ring[RCS]); + notify_ring(&dev_priv->engine[RCS]); if (gt_iir & GT_BSD_USER_INTERRUPT) - notify_ring(&dev_priv->ring[VCS]); + notify_ring(&dev_priv->engine[VCS]); if (gt_iir & GT_BLT_USER_INTERRUPT) - notify_ring(&dev_priv->ring[BCS]); + notify_ring(&dev_priv->engine[BCS]); if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | GT_BSD_CS_ERROR_INTERRUPT | @@ -1338,11 +1338,11 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv, I915_WRITE_FW(GEN8_GT_IIR(0), iir); ret = IRQ_HANDLED; - gen8_cs_irq_handler(&dev_priv->ring[RCS], - iir, GEN8_RCS_IRQ_SHIFT); + gen8_cs_irq_handler(&dev_priv->engine[RCS], + iir, GEN8_RCS_IRQ_SHIFT); - gen8_cs_irq_handler(&dev_priv->ring[BCS], - iir, GEN8_BCS_IRQ_SHIFT); + gen8_cs_irq_handler(&dev_priv->engine[BCS], + iir, GEN8_BCS_IRQ_SHIFT); } else DRM_ERROR("The master control interrupt lied (GT0)!\n"); } @@ -1353,11 +1353,11 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv, I915_WRITE_FW(GEN8_GT_IIR(1), iir); ret = IRQ_HANDLED; - gen8_cs_irq_handler(&dev_priv->ring[VCS], - iir, GEN8_VCS1_IRQ_SHIFT); + gen8_cs_irq_handler(&dev_priv->engine[VCS], + iir, GEN8_VCS1_IRQ_SHIFT); - gen8_cs_irq_handler(&dev_priv->ring[VCS2], - iir, GEN8_VCS2_IRQ_SHIFT); + gen8_cs_irq_handler(&dev_priv->engine[VCS2], + iir, GEN8_VCS2_IRQ_SHIFT); } else DRM_ERROR("The master control interrupt lied (GT1)!\n"); } @@ -1368,8 +1368,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv, I915_WRITE_FW(GEN8_GT_IIR(3), iir); ret = IRQ_HANDLED; - gen8_cs_irq_handler(&dev_priv->ring[VECS], - iir, GEN8_VECS_IRQ_SHIFT); + gen8_cs_irq_handler(&dev_priv->engine[VECS], + iir, GEN8_VECS_IRQ_SHIFT); } else DRM_ERROR("The master control interrupt lied (GT3)!\n"); } @@ -1629,7 +1629,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) if (HAS_VEBOX(dev_priv->dev)) { if (pm_iir & PM_VEBOX_USER_INTERRUPT) - notify_ring(&dev_priv->ring[VECS]); + notify_ring(&dev_priv->engine[VECS]); if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); @@ -4042,7 +4042,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) new_iir = I915_READ16(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) - notify_ring(&dev_priv->ring[RCS]); + notify_ring(&dev_priv->engine[RCS]); for_each_pipe(dev_priv, pipe) { int plane = pipe; @@ -4238,7 +4238,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) new_iir = I915_READ(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) - notify_ring(&dev_priv->ring[RCS]); + notify_ring(&dev_priv->engine[RCS]); for_each_pipe(dev_priv, pipe) { int plane = pipe; @@ -4468,9 +4468,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) new_iir = I915_READ(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) - notify_ring(&dev_priv->ring[RCS]); + notify_ring(&dev_priv->engine[RCS]); if (iir & I915_BSD_USER_INTERRUPT) - notify_ring(&dev_priv->ring[VCS]); + notify_ring(&dev_priv->engine[VCS]); for_each_pipe(dev_priv, pipe) { if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS && diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index fa09e55..923cf6e 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -464,7 +464,7 @@ TRACE_EVENT(i915_gem_ring_sync_to, TP_fast_assign( __entry->dev = from->dev->primary->index; __entry->sync_from = from->id; - __entry->sync_to = to_req->ring->id; + __entry->sync_to = to_req->engine->id; __entry->seqno = i915_gem_request_get_seqno(req); ), @@ -486,13 +486,13 @@ TRACE_EVENT(i915_gem_ring_dispatch, ), TP_fast_assign( - struct intel_engine_cs *ring = + struct intel_engine_cs *engine = i915_gem_request_get_ring(req); - __entry->dev = ring->dev->primary->index; - __entry->ring = ring->id; + __entry->dev = engine->dev->primary->index; + __entry->ring = engine->id; __entry->seqno = i915_gem_request_get_seqno(req); __entry->flags = flags; - i915_trace_irq_get(ring, req); + i915_trace_irq_get(engine, req); ), TP_printk("dev=%u, ring=%u, seqno=%u, flags=%x", @@ -511,8 +511,8 @@ TRACE_EVENT(i915_gem_ring_flush, ), TP_fast_assign( - __entry->dev = req->ring->dev->primary->index; - __entry->ring = req->ring->id; + __entry->dev = req->engine->dev->primary->index; + __entry->ring = req->engine->id; __entry->invalidate = invalidate; __entry->flush = flush; ), @@ -533,10 +533,10 @@ DECLARE_EVENT_CLASS(i915_gem_request, ), TP_fast_assign( - struct intel_engine_cs *ring = + struct intel_engine_cs *engine = i915_gem_request_get_ring(req); - __entry->dev = ring->dev->primary->index; - __entry->ring = ring->id; + __entry->dev = engine->dev->primary->index; + __entry->ring = engine->id; __entry->seqno = i915_gem_request_get_seqno(req); ), @@ -550,8 +550,8 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_add, ); TRACE_EVENT(i915_gem_request_notify, - TP_PROTO(struct intel_engine_cs *ring), - TP_ARGS(ring), + TP_PROTO(struct intel_engine_cs *engine), + TP_ARGS(engine), TP_STRUCT__entry( __field(u32, dev) @@ -560,9 +560,9 @@ TRACE_EVENT(i915_gem_request_notify, ), TP_fast_assign( - __entry->dev = ring->dev->primary->index; - __entry->ring = ring->id; - __entry->seqno = ring->get_seqno(ring, false); + __entry->dev = engine->dev->primary->index; + __entry->ring = engine->id; + __entry->seqno = engine->get_seqno(engine, false); ), TP_printk("dev=%u, ring=%u, seqno=%u", @@ -597,13 +597,13 @@ TRACE_EVENT(i915_gem_request_wait_begin, * less desirable. */ TP_fast_assign( - struct intel_engine_cs *ring = + struct intel_engine_cs *engine = i915_gem_request_get_ring(req); - __entry->dev = ring->dev->primary->index; - __entry->ring = ring->id; + __entry->dev = engine->dev->primary->index; + __entry->ring = engine->id; __entry->seqno = i915_gem_request_get_seqno(req); __entry->blocking = - mutex_is_locked(&ring->dev->struct_mutex); + mutex_is_locked(&engine->dev->struct_mutex); ), TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s", @@ -777,9 +777,9 @@ DEFINE_EVENT(i915_context, i915_context_free, * called only if full ppgtt is enabled. */ TRACE_EVENT(switch_mm, - TP_PROTO(struct intel_engine_cs *ring, struct intel_context *to), + TP_PROTO(struct intel_engine_cs *engine, struct intel_context *to), - TP_ARGS(ring, to), + TP_ARGS(engine, to), TP_STRUCT__entry( __field(u32, ring) @@ -789,10 +789,10 @@ TRACE_EVENT(switch_mm, ), TP_fast_assign( - __entry->ring = ring->id; + __entry->ring = engine->id; __entry->to = to; __entry->vm = to->ppgtt? &to->ppgtt->base : NULL; - __entry->dev = ring->dev->primary->index; + __entry->dev = engine->dev->primary->index; ), TP_printk("dev=%u, ring=%u, ctx=%p, ctx_vm=%p", diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 317b55b..f271b0f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10984,7 +10984,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); u32 flip_mask; int ret; @@ -11019,7 +11019,7 @@ static int intel_gen3_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); u32 flip_mask; int ret; @@ -11051,7 +11051,7 @@ static int intel_gen4_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t pf, pipesrc; @@ -11090,7 +11090,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t pf, pipesrc; @@ -11126,7 +11126,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, struct drm_i915_gem_request *req, uint32_t flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t plane_bit = 0; int len, ret; @@ -11575,18 +11575,18 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1; if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { - engine = &dev_priv->ring[BCS]; + engine = &dev_priv->engine[BCS]; if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode) /* vlv: DISPLAY_FLIP fails to change tiling */ engine = NULL; } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { - engine = &dev_priv->ring[BCS]; + engine = &dev_priv->engine[BCS]; } else if (INTEL_INFO(dev)->gen >= 7) { engine = i915_gem_request_get_ring(obj->last_write_req); if (engine == NULL || engine->id != RCS) - engine = &dev_priv->ring[BCS]; + engine = &dev_priv->engine[BCS]; } else { - engine = &dev_priv->ring[RCS]; + engine = &dev_priv->engine[RCS]; } mmio_flip = use_mmio_flip(engine, obj); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 25514e9..bbcc31f 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -360,19 +360,19 @@ static void execlists_elsp_write(struct drm_i915_gem_request *rq0, struct drm_i915_gem_request *rq1) { - struct intel_engine_cs *engine = rq0->ring; + struct intel_engine_cs *engine = rq0->engine; struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; uint64_t desc[2]; if (rq1) { - desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->ring); + desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->engine); rq1->elsp_submitted++; } else { desc[1] = 0; } - desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->ring); + desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->engine); rq0->elsp_submitted++; /* You must always write both descriptors in the order below. */ @@ -398,7 +398,7 @@ execlists_update_context_pdps(struct i915_hw_ppgtt *ppgtt, u32 *reg_state) static void execlists_update_context(struct drm_i915_gem_request *rq) { - struct intel_engine_cs *engine = rq->ring; + struct intel_engine_cs *engine = rq->engine; struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt; uint32_t *reg_state = rq->ctx->engine[engine->id].lrc_reg_state; @@ -611,7 +611,7 @@ void intel_lrc_irq_handler(struct intel_engine_cs *engine) static void execlists_context_queue(struct drm_i915_gem_request *request) { - struct intel_engine_cs *engine = request->ring; + struct intel_engine_cs *engine = request->engine; struct drm_i915_gem_request *cursor; int num_elements = 0; @@ -650,7 +650,7 @@ static void execlists_context_queue(struct drm_i915_gem_request *request) static int logical_ring_invalidate_all_caches(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; uint32_t flush_domains; int ret; @@ -669,7 +669,7 @@ static int logical_ring_invalidate_all_caches(struct drm_i915_gem_request *req) static int execlists_move_to_gpu(struct drm_i915_gem_request *req, struct list_head *vmas) { - const unsigned other_rings = ~intel_ring_flag(req->ring); + const unsigned other_rings = ~intel_ring_flag(req->engine); struct i915_vma *vma; uint32_t flush_domains = 0; bool flush_chipset = false; @@ -679,7 +679,7 @@ static int execlists_move_to_gpu(struct drm_i915_gem_request *req, struct drm_i915_gem_object *obj = vma->obj; if (obj->active & other_rings) { - ret = i915_gem_object_sync(obj, req->ring, &req); + ret = i915_gem_object_sync(obj, req->engine, &req); if (ret) return ret; } @@ -703,7 +703,7 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request { int ret = 0; - request->ringbuf = request->ctx->engine[request->ring->id].ringbuf; + request->ringbuf = request->ctx->engine[request->engine->id].ringbuf; if (i915.enable_guc_submission) { /* @@ -719,7 +719,7 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request } if (request->ctx != request->i915->kernel_context) - ret = intel_lr_context_pin(request->ctx, request->ring); + ret = intel_lr_context_pin(request->ctx, request->engine); return ret; } @@ -728,7 +728,7 @@ static int logical_ring_wait_for_space(struct drm_i915_gem_request *req, int bytes) { struct intel_ringbuffer *ringbuf = req->ringbuf; - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_i915_gem_request *target; unsigned space; int ret; @@ -780,7 +780,7 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request) { struct intel_ringbuffer *ringbuf = request->ringbuf; struct drm_i915_private *dev_priv = request->i915; - struct intel_engine_cs *engine = request->ring; + struct intel_engine_cs *engine = request->engine; intel_logical_ring_advance(ringbuf); request->tail = ringbuf->tail; @@ -897,7 +897,7 @@ int intel_logical_ring_begin(struct drm_i915_gem_request *req, int num_dwords) int ret; WARN_ON(req == NULL); - dev_priv = req->ring->dev->dev_private; + dev_priv = req->engine->dev->dev_private; ret = i915_gem_check_wedge(&dev_priv->gpu_error, dev_priv->mm.interruptible); @@ -949,7 +949,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, struct list_head *vmas) { struct drm_device *dev = params->dev; - struct intel_engine_cs *engine = params->ring; + struct intel_engine_cs *engine = params->engine; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ringbuffer *ringbuf = params->ctx->engine[engine->id].ringbuf; u64 exec_start; @@ -963,7 +963,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, case I915_EXEC_CONSTANTS_REL_GENERAL: case I915_EXEC_CONSTANTS_ABSOLUTE: case I915_EXEC_CONSTANTS_REL_SURFACE: - if (instp_mode != 0 && engine != &dev_priv->ring[RCS]) { + if (instp_mode != 0 && engine != &dev_priv->engine[RCS]) { DRM_DEBUG("non-0 rel constants mode on non-RCS\n"); return -EINVAL; } @@ -992,7 +992,7 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, if (ret) return ret; - if (engine == &dev_priv->ring[RCS] && + if (engine == &dev_priv->engine[RCS] && instp_mode != dev_priv->relative_constants_mode) { ret = intel_logical_ring_begin(params->request, 4); if (ret) @@ -1073,7 +1073,7 @@ void intel_logical_ring_stop(struct intel_engine_cs *engine) int logical_ring_flush_all_caches(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; if (!engine->gpu_caches_dirty) @@ -1174,7 +1174,7 @@ void intel_lr_context_unpin(struct intel_context *ctx, static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req) { int ret, i; - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct intel_ringbuffer *ringbuf = req->ringbuf; struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1647,7 +1647,7 @@ static int gen9_init_render_ring(struct intel_engine_cs *engine) static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) { struct i915_hw_ppgtt *ppgtt = req->ctx->ppgtt; - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct intel_ringbuffer *ringbuf = req->ringbuf; const int num_lri_cmds = GEN8_LEGACY_PDPES * 2; int i, ret; @@ -1688,7 +1688,7 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req, * not idle). PML4 is allocated during ppgtt init so this is * not needed in 48-bit.*/ if (req->ctx->ppgtt && - (intel_ring_flag(req->ring) & req->ctx->ppgtt->pd_dirty_rings)) { + (intel_ring_flag(req->engine) & req->ctx->ppgtt->pd_dirty_rings)) { if (!USES_FULL_48BIT_PPGTT(req->i915) && !intel_vgpu_active(req->i915->dev)) { ret = intel_logical_ring_emit_pdps(req); @@ -1696,7 +1696,7 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req, return ret; } - req->ctx->ppgtt->pd_dirty_rings &= ~intel_ring_flag(req->ring); + req->ctx->ppgtt->pd_dirty_rings &= ~intel_ring_flag(req->engine); } ret = intel_logical_ring_begin(req, 4); @@ -1755,7 +1755,7 @@ static int gen8_emit_flush(struct drm_i915_gem_request *request, u32 unused) { struct intel_ringbuffer *ringbuf = request->ringbuf; - struct intel_engine_cs *engine = ringbuf->ring; + struct intel_engine_cs *engine = ringbuf->engine; struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; uint32_t cmd; @@ -1776,7 +1776,7 @@ static int gen8_emit_flush(struct drm_i915_gem_request *request, if (invalidate_domains & I915_GEM_GPU_DOMAINS) { cmd |= MI_INVALIDATE_TLB; - if (engine == &dev_priv->ring[VCS]) + if (engine == &dev_priv->engine[VCS]) cmd |= MI_INVALIDATE_BSD; } @@ -1796,7 +1796,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, u32 flush_domains) { struct intel_ringbuffer *ringbuf = request->ringbuf; - struct intel_engine_cs *engine = ringbuf->ring; + struct intel_engine_cs *engine = ringbuf->engine; u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; bool vf_flush_wa = false; u32 flags = 0; @@ -1919,7 +1919,7 @@ static int gen8_emit_request(struct drm_i915_gem_request *request) intel_logical_ring_emit(ringbuf, (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW); intel_logical_ring_emit(ringbuf, - hws_seqno_address(request->ring) | + hws_seqno_address(request->engine) | MI_FLUSH_DW_USE_GTT); intel_logical_ring_emit(ringbuf, 0); intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request)); @@ -1946,7 +1946,7 @@ static int gen8_emit_request_render(struct drm_i915_gem_request *request) (PIPE_CONTROL_GLOBAL_GTT_IVB | PIPE_CONTROL_CS_STALL | PIPE_CONTROL_QW_WRITE)); - intel_logical_ring_emit(ringbuf, hws_seqno_address(request->ring)); + intel_logical_ring_emit(ringbuf, hws_seqno_address(request->engine)); intel_logical_ring_emit(ringbuf, 0); intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request)); intel_logical_ring_emit(ringbuf, MI_USER_INTERRUPT); @@ -1958,19 +1958,19 @@ static int intel_lr_context_render_state_init(struct drm_i915_gem_request *req) struct render_state so; int ret; - ret = i915_gem_render_state_prepare(req->ring, &so); + ret = i915_gem_render_state_prepare(req->engine, &so); if (ret) return ret; if (so.rodata == NULL) return 0; - ret = req->ring->emit_bb_start(req, so.ggtt_offset, + ret = req->engine->emit_bb_start(req, so.ggtt_offset, I915_DISPATCH_SECURE); if (ret) goto out; - ret = req->ring->emit_bb_start(req, + ret = req->engine->emit_bb_start(req, (so.ggtt_offset + so.aux_batch_offset), I915_DISPATCH_SECURE); if (ret) @@ -2117,7 +2117,7 @@ error: static int logical_render_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->engine[RCS]; int ret; engine->name = "render ring"; @@ -2170,7 +2170,7 @@ static int logical_render_ring_init(struct drm_device *dev) static int logical_bsd_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[VCS]; + struct intel_engine_cs *engine = &dev_priv->engine[VCS]; engine->name = "bsd ring"; engine->id = VCS; @@ -2187,7 +2187,7 @@ static int logical_bsd_ring_init(struct drm_device *dev) static int logical_bsd2_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[VCS2]; + struct intel_engine_cs *engine = &dev_priv->engine[VCS2]; engine->name = "bsd2 ring"; engine->id = VCS2; @@ -2204,7 +2204,7 @@ static int logical_bsd2_ring_init(struct drm_device *dev) static int logical_blt_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[BCS]; + struct intel_engine_cs *engine = &dev_priv->engine[BCS]; engine->name = "blitter ring"; engine->id = BCS; @@ -2221,7 +2221,7 @@ static int logical_blt_ring_init(struct drm_device *dev) static int logical_vebox_ring_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[VECS]; + struct intel_engine_cs *engine = &dev_priv->engine[VECS]; engine->name = "video enhancement ring"; engine->id = VECS; @@ -2281,13 +2281,13 @@ int intel_logical_rings_init(struct drm_device *dev) return 0; cleanup_vebox_ring: - intel_logical_ring_cleanup(&dev_priv->ring[VECS]); + intel_logical_ring_cleanup(&dev_priv->engine[VECS]); cleanup_blt_ring: - intel_logical_ring_cleanup(&dev_priv->ring[BCS]); + intel_logical_ring_cleanup(&dev_priv->engine[BCS]); cleanup_bsd_ring: - intel_logical_ring_cleanup(&dev_priv->ring[VCS]); + intel_logical_ring_cleanup(&dev_priv->engine[VCS]); cleanup_render_ring: - intel_logical_ring_cleanup(&dev_priv->ring[RCS]); + intel_logical_ring_cleanup(&dev_priv->engine[RCS]); return ret; } diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c index d559259..2c89563 100644 --- a/drivers/gpu/drm/i915/intel_mocs.c +++ b/drivers/gpu/drm/i915/intel_mocs.c @@ -322,7 +322,7 @@ int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req) struct drm_i915_mocs_table t; int ret; - if (get_mocs_settings(req->ring->dev, &t)) { + if (get_mocs_settings(req->engine->dev, &t)) { struct drm_i915_private *dev_priv = req->i915; struct intel_engine_cs *engine; enum intel_ring_id ring_id; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 13b2763..13e22f5 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -233,7 +233,7 @@ static int intel_overlay_on(struct intel_overlay *overlay) { struct drm_device *dev = overlay->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->engine[RCS]; struct drm_i915_gem_request *req; int ret; @@ -267,7 +267,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay, { struct drm_device *dev = overlay->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->engine[RCS]; struct drm_i915_gem_request *req; u32 flip_addr = overlay->flip_addr; u32 tmp; @@ -336,7 +336,7 @@ static int intel_overlay_off(struct intel_overlay *overlay) { struct drm_device *dev = overlay->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->engine[RCS]; struct drm_i915_gem_request *req; u32 flip_addr = overlay->flip_addr; int ret; @@ -409,7 +409,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay) { struct drm_device *dev = overlay->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->engine[RCS]; int ret; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c54a7df..e51c284 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7365,7 +7365,7 @@ static void __intel_rps_boost_work(struct work_struct *work) struct drm_i915_gem_request *req = boost->req; if (!i915_gem_request_completed(req, true)) - gen6_rps_boost(to_i915(req->ring->dev), NULL, + gen6_rps_boost(to_i915(req->engine->dev), NULL, req->emitted_jiffies); i915_gem_request_unreference__unlocked(req); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 5323761..7075b93 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -79,7 +79,7 @@ gen2_render_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; u32 cmd; int ret; @@ -106,7 +106,7 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_device *dev = engine->dev; u32 cmd; int ret; @@ -200,7 +200,7 @@ gen4_render_ring_flush(struct drm_i915_gem_request *req, static int intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; int ret; @@ -236,7 +236,7 @@ static int gen6_render_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; u32 flags = 0; u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; int ret; @@ -288,7 +288,7 @@ gen6_render_ring_flush(struct drm_i915_gem_request *req, static int gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; ret = intel_ring_begin(req, 4); @@ -309,7 +309,7 @@ static int gen7_render_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; u32 flags = 0; u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; int ret; @@ -373,7 +373,7 @@ static int gen8_emit_pipe_control(struct drm_i915_gem_request *req, u32 flags, u32 scratch_addr) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; ret = intel_ring_begin(req, 6); @@ -396,7 +396,7 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { u32 flags = 0; - u32 scratch_addr = req->ring->scratch.gtt_offset + 2 * CACHELINE_BYTES; + u32 scratch_addr = req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; int ret; flags |= PIPE_CONTROL_CS_STALL; @@ -704,7 +704,7 @@ err: static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) { int ret, i; - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct i915_workarounds *w = &dev_priv->workarounds; @@ -1269,7 +1269,7 @@ static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, unsigned int num_dwords) { #define MBOX_UPDATE_DWORDS 8 - struct intel_engine_cs *signaller = signaller_req->ring; + struct intel_engine_cs *signaller = signaller_req->engine; struct drm_device *dev = signaller->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *waiter; @@ -1310,7 +1310,7 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, unsigned int num_dwords) { #define MBOX_UPDATE_DWORDS 6 - struct intel_engine_cs *signaller = signaller_req->ring; + struct intel_engine_cs *signaller = signaller_req->engine; struct drm_device *dev = signaller->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *waiter; @@ -1348,7 +1348,7 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, static int gen6_signal(struct drm_i915_gem_request *signaller_req, unsigned int num_dwords) { - struct intel_engine_cs *signaller = signaller_req->ring; + struct intel_engine_cs *signaller = signaller_req->engine; struct drm_device *dev = signaller->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *useless; @@ -1393,7 +1393,7 @@ static int gen6_signal(struct drm_i915_gem_request *signaller_req, static int gen6_add_request(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; if (engine->semaphore.signal) @@ -1434,7 +1434,7 @@ gen8_ring_sync(struct drm_i915_gem_request *waiter_req, struct intel_engine_cs *signaller, u32 seqno) { - struct intel_engine_cs *waiter = waiter_req->ring; + struct intel_engine_cs *waiter = waiter_req->engine; struct drm_i915_private *dev_priv = waiter->dev->dev_private; int ret; @@ -1460,7 +1460,7 @@ gen6_ring_sync(struct drm_i915_gem_request *waiter_req, struct intel_engine_cs *signaller, u32 seqno) { - struct intel_engine_cs *waiter = waiter_req->ring; + struct intel_engine_cs *waiter = waiter_req->engine; u32 dw1 = MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE | MI_SEMAPHORE_REGISTER; @@ -1508,7 +1508,7 @@ do { \ static int pc_render_add_request(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES; int ret; @@ -1706,7 +1706,7 @@ bsd_ring_flush(struct drm_i915_gem_request *req, u32 invalidate_domains, u32 flush_domains) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; ret = intel_ring_begin(req, 2); @@ -1722,7 +1722,7 @@ bsd_ring_flush(struct drm_i915_gem_request *req, static int i9xx_add_request(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; ret = intel_ring_begin(req, 4); @@ -1868,7 +1868,7 @@ i965_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 length, unsigned dispatch_flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; ret = intel_ring_begin(req, 2); @@ -1895,7 +1895,7 @@ i830_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 len, unsigned dispatch_flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; u32 cs_offset = engine->scratch.gtt_offset; int ret; @@ -1957,7 +1957,7 @@ i915_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 len, unsigned dispatch_flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; ret = intel_ring_begin(req, 2); @@ -2187,7 +2187,7 @@ intel_engine_create_ringbuffer(struct intel_engine_cs *engine, int size) return ERR_PTR(-ENOMEM); } - ring->ring = engine; + ring->engine = engine; list_add(&ring->link, &engine->buffers); ring->size = size; @@ -2377,7 +2377,7 @@ int intel_ring_idle(struct intel_engine_cs *engine) int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request) { - request->ringbuf = request->ring->buffer; + request->ringbuf = request->engine->buffer; return 0; } @@ -2498,7 +2498,7 @@ int intel_ring_begin(struct drm_i915_gem_request *req, int ret; WARN_ON(req == NULL); - engine = req->ring; + engine = req->engine; dev_priv = engine->dev->dev_private; ret = i915_gem_check_wedge(&dev_priv->gpu_error, @@ -2517,7 +2517,7 @@ int intel_ring_begin(struct drm_i915_gem_request *req, /* Align the ring tail to a cacheline boundary */ int intel_ring_cacheline_align(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int num_dwords = (engine->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t); int ret; @@ -2589,7 +2589,7 @@ static void gen6_bsd_ring_write_tail(struct intel_engine_cs *engine, static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req, u32 invalidate, u32 flush) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; uint32_t cmd; int ret; @@ -2636,7 +2636,7 @@ gen8_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 len, unsigned dispatch_flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; bool ppgtt = USES_PPGTT(engine->dev) && !(dispatch_flags & I915_DISPATCH_SECURE); int ret; @@ -2662,7 +2662,7 @@ hsw_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 len, unsigned dispatch_flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; ret = intel_ring_begin(req, 2); @@ -2687,7 +2687,7 @@ gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, u64 offset, u32 len, unsigned dispatch_flags) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; ret = intel_ring_begin(req, 2); @@ -2710,7 +2710,7 @@ gen6_ring_dispatch_execbuffer(struct drm_i915_gem_request *req, static int gen6_ring_flush(struct drm_i915_gem_request *req, u32 invalidate, u32 flush) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; struct drm_device *dev = engine->dev; uint32_t cmd; int ret; @@ -2756,7 +2756,7 @@ static int gen6_ring_flush(struct drm_i915_gem_request *req, int intel_init_render_ring_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[RCS]; + struct intel_engine_cs *engine = &dev_priv->engine[RCS]; struct drm_i915_gem_object *obj; int ret; @@ -2907,7 +2907,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev) int intel_init_bsd_ring_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[VCS]; + struct intel_engine_cs *engine = &dev_priv->engine[VCS]; engine->name = "bsd ring"; engine->id = VCS; @@ -2984,7 +2984,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) int intel_init_bsd2_ring_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[VCS2]; + struct intel_engine_cs *engine = &dev_priv->engine[VCS2]; engine->name = "bsd2 ring"; engine->id = VCS2; @@ -3015,7 +3015,7 @@ int intel_init_bsd2_ring_buffer(struct drm_device *dev) int intel_init_blt_ring_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[BCS]; + struct intel_engine_cs *engine = &dev_priv->engine[BCS]; engine->name = "blitter ring"; engine->id = BCS; @@ -3073,7 +3073,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev) int intel_init_vebox_ring_buffer(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_engine_cs *engine = &dev_priv->ring[VECS]; + struct intel_engine_cs *engine = &dev_priv->engine[VECS]; engine->name = "video enhancement ring"; engine->id = VECS; @@ -3125,7 +3125,7 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev) int intel_ring_flush_all_caches(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; int ret; if (!engine->gpu_caches_dirty) @@ -3144,7 +3144,7 @@ intel_ring_flush_all_caches(struct drm_i915_gem_request *req) int intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = req->ring; + struct intel_engine_cs *engine = req->engine; uint32_t flush_domains; int ret; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 4848463..4b0114e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -99,7 +99,7 @@ struct intel_ringbuffer { void __iomem *virtual_start; struct i915_vma *vma; - struct intel_engine_cs *ring; + struct intel_engine_cs *engine; struct list_head link; u32 head; -- cgit v0.10.2 From 666796da7abbc9c8c1805efa6d43bf078ddb282e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 16 Mar 2016 11:00:39 +0000 Subject: drm/i915: More intel_engine_cs renaming Some trivial ones, first pass done with Coccinelle: @@ @@ ( - I915_NUM_RINGS + I915_NUM_ENGINES | - intel_ring_flag + intel_engine_flag | - for_each_ring + for_each_engine | - i915_gem_request_get_ring + i915_gem_request_get_engine | - intel_ring_idle + intel_engine_idle | - i915_gem_reset_ring_status + i915_gem_reset_engine_status | - i915_gem_reset_ring_cleanup + i915_gem_reset_engine_cleanup | - init_ring_lists + init_engine_lists ) But that didn't fully work so I cleaned it up with: for f in *.[hc]; do sed -i -e s/I915_NUM_RINGS/I915_NUM_ENGINES/ $f; done for f in *.[hc]; do sed -i -e s/i915_gem_request_get_ring/i915_gem_request_get_engine/ $f; done for f in *.[hc]; do sed -i -e s/intel_ring_flag/intel_engine_flag/ $f; done for f in *.[hc]; do sed -i -e s/intel_ring_idle/intel_engine_idle/ $f; done for f in *.[hc]; do sed -i -e s/init_ring_lists/init_engine_lists/ $f; done for f in *.[hc]; do sed -i -e s/i915_gem_reset_ring_cleanup/i915_gem_reset_engine_cleanup/ $f; done for f in *.[hc]; do sed -i -e s/i915_gem_reset_ring_status/i915_gem_reset_engine_status/ $f; done v2: Rebase. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a71ffaa..dabce84 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -143,7 +143,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) obj->base.size / 1024, obj->base.read_domains, obj->base.write_domain); - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) seq_printf(m, "%x ", i915_gem_request_get_seqno(obj->last_read_req[i])); seq_printf(m, "] %x %x%s%s%s", @@ -184,7 +184,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) } if (obj->last_write_req != NULL) seq_printf(m, " (%s)", - i915_gem_request_get_ring(obj->last_write_req)->name); + i915_gem_request_get_engine(obj->last_write_req)->name); if (obj->frontbuffer_bits) seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits); } @@ -402,7 +402,7 @@ static void print_batch_pool_stats(struct seq_file *m, memset(&stats, 0, sizeof(stats)); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { list_for_each_entry(obj, &engine->batch_pool.cache_list[j], @@ -591,7 +591,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data) pipe, plane); } if (work->flip_queued_req) { - struct intel_engine_cs *engine = i915_gem_request_get_ring(work->flip_queued_req); + struct intel_engine_cs *engine = i915_gem_request_get_engine(work->flip_queued_req); seq_printf(m, "Flip queued on %s at seqno %x, next seqno %x [current breadcrumb %x], completed? %d\n", engine->name, @@ -644,7 +644,7 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) if (ret) return ret; - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { int count; @@ -689,7 +689,7 @@ static int i915_gem_request_info(struct seq_file *m, void *data) return ret; any = 0; - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { int count; count = 0; @@ -746,7 +746,7 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) return ret; intel_runtime_pm_get(dev_priv); - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) i915_ring_seqno_info(m, engine); intel_runtime_pm_put(dev_priv); @@ -933,7 +933,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) seq_printf(m, "Graphics Interrupt mask: %08x\n", I915_READ(GTIMR)); } - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { if (INTEL_INFO(dev)->gen >= 6) { seq_printf(m, "Graphics Interrupt mask (%s): %08x\n", @@ -1331,8 +1331,8 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - u64 acthd[I915_NUM_RINGS]; - u32 seqno[I915_NUM_RINGS]; + u64 acthd[I915_NUM_ENGINES]; + u32 seqno[I915_NUM_ENGINES]; u32 instdone[I915_NUM_INSTDONE_REG]; int i, j; @@ -1343,7 +1343,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { seqno[i] = engine->get_seqno(engine, false); acthd[i] = intel_ring_get_active_head(engine); } @@ -1359,7 +1359,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) } else seq_printf(m, "Hangcheck inactive\n"); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { seq_printf(m, "%s:\n", engine->name); seq_printf(m, "\tseqno = %x [current %x]\n", engine->hangcheck.seqno, seqno[i]); @@ -1965,7 +1965,7 @@ static int i915_context_status(struct seq_file *m, void *unused) if (i915.enable_execlists) { seq_putc(m, '\n'); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state; struct intel_ringbuffer *ringbuf = @@ -2055,7 +2055,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) list_for_each_entry(ctx, &dev_priv->context_list, link) if (ctx != dev_priv->kernel_context) - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) i915_dump_lrc_obj(m, ctx, engine); mutex_unlock(&dev->struct_mutex); @@ -2089,7 +2089,7 @@ static int i915_execlists(struct seq_file *m, void *data) intel_runtime_pm_get(dev_priv); - for_each_ring(engine, dev_priv, ring_id) { + for_each_engine(engine, dev_priv, ring_id) { struct drm_i915_gem_request *head_req = NULL; int count = 0; unsigned long flags; @@ -2253,7 +2253,7 @@ static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev) if (!ppgtt) return; - for_each_ring(engine, dev_priv, unused) { + for_each_engine(engine, dev_priv, unused) { seq_printf(m, "%s\n", engine->name); for (i = 0; i < 4; i++) { u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i)); @@ -2273,7 +2273,7 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) if (INTEL_INFO(dev)->gen == 6) seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE)); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { seq_printf(m, "%s\n", engine->name); if (INTEL_INFO(dev)->gen == 7) seq_printf(m, "GFX_MODE: 0x%08x\n", @@ -2342,7 +2342,7 @@ static int count_irq_waiters(struct drm_i915_private *i915) int count = 0; int i; - for_each_ring(engine, i915, i) + for_each_engine(engine, i915, i) count += engine->irq_refcount; return count; @@ -2466,7 +2466,7 @@ static void i915_guc_client_info(struct seq_file *m, seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail); seq_printf(m, "\tLast submission result: %d\n", client->retcode); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { seq_printf(m, "\tSubmissions: %llu %s\n", client->submissions[engine->guc_id], engine->name); @@ -2506,7 +2506,7 @@ static int i915_guc_info(struct seq_file *m, void *data) seq_printf(m, "GuC last action error code: %d\n", guc.action_err); seq_printf(m, "\nGuC submissions:\n"); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n", engine->name, guc.submissions[engine->guc_id], guc.last_seqno[engine->guc_id]); @@ -3153,14 +3153,14 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) page = i915_gem_object_get_page(dev_priv->semaphore_obj, 0); seqno = (uint64_t *)kmap_atomic(page); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { uint64_t offset; seq_printf(m, "%s\n", engine->name); seq_puts(m, " Last signal:"); for (j = 0; j < num_rings; j++) { - offset = i * I915_NUM_RINGS + j; + offset = i * I915_NUM_ENGINES + j; seq_printf(m, "0x%08llx (0x%02llx) ", seqno[offset], offset * 8); } @@ -3168,7 +3168,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) seq_puts(m, " Last wait: "); for (j = 0; j < num_rings; j++) { - offset = i + (j * I915_NUM_RINGS); + offset = i + (j * I915_NUM_ENGINES); seq_printf(m, "0x%08llx (0x%02llx) ", seqno[offset], offset * 8); } @@ -3178,7 +3178,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) kunmap_atomic(seqno); } else { seq_puts(m, " Last signal:"); - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) for (j = 0; j < num_rings; j++) seq_printf(m, "0x%08x\n", I915_READ(engine->semaphore.mbox.signal[j])); @@ -3186,7 +3186,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) } seq_puts(m, "\nSync seqno:\n"); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { for (j = 0; j < num_rings; j++) { seq_printf(m, " 0x%08x ", engine->semaphore.sync_seqno[j]); @@ -3244,7 +3244,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); seq_printf(m, "Workarounds applied: %d\n", workarounds->count); - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) seq_printf(m, "HW whitelist count for %s: %d\n", engine->name, workarounds->hw_whitelist_count[i]); for (i = 0; i < workarounds->count; ++i) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0187a56..db999c2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -459,7 +459,7 @@ struct drm_i915_error_state { u32 cpu_ring_head; u32 cpu_ring_tail; - u32 semaphore_seqno[I915_NUM_RINGS - 1]; + u32 semaphore_seqno[I915_NUM_ENGINES - 1]; /* Register state */ u32 start; @@ -479,7 +479,7 @@ struct drm_i915_error_state { u32 fault_reg; u64 faddr; u32 rc_psmi; /* sleep state */ - u32 semaphore_mboxes[I915_NUM_RINGS - 1]; + u32 semaphore_mboxes[I915_NUM_ENGINES - 1]; struct drm_i915_error_object { int page_count; @@ -505,12 +505,12 @@ struct drm_i915_error_state { pid_t pid; char comm[TASK_COMM_LEN]; - } ring[I915_NUM_RINGS]; + } ring[I915_NUM_ENGINES]; struct drm_i915_error_buffer { u32 size; u32 name; - u32 rseqno[I915_NUM_RINGS], wseqno; + u32 rseqno[I915_NUM_ENGINES], wseqno; u64 gtt_offset; u32 read_domains; u32 write_domain; @@ -824,7 +824,7 @@ struct intel_context { struct i915_vma *lrc_vma; u64 lrc_desc; uint32_t *lrc_reg_state; - } engine[I915_NUM_RINGS]; + } engine[I915_NUM_ENGINES]; struct list_head link; }; @@ -1639,7 +1639,7 @@ struct i915_wa_reg { struct i915_workarounds { struct i915_wa_reg reg[I915_MAX_WA_REGS]; u32 count; - u32 hw_whitelist_count[I915_NUM_RINGS]; + u32 hw_whitelist_count[I915_NUM_ENGINES]; }; struct i915_virtual_gpu { @@ -1704,7 +1704,7 @@ struct drm_i915_private { wait_queue_head_t gmbus_wait_queue; struct pci_dev *bridge_dev; - struct intel_engine_cs engine[I915_NUM_RINGS]; + struct intel_engine_cs engine[I915_NUM_ENGINES]; struct drm_i915_gem_object *semaphore_obj; uint32_t last_seqno, next_seqno; @@ -1967,8 +1967,8 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) } /* Iterate over initialised rings */ -#define for_each_ring(ring__, dev_priv__, i__) \ - for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \ +#define for_each_engine(ring__, dev_priv__, i__) \ + for ((i__) = 0; (i__) < I915_NUM_ENGINES; (i__)++) \ for_each_if ((((ring__) = &(dev_priv__)->engine[(i__)]), intel_ring_initialized((ring__)))) enum hdmi_force_audio { @@ -2039,7 +2039,7 @@ struct drm_i915_gem_object { struct drm_mm_node *stolen; struct list_head global_list; - struct list_head ring_list[I915_NUM_RINGS]; + struct list_head ring_list[I915_NUM_ENGINES]; /** Used in execbuf to temporarily hold a ref */ struct list_head obj_exec_link; @@ -2050,7 +2050,7 @@ struct drm_i915_gem_object { * rendering and so a non-zero seqno), and is not set if it i s on * inactive (ready to be unbound) list. */ - unsigned int active:I915_NUM_RINGS; + unsigned int active:I915_NUM_ENGINES; /** * This is set if the object has been written to since last bound @@ -2129,7 +2129,7 @@ struct drm_i915_gem_object { * read request. This allows for the CPU to read from an active * buffer by only waiting for the write to complete. * */ - struct drm_i915_gem_request *last_read_req[I915_NUM_RINGS]; + struct drm_i915_gem_request *last_read_req[I915_NUM_ENGINES]; struct drm_i915_gem_request *last_write_req; /** Breadcrumb of last fenced GPU access to the buffer. */ struct drm_i915_gem_request *last_fenced_req; @@ -2277,7 +2277,7 @@ i915_gem_request_get_seqno(struct drm_i915_gem_request *req) } static inline struct intel_engine_cs * -i915_gem_request_get_ring(struct drm_i915_gem_request *req) +i915_gem_request_get_engine(struct drm_i915_gem_request *req) { return req ? req->engine : NULL; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cd68a86..0ae193f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1243,11 +1243,11 @@ int __i915_wait_request(struct drm_i915_gem_request *req, s64 *timeout, struct intel_rps_client *rps) { - struct intel_engine_cs *engine = i915_gem_request_get_ring(req); + struct intel_engine_cs *engine = i915_gem_request_get_engine(req); struct drm_device *dev = engine->dev; struct drm_i915_private *dev_priv = dev->dev_private; const bool irq_test_in_progress = - ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(engine); + ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_engine_flag(engine); int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE; DEFINE_WAIT(wait); unsigned long timeout_expire; @@ -1512,7 +1512,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, i915_gem_object_retire__write(obj); } } else { - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = 0; i < I915_NUM_ENGINES; i++) { if (obj->last_read_req[i] == NULL) continue; @@ -1552,7 +1552,7 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, { struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_request *requests[I915_NUM_RINGS]; + struct drm_i915_gem_request *requests[I915_NUM_ENGINES]; unsigned reset_counter; int ret, i, n = 0; @@ -1577,7 +1577,7 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, requests[n++] = i915_gem_request_reference(req); } else { - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = 0; i < I915_NUM_ENGINES; i++) { struct drm_i915_gem_request *req; req = obj->last_read_req[i]; @@ -2406,12 +2406,12 @@ void i915_vma_move_to_active(struct i915_vma *vma, struct drm_i915_gem_object *obj = vma->obj; struct intel_engine_cs *engine; - engine = i915_gem_request_get_ring(req); + engine = i915_gem_request_get_engine(req); /* Add a reference if we're newly entering the active list. */ if (obj->active == 0) drm_gem_object_reference(&obj->base); - obj->active |= intel_ring_flag(engine); + obj->active |= intel_engine_flag(engine); list_move_tail(&obj->ring_list[engine->id], &engine->active_list); i915_gem_request_assign(&obj->last_read_req[engine->id], req); @@ -2423,7 +2423,7 @@ static void i915_gem_object_retire__write(struct drm_i915_gem_object *obj) { RQ_BUG_ON(obj->last_write_req == NULL); - RQ_BUG_ON(!(obj->active & intel_ring_flag(obj->last_write_req->engine))); + RQ_BUG_ON(!(obj->active & intel_engine_flag(obj->last_write_req->engine))); i915_gem_request_assign(&obj->last_write_req, NULL); intel_fb_obj_flush(obj, true, ORIGIN_CS); @@ -2471,15 +2471,15 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno) int ret, i, j; /* Carefully retire all requests without writing to the rings */ - for_each_ring(engine, dev_priv, i) { - ret = intel_ring_idle(engine); + for_each_engine(engine, dev_priv, i) { + ret = intel_engine_idle(engine); if (ret) return ret; } i915_gem_retire_requests(dev); /* Finally reset hw state */ - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { intel_ring_init_seqno(engine, seqno); for (j = 0; j < ARRAY_SIZE(engine->semaphore.sync_seqno); j++) @@ -2801,7 +2801,7 @@ i915_gem_find_active_request(struct intel_engine_cs *engine) return NULL; } -static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv, +static void i915_gem_reset_engine_status(struct drm_i915_private *dev_priv, struct intel_engine_cs *engine) { struct drm_i915_gem_request *request; @@ -2820,7 +2820,7 @@ static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv, i915_set_reset_status(dev_priv, request->ctx, false); } -static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv, +static void i915_gem_reset_engine_cleanup(struct drm_i915_private *dev_priv, struct intel_engine_cs *engine) { struct intel_ringbuffer *buffer; @@ -2893,11 +2893,11 @@ void i915_gem_reset(struct drm_device *dev) * them for finding the guilty party. As the requests only borrow * their reference to the objects, the inspection must be done first. */ - for_each_ring(engine, dev_priv, i) - i915_gem_reset_ring_status(dev_priv, engine); + for_each_engine(engine, dev_priv, i) + i915_gem_reset_engine_status(dev_priv, engine); - for_each_ring(engine, dev_priv, i) - i915_gem_reset_ring_cleanup(dev_priv, engine); + for_each_engine(engine, dev_priv, i) + i915_gem_reset_engine_cleanup(dev_priv, engine); i915_gem_context_reset(dev); @@ -2966,7 +2966,7 @@ i915_gem_retire_requests(struct drm_device *dev) bool idle = true; int i; - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { i915_gem_retire_requests_ring(engine); idle &= list_empty(&engine->request_list); if (i915.enable_execlists) { @@ -3014,7 +3014,7 @@ i915_gem_idle_work_handler(struct work_struct *work) struct intel_engine_cs *ring; int i; - for_each_ring(ring, dev_priv, i) + for_each_engine(ring, dev_priv, i) if (!list_empty(&ring->request_list)) return; @@ -3028,7 +3028,7 @@ i915_gem_idle_work_handler(struct work_struct *work) struct intel_engine_cs *engine; int i; - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) i915_gem_batch_pool_fini(&engine->batch_pool); mutex_unlock(&dev->struct_mutex); @@ -3048,7 +3048,7 @@ i915_gem_object_flush_active(struct drm_i915_gem_object *obj) if (!obj->active) return 0; - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = 0; i < I915_NUM_ENGINES; i++) { struct drm_i915_gem_request *req; req = obj->last_read_req[i]; @@ -3096,7 +3096,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_wait *args = data; struct drm_i915_gem_object *obj; - struct drm_i915_gem_request *req[I915_NUM_RINGS]; + struct drm_i915_gem_request *req[I915_NUM_ENGINES]; unsigned reset_counter; int i, n = 0; int ret; @@ -3133,7 +3133,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) drm_gem_object_unreference(&obj->base); reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = 0; i < I915_NUM_ENGINES; i++) { if (obj->last_read_req[i] == NULL) continue; @@ -3166,7 +3166,7 @@ __i915_gem_object_sync(struct drm_i915_gem_object *obj, struct intel_engine_cs *from; int ret; - from = i915_gem_request_get_ring(from_req); + from = i915_gem_request_get_engine(from_req); if (to == from) return 0; @@ -3260,7 +3260,7 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj, struct drm_i915_gem_request **to_req) { const bool readonly = obj->base.pending_write_domain == 0; - struct drm_i915_gem_request *req[I915_NUM_RINGS]; + struct drm_i915_gem_request *req[I915_NUM_ENGINES]; int ret, i, n; if (!obj->active) @@ -3274,7 +3274,7 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj, if (obj->last_write_req) req[n++] = obj->last_write_req; } else { - for (i = 0; i < I915_NUM_RINGS; i++) + for (i = 0; i < I915_NUM_ENGINES; i++) if (obj->last_read_req[i]) req[n++] = obj->last_read_req[i]; } @@ -3395,7 +3395,7 @@ int i915_gpu_idle(struct drm_device *dev) int ret, i; /* Flush everything onto the inactive list. */ - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { if (!i915.enable_execlists) { struct drm_i915_gem_request *req; @@ -3412,7 +3412,7 @@ int i915_gpu_idle(struct drm_device *dev) i915_add_request_no_flush(req); } - ret = intel_ring_idle(engine); + ret = intel_engine_idle(engine); if (ret) return ret; } @@ -4359,7 +4359,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, if (obj->active) { int i; - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = 0; i < I915_NUM_ENGINES; i++) { struct drm_i915_gem_request *req; req = obj->last_read_req[i]; @@ -4447,7 +4447,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, int i; INIT_LIST_HEAD(&obj->global_list); - for (i = 0; i < I915_NUM_RINGS; i++) + for (i = 0; i < I915_NUM_ENGINES; i++) INIT_LIST_HEAD(&obj->ring_list[i]); INIT_LIST_HEAD(&obj->obj_exec_link); INIT_LIST_HEAD(&obj->vma_list); @@ -4659,7 +4659,7 @@ i915_gem_stop_ringbuffers(struct drm_device *dev) struct intel_engine_cs *engine; int i; - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) dev_priv->gt.stop_ring(engine); } @@ -4876,7 +4876,7 @@ i915_gem_init_hw(struct drm_device *dev) } /* Need to do basic initialisation of all rings first: */ - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { ret = engine->init_hw(engine); if (ret) goto out; @@ -4901,7 +4901,7 @@ i915_gem_init_hw(struct drm_device *dev) goto out; /* Now it is safe to go back round and do everything else: */ - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { struct drm_i915_gem_request *req; req = i915_gem_request_alloc(engine, NULL); @@ -5009,7 +5009,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) struct intel_engine_cs *engine; int i; - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) dev_priv->gt.cleanup_ring(engine); if (i915.enable_execlists) @@ -5022,7 +5022,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) } static void -init_ring_lists(struct intel_engine_cs *engine) +init_engine_lists(struct intel_engine_cs *engine) { INIT_LIST_HEAD(&engine->active_list); INIT_LIST_HEAD(&engine->request_list); @@ -5055,8 +5055,8 @@ i915_gem_load_init(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->mm.unbound_list); INIT_LIST_HEAD(&dev_priv->mm.bound_list); INIT_LIST_HEAD(&dev_priv->mm.fence_list); - for (i = 0; i < I915_NUM_RINGS; i++) - init_ring_lists(&dev_priv->engine[i]); + for (i = 0; i < I915_NUM_ENGINES; i++) + init_engine_lists(&dev_priv->engine[i]); for (i = 0; i < I915_MAX_NUM_FENCES; i++) INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); INIT_DELAYED_WORK(&dev_priv->mm.retire_work, diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6c325e4..1993449 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -345,7 +345,7 @@ void i915_gem_context_reset(struct drm_device *dev) intel_lr_context_reset(dev, ctx); } - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = 0; i < I915_NUM_ENGINES; i++) { struct intel_engine_cs *engine = &dev_priv->engine[i]; if (engine->last_context) { @@ -426,7 +426,7 @@ void i915_gem_context_fini(struct drm_device *dev) i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state); } - for (i = I915_NUM_RINGS; --i >= 0;) { + for (i = I915_NUM_ENGINES; --i >= 0;) { struct intel_engine_cs *engine = &dev_priv->engine[i]; if (engine->last_context) { @@ -553,7 +553,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(num_rings)); - for_each_ring(signaller, to_i915(engine->dev), i) { + for_each_engine(signaller, to_i915(engine->dev), i) { if (signaller == engine) continue; @@ -582,7 +582,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(num_rings)); - for_each_ring(signaller, to_i915(engine->dev), i) { + for_each_engine(signaller, to_i915(engine->dev), i) { if (signaller == engine) continue; @@ -608,7 +608,7 @@ static inline bool should_skip_switch(struct intel_engine_cs *engine, return false; if (to->ppgtt && from == to && - !(intel_ring_flag(engine) & to->ppgtt->pd_dirty_rings)) + !(intel_engine_flag(engine) & to->ppgtt->pd_dirty_rings)) return true; return false; @@ -697,7 +697,7 @@ static int do_switch(struct drm_i915_gem_request *req) goto unpin_out; /* Doing a PD load always reloads the page dirs */ - to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(engine); + to->ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine); } if (engine != &dev_priv->engine[RCS]) { @@ -725,9 +725,9 @@ static int do_switch(struct drm_i915_gem_request *req) * space. This means we must enforce that a page table load * occur when this occurs. */ } else if (to->ppgtt && - (intel_ring_flag(engine) & to->ppgtt->pd_dirty_rings)) { + (intel_engine_flag(engine) & to->ppgtt->pd_dirty_rings)) { hw_flags |= MI_FORCE_RESTORE; - to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(engine); + to->ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine); } /* We should never emit switch_mm more than once */ diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index 202a7e6..e0bca7d 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c @@ -43,7 +43,7 @@ i915_verify_lists(struct drm_device *dev) if (warned) return 0; - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { list_for_each_entry(obj, &engine->active_list, ring_list[engine->id]) { if (obj->base.dev != dev || diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index bb1ed8c..c0545db 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -942,7 +942,7 @@ static int i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req, struct list_head *vmas) { - const unsigned other_rings = ~intel_ring_flag(req->engine); + const unsigned other_rings = ~intel_engine_flag(req->engine); struct i915_vma *vma; uint32_t flush_domains = 0; bool flush_chipset = false; @@ -1099,7 +1099,7 @@ void i915_gem_execbuffer_move_to_active(struct list_head *vmas, struct drm_i915_gem_request *req) { - struct intel_engine_cs *engine = i915_gem_request_get_ring(req); + struct intel_engine_cs *engine = i915_gem_request_get_engine(req); struct i915_vma *vma; list_for_each_entry(vma, vmas, exec_list) { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index ab54396..9c752fe 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1739,7 +1739,7 @@ static void gen8_ppgtt_enable(struct drm_device *dev) struct intel_engine_cs *engine; int j; - for_each_ring(engine, dev_priv, j) { + for_each_engine(engine, dev_priv, j) { u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0; I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level)); @@ -1765,7 +1765,7 @@ static void gen7_ppgtt_enable(struct drm_device *dev) } I915_WRITE(GAM_ECOCHK, ecochk); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { /* GFX_MODE is per-ring on gen7+ */ I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); @@ -2292,7 +2292,7 @@ void i915_check_and_clear_faults(struct drm_device *dev) if (INTEL_INFO(dev)->gen < 6) return; - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { u32 fault_reg; fault_reg = I915_READ(RING_FAULT_REG(engine)); if (fault_reg & RING_FAULT_VALID) { diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index a73f705..34397a6 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -198,7 +198,7 @@ static void print_error_buffers(struct drm_i915_error_state_buf *m, err->size, err->read_domains, err->write_domain); - for (i = 0; i < I915_NUM_RINGS; i++) + for (i = 0; i < I915_NUM_ENGINES; i++) err_printf(m, "%02x ", err->rseqno[i]); err_printf(m, "] %02x", err->wseqno); @@ -732,7 +732,7 @@ static void capture_bo(struct drm_i915_error_buffer *err, err->size = obj->base.size; err->name = obj->base.name; - for (i = 0; i < I915_NUM_RINGS; i++) + for (i = 0; i < I915_NUM_ENGINES; i++) err->rseqno[i] = i915_gem_request_get_seqno(obj->last_read_req[i]); err->wseqno = i915_gem_request_get_seqno(obj->last_write_req); err->gtt_offset = vma->node.start; @@ -747,7 +747,7 @@ static void capture_bo(struct drm_i915_error_buffer *err, err->purgeable = obj->madv != I915_MADV_WILLNEED; err->userptr = obj->userptr.mm != NULL; err->ring = obj->last_write_req ? - i915_gem_request_get_ring(obj->last_write_req)->id : -1; + i915_gem_request_get_engine(obj->last_write_req)->id : -1; err->cache_level = obj->cache_level; } @@ -809,7 +809,7 @@ static uint32_t i915_error_generate_code(struct drm_i915_private *dev_priv, * synchronization commands which almost always appear in the case * strictly a client bug. Use instdone to differentiate those some. */ - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = 0; i < I915_NUM_ENGINES; i++) { if (error->ring[i].hangcheck_action == HANGCHECK_HUNG) { if (ring_id) *ring_id = i; @@ -856,7 +856,7 @@ static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv, i915_error_ggtt_object_create(dev_priv, dev_priv->semaphore_obj); - for_each_ring(to, dev_priv, i) { + for_each_engine(to, dev_priv, i) { int idx; u16 signal_offset; u32 *tmp; @@ -1019,7 +1019,7 @@ static void i915_gem_record_rings(struct drm_device *dev, struct drm_i915_gem_request *request; int i, count; - for (i = 0; i < I915_NUM_RINGS; i++) { + for (i = 0; i < I915_NUM_ENGINES; i++) { struct intel_engine_cs *engine = &dev_priv->engine[i]; struct intel_ringbuffer *rbuf; diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index ed4f076..ae1f58d 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -390,7 +390,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc, desc.priority = client->priority; desc.db_id = client->doorbell_id; - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { struct guc_execlist_context *lrc = &desc.lrc[engine->guc_id]; struct drm_i915_gem_object *obj; uint64_t ctx_desc; @@ -871,7 +871,7 @@ static void guc_create_ads(struct intel_guc *guc) engine = &dev_priv->engine[RCS]; ads->golden_context_lrca = engine->status_page.gfx_addr; - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) ads->eng_state_size[engine->guc_id] = intel_lr_context_size(engine); /* GuC scheduling policies */ @@ -884,7 +884,7 @@ static void guc_create_ads(struct intel_guc *guc) /* MMIO reg state */ reg_state = (void *)policies + sizeof(struct guc_policies); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { reg_state->mmio_white_list[engine->guc_id].mmio_start = engine->mmio_base + GUC_MMIO_WHITE_LIST_START; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 6b7bee5..63ed77f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1082,7 +1082,7 @@ static bool any_waiters(struct drm_i915_private *dev_priv) struct intel_engine_cs *engine; int i; - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) if (engine->irq_refcount) return true; @@ -2460,7 +2460,7 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv, */ /* Wake up __wait_seqno, potentially holding dev->struct_mutex. */ - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) wake_up_all(&engine->irq_queue); /* Wake up intel_crtc_wait_for_pending_flips, holding crtc->mutex. */ @@ -2832,7 +2832,7 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, int i; if (INTEL_INFO(dev_priv->dev)->gen >= 8) { - for_each_ring(signaller, dev_priv, i) { + for_each_engine(signaller, dev_priv, i) { if (engine == signaller) continue; @@ -2842,7 +2842,7 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, } else { u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK; - for_each_ring(signaller, dev_priv, i) { + for_each_engine(signaller, dev_priv, i) { if(engine == signaller) continue; @@ -2941,7 +2941,7 @@ static int semaphore_passed(struct intel_engine_cs *engine) return -1; /* Prevent pathological recursion due to driver bugs */ - if (signaller->hangcheck.deadlock >= I915_NUM_RINGS) + if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES) return -1; if (i915_seqno_passed(signaller->get_seqno(signaller, false), seqno)) @@ -2960,7 +2960,7 @@ static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) struct intel_engine_cs *engine; int i; - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) engine->hangcheck.deadlock = 0; } @@ -3075,7 +3075,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) struct intel_engine_cs *engine; int i; int busy_count = 0, rings_hung = 0; - bool stuck[I915_NUM_RINGS] = { 0 }; + bool stuck[I915_NUM_ENGINES] = { 0 }; #define BUSY 1 #define KICK 5 #define HUNG 20 @@ -3097,7 +3097,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) */ intel_uncore_arm_unclaimed_mmio_detection(dev_priv); - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { u64 acthd; u32 seqno; bool busy = true; @@ -3114,7 +3114,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) if (waitqueue_active(&engine->irq_queue)) { /* Issue a wake-up to catch stuck h/w. */ if (!test_and_set_bit(engine->id, &dev_priv->gpu_error.missed_irq_rings)) { - if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(engine))) + if (!(dev_priv->gpu_error.test_irq_rings & intel_engine_flag(engine))) DRM_ERROR("Hangcheck timer elapsed... %s idle\n", engine->name); else @@ -3184,7 +3184,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) busy_count += busy; } - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) { DRM_INFO("%s on %s\n", stuck[i] ? "stuck" : "no progress", diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 923cf6e..afdd8ae 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -487,7 +487,7 @@ TRACE_EVENT(i915_gem_ring_dispatch, TP_fast_assign( struct intel_engine_cs *engine = - i915_gem_request_get_ring(req); + i915_gem_request_get_engine(req); __entry->dev = engine->dev->primary->index; __entry->ring = engine->id; __entry->seqno = i915_gem_request_get_seqno(req); @@ -534,7 +534,7 @@ DECLARE_EVENT_CLASS(i915_gem_request, TP_fast_assign( struct intel_engine_cs *engine = - i915_gem_request_get_ring(req); + i915_gem_request_get_engine(req); __entry->dev = engine->dev->primary->index; __entry->ring = engine->id; __entry->seqno = i915_gem_request_get_seqno(req); @@ -598,7 +598,7 @@ TRACE_EVENT(i915_gem_request_wait_begin, */ TP_fast_assign( struct intel_engine_cs *engine = - i915_gem_request_get_ring(req); + i915_gem_request_get_engine(req); __entry->dev = engine->dev->primary->index; __entry->ring = engine->id; __entry->seqno = i915_gem_request_get_seqno(req); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f271b0f..79eea3d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11242,7 +11242,7 @@ static bool use_mmio_flip(struct intel_engine_cs *engine, false)) return true; else - return engine != i915_gem_request_get_ring(obj->last_write_req); + return engine != i915_gem_request_get_engine(obj->last_write_req); } static void skl_do_mmio_flip(struct intel_crtc *intel_crtc, @@ -11582,7 +11582,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { engine = &dev_priv->engine[BCS]; } else if (INTEL_INFO(dev)->gen >= 7) { - engine = i915_gem_request_get_ring(obj->last_write_req); + engine = i915_gem_request_get_engine(obj->last_write_req); if (engine == NULL || engine->id != RCS) engine = &dev_priv->engine[BCS]; } else { diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index fc2c518..9f30921 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -87,7 +87,7 @@ static void direct_interrupts_to_host(struct drm_i915_private *dev_priv) /* tell all command streamers NOT to forward interrupts and vblank to GuC */ irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER); irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING); - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) I915_WRITE(RING_MODE_GEN7(engine), irqs); /* route all GT interrupts to the host */ @@ -104,7 +104,7 @@ static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv) /* tell all command streamers to forward interrupts and vblank to GuC */ irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_ALWAYS); irqs |= _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) I915_WRITE(RING_MODE_GEN7(engine), irqs); /* route USER_INTERRUPT to Host, all others are sent to GuC. */ diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index bbcc31f..f2cf0e1 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -669,7 +669,7 @@ static int logical_ring_invalidate_all_caches(struct drm_i915_gem_request *req) static int execlists_move_to_gpu(struct drm_i915_gem_request *req, struct list_head *vmas) { - const unsigned other_rings = ~intel_ring_flag(req->engine); + const unsigned other_rings = ~intel_engine_flag(req->engine); struct i915_vma *vma; uint32_t flush_domains = 0; bool flush_chipset = false; @@ -1057,7 +1057,7 @@ void intel_logical_ring_stop(struct intel_engine_cs *engine) if (!intel_ring_initialized(engine)) return; - ret = intel_ring_idle(engine); + ret = intel_engine_idle(engine); if (ret && !i915_reset_in_progress(&to_i915(engine->dev)->gpu_error)) DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", engine->name, ret); @@ -1688,7 +1688,7 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req, * not idle). PML4 is allocated during ppgtt init so this is * not needed in 48-bit.*/ if (req->ctx->ppgtt && - (intel_ring_flag(req->engine) & req->ctx->ppgtt->pd_dirty_rings)) { + (intel_engine_flag(req->engine) & req->ctx->ppgtt->pd_dirty_rings)) { if (!USES_FULL_48BIT_PPGTT(req->i915) && !intel_vgpu_active(req->i915->dev)) { ret = intel_logical_ring_emit_pdps(req); @@ -1696,7 +1696,7 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req, return ret; } - req->ctx->ppgtt->pd_dirty_rings &= ~intel_ring_flag(req->engine); + req->ctx->ppgtt->pd_dirty_rings &= ~intel_engine_flag(req->engine); } ret = intel_logical_ring_begin(req, 4); @@ -2511,7 +2511,7 @@ void intel_lr_context_free(struct intel_context *ctx) { int i; - for (i = I915_NUM_RINGS; --i >= 0; ) { + for (i = I915_NUM_ENGINES; --i >= 0; ) { struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf; struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state; @@ -2674,7 +2674,7 @@ void intel_lr_context_reset(struct drm_device *dev, struct intel_engine_cs *engine; int i; - for_each_ring(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, i) { struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state; struct intel_ringbuffer *ringbuf = diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c index 2c89563..6e936c7 100644 --- a/drivers/gpu/drm/i915/intel_mocs.c +++ b/drivers/gpu/drm/i915/intel_mocs.c @@ -328,7 +328,7 @@ int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req) enum intel_ring_id ring_id; /* Program the control registers */ - for_each_ring(engine, dev_priv, ring_id) { + for_each_engine(engine, dev_priv, ring_id) { ret = emit_mocs_control_table(req, &t, ring_id); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e51c284..20c8243 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4838,7 +4838,7 @@ static void gen9_enable_rc6(struct drm_device *dev) 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(engine, dev_priv, unused) + for_each_engine(engine, dev_priv, unused) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); if (HAS_GUC_UCODE(dev)) @@ -4906,7 +4906,7 @@ static void gen8_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16); I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ - for_each_ring(engine, dev_priv, unused) + for_each_engine(engine, dev_priv, unused) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); if (IS_BROADWELL(dev)) @@ -5003,7 +5003,7 @@ static void gen6_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); @@ -5522,7 +5522,7 @@ static void cherryview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); @@ -5633,7 +5633,7 @@ static void valleyview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); @@ -6019,7 +6019,7 @@ bool i915_gpu_busy(void) goto out_unlock; dev_priv = i915_mch_dev; - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) ret |= !list_empty(&engine->request_list); out_unlock: diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 7075b93..f7493c5 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -62,7 +62,7 @@ int intel_ring_space(struct intel_ringbuffer *ringbuf) bool intel_ring_stopped(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->dev->dev_private; - return dev_priv->gpu_error.stop_rings & intel_ring_flag(engine); + return dev_priv->gpu_error.stop_rings & intel_engine_flag(engine); } static void __intel_ring_advance(struct intel_engine_cs *engine) @@ -1283,7 +1283,7 @@ static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, if (ret) return ret; - for_each_ring(waiter, dev_priv, i) { + for_each_engine(waiter, dev_priv, i) { u32 seqno; u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) @@ -1324,7 +1324,7 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, if (ret) return ret; - for_each_ring(waiter, dev_priv, i) { + for_each_engine(waiter, dev_priv, i) { u32 seqno; u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) @@ -1363,7 +1363,7 @@ static int gen6_signal(struct drm_i915_gem_request *signaller_req, if (ret) return ret; - for_each_ring(useless, dev_priv, i) { + for_each_engine(useless, dev_priv, i) { i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[i]; if (i915_mmio_reg_valid(mbox_reg)) { @@ -2356,7 +2356,7 @@ static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf) intel_ring_update_space(ringbuf); } -int intel_ring_idle(struct intel_engine_cs *engine) +int intel_engine_idle(struct intel_engine_cs *engine) { struct drm_i915_gem_request *req; @@ -3170,7 +3170,7 @@ intel_stop_ring_buffer(struct intel_engine_cs *engine) if (!intel_ring_initialized(engine)) return; - ret = intel_ring_idle(engine); + ret = intel_engine_idle(engine); if (ret && !i915_reset_in_progress(&to_i915(engine->dev)->gpu_error)) DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", engine->name, ret); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 4b0114e..ee4d9a8 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -55,12 +55,12 @@ struct intel_hw_status_page { #define i915_semaphore_seqno_size sizeof(uint64_t) #define GEN8_SIGNAL_OFFSET(__ring, to) \ (i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \ - ((__ring)->id * I915_NUM_RINGS * i915_semaphore_seqno_size) + \ + ((__ring)->id * I915_NUM_ENGINES * i915_semaphore_seqno_size) + \ (i915_semaphore_seqno_size * (to))) #define GEN8_WAIT_OFFSET(__ring, from) \ (i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \ - ((from) * I915_NUM_RINGS * i915_semaphore_seqno_size) + \ + ((from) * I915_NUM_ENGINES * i915_semaphore_seqno_size) + \ (i915_semaphore_seqno_size * (__ring)->id)) #define GEN8_RING_SEMAPHORE_INIT(e) do { \ @@ -153,7 +153,7 @@ struct intel_engine_cs { VCS2, /* Keep instances of the same type engine together. */ VECS } id; -#define I915_NUM_RINGS 5 +#define I915_NUM_ENGINES 5 #define _VCS(n) (VCS + (n)) unsigned int exec_id; unsigned int guc_id; @@ -244,16 +244,16 @@ struct intel_engine_cs { * ie. transpose of f(x, y) */ struct { - u32 sync_seqno[I915_NUM_RINGS-1]; + u32 sync_seqno[I915_NUM_ENGINES-1]; union { struct { /* our mbox written by others */ - u32 wait[I915_NUM_RINGS]; + u32 wait[I915_NUM_ENGINES]; /* mboxes this ring signals to */ - i915_reg_t signal[I915_NUM_RINGS]; + i915_reg_t signal[I915_NUM_ENGINES]; } mbox; - u64 signal_ggtt[I915_NUM_RINGS]; + u64 signal_ggtt[I915_NUM_ENGINES]; }; /* AKA wait() */ @@ -361,7 +361,7 @@ intel_ring_initialized(struct intel_engine_cs *engine) } static inline unsigned -intel_ring_flag(struct intel_engine_cs *engine) +intel_engine_flag(struct intel_engine_cs *engine) { return 1 << engine->id; } @@ -382,7 +382,7 @@ intel_ring_sync_index(struct intel_engine_cs *engine, idx = (other - engine) - 1; if (idx < 0) - idx += I915_NUM_RINGS; + idx += I915_NUM_ENGINES; return idx; } @@ -467,7 +467,7 @@ void intel_ring_update_space(struct intel_ringbuffer *ringbuf); int intel_ring_space(struct intel_ringbuffer *ringbuf); bool intel_ring_stopped(struct intel_engine_cs *engine); -int __must_check intel_ring_idle(struct intel_engine_cs *engine); +int __must_check intel_engine_idle(struct intel_engine_cs *engine); void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno); int intel_ring_flush_all_caches(struct drm_i915_gem_request *req); int intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req); diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index d31447f..02add02 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1573,14 +1573,14 @@ static int gen8_do_reset(struct drm_device *dev) struct intel_engine_cs *engine; int i; - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) if (gen8_request_engine_reset(engine)) goto not_ready; return gen6_do_reset(dev); not_ready: - for_each_ring(engine, dev_priv, i) + for_each_engine(engine, dev_priv, i) gen8_unrequest_engine_reset(engine); return -EIO; -- cgit v0.10.2 From 117897f42c87c11a3a8315507d38cbd99ea46fda Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 16 Mar 2016 11:00:40 +0000 Subject: drm/i915: More renaming of rings to engines This time using only sed and a few by hand. v2: Rename also intel_ring_id and intel_ring_initialized. v3: Fixed typo in intel_ring_initialized. Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458126040-33105-1-git-send-email-tvrtko.ursulin@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index dabce84..1d8c3ef 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2483,7 +2483,7 @@ static int i915_guc_info(struct seq_file *m, void *data) struct intel_guc guc; struct i915_guc_client client = {}; struct intel_engine_cs *engine; - enum intel_ring_id i; + enum intel_engine_id i; u64 total = 0; if (!HAS_GUC_SCHED(dev_priv->dev)) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 19f605b..85b3130 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -87,16 +87,16 @@ static int i915_getparam(struct drm_device *dev, void *data, value = 1; break; case I915_PARAM_HAS_BSD: - value = intel_ring_initialized(&dev_priv->engine[VCS]); + value = intel_engine_initialized(&dev_priv->engine[VCS]); break; case I915_PARAM_HAS_BLT: - value = intel_ring_initialized(&dev_priv->engine[BCS]); + value = intel_engine_initialized(&dev_priv->engine[BCS]); break; case I915_PARAM_HAS_VEBOX: - value = intel_ring_initialized(&dev_priv->engine[VECS]); + value = intel_engine_initialized(&dev_priv->engine[VECS]); break; case I915_PARAM_HAS_BSD2: - value = intel_ring_initialized(&dev_priv->engine[VCS2]); + value = intel_engine_initialized(&dev_priv->engine[VCS2]); break; case I915_PARAM_HAS_RELAXED_FENCING: value = 1; @@ -444,7 +444,7 @@ static int i915_load_modeset_init(struct drm_device *dev) cleanup_gem: mutex_lock(&dev->struct_mutex); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); cleanup_irq: @@ -1261,7 +1261,7 @@ int i915_driver_unload(struct drm_device *dev) intel_guc_ucode_fini(dev); mutex_lock(&dev->struct_mutex); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); i915_gem_context_fini(dev); mutex_unlock(&dev->struct_mutex); intel_fbc_cleanup_cfb(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index db999c2..fd1ed66 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1931,9 +1931,9 @@ struct drm_i915_private { int (*execbuf_submit)(struct i915_execbuffer_params *params, struct drm_i915_gem_execbuffer2 *args, struct list_head *vmas); - int (*init_rings)(struct drm_device *dev); - void (*cleanup_ring)(struct intel_engine_cs *ring); - void (*stop_ring)(struct intel_engine_cs *ring); + int (*init_engines)(struct drm_device *dev); + void (*cleanup_engine)(struct intel_engine_cs *engine); + void (*stop_engine)(struct intel_engine_cs *engine); } gt; struct intel_context *kernel_context; @@ -1969,7 +1969,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) /* Iterate over initialised rings */ #define for_each_engine(ring__, dev_priv__, i__) \ for ((i__) = 0; (i__) < I915_NUM_ENGINES; (i__)++) \ - for_each_if ((((ring__) = &(dev_priv__)->engine[(i__)]), intel_ring_initialized((ring__)))) + for_each_if ((((ring__) = &(dev_priv__)->engine[(i__)]), intel_engine_initialized((ring__)))) enum hdmi_force_audio { HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ @@ -2039,7 +2039,7 @@ struct drm_i915_gem_object { struct drm_mm_node *stolen; struct list_head global_list; - struct list_head ring_list[I915_NUM_ENGINES]; + struct list_head engine_list[I915_NUM_ENGINES]; /** Used in execbuf to temporarily hold a ref */ struct list_head obj_exec_link; @@ -3002,11 +3002,11 @@ static inline bool i915_stop_ring_allow_warn(struct drm_i915_private *dev_priv) void i915_gem_reset(struct drm_device *dev); bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force); int __must_check i915_gem_init(struct drm_device *dev); -int i915_gem_init_rings(struct drm_device *dev); +int i915_gem_init_engines(struct drm_device *dev); int __must_check i915_gem_init_hw(struct drm_device *dev); int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice); void i915_gem_init_swizzling(struct drm_device *dev); -void i915_gem_cleanup_ringbuffer(struct drm_device *dev); +void i915_gem_cleanup_engines(struct drm_device *dev); int __must_check i915_gpu_idle(struct drm_device *dev); int __must_check i915_gem_suspend(struct drm_device *dev); void __i915_add_request(struct drm_i915_gem_request *req, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0ae193f..31652c1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2413,7 +2413,7 @@ void i915_vma_move_to_active(struct i915_vma *vma, drm_gem_object_reference(&obj->base); obj->active |= intel_engine_flag(engine); - list_move_tail(&obj->ring_list[engine->id], &engine->active_list); + list_move_tail(&obj->engine_list[engine->id], &engine->active_list); i915_gem_request_assign(&obj->last_read_req[engine->id], req); list_move_tail(&vma->vm_link, &vma->vm->active_list); @@ -2437,7 +2437,7 @@ i915_gem_object_retire__read(struct drm_i915_gem_object *obj, int ring) RQ_BUG_ON(obj->last_read_req[ring] == NULL); RQ_BUG_ON(!(obj->active & (1 << ring))); - list_del_init(&obj->ring_list[ring]); + list_del_init(&obj->engine_list[ring]); i915_gem_request_assign(&obj->last_read_req[ring], NULL); if (obj->last_write_req && obj->last_write_req->engine->id == ring) @@ -2830,7 +2830,7 @@ static void i915_gem_reset_engine_cleanup(struct drm_i915_private *dev_priv, obj = list_first_entry(&engine->active_list, struct drm_i915_gem_object, - ring_list[engine->id]); + engine_list[engine->id]); i915_gem_object_retire__read(obj, engine->id); } @@ -2941,7 +2941,7 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *engine) obj = list_first_entry(&engine->active_list, struct drm_i915_gem_object, - ring_list[engine->id]); + engine_list[engine->id]); if (!list_empty(&obj->last_read_req[engine->id]->list)) break; @@ -4448,7 +4448,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, INIT_LIST_HEAD(&obj->global_list); for (i = 0; i < I915_NUM_ENGINES; i++) - INIT_LIST_HEAD(&obj->ring_list[i]); + INIT_LIST_HEAD(&obj->engine_list[i]); INIT_LIST_HEAD(&obj->obj_exec_link); INIT_LIST_HEAD(&obj->vma_list); INIT_LIST_HEAD(&obj->batch_pool_link); @@ -4653,14 +4653,14 @@ void i915_gem_vma_destroy(struct i915_vma *vma) } static void -i915_gem_stop_ringbuffers(struct drm_device *dev) +i915_gem_stop_engines(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; int i; for_each_engine(engine, dev_priv, i) - dev_priv->gt.stop_ring(engine); + dev_priv->gt.stop_engine(engine); } int @@ -4676,7 +4676,7 @@ i915_gem_suspend(struct drm_device *dev) i915_gem_retire_requests(dev); - i915_gem_stop_ringbuffers(dev); + i915_gem_stop_engines(dev); mutex_unlock(&dev->struct_mutex); cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work); @@ -4778,7 +4778,7 @@ static void init_unused_rings(struct drm_device *dev) } } -int i915_gem_init_rings(struct drm_device *dev) +int i915_gem_init_engines(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int ret; @@ -4814,13 +4814,13 @@ int i915_gem_init_rings(struct drm_device *dev) return 0; cleanup_vebox_ring: - intel_cleanup_ring_buffer(&dev_priv->engine[VECS]); + intel_cleanup_engine(&dev_priv->engine[VECS]); cleanup_blt_ring: - intel_cleanup_ring_buffer(&dev_priv->engine[BCS]); + intel_cleanup_engine(&dev_priv->engine[BCS]); cleanup_bsd_ring: - intel_cleanup_ring_buffer(&dev_priv->engine[VCS]); + intel_cleanup_engine(&dev_priv->engine[VCS]); cleanup_render_ring: - intel_cleanup_ring_buffer(&dev_priv->engine[RCS]); + intel_cleanup_engine(&dev_priv->engine[RCS]); return ret; } @@ -4907,7 +4907,7 @@ i915_gem_init_hw(struct drm_device *dev) req = i915_gem_request_alloc(engine, NULL); if (IS_ERR(req)) { ret = PTR_ERR(req); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); goto out; } @@ -4920,7 +4920,7 @@ i915_gem_init_hw(struct drm_device *dev) if (ret && ret != -EIO) { DRM_ERROR("PPGTT enable ring #%d failed %d\n", i, ret); i915_gem_request_cancel(req); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); goto out; } @@ -4928,7 +4928,7 @@ i915_gem_init_hw(struct drm_device *dev) if (ret && ret != -EIO) { DRM_ERROR("Context enable ring #%d failed %d\n", i, ret); i915_gem_request_cancel(req); - i915_gem_cleanup_ringbuffer(dev); + i915_gem_cleanup_engines(dev); goto out; } @@ -4952,14 +4952,14 @@ int i915_gem_init(struct drm_device *dev) if (!i915.enable_execlists) { dev_priv->gt.execbuf_submit = i915_gem_ringbuffer_submission; - dev_priv->gt.init_rings = i915_gem_init_rings; - dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer; - dev_priv->gt.stop_ring = intel_stop_ring_buffer; + dev_priv->gt.init_engines = i915_gem_init_engines; + dev_priv->gt.cleanup_engine = intel_cleanup_engine; + dev_priv->gt.stop_engine = intel_stop_engine; } else { dev_priv->gt.execbuf_submit = intel_execlists_submission; - dev_priv->gt.init_rings = intel_logical_rings_init; - dev_priv->gt.cleanup_ring = intel_logical_ring_cleanup; - dev_priv->gt.stop_ring = intel_logical_ring_stop; + dev_priv->gt.init_engines = intel_logical_rings_init; + dev_priv->gt.cleanup_engine = intel_logical_ring_cleanup; + dev_priv->gt.stop_engine = intel_logical_ring_stop; } /* This is just a security blanket to placate dragons. @@ -4980,7 +4980,7 @@ int i915_gem_init(struct drm_device *dev) if (ret) goto out_unlock; - ret = dev_priv->gt.init_rings(dev); + ret = dev_priv->gt.init_engines(dev); if (ret) goto out_unlock; @@ -5003,14 +5003,14 @@ out_unlock: } void -i915_gem_cleanup_ringbuffer(struct drm_device *dev) +i915_gem_cleanup_engines(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; int i; for_each_engine(engine, dev_priv, i) - dev_priv->gt.cleanup_ring(engine); + dev_priv->gt.cleanup_engine(engine); if (i915.enable_execlists) /* diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index e0bca7d..ef9cd70 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c @@ -45,7 +45,7 @@ i915_verify_lists(struct drm_device *dev) for_each_engine(engine, dev_priv, i) { list_for_each_entry(obj, &engine->active_list, - ring_list[engine->id]) { + engine_list[engine->id]) { if (obj->base.dev != dev || !atomic_read(&obj->base.refcount.refcount)) { DRM_ERROR("%s: freed active obj %p\n", diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index c0545db..dac01ee 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1369,7 +1369,7 @@ eb_get_batch(struct eb_vmas *eb) #define I915_USER_RINGS (4) -static const enum intel_ring_id user_ring_map[I915_USER_RINGS + 1] = { +static const enum intel_engine_id user_ring_map[I915_USER_RINGS + 1] = { [I915_EXEC_DEFAULT] = RCS, [I915_EXEC_RENDER] = RCS, [I915_EXEC_BLT] = BCS, @@ -1417,7 +1417,7 @@ eb_select_ring(struct drm_i915_private *dev_priv, *ring = &dev_priv->engine[user_ring_map[user_ring_id]]; } - if (!intel_ring_initialized(*ring)) { + if (!intel_engine_initialized(*ring)) { DRM_DEBUG("execbuf with invalid ring: %u\n", user_ring_id); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 63ed77f..0f61ae0 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -996,7 +996,7 @@ static void ironlake_rps_change_irq_handler(struct drm_device *dev) static void notify_ring(struct intel_engine_cs *engine) { - if (!intel_ring_initialized(engine)) + if (!intel_engine_initialized(engine)) return; trace_i915_gem_request_notify(engine); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index f2cf0e1..f727822 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -795,7 +795,7 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request) intel_logical_ring_emit(ringbuf, MI_NOOP); intel_logical_ring_advance(ringbuf); - if (intel_ring_stopped(engine)) + if (intel_engine_stopped(engine)) return 0; if (engine->last_context != request->ctx) { @@ -1054,7 +1054,7 @@ void intel_logical_ring_stop(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = engine->dev->dev_private; int ret; - if (!intel_ring_initialized(engine)) + if (!intel_engine_initialized(engine)) return; ret = intel_engine_idle(engine); @@ -2012,7 +2012,7 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv; - if (!intel_ring_initialized(engine)) + if (!intel_engine_initialized(engine)) return; dev_priv = engine->dev->dev_private; @@ -2240,7 +2240,7 @@ static int logical_vebox_ring_init(struct drm_device *dev) * @dev: DRM device. * * This function inits the engines for an Execlists submission style (the equivalent in the - * legacy ringbuffer submission world would be i915_gem_init_rings). It does it only for + * legacy ringbuffer submission world would be i915_gem_init_engines). It does it only for * those engines that are present in the hardware. * * Return: non-zero if the initialization failed. diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c index 6e936c7..3c725dd 100644 --- a/drivers/gpu/drm/i915/intel_mocs.c +++ b/drivers/gpu/drm/i915/intel_mocs.c @@ -159,7 +159,7 @@ static bool get_mocs_settings(struct drm_device *dev, return result; } -static i915_reg_t mocs_register(enum intel_ring_id ring, int index) +static i915_reg_t mocs_register(enum intel_engine_id ring, int index) { switch (ring) { case RCS: @@ -191,7 +191,7 @@ static i915_reg_t mocs_register(enum intel_ring_id ring, int index) */ static int emit_mocs_control_table(struct drm_i915_gem_request *req, const struct drm_i915_mocs_table *table, - enum intel_ring_id ring) + enum intel_engine_id ring) { struct intel_ringbuffer *ringbuf = req->ringbuf; unsigned int index; @@ -325,7 +325,7 @@ int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req) if (get_mocs_settings(req->engine->dev, &t)) { struct drm_i915_private *dev_priv = req->i915; struct intel_engine_cs *engine; - enum intel_ring_id ring_id; + enum intel_engine_id ring_id; /* Program the control registers */ for_each_engine(engine, dev_priv, ring_id) { diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index f7493c5..015dc7d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -59,7 +59,7 @@ int intel_ring_space(struct intel_ringbuffer *ringbuf) return ringbuf->space; } -bool intel_ring_stopped(struct intel_engine_cs *engine) +bool intel_engine_stopped(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->dev->dev_private; return dev_priv->gpu_error.stop_rings & intel_engine_flag(engine); @@ -69,7 +69,7 @@ static void __intel_ring_advance(struct intel_engine_cs *engine) { struct intel_ringbuffer *ringbuf = engine->buffer; ringbuf->tail &= ringbuf->size - 1; - if (intel_ring_stopped(engine)) + if (intel_engine_stopped(engine)) return; engine->write_tail(engine, ringbuf->tail); } @@ -2274,21 +2274,21 @@ static int intel_init_ring_buffer(struct drm_device *dev, return 0; error: - intel_cleanup_ring_buffer(engine); + intel_cleanup_engine(engine); return ret; } -void intel_cleanup_ring_buffer(struct intel_engine_cs *engine) +void intel_cleanup_engine(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv; - if (!intel_ring_initialized(engine)) + if (!intel_engine_initialized(engine)) return; dev_priv = to_i915(engine->dev); if (engine->buffer) { - intel_stop_ring_buffer(engine); + intel_stop_engine(engine); WARN_ON(!IS_GEN2(engine->dev) && (I915_READ_MODE(engine) & MODE_IDLE) == 0); intel_unpin_ringbuffer_obj(engine->buffer); @@ -3163,11 +3163,11 @@ intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req) } void -intel_stop_ring_buffer(struct intel_engine_cs *engine) +intel_stop_engine(struct intel_engine_cs *engine) { int ret; - if (!intel_ring_initialized(engine)) + if (!intel_engine_initialized(engine)) return; ret = intel_engine_idle(engine); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index ee4d9a8..3e40f7b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -146,7 +146,7 @@ struct i915_ctx_workarounds { struct intel_engine_cs { const char *name; - enum intel_ring_id { + enum intel_engine_id { RCS = 0, BCS, VCS, @@ -355,7 +355,7 @@ struct intel_engine_cs { }; static inline bool -intel_ring_initialized(struct intel_engine_cs *engine) +intel_engine_initialized(struct intel_engine_cs *engine) { return engine->dev != NULL; } @@ -438,8 +438,8 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf); void intel_ringbuffer_free(struct intel_ringbuffer *ring); -void intel_stop_ring_buffer(struct intel_engine_cs *engine); -void intel_cleanup_ring_buffer(struct intel_engine_cs *engine); +void intel_stop_engine(struct intel_engine_cs *engine); +void intel_cleanup_engine(struct intel_engine_cs *engine); int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request); @@ -465,7 +465,7 @@ static inline void intel_ring_advance(struct intel_engine_cs *engine) int __intel_ring_space(int head, int tail, int size); void intel_ring_update_space(struct intel_ringbuffer *ringbuf); int intel_ring_space(struct intel_ringbuffer *ringbuf); -bool intel_ring_stopped(struct intel_engine_cs *engine); +bool intel_engine_stopped(struct intel_engine_cs *engine); int __must_check intel_engine_idle(struct intel_engine_cs *engine); void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno); -- cgit v0.10.2 From 7cc96139d9e3f627bd18e5ee6a5e4e305369865b Mon Sep 17 00:00:00 2001 From: Nathan Schulte Date: Tue, 15 Mar 2016 10:14:05 -0500 Subject: drm/i915: add module param "enable_dp_mst" Adds an (unsafe; auto-kernel-tainting) boolean module parameter to the i915 drm driver: "enable_dp_mst", which is enabled by default. Disabling the parameter forces newly connected DisplayPort sinks to report as not supporting multi-stream transport (MST), thus "forcing" the use of single-stream transport (SST). v2: rename parameter to conform to style v3: add signoff Signed-off-by: Nathan Schulte Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1458054845-5837-1-git-send-email-nmschulte@gmail.com diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 278c9c4..97691f1 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -56,6 +56,7 @@ struct i915_params i915 __read_mostly = { .edp_vswing = 0, .enable_guc_submission = false, .guc_log_level = -1, + .enable_dp_mst = true, }; module_param_named(modeset, i915.modeset, int, 0400); @@ -201,3 +202,7 @@ MODULE_PARM_DESC(enable_guc_submission, "Enable GuC submission (default:false)") module_param_named(guc_log_level, i915.guc_log_level, int, 0400); MODULE_PARM_DESC(guc_log_level, "GuC firmware logging level (-1:disabled (default), 0-3:enabled)"); + +module_param_named_unsafe(enable_dp_mst, i915.enable_dp_mst, bool, 0600); +MODULE_PARM_DESC(enable_dp_mst, + "Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)"); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index bd5026b..87153b0 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -59,6 +59,7 @@ struct i915_params { bool enable_guc_submission; bool verbose_state_checks; bool nuclear_pageflip; + bool enable_dp_mst; }; extern struct i915_params i915 __read_mostly; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0e326e7..ba2d024 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3882,6 +3882,9 @@ intel_dp_probe_mst(struct intel_dp *intel_dp) { u8 buf[1]; + if (!i915.enable_dp_mst) + return false; + if (!intel_dp->can_mst) return false; -- cgit v0.10.2 From 1bb4308e7130428917bfa54c556daa98f7aa1ac9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 7 Mar 2016 12:05:57 +0000 Subject: drm/i915/csr: Allow matching unknown HW steppings with generic firmware If the firmware is generic and has a run-anywhere mode, enable it rather than completely failing on unknown HW revisions. Signed-off-by: Chris Wilson Cc: Damien Lespiau Cc: Imre Deak Cc: Sunil Kamath Cc: Daniel Vetter Cc: Animesh Manna Cc: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1457352357-8433-1-git-send-email-chris@chris-wilson.co.uk diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index d417d9a..3f57cb9 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -188,28 +188,31 @@ static const struct stepping_info bxt_stepping_info[] = { {'B', '0'}, {'B', '1'}, {'B', '2'} }; -static const struct stepping_info *intel_get_stepping_info(struct drm_device *dev) +static const struct stepping_info no_stepping_info = { '*', '*' }; + +static const struct stepping_info * +intel_get_stepping_info(struct drm_i915_private *dev_priv) { const struct stepping_info *si; unsigned int size; - if (IS_KABYLAKE(dev)) { + if (IS_KABYLAKE(dev_priv)) { size = ARRAY_SIZE(kbl_stepping_info); si = kbl_stepping_info; - } else if (IS_SKYLAKE(dev)) { + } else if (IS_SKYLAKE(dev_priv)) { size = ARRAY_SIZE(skl_stepping_info); si = skl_stepping_info; - } else if (IS_BROXTON(dev)) { + } else if (IS_BROXTON(dev_priv)) { size = ARRAY_SIZE(bxt_stepping_info); si = bxt_stepping_info; } else { - return NULL; + size = 0; } - if (INTEL_REVID(dev) < size) - return si + INTEL_REVID(dev); + if (INTEL_REVID(dev_priv) < size) + return si + INTEL_REVID(dev_priv); - return NULL; + return &no_stepping_info; } static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv) @@ -270,13 +273,11 @@ void intel_csr_load_program(struct drm_i915_private *dev_priv) static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, const struct firmware *fw) { - struct drm_device *dev = dev_priv->dev; struct intel_css_header *css_header; struct intel_package_header *package_header; struct intel_dmc_header *dmc_header; struct intel_csr *csr = &dev_priv->csr; - const struct stepping_info *stepping_info = intel_get_stepping_info(dev); - char stepping, substepping; + const struct stepping_info *si = intel_get_stepping_info(dev_priv); uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes; uint32_t i; uint32_t *dmc_payload; @@ -284,14 +285,6 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, if (!fw) return NULL; - if (!stepping_info) { - DRM_ERROR("Unknown stepping info, firmware loading failed\n"); - return NULL; - } - - stepping = stepping_info->stepping; - substepping = stepping_info->substepping; - /* Extract CSS Header information*/ css_header = (struct intel_css_header *)fw->data; if (sizeof(struct intel_css_header) != @@ -303,7 +296,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, csr->version = css_header->version; - if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && + if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && csr->version < SKL_CSR_VERSION_REQUIRED) { DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u," " please upgrade to v%u.%u or later" @@ -331,11 +324,11 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, /* Search for dmc_offset to find firware binary. */ for (i = 0; i < package_header->num_entries; i++) { if (package_header->fw_info[i].substepping == '*' && - stepping == package_header->fw_info[i].stepping) { + si->stepping == package_header->fw_info[i].stepping) { dmc_offset = package_header->fw_info[i].offset; break; - } else if (stepping == package_header->fw_info[i].stepping && - substepping == package_header->fw_info[i].substepping) { + } else if (si->stepping == package_header->fw_info[i].stepping && + si->substepping == package_header->fw_info[i].substepping) { dmc_offset = package_header->fw_info[i].offset; break; } else if (package_header->fw_info[i].stepping == '*' && @@ -343,7 +336,8 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, dmc_offset = package_header->fw_info[i].offset; } if (dmc_offset == CSR_DEFAULT_FW_OFFSET) { - DRM_ERROR("Firmware not supported for %c stepping\n", stepping); + DRM_ERROR("Firmware not supported for %c stepping\n", + si->stepping); return NULL; } readcount += dmc_offset; @@ -389,9 +383,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, return NULL; } - memcpy(dmc_payload, &fw->data[readcount], nbytes); - - return dmc_payload; + return memcpy(dmc_payload, &fw->data[readcount], nbytes); } static void csr_load_work_fn(struct work_struct *work) -- cgit v0.10.2 From 42c151e65e80d22b611ba07812374ed726ebb947 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2016 12:21:39 +0200 Subject: drm/i915/dsi: lose the loose 666 format name in favor of packed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The enum mipi_dsi_pixel_format defines MIPI_DSI_FMT_RGB666 for the "loose" 24 bpp format and MIPI_DSI_FMT_RGB666_PACKED for the 18 bpp format. We have this the other way round, defining a loose version for 24 bpp. Follow suit with what's in enum mipi_dsi_pixel_format to avoid future confusion. Rename VID_MODE_FORMAT_RGB666 -> VID_MODE_FORMAT_RGB666_PACKED VID_MODE_FORMAT_RGB666_LOOSE -> VID_MODE_FORMAT_RGB666 Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458123700-16003-1-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7dfc400..85ceec6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7887,8 +7887,8 @@ enum skl_disp_power_wells { #define VID_MODE_FORMAT_MASK (0xf << 7) #define VID_MODE_NOT_SUPPORTED (0 << 7) #define VID_MODE_FORMAT_RGB565 (1 << 7) -#define VID_MODE_FORMAT_RGB666 (2 << 7) -#define VID_MODE_FORMAT_RGB666_LOOSE (3 << 7) +#define VID_MODE_FORMAT_RGB666_PACKED (2 << 7) +#define VID_MODE_FORMAT_RGB666 (3 << 7) #define VID_MODE_FORMAT_RGB888 (4 << 7) #define CMD_MODE_CHANNEL_NUMBER_SHIFT 5 #define CMD_MODE_CHANNEL_NUMBER_MASK (3 << 5) diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 2451c84..9ef0f78 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -37,10 +37,10 @@ int dsi_pixel_format_bpp(int pixel_format) switch (pixel_format) { default: case VID_MODE_FORMAT_RGB888: - case VID_MODE_FORMAT_RGB666_LOOSE: + case VID_MODE_FORMAT_RGB666: bpp = 24; break; - case VID_MODE_FORMAT_RGB666: + case VID_MODE_FORMAT_RGB666_PACKED: bpp = 18; break; case VID_MODE_FORMAT_RGB565: -- cgit v0.10.2 From 1e78aa014b84ff23f99daa0e0832b01337244062 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2016 12:21:40 +0200 Subject: drm/i915/dsi: start using enum mipi_dsi_pixel_format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A small step moving us closer to DRM MIPI DSI code. Use enum mipi_dsi_pixel_format instead of our own. The first benefit is being able to use common mipi_dsi_pixel_format_to_bpp(). There's a little back and forth conversion with the VBT -> enum -> register, since we have just shoved the VBT value into the register directly. Longer term, all the VBT parsing and deciphering should be done in intel_bios.c, and abstracted there. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458123700-16003-2-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 01b8e9f..ea78b0b 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -787,7 +787,7 @@ static void set_dsi_timings(struct drm_encoder *encoder, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; - unsigned int bpp = dsi_pixel_format_bpp(intel_dsi->pixel_format); + unsigned int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); unsigned int lane_count = intel_dsi->lane_count; u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp; @@ -849,6 +849,23 @@ static void set_dsi_timings(struct drm_encoder *encoder, } } +static u32 pixel_format_to_reg(enum mipi_dsi_pixel_format fmt) +{ + switch (fmt) { + case MIPI_DSI_FMT_RGB888: + return VID_MODE_FORMAT_RGB888; + case MIPI_DSI_FMT_RGB666: + return VID_MODE_FORMAT_RGB666; + case MIPI_DSI_FMT_RGB666_PACKED: + return VID_MODE_FORMAT_RGB666_PACKED; + case MIPI_DSI_FMT_RGB565: + return VID_MODE_FORMAT_RGB565; + default: + MISSING_CASE(fmt); + return VID_MODE_FORMAT_RGB666; + } +} + static void intel_dsi_prepare(struct intel_encoder *intel_encoder) { struct drm_encoder *encoder = &intel_encoder->base; @@ -858,7 +875,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode; enum port port; - unsigned int bpp = dsi_pixel_format_bpp(intel_dsi->pixel_format); + unsigned int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); u32 val, tmp; u16 mode_hdisplay; @@ -917,9 +934,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder) val |= CMD_MODE_DATA_WIDTH_8_BIT; /* XXX */ } else { val |= intel_dsi->channel << VID_MODE_CHANNEL_NUMBER_SHIFT; - - /* XXX: cross-check bpp vs. pixel format? */ - val |= intel_dsi->pixel_format; + val |= pixel_format_to_reg(intel_dsi->pixel_format); } tmp = 0; diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 92f3922..54f072c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -34,8 +34,6 @@ #define DSI_DUAL_LINK_FRONT_BACK 1 #define DSI_DUAL_LINK_PIXEL_ALT 2 -int dsi_pixel_format_bpp(int pixel_format); - struct intel_dsi_host; struct intel_dsi { @@ -64,8 +62,12 @@ struct intel_dsi { /* number of DSI lanes */ unsigned int lane_count; - /* video mode pixel format for MIPI_DSI_FUNC_PRG register */ - u32 pixel_format; + /* + * video mode pixel format + * + * XXX: consolidate on .format in struct mipi_dsi_device. + */ + enum mipi_dsi_pixel_format pixel_format; /* video mode format for MIPI_VIDEO_MODE_FORMAT register */ u32 video_mode_format; diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 7f145b4..8302a97 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -412,6 +412,25 @@ static const struct drm_panel_funcs vbt_panel_funcs = { .get_modes = vbt_panel_get_modes, }; +/* XXX: This should be done when parsing the VBT in intel_bios.c */ +static enum mipi_dsi_pixel_format pixel_format_from_vbt(u32 fmt) +{ + /* It just so happens the VBT matches register contents. */ + switch (fmt) { + case VID_MODE_FORMAT_RGB888: + return MIPI_DSI_FMT_RGB888; + case VID_MODE_FORMAT_RGB666: + return MIPI_DSI_FMT_RGB666; + case VID_MODE_FORMAT_RGB666_PACKED: + return MIPI_DSI_FMT_RGB666_PACKED; + case VID_MODE_FORMAT_RGB565: + return MIPI_DSI_FMT_RGB565; + default: + MISSING_CASE(fmt); + return MIPI_DSI_FMT_RGB666; + } +} + struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id) { struct drm_device *dev = intel_dsi->base.base.dev; @@ -420,7 +439,7 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id) struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps; struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode; struct vbt_panel *vbt_panel; - u32 bits_per_pixel = 24; + u32 bpp; u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui; u32 ui_num, ui_den; u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt; @@ -436,12 +455,11 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id) intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1; intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0; intel_dsi->lane_count = mipi_config->lane_cnt + 1; - intel_dsi->pixel_format = mipi_config->videomode_color_format << 7; + intel_dsi->pixel_format = pixel_format_from_vbt(mipi_config->videomode_color_format << 7); + bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); + intel_dsi->dual_link = mipi_config->dual_link; intel_dsi->pixel_overlap = mipi_config->pixel_overlap; - - bits_per_pixel = dsi_pixel_format_bpp(intel_dsi->pixel_format); - intel_dsi->operation_mode = mipi_config->is_cmd_mode; intel_dsi->video_mode_format = mipi_config->video_transfer_mode; intel_dsi->escape_clk_div = mipi_config->byte_clk_sel; @@ -475,8 +493,7 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id) */ if (intel_dsi->video_mode_format == VIDEO_MODE_BURST) { if (mipi_config->target_burst_mode_freq) { - computed_ddr = - (pclk * bits_per_pixel) / intel_dsi->lane_count; + computed_ddr = (pclk * bpp) / intel_dsi->lane_count; if (mipi_config->target_burst_mode_freq < computed_ddr) { @@ -499,7 +516,7 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id) intel_dsi->burst_mode_ratio = burst_mode_ratio; intel_dsi->pclk = pclk; - bitrate = (pclk * bits_per_pixel) / intel_dsi->lane_count; + bitrate = (pclk * bpp) / intel_dsi->lane_count; switch (intel_dsi->escape_clk_div) { case 0: diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 9ef0f78..e3e343c 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -30,27 +30,6 @@ #include "i915_drv.h" #include "intel_dsi.h" -int dsi_pixel_format_bpp(int pixel_format) -{ - int bpp; - - switch (pixel_format) { - default: - case VID_MODE_FORMAT_RGB888: - case VID_MODE_FORMAT_RGB666: - bpp = 24; - break; - case VID_MODE_FORMAT_RGB666_PACKED: - bpp = 18; - break; - case VID_MODE_FORMAT_RGB565: - bpp = 16; - break; - } - - return bpp; -} - struct dsi_mnp { u32 dsi_pll_ctrl; u32 dsi_pll_div; @@ -64,10 +43,11 @@ static const u32 lfsr_converts[] = { }; /* Get DSI clock from pixel clock */ -static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count) +static u32 dsi_clk_from_pclk(u32 pclk, enum mipi_dsi_pixel_format fmt, + int lane_count) { u32 dsi_clk_khz; - u32 bpp = dsi_pixel_format_bpp(pixel_format); + u32 bpp = mipi_dsi_pixel_format_to_bpp(fmt); /* DSI data rate = pixel clock * bits per pixel / lane count pixel clock is converted from KHz to Hz */ @@ -232,9 +212,9 @@ static void bxt_disable_dsi_pll(struct intel_encoder *encoder) DRM_ERROR("Timeout waiting for PLL lock deassertion\n"); } -static void assert_bpp_mismatch(int pixel_format, int pipe_bpp) +static void assert_bpp_mismatch(enum mipi_dsi_pixel_format fmt, int pipe_bpp) { - int bpp = dsi_pixel_format_bpp(pixel_format); + int bpp = mipi_dsi_pixel_format_to_bpp(fmt); WARN(bpp != pipe_bpp, "bpp match assertion failure (expected %d, current %d)\n", -- cgit v0.10.2 From c3aeadc8d3580b319d51c62fb82255b06a1c4fd8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 15 Mar 2016 21:51:09 +0200 Subject: drm/i915: add for_each_port_masked macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same as for_each_dsi_port, but for general use. Leave the for_each_dsi_port version around as an "alias" for now to not cause too much churn. No functional changes. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/a0ef5bf33395e1fcd87178b17d6687b022042cf7.1458070700.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fd1ed66..e5e2982 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -274,6 +274,10 @@ struct i915_hotplug { (__s) < INTEL_INFO(__dev_priv)->num_sprites[(__p)]; \ (__s)++) +#define for_each_port_masked(__port, __ports_mask) \ + for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++) \ + for_each_if ((__ports_mask) & (1 << (__port))) + #define for_each_crtc(dev, crtc) \ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 54f072c..e582ef8 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -119,9 +119,7 @@ static inline struct intel_dsi_host *to_intel_dsi_host(struct mipi_dsi_host *h) return container_of(h, struct intel_dsi_host, base); } -#define for_each_dsi_port(__port, __ports_mask) \ - for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++) \ - for_each_if ((__ports_mask) & (1 << (__port))) +#define for_each_dsi_port(__port, __ports_mask) for_each_port_masked(__port, __ports_mask) static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) { -- cgit v0.10.2 From da20563097796cdba10e253581861ad0e2b0c695 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 15 Mar 2016 21:51:10 +0200 Subject: drm/i915: make transcoder_name return a string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nicer for eDP (actually "EDP" instead of "D"), and makes future expansion for DSI transcoders easier. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/2ac55ed584e450fe154daecb6453dff8eede5e7d.1458070700.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e5e2982..33e1311 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -125,7 +125,22 @@ enum transcoder { TRANSCODER_EDP, I915_MAX_TRANSCODERS }; -#define transcoder_name(t) ((t) + 'A') + +static inline const char *transcoder_name(enum transcoder transcoder) +{ + switch (transcoder) { + case TRANSCODER_A: + return "A"; + case TRANSCODER_B: + return "B"; + case TRANSCODER_C: + return "C"; + case TRANSCODER_EDP: + return "EDP"; + default: + return ""; + } +} /* * I915_MAX_PLANES in the enum below is the maximum (across all platforms) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 79eea3d..f3bcafa 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12092,7 +12092,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, DRM_DEBUG_KMS("[CRTC:%d]%s config %p for pipe %c\n", crtc->base.base.id, context, pipe_config, pipe_name(crtc->pipe)); - DRM_DEBUG_KMS("cpu_transcoder: %c\n", transcoder_name(pipe_config->cpu_transcoder)); + DRM_DEBUG_KMS("cpu_transcoder: %s\n", transcoder_name(pipe_config->cpu_transcoder)); DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n", pipe_config->pipe_bpp, pipe_config->dither); DRM_DEBUG_KMS("fdi/pch: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n", @@ -16221,7 +16221,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, } for (i = 0; i < error->num_transcoders; i++) { - err_printf(m, "CPU transcoder: %c\n", + err_printf(m, "CPU transcoder: %s\n", transcoder_name(error->transcoder[i].cpu_transcoder)); err_printf(m, " Power: %s\n", onoff(error->transcoder[i].power_domain_on)); diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index bda5266..19e50fd 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -212,7 +212,7 @@ static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc) I915_WRITE(SERR_INT, SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)); POSTING_READ(SERR_INT); - DRM_ERROR("pch fifo underrun on pch transcoder %c\n", + DRM_ERROR("pch fifo underrun on pch transcoder %s\n", transcoder_name(pch_transcoder)); } @@ -235,7 +235,7 @@ static void cpt_set_fifo_underrun_reporting(struct drm_device *dev, if (old && I915_READ(SERR_INT) & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) { - DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n", + DRM_ERROR("uncleared pch fifo underrun on pch transcoder %s\n", transcoder_name(pch_transcoder)); } } @@ -386,7 +386,7 @@ void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, { if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder, false)) - DRM_ERROR("PCH transcoder %c FIFO underrun\n", + DRM_ERROR("PCH transcoder %s FIFO underrun\n", transcoder_name(pch_transcoder)); } -- cgit v0.10.2 From 1dcec2f39f128d3cb4784a0889f6c70aab675ed2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 15 Mar 2016 21:51:11 +0200 Subject: drm/i915/dsi: refactor dsi get hw state readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the code easier to read and update. No functional changes. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/04b20a9be6a9481ca2eb2a42cdcdc27358152e5f.1458070700.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index ea78b0b..3260665 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -667,7 +667,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, struct drm_device *dev = encoder->base.dev; enum intel_display_power_domain power_domain; enum port port; - bool ret; + bool active = false; DRM_DEBUG_KMS("\n"); @@ -675,38 +675,39 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; - ret = false; - /* XXX: this only works for one DSI output */ for_each_dsi_port(port, intel_dsi->ports) { i915_reg_t ctrl_reg = IS_BROXTON(dev) ? BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); - u32 dpi_enabled, func; - - func = I915_READ(MIPI_DSI_FUNC_PRG(port)); - dpi_enabled = I915_READ(ctrl_reg) & DPI_ENABLE; + bool enabled = I915_READ(ctrl_reg) & DPI_ENABLE; /* Due to some hardware limitations on BYT, MIPI Port C DPI * Enable bit does not get set. To check whether DSI Port C * was enabled in BIOS, check the Pipe B enable bit */ if (IS_VALLEYVIEW(dev) && port == PORT_C) - dpi_enabled = I915_READ(PIPECONF(PIPE_B)) & - PIPECONF_ENABLE; + enabled = I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE; - if (dpi_enabled || (func & CMD_MODE_DATA_WIDTH_MASK)) { - if (I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY) { - *pipe = port == PORT_A ? PIPE_A : PIPE_B; - ret = true; - - goto out; - } + /* Try command mode if video mode not enabled */ + if (!enabled) { + u32 tmp = I915_READ(MIPI_DSI_FUNC_PRG(port)); + enabled = tmp & CMD_MODE_DATA_WIDTH_MASK; } + + if (!enabled) + continue; + + if (!(I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY)) + continue; + + *pipe = port == PORT_A ? PIPE_A : PIPE_B; + active = true; + break; } -out: + intel_display_power_put(dev_priv, power_domain); - return ret; + return active; } static void intel_dsi_get_config(struct intel_encoder *encoder, -- cgit v0.10.2 From 6b93e9c89ee553c1f062cd5c7dcd35e06846568f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 15 Mar 2016 21:51:12 +0200 Subject: drm/i915/bxt: fix dsi hw state pipe readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BXT isn't as limited as BYT and CHT regarding DSI pipes and ports. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/8bea85b86aaf7a15f854a656bf8d3208a3afe0bd.1458070700.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 85ceec6..d4a298f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8144,6 +8144,7 @@ enum skl_disp_power_wells { #define READ_REQUEST_PRIORITY_HIGH (3 << 3) #define RGB_FLIP_TO_BGR (1 << 2) +#define BXT_PIPE_SELECT_SHIFT 7 #define BXT_PIPE_SELECT_MASK (7 << 7) #define BXT_PIPE_SELECT(pipe) ((pipe) << 7) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 3260665..4756346 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -700,7 +700,19 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, if (!(I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY)) continue; - *pipe = port == PORT_A ? PIPE_A : PIPE_B; + if (IS_BROXTON(dev_priv)) { + u32 tmp = I915_READ(MIPI_CTRL(port)); + tmp &= BXT_PIPE_SELECT_MASK; + tmp >>= BXT_PIPE_SELECT_SHIFT; + + if (WARN_ON(tmp > PIPE_C)) + continue; + + *pipe = tmp; + } else { + *pipe = port == PORT_A ? PIPE_A : PIPE_B; + } + active = true; break; } -- cgit v0.10.2 From 3bdd14d542c207528b6ca71946c79b39af39ea51 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2016 12:43:29 +0200 Subject: drm/i915: move VBT based TV presence check to intel_bios.c Hide knowledge about VBT child devices in intel_bios.c. v2: also move int_tv_support check to intel_bios.c (Sivakumar) Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458125015-7931-1-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 33e1311..3724edd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3353,6 +3353,7 @@ extern void intel_i2c_reset(struct drm_device *dev); /* intel_bios.c */ int intel_bios_init(struct drm_i915_private *dev_priv); bool intel_bios_is_valid_vbt(const void *buf, size_t size); +bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); /* intel_opregion.c */ #ifdef CONFIG_ACPI diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index bf62a19..d5e6da0 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1431,3 +1431,44 @@ intel_bios_init(struct drm_i915_private *dev_priv) return 0; } + +/** + * intel_bios_is_tv_present - is integrated TV present in VBT + * @dev_priv: i915 device instance + * + * Return true if TV is present. If no child devices were parsed from VBT, + * assume TV is present. + */ +bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv) +{ + union child_device_config *p_child; + int i; + + if (!dev_priv->vbt.int_tv_support) + return false; + + if (!dev_priv->vbt.child_dev_num) + return true; + + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { + p_child = dev_priv->vbt.child_dev + i; + /* + * If the device type is not TV, continue. + */ + switch (p_child->old.device_type) { + case DEVICE_TYPE_INT_TV: + case DEVICE_TYPE_TV: + case DEVICE_TYPE_TV_SVIDEO_COMPOSITE: + break; + default: + continue; + } + /* Only when the addin_offset is non-zero, it is regarded + * as present. + */ + if (p_child->old.addin_offset) + return true; + } + + return false; +} diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index d5570c8..223129d 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1519,47 +1519,6 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = { .destroy = intel_encoder_destroy, }; -/* - * Enumerate the child dev array parsed from VBT to check whether - * the integrated TV is present. - * If it is present, return 1. - * If it is not present, return false. - * If no child dev is parsed from VBT, it assumes that the TV is present. - */ -static int tv_is_present_in_vbt(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - union child_device_config *p_child; - int i, ret; - - if (!dev_priv->vbt.child_dev_num) - return 1; - - ret = 0; - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - p_child = dev_priv->vbt.child_dev + i; - /* - * If the device type is not TV, continue. - */ - switch (p_child->old.device_type) { - case DEVICE_TYPE_INT_TV: - case DEVICE_TYPE_TV: - case DEVICE_TYPE_TV_SVIDEO_COMPOSITE: - break; - default: - continue; - } - /* Only when the addin_offset is non-zero, it is regarded - * as present. - */ - if (p_child->old.addin_offset) { - ret = 1; - break; - } - } - return ret; -} - void intel_tv_init(struct drm_device *dev) { @@ -1575,13 +1534,10 @@ intel_tv_init(struct drm_device *dev) if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) return; - if (!tv_is_present_in_vbt(dev)) { + if (!intel_bios_is_tv_present(dev_priv)) { DRM_DEBUG_KMS("Integrated TV is not present.\n"); return; } - /* Even if we have an encoder we may not have a connector */ - if (!dev_priv->vbt.int_tv_support) - return; /* * Sanity check the TV output by checking to see if the -- cgit v0.10.2 From 5a69d13d78d730261edcf83a96704f388c6357d1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2016 12:43:30 +0200 Subject: drm/i915: move VBT based LVDS presence check to intel_bios.c Hide knowledge about VBT child devices in intel_bios.c. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458125015-7931-2-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3724edd..c3c8663 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3354,6 +3354,7 @@ extern void intel_i2c_reset(struct drm_device *dev); int intel_bios_init(struct drm_i915_private *dev_priv); bool intel_bios_is_valid_vbt(const void *buf, size_t size); bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); +bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); /* intel_opregion.c */ #ifdef CONFIG_ACPI diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index d5e6da0..4f7eba3 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1472,3 +1472,53 @@ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv) return false; } + +/** + * intel_bios_is_lvds_present - is LVDS present in VBT + * @dev_priv: i915 device instance + * @i2c_pin: i2c pin for LVDS if present + * + * Return true if LVDS is present. If no child devices were parsed from VBT, + * assume LVDS is present. + */ +bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin) +{ + int i; + + if (!dev_priv->vbt.child_dev_num) + return true; + + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { + union child_device_config *uchild = dev_priv->vbt.child_dev + i; + struct old_child_dev_config *child = &uchild->old; + + /* If the device type is not LFP, continue. + * We have to check both the new identifiers as well as the + * old for compatibility with some BIOSes. + */ + if (child->device_type != DEVICE_TYPE_INT_LFP && + child->device_type != DEVICE_TYPE_LFP) + continue; + + if (intel_gmbus_is_valid_pin(dev_priv, child->i2c_pin)) + *i2c_pin = child->i2c_pin; + + /* However, we cannot trust the BIOS writers to populate + * the VBT correctly. Since LVDS requires additional + * information from AIM blocks, a non-zero addin offset is + * a good indicator that the LVDS is actually present. + */ + if (child->addin_offset) + return true; + + /* But even then some BIOS writers perform some black magic + * and instantiate the device without reference to any + * additional data. Trust that if the VBT was written into + * the OpRegion then they have validated the LVDS's existence. + */ + if (dev_priv->opregion.vbt) + return true; + } + + return false; +} diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index cbd1b0d..766ba56 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -775,57 +775,6 @@ static const struct dmi_system_id intel_no_lvds[] = { { } /* terminating entry */ }; -/* - * Enumerate the child dev array parsed from VBT to check whether - * the LVDS is present. - * If it is present, return 1. - * If it is not present, return false. - * If no child dev is parsed from VBT, it assumes that the LVDS is present. - */ -static bool lvds_is_present_in_vbt(struct drm_device *dev, - u8 *i2c_pin) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int i; - - if (!dev_priv->vbt.child_dev_num) - return true; - - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - union child_device_config *uchild = dev_priv->vbt.child_dev + i; - struct old_child_dev_config *child = &uchild->old; - - /* If the device type is not LFP, continue. - * We have to check both the new identifiers as well as the - * old for compatibility with some BIOSes. - */ - if (child->device_type != DEVICE_TYPE_INT_LFP && - child->device_type != DEVICE_TYPE_LFP) - continue; - - if (intel_gmbus_is_valid_pin(dev_priv, child->i2c_pin)) - *i2c_pin = child->i2c_pin; - - /* However, we cannot trust the BIOS writers to populate - * the VBT correctly. Since LVDS requires additional - * information from AIM blocks, a non-zero addin offset is - * a good indicator that the LVDS is actually present. - */ - if (child->addin_offset) - return true; - - /* But even then some BIOS writers perform some black magic - * and instantiate the device without reference to any - * additional data. Trust that if the VBT was written into - * the OpRegion then they have validated the LVDS's existence. - */ - if (dev_priv->opregion.vbt) - return true; - } - - return false; -} - static int intel_dual_link_lvds_callback(const struct dmi_system_id *id) { DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident); @@ -982,7 +931,7 @@ void intel_lvds_init(struct drm_device *dev) } pin = GMBUS_PIN_PANEL; - if (!lvds_is_present_in_vbt(dev, &pin)) { + if (!intel_bios_is_lvds_present(dev_priv, &pin)) { if ((lvds & LVDS_PORT_EN) == 0) { DRM_DEBUG_KMS("LVDS is not present in VBT\n"); return; -- cgit v0.10.2 From 951d9efe07877a3f1bb04e8932d11eafbfad02bf Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2016 12:43:31 +0200 Subject: drm/i915: move VBT based eDP port check to intel_bios.c Hide knowledge about VBT child devices in intel_bios.c. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458125015-7931-3-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c3c8663..e252978 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3355,6 +3355,7 @@ int intel_bios_init(struct drm_i915_private *dev_priv); bool intel_bios_is_valid_vbt(const void *buf, size_t size); bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); +bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port); /* intel_opregion.c */ #ifdef CONFIG_ACPI diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4f7eba3..7f61ca8 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1522,3 +1522,36 @@ bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin) return false; } + +/** + * intel_bios_is_port_edp - is the device in given port eDP + * @dev_priv: i915 device instance + * @port: port to check + * + * Return true if the device in %port is eDP. + */ +bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port) +{ + union child_device_config *p_child; + static const short port_mapping[] = { + [PORT_B] = DVO_PORT_DPB, + [PORT_C] = DVO_PORT_DPC, + [PORT_D] = DVO_PORT_DPD, + [PORT_E] = DVO_PORT_DPE, + }; + int i; + + if (!dev_priv->vbt.child_dev_num) + return false; + + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { + p_child = dev_priv->vbt.child_dev + i; + + if (p_child->common.dvo_port == port_mapping[port] && + (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) == + (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS)) + return true; + } + + return false; +} diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ba2d024..3ff8f1d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4993,14 +4993,6 @@ put_power: bool intel_dp_is_edp(struct drm_device *dev, enum port port) { struct drm_i915_private *dev_priv = dev->dev_private; - union child_device_config *p_child; - int i; - static const short port_mapping[] = { - [PORT_B] = DVO_PORT_DPB, - [PORT_C] = DVO_PORT_DPC, - [PORT_D] = DVO_PORT_DPD, - [PORT_E] = DVO_PORT_DPE, - }; /* * eDP not supported on g4x. so bail out early just @@ -5012,18 +5004,7 @@ bool intel_dp_is_edp(struct drm_device *dev, enum port port) if (port == PORT_A) return true; - if (!dev_priv->vbt.child_dev_num) - return false; - - for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { - p_child = dev_priv->vbt.child_dev + i; - - if (p_child->common.dvo_port == port_mapping[port] && - (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) == - (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS)) - return true; - } - return false; + return intel_bios_is_port_edp(dev_priv, port); } void -- cgit v0.10.2 From 7137aec1cfd3fd417023ce4edd0f348e5d72115f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2016 12:43:32 +0200 Subject: drm/i915: move VBT based DSI presence check to intel_bios.c Hide knowledge about VBT child devices in intel_bios.c. v2: Move port check to intel_bios.c (Sivakumar) Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458125015-7931-4-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e252978..f6a84ba 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1468,7 +1468,6 @@ struct intel_vbt_data { /* MIPI DSI */ struct { - u16 port; u16 panel_id; struct mipi_config *config; struct mipi_pps_data *pps; @@ -3356,6 +3355,7 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size); bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port); +bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port); /* intel_opregion.c */ #ifdef CONFIG_ACPI diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 7f61ca8..4b6bd6f 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1237,7 +1237,6 @@ parse_device_mapping(struct drm_i915_private *dev_priv, &&p_child->common.device_type & DEVICE_TYPE_MIPI_OUTPUT) { DRM_DEBUG_KMS("Found MIPI as LFP\n"); dev_priv->vbt.has_mipi = 1; - dev_priv->vbt.dsi.port = p_child->common.dvo_port; } child_dev_ptr = dev_priv->vbt.child_dev + count; @@ -1555,3 +1554,41 @@ bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port) return false; } + +/** + * intel_bios_is_dsi_present - is DSI present in VBT + * @dev_priv: i915 device instance + * @port: port for DSI if present + * + * Return true if DSI is present, and return the port in %port. + */ +bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, + enum port *port) +{ + union child_device_config *p_child; + u8 dvo_port; + int i; + + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { + p_child = dev_priv->vbt.child_dev + i; + + if (!(p_child->common.device_type & DEVICE_TYPE_MIPI_OUTPUT)) + continue; + + dvo_port = p_child->common.dvo_port; + + switch (dvo_port) { + case DVO_PORT_MIPIA: + case DVO_PORT_MIPIC: + *port = dvo_port - DVO_PORT_MIPIA; + return true; + case DVO_PORT_MIPIB: + case DVO_PORT_MIPID: + DRM_DEBUG_KMS("VBT has unsupported DSI port %c\n", + port_name(dvo_port - DVO_PORT_MIPIA)); + break; + } + } + + return false; +} diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 4756346..3562bf3 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -1149,7 +1149,7 @@ void intel_dsi_init(struct drm_device *dev) DRM_DEBUG_KMS("\n"); /* There is no detection method for MIPI so rely on VBT */ - if (!dev_priv->vbt.has_mipi) + if (!intel_bios_is_dsi_present(dev_priv, &port)) return; if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { @@ -1190,16 +1190,15 @@ void intel_dsi_init(struct drm_device *dev) intel_connector->unregister = intel_connector_unregister; /* Pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI port C */ - if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIA) { - intel_encoder->crtc_mask = (1 << PIPE_A); - intel_dsi->ports = (1 << PORT_A); - } else if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIC) { - intel_encoder->crtc_mask = (1 << PIPE_B); - intel_dsi->ports = (1 << PORT_C); - } + if (port == PORT_A) + intel_encoder->crtc_mask = 1 << PIPE_A; + else + intel_encoder->crtc_mask = 1 << PIPE_B; if (dev_priv->vbt.dsi.config->dual_link) - intel_dsi->ports = ((1 << PORT_A) | (1 << PORT_C)); + intel_dsi->ports = (1 << PORT_A) | (1 << PORT_C); + else + intel_dsi->ports = 1 << port; /* Create a DSI host (and a device) for each port. */ for_each_dsi_port(port, intel_dsi->ports) { -- cgit v0.10.2 From 92c4565e93609314b34bb810ba54cb73eb006987 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2016 12:43:33 +0200 Subject: drm/i915/panel: setup pwm backlight based on connector type Use the connector type instead of VBT directly to decide which backlight mechanism to use on VLV/CHV. (Indirectly, this is the same thing, but hides the VBT use.) Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458125015-7931-5-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 0fe059b..8c8996f 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1743,7 +1743,7 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel) panel->backlight.get = pch_get_backlight; panel->backlight.hz_to_pwm = pch_hz_to_pwm; } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - if (dev_priv->vbt.has_mipi) { + if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) { panel->backlight.setup = pwm_setup_backlight; panel->backlight.enable = pwm_enable_backlight; panel->backlight.disable = pwm_disable_backlight; -- cgit v0.10.2 From 7caaef332abaae872ddd2cd65bbe8a8bc0d8f5cc Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2016 12:43:34 +0200 Subject: drm/i915/bios: drop has_mipi in favor of intel_bios_is_dsi_present Favor a single point of truth instead of duplicating the information. The change also filters out unsupported DSI ports at this stage, accepting only ports A and C, instead of waiting until the port checks. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458125015-7931-6-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f6a84ba..8a10c4b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1434,7 +1434,6 @@ struct intel_vbt_data { unsigned int lvds_use_ssc:1; unsigned int display_clock_mode:1; unsigned int fdi_rx_polarity_inverted:1; - unsigned int has_mipi:1; int lvds_ssc_freq; unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */ diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4b6bd6f..aa90dc6 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -706,7 +706,7 @@ parse_mipi_config(struct drm_i915_private *dev_priv, const struct mipi_pps_data *pps; /* parse MIPI blocks only if LFP type is MIPI */ - if (!dev_priv->vbt.has_mipi) + if (!intel_bios_is_dsi_present(dev_priv, NULL)) return; /* Initialize this to undefined indicating no generic MIPI support */ @@ -1232,13 +1232,6 @@ parse_device_mapping(struct drm_i915_private *dev_priv, continue; } - if (p_child->common.dvo_port >= DVO_PORT_MIPIA - && p_child->common.dvo_port <= DVO_PORT_MIPID - &&p_child->common.device_type & DEVICE_TYPE_MIPI_OUTPUT) { - DRM_DEBUG_KMS("Found MIPI as LFP\n"); - dev_priv->vbt.has_mipi = 1; - } - child_dev_ptr = dev_priv->vbt.child_dev + count; count++; @@ -1580,7 +1573,8 @@ bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, switch (dvo_port) { case DVO_PORT_MIPIA: case DVO_PORT_MIPIC: - *port = dvo_port - DVO_PORT_MIPIA; + if (port) + *port = dvo_port - DVO_PORT_MIPIA; return true; case DVO_PORT_MIPIB: case DVO_PORT_MIPID: -- cgit v0.10.2 From ab65cce821cc46ccdc0b62f99bb79f75c1c7412c Mon Sep 17 00:00:00 2001 From: Alex Dai Date: Wed, 16 Mar 2016 15:24:13 -0700 Subject: drm/i915/guc: Support GuC SKL v6.1 This version of GuC firmware fixes the engine reset issue where golden context LRC address is treated as page index by mistake. It also fixes the problem that scheduler stops submiting to one engine when the other engine work queue is full. Signed-off-by: Alex Dai Reviewed-by: Dave Gordon Signed-off-by: Rodrigo Vivi diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 9f30921..e1aff62 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -59,7 +59,7 @@ * */ -#define I915_SKL_GUC_UCODE "i915/skl_guc_ver4.bin" +#define I915_SKL_GUC_UCODE "i915/skl_guc_ver6.bin" MODULE_FIRMWARE(I915_SKL_GUC_UCODE); /* User-friendly representation of an enum */ @@ -595,8 +595,8 @@ void intel_guc_ucode_init(struct drm_device *dev) fw_path = NULL; } else if (IS_SKYLAKE(dev)) { fw_path = I915_SKL_GUC_UCODE; - guc_fw->guc_fw_major_wanted = 4; - guc_fw->guc_fw_minor_wanted = 3; + guc_fw->guc_fw_major_wanted = 6; + guc_fw->guc_fw_minor_wanted = 1; } else { i915.enable_guc_submission = false; fw_path = ""; /* unknown device */ -- cgit v0.10.2 From 1f7717552ef1306be3b7ed28c66c6eff550e3a23 Mon Sep 17 00:00:00 2001 From: Lyude Date: Wed, 16 Mar 2016 15:18:04 -0400 Subject: drm/i915: Fix race condition in intel_dp_destroy_mst_connector() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After unplugging a DP MST display from the system, we have to go through and destroy all of the DRM connectors associated with it since none of them are valid anymore. Unfortunately, intel_dp_destroy_mst_connector() doesn't do a good enough job of ensuring that throughout the destruction process that no modesettings can be done with the connectors. As it is right now, intel_dp_destroy_mst_connector() works like this: * Take all modeset locks * Clear the configuration of the crtc on the connector, if there is one * Drop all modeset locks, this is required because of circular dependency issues that arise with trying to remove the connector from sysfs with modeset locks held * Unregister the connector * Take all modeset locks, again * Do the rest of the required cleaning for destroying the connector * Finally drop all modeset locks for good This only works sometimes. During the destruction process, it's very possible that a userspace application will attempt to do a modesetting using the connector. When we drop the modeset locks, an ioctl handler such as drm_mode_setcrtc has the oppurtunity to take all of the modeset locks from us. When this happens, one thing leads to another and eventually we end up committing a mode with the non-existent connector: [drm:intel_dp_link_training_clock_recovery [i915]] *ERROR* failed to enable link training [drm:intel_dp_aux_ch] dp_aux_ch timeout status 0x7cf0001f [drm:intel_dp_start_link_train [i915]] *ERROR* failed to start channel equalization [drm:intel_dp_aux_ch] dp_aux_ch timeout status 0x7cf0001f [drm:intel_mst_pre_enable_dp [i915]] *ERROR* failed to allocate vcpi And in some cases, such as with the T460s using an MST dock, this results in breaking modesetting and/or panicking the system. To work around this, we now unregister the connector at the very beginning of intel_dp_destroy_mst_connector(), grab all the modesetting locks, and then hold them until we finish the rest of the function. CC: stable@vger.kernel.org Signed-off-by: Lyude Signed-off-by: Rob Clark Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1458155884-13877-1-git-send-email-cpaul@redhat.com diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 8d1b703..94b4e83 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -502,6 +502,8 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_device *dev = connector->dev; + intel_connector->unregister(intel_connector); + /* need to nuke the connector */ drm_modeset_lock_all(dev); if (connector->state->crtc) { @@ -515,11 +517,7 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, WARN(ret, "Disabling mst crtc failed with %i\n", ret); } - drm_modeset_unlock_all(dev); - intel_connector->unregister(intel_connector); - - drm_modeset_lock_all(dev); intel_connector_remove_from_fbdev(intel_connector); drm_connector_cleanup(connector); drm_modeset_unlock_all(dev); -- cgit v0.10.2 From 2dd66ebde4431c93bfa211bc967a6f2089283aa6 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 14 Mar 2016 09:27:52 +0100 Subject: drm/i915: Use a crtc mask instead of a refcount for dpll functions, v2. This makes it easier to verify correct dpll setup with only a single crtc. It is also useful to detect double dpll enable/disable. Changes since v1: - Rebase on top of Ander's dpll rework. - Change debugfs active to a mask. - Change enabled_crtcs and active_crtcs to unsigned. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457944075-14123-2-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ander Conselvan de Oliveira diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1d8c3ef..ccdca2c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3212,8 +3212,8 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->name, pll->id); - seq_printf(m, " crtc_mask: 0x%08x, active: %d, on: %s\n", - pll->config.crtc_mask, pll->active, yesno(pll->on)); + seq_printf(m, " crtc_mask: 0x%08x, active: 0x%x, on: %s\n", + pll->config.crtc_mask, pll->active_mask, yesno(pll->on)); seq_printf(m, " tracked hardware state:\n"); seq_printf(m, " dpll: 0x%08x\n", pll->config.hw_state.dpll); seq_printf(m, " dpll_md: 0x%08x\n", diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f3bcafa..089d65e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12962,7 +12962,7 @@ check_shared_dpll_state(struct drm_device *dev) for (i = 0; i < dev_priv->num_shared_dpll; i++) { struct intel_shared_dpll *pll = intel_get_shared_dpll_by_id(dev_priv, i); - int enabled_crtcs = 0, active_crtcs = 0; + unsigned enabled_crtcs = 0, active_crtcs = 0; bool active; memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); @@ -12971,15 +12971,15 @@ check_shared_dpll_state(struct drm_device *dev) active = pll->funcs.get_hw_state(dev_priv, pll, &dpll_hw_state); - I915_STATE_WARN(pll->active > hweight32(pll->config.crtc_mask), - "more active pll users than references: %i vs %i\n", - pll->active, hweight32(pll->config.crtc_mask)); - I915_STATE_WARN(pll->active && !pll->on, - "pll in active use but not on in sw tracking\n"); + I915_STATE_WARN(pll->active_mask & ~pll->config.crtc_mask, + "more active pll users than references: %x vs %x\n", + pll->active_mask, pll->config.crtc_mask); if (!(pll->flags & INTEL_DPLL_ALWAYS_ON)) { - I915_STATE_WARN(pll->on && !pll->active, - "pll in on but not on in use in sw tracking\n"); + I915_STATE_WARN(!pll->on && pll->active_mask, + "pll in active use but not on in sw tracking\n"); + I915_STATE_WARN(pll->on && !pll->active_mask, + "pll is on but not used by any active crtc\n"); I915_STATE_WARN(pll->on != active, "pll on state mismatch (expected %i, found %i)\n", pll->on, active); @@ -12987,16 +12987,17 @@ check_shared_dpll_state(struct drm_device *dev) for_each_intel_crtc(dev, crtc) { if (crtc->base.state->enable && crtc->config->shared_dpll == pll) - enabled_crtcs++; - if (crtc->active && crtc->config->shared_dpll == pll) - active_crtcs++; + enabled_crtcs |= 1 << drm_crtc_index(&crtc->base); + if (crtc->base.state->active && crtc->config->shared_dpll == pll) + active_crtcs |= 1 << drm_crtc_index(&crtc->base); } - I915_STATE_WARN(pll->active != active_crtcs, - "pll active crtcs mismatch (expected %i, found %i)\n", - pll->active, active_crtcs); - I915_STATE_WARN(hweight32(pll->config.crtc_mask) != enabled_crtcs, - "pll enabled crtcs mismatch (expected %i, found %i)\n", - hweight32(pll->config.crtc_mask), enabled_crtcs); + + I915_STATE_WARN(pll->active_mask != active_crtcs, + "pll active crtcs mismatch (expected %x, found %x)\n", + pll->active_mask, active_crtcs); + I915_STATE_WARN(pll->config.crtc_mask != enabled_crtcs, + "pll enabled crtcs mismatch (expected %x, found %x)\n", + pll->config.crtc_mask, enabled_crtcs); I915_STATE_WARN(pll->on && memcmp(&pll->config.hw_state, &dpll_hw_state, sizeof(dpll_hw_state)), @@ -15694,14 +15695,12 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) pll->on = pll->funcs.get_hw_state(dev_priv, pll, &pll->config.hw_state); - pll->active = 0; pll->config.crtc_mask = 0; for_each_intel_crtc(dev, crtc) { - if (crtc->active && crtc->config->shared_dpll == pll) { - pll->active++; + if (crtc->active && crtc->config->shared_dpll == pll) pll->config.crtc_mask |= 1 << crtc->pipe; - } } + pll->active_mask = pll->config.crtc_mask; DRM_DEBUG_KMS("%s hw state readout: crtc_mask 0x%08x, on %i\n", pll->name, pll->config.crtc_mask, pll->on); @@ -15825,7 +15824,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev) for (i = 0; i < dev_priv->num_shared_dpll; i++) { struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i]; - if (!pll->on || pll->active) + if (!pll->on || pll->active_mask) continue; DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name); diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 74d5aec..9bf2c39 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -90,7 +90,7 @@ void intel_prepare_shared_dpll(struct intel_crtc *crtc) return; WARN_ON(!pll->config.crtc_mask); - if (pll->active == 0) { + if (pll->active_mask == 0) { DRM_DEBUG_DRIVER("setting up %s\n", pll->name); WARN_ON(pll->on); assert_shared_dpll_disabled(dev_priv, pll); @@ -112,18 +112,23 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_shared_dpll *pll = crtc->config->shared_dpll; + unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base); + unsigned old_mask = pll->active_mask; if (WARN_ON(pll == NULL)) return; - if (WARN_ON(pll->config.crtc_mask == 0)) + if (WARN_ON(!(pll->config.crtc_mask & crtc_mask)) || + WARN_ON(pll->active_mask & crtc_mask)) return; - DRM_DEBUG_KMS("enable %s (active %d, on? %d) for crtc %d\n", - pll->name, pll->active, pll->on, + pll->active_mask |= crtc_mask; + + DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n", + pll->name, pll->active_mask, pll->on, crtc->base.base.id); - if (pll->active++) { + if (old_mask) { WARN_ON(!pll->on); assert_shared_dpll_enabled(dev_priv, pll); return; @@ -142,6 +147,7 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_shared_dpll *pll = crtc->config->shared_dpll; + unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base); /* PCH only available on ILK+ */ if (INTEL_INFO(dev)->gen < 5) @@ -150,21 +156,18 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) if (pll == NULL) return; - if (WARN_ON(!(pll->config.crtc_mask & (1 << drm_crtc_index(&crtc->base))))) + if (WARN_ON(!(pll->config.crtc_mask & crtc_mask))) return; - DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n", - pll->name, pll->active, pll->on, + DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n", + pll->name, pll->active_mask, pll->on, crtc->base.base.id); - if (WARN_ON(pll->active == 0)) { - assert_shared_dpll_disabled(dev_priv, pll); - return; - } - assert_shared_dpll_enabled(dev_priv, pll); WARN_ON(!pll->on); - if (--pll->active) + + pll->active_mask &= ~crtc_mask; + if (pll->active_mask) return; DRM_DEBUG_KMS("disabling %s\n", pll->name); @@ -197,10 +200,10 @@ intel_find_shared_dpll(struct intel_crtc *crtc, if (memcmp(&crtc_state->dpll_hw_state, &shared_dpll[i].hw_state, sizeof(crtc_state->dpll_hw_state)) == 0) { - DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n", + DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, active %x)\n", crtc->base.base.id, pll->name, shared_dpll[i].crtc_mask, - pll->active); + pll->active_mask); return pll; } } diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h index 1d34147..89c5ada 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h @@ -115,7 +115,7 @@ struct intel_shared_dpll_funcs { struct intel_shared_dpll { struct intel_shared_dpll_config config; - int active; /* count of number of active CRTCs (i.e. DPMS on) */ + unsigned active_mask; /* mask of active CRTCs (i.e. DPMS on) */ bool on; /* is the PLL actually active? Disabled during modeset */ const char *name; /* should match the index in the dev_priv->shared_dplls array */ -- cgit v0.10.2 From a1475e775edc7bc8c0528d834d90a0ee93e57b1e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 14 Mar 2016 09:27:53 +0100 Subject: drm/i915: Perform dpll commit first, v2. Warn for the wrong mask in enable only. Disable will have the wrong mask now because the new state is committed before disabling the old state. Changes since v1: - Use crtc_mask (Durgadoss) - Rebase. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457944075-14123-3-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ander Conselvan de Oliveira diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 089d65e..80aa51c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13525,7 +13525,8 @@ static int intel_atomic_commit(struct drm_device *dev, } drm_atomic_helper_swap_state(dev, state); - dev_priv->wm.config = to_intel_atomic_state(state)->wm_config; + dev_priv->wm.config = intel_state->wm_config; + intel_shared_dpll_commit(state); if (intel_state->modeset) { memcpy(dev_priv->min_pixclk, intel_state->min_pixclk, @@ -13577,8 +13578,6 @@ static int intel_atomic_commit(struct drm_device *dev, intel_modeset_update_crtc_state(state); if (intel_state->modeset) { - intel_shared_dpll_commit(state); - drm_atomic_helper_update_legacy_modeset_state(state->dev, state); if (dev_priv->display.modeset_commit_cdclk && diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 9bf2c39..2c98610 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -156,7 +156,7 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) if (pll == NULL) return; - if (WARN_ON(!(pll->config.crtc_mask & crtc_mask))) + if (WARN_ON(!(pll->active_mask & crtc_mask))) return; DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n", -- cgit v0.10.2 From 15e7ec29ce5555a7b6048a1cfdaeb172de75a649 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 14 Mar 2016 09:27:54 +0100 Subject: drm/i915: Move pll power state to crtc power domains. Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1457944075-14123-4-git-send-email-maarten.lankhorst@linux.intel.com Reviewed-by: Ander Conselvan de Oliveira diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 80aa51c..e3e1581 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5273,6 +5273,9 @@ static unsigned long get_crtc_power_domains(struct drm_crtc *crtc, mask |= BIT(intel_display_port_power_domain(intel_encoder)); } + if (crtc_state->shared_dpll) + mask |= BIT(POWER_DOMAIN_PLLS); + return mask; } @@ -15703,9 +15706,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) DRM_DEBUG_KMS("%s hw state readout: crtc_mask 0x%08x, on %i\n", pll->name, pll->config.crtc_mask, pll->on); - - if (pll->config.crtc_mask) - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); } for_each_intel_encoder(dev, encoder) { diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 2c98610..fc5cfc8 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -135,8 +135,6 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc) } WARN_ON(pll->on); - intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS); - DRM_DEBUG_KMS("enabling %s\n", pll->name); pll->funcs.enable(dev_priv, pll); pll->on = true; @@ -173,8 +171,6 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) DRM_DEBUG_KMS("disabling %s\n", pll->name); pll->funcs.disable(dev_priv, pll); pll->on = false; - - intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS); } static struct intel_shared_dpll * -- cgit v0.10.2 From 52e2abb30cf0560edbb8f898d6c308e5ef80dd3f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2016 18:06:58 +0200 Subject: drm/i915: fix sparse warning for using false as NULL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/intel_dpll_mgr.c:1200:32: warning: Using plain integer as NULL pointer Fixes: 304b65cbdc8d ("drm/i915: Move SKL/KLB pll selection logic to intel_dpll_mgr.c") Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458144418-20046-1-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index fc5cfc8..19bfe67 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1196,7 +1196,7 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params)) - return false; + return NULL; cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE | DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) | -- cgit v0.10.2 From 72341af4285ae1337c0dfdfa3e68318b52b8757c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2016 12:43:35 +0200 Subject: drm/i915: hide away VBT private data in a separate header We've been accumulating code across the driver that depends on the VBT specific structures and defines. The VBT is an uncontrollable beast. Encourage encapsulation of the VBT data by hiding the structures and defines in a private header only to be included from intel_bios.c. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458125015-7931-7-git-send-email-jani.nikula@intel.com diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index 1692c4d..ab7ffeb 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -3334,7 +3334,7 @@ int num_ioctls; Video BIOS Table (VBT) !Pdrivers/gpu/drm/i915/intel_bios.c Video BIOS Table (VBT) !Idrivers/gpu/drm/i915/intel_bios.c -!Idrivers/gpu/drm/i915/intel_bios.h +!Idrivers/gpu/drm/i915/intel_vbt_defs.h diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index aa90dc6..083003b 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -29,7 +29,9 @@ #include #include #include "i915_drv.h" -#include "intel_bios.h" + +#define _INTEL_BIOS_PRIVATE +#include "intel_vbt_defs.h" /** * DOC: Video BIOS Table (VBT) diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 350d4e0..ab0ea31 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -1,5 +1,5 @@ /* - * Copyright © 2006 Intel Corporation + * Copyright © 2016 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,543 +19,16 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. - * - * Authors: - * Eric Anholt - * - */ - -#ifndef _INTEL_BIOS_H_ -#define _INTEL_BIOS_H_ - -/** - * struct vbt_header - VBT Header structure - * @signature: VBT signature, always starts with "$VBT" - * @version: Version of this structure - * @header_size: Size of this structure - * @vbt_size: Size of VBT (VBT Header, BDB Header and data blocks) - * @vbt_checksum: Checksum - * @reserved0: Reserved - * @bdb_offset: Offset of &struct bdb_header from beginning of VBT - * @aim_offset: Offsets of add-in data blocks from beginning of VBT - */ -struct vbt_header { - u8 signature[20]; - u16 version; - u16 header_size; - u16 vbt_size; - u8 vbt_checksum; - u8 reserved0; - u32 bdb_offset; - u32 aim_offset[4]; -} __packed; - -/** - * struct bdb_header - BDB Header structure - * @signature: BDB signature "BIOS_DATA_BLOCK" - * @version: Version of the data block definitions - * @header_size: Size of this structure - * @bdb_size: Size of BDB (BDB Header and data blocks) - */ -struct bdb_header { - u8 signature[16]; - u16 version; - u16 header_size; - u16 bdb_size; -} __packed; - -/* strictly speaking, this is a "skip" block, but it has interesting info */ -struct vbios_data { - u8 type; /* 0 == desktop, 1 == mobile */ - u8 relstage; - u8 chipset; - u8 lvds_present:1; - u8 tv_present:1; - u8 rsvd2:6; /* finish byte */ - u8 rsvd3[4]; - u8 signon[155]; - u8 copyright[61]; - u16 code_segment; - u8 dos_boot_mode; - u8 bandwidth_percent; - u8 rsvd4; /* popup memory size */ - u8 resize_pci_bios; - u8 rsvd5; /* is crt already on ddc2 */ -} __packed; - -/* - * There are several types of BIOS data blocks (BDBs), each block has - * an ID and size in the first 3 bytes (ID in first, size in next 2). - * Known types are listed below. */ -#define BDB_GENERAL_FEATURES 1 -#define BDB_GENERAL_DEFINITIONS 2 -#define BDB_OLD_TOGGLE_LIST 3 -#define BDB_MODE_SUPPORT_LIST 4 -#define BDB_GENERIC_MODE_TABLE 5 -#define BDB_EXT_MMIO_REGS 6 -#define BDB_SWF_IO 7 -#define BDB_SWF_MMIO 8 -#define BDB_PSR 9 -#define BDB_MODE_REMOVAL_TABLE 10 -#define BDB_CHILD_DEVICE_TABLE 11 -#define BDB_DRIVER_FEATURES 12 -#define BDB_DRIVER_PERSISTENCE 13 -#define BDB_EXT_TABLE_PTRS 14 -#define BDB_DOT_CLOCK_OVERRIDE 15 -#define BDB_DISPLAY_SELECT 16 -/* 17 rsvd */ -#define BDB_DRIVER_ROTATION 18 -#define BDB_DISPLAY_REMOVE 19 -#define BDB_OEM_CUSTOM 20 -#define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */ -#define BDB_SDVO_LVDS_OPTIONS 22 -#define BDB_SDVO_PANEL_DTDS 23 -#define BDB_SDVO_LVDS_PNP_IDS 24 -#define BDB_SDVO_LVDS_POWER_SEQ 25 -#define BDB_TV_OPTIONS 26 -#define BDB_EDP 27 -#define BDB_LVDS_OPTIONS 40 -#define BDB_LVDS_LFP_DATA_PTRS 41 -#define BDB_LVDS_LFP_DATA 42 -#define BDB_LVDS_BACKLIGHT 43 -#define BDB_LVDS_POWER 44 -#define BDB_MIPI_CONFIG 52 -#define BDB_MIPI_SEQUENCE 53 -#define BDB_SKIP 254 /* VBIOS private block, ignore */ - -struct bdb_general_features { - /* bits 1 */ - u8 panel_fitting:2; - u8 flexaim:1; - u8 msg_enable:1; - u8 clear_screen:3; - u8 color_flip:1; - - /* bits 2 */ - u8 download_ext_vbt:1; - u8 enable_ssc:1; - u8 ssc_freq:1; - u8 enable_lfp_on_override:1; - u8 disable_ssc_ddt:1; - u8 rsvd7:1; - u8 display_clock_mode:1; - u8 rsvd8:1; /* finish byte */ - - /* bits 3 */ - u8 disable_smooth_vision:1; - u8 single_dvi:1; - u8 rsvd9:1; - u8 fdi_rx_polarity_inverted:1; - u8 rsvd10:4; /* finish byte */ - - /* bits 4 */ - u8 legacy_monitor_detect; - - /* bits 5 */ - u8 int_crt_support:1; - u8 int_tv_support:1; - u8 int_efp_support:1; - u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */ - u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */ - u8 rsvd11:3; /* finish byte */ -} __packed; - -/* pre-915 */ -#define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */ -#define GPIO_PIN_ADD_I2C 0x05 /* "ADDCARD I2C GPIO pins" */ -#define GPIO_PIN_ADD_DDC 0x04 /* "ADDCARD DDC GPIO pins" */ -#define GPIO_PIN_ADD_DDC_I2C 0x06 /* "ADDCARD DDC/I2C GPIO pins" */ - -/* Pre 915 */ -#define DEVICE_TYPE_NONE 0x00 -#define DEVICE_TYPE_CRT 0x01 -#define DEVICE_TYPE_TV 0x09 -#define DEVICE_TYPE_EFP 0x12 -#define DEVICE_TYPE_LFP 0x22 -/* On 915+ */ -#define DEVICE_TYPE_CRT_DPMS 0x6001 -#define DEVICE_TYPE_CRT_DPMS_HOTPLUG 0x4001 -#define DEVICE_TYPE_TV_COMPOSITE 0x0209 -#define DEVICE_TYPE_TV_MACROVISION 0x0289 -#define DEVICE_TYPE_TV_RF_COMPOSITE 0x020c -#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE 0x0609 -#define DEVICE_TYPE_TV_SCART 0x0209 -#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009 -#define DEVICE_TYPE_EFP_HOTPLUG_PWR 0x6012 -#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR 0x6052 -#define DEVICE_TYPE_EFP_DVI_I 0x6053 -#define DEVICE_TYPE_EFP_DVI_D_DUAL 0x6152 -#define DEVICE_TYPE_EFP_DVI_D_HDCP 0x60d2 -#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR 0x6062 -#define DEVICE_TYPE_OPENLDI_DUALPIX 0x6162 -#define DEVICE_TYPE_LFP_PANELLINK 0x5012 -#define DEVICE_TYPE_LFP_CMOS_PWR 0x5042 -#define DEVICE_TYPE_LFP_LVDS_PWR 0x5062 -#define DEVICE_TYPE_LFP_LVDS_DUAL 0x5162 -#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP 0x51e2 - -#define DEVICE_CFG_NONE 0x00 -#define DEVICE_CFG_12BIT_DVOB 0x01 -#define DEVICE_CFG_12BIT_DVOC 0x02 -#define DEVICE_CFG_24BIT_DVOBC 0x09 -#define DEVICE_CFG_24BIT_DVOCB 0x0a -#define DEVICE_CFG_DUAL_DVOB 0x11 -#define DEVICE_CFG_DUAL_DVOC 0x12 -#define DEVICE_CFG_DUAL_DVOBC 0x13 -#define DEVICE_CFG_DUAL_LINK_DVOBC 0x19 -#define DEVICE_CFG_DUAL_LINK_DVOCB 0x1a - -#define DEVICE_WIRE_NONE 0x00 -#define DEVICE_WIRE_DVOB 0x01 -#define DEVICE_WIRE_DVOC 0x02 -#define DEVICE_WIRE_DVOBC 0x03 -#define DEVICE_WIRE_DVOBB 0x05 -#define DEVICE_WIRE_DVOCC 0x06 -#define DEVICE_WIRE_DVOB_MASTER 0x0d -#define DEVICE_WIRE_DVOC_MASTER 0x0e - -#define DEVICE_PORT_DVOA 0x00 /* none on 845+ */ -#define DEVICE_PORT_DVOB 0x01 -#define DEVICE_PORT_DVOC 0x02 /* - * We used to keep this struct but without any version control. We should avoid - * using it in the future, but it should be safe to keep using it in the old - * code. Do not change; we rely on its size. + * Please use intel_vbt_defs.h for VBT private data, to hide and abstract away + * the VBT from the rest of the driver. Add the parsed, clean data to struct + * intel_vbt_data within struct drm_i915_private. */ -struct old_child_dev_config { - u16 handle; - u16 device_type; - u8 device_id[10]; /* ascii string */ - u16 addin_offset; - u8 dvo_port; /* See Device_PORT_* above */ - u8 i2c_pin; - u8 slave_addr; - u8 ddc_pin; - u16 edid_ptr; - u8 dvo_cfg; /* See DEVICE_CFG_* above */ - u8 dvo2_port; - u8 i2c2_pin; - u8 slave2_addr; - u8 ddc2_pin; - u8 capabilities; - u8 dvo_wiring;/* See DEVICE_WIRE_* above */ - u8 dvo2_wiring; - u16 extended_type; - u8 dvo_function; -} __packed; - -/* This one contains field offsets that are known to be common for all BDB - * versions. Notice that the meaning of the contents contents may still change, - * but at least the offsets are consistent. */ - -/* Definitions for flags_1 */ -#define IBOOST_ENABLE (1<<3) - -struct common_child_dev_config { - u16 handle; - u16 device_type; - u8 not_common1[12]; - u8 dvo_port; - u8 not_common2[2]; - u8 ddc_pin; - u16 edid_ptr; - u8 obsolete; - u8 flags_1; - u8 not_common3[13]; - u8 iboost_level; -} __packed; - - -/* This field changes depending on the BDB version, so the most reliable way to - * read it is by checking the BDB version and reading the raw pointer. */ -union child_device_config { - /* This one is safe to be used anywhere, but the code should still check - * the BDB version. */ - u8 raw[33]; - /* This one should only be kept for legacy code. */ - struct old_child_dev_config old; - /* This one should also be safe to use anywhere, even without version - * checks. */ - struct common_child_dev_config common; -} __packed; - -struct bdb_general_definitions { - /* DDC GPIO */ - u8 crt_ddc_gmbus_pin; - - /* DPMS bits */ - u8 dpms_acpi:1; - u8 skip_boot_crt_detect:1; - u8 dpms_aim:1; - u8 rsvd1:5; /* finish byte */ - - /* boot device bits */ - u8 boot_display[2]; - u8 child_dev_size; - - /* - * Device info: - * If TV is present, it'll be at devices[0]. - * LVDS will be next, either devices[0] or [1], if present. - * On some platforms the number of device is 6. But could be as few as - * 4 if both TV and LVDS are missing. - * And the device num is related with the size of general definition - * block. It is obtained by using the following formula: - * number = (block_size - sizeof(bdb_general_definitions))/ - * defs->child_dev_size; - */ - uint8_t devices[0]; -} __packed; - -/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */ -#define MODE_MASK 0x3 - -struct bdb_lvds_options { - u8 panel_type; - u8 rsvd1; - /* LVDS capabilities, stored in a dword */ - u8 pfit_mode:2; - u8 pfit_text_mode_enhanced:1; - u8 pfit_gfx_mode_enhanced:1; - u8 pfit_ratio_auto:1; - u8 pixel_dither:1; - u8 lvds_edid:1; - u8 rsvd2:1; - u8 rsvd4; - /* LVDS Panel channel bits stored here */ - u32 lvds_panel_channel_bits; - /* LVDS SSC (Spread Spectrum Clock) bits stored here. */ - u16 ssc_bits; - u16 ssc_freq; - u16 ssc_ddt; - /* Panel color depth defined here */ - u16 panel_color_depth; - /* LVDS panel type bits stored here */ - u32 dps_panel_type_bits; - /* LVDS backlight control type bits stored here */ - u32 blt_control_type_bits; -} __packed; - -/* LFP pointer table contains entries to the struct below */ -struct bdb_lvds_lfp_data_ptr { - u16 fp_timing_offset; /* offsets are from start of bdb */ - u8 fp_table_size; - u16 dvo_timing_offset; - u8 dvo_table_size; - u16 panel_pnp_id_offset; - u8 pnp_table_size; -} __packed; - -struct bdb_lvds_lfp_data_ptrs { - u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */ - struct bdb_lvds_lfp_data_ptr ptr[16]; -} __packed; - -/* LFP data has 3 blocks per entry */ -struct lvds_fp_timing { - u16 x_res; - u16 y_res; - u32 lvds_reg; - u32 lvds_reg_val; - u32 pp_on_reg; - u32 pp_on_reg_val; - u32 pp_off_reg; - u32 pp_off_reg_val; - u32 pp_cycle_reg; - u32 pp_cycle_reg_val; - u32 pfit_reg; - u32 pfit_reg_val; - u16 terminator; -} __packed; - -struct lvds_dvo_timing { - u16 clock; /**< In 10khz */ - u8 hactive_lo; - u8 hblank_lo; - u8 hblank_hi:4; - u8 hactive_hi:4; - u8 vactive_lo; - u8 vblank_lo; - u8 vblank_hi:4; - u8 vactive_hi:4; - u8 hsync_off_lo; - u8 hsync_pulse_width; - u8 vsync_pulse_width:4; - u8 vsync_off:4; - u8 rsvd0:6; - u8 hsync_off_hi:2; - u8 h_image; - u8 v_image; - u8 max_hv; - u8 h_border; - u8 v_border; - u8 rsvd1:3; - u8 digital:2; - u8 vsync_positive:1; - u8 hsync_positive:1; - u8 rsvd2:1; -} __packed; - -struct lvds_pnp_id { - u16 mfg_name; - u16 product_code; - u32 serial; - u8 mfg_week; - u8 mfg_year; -} __packed; - -struct bdb_lvds_lfp_data_entry { - struct lvds_fp_timing fp_timing; - struct lvds_dvo_timing dvo_timing; - struct lvds_pnp_id pnp_id; -} __packed; - -struct bdb_lvds_lfp_data { - struct bdb_lvds_lfp_data_entry data[16]; -} __packed; - -#define BDB_BACKLIGHT_TYPE_NONE 0 -#define BDB_BACKLIGHT_TYPE_PWM 2 - -struct bdb_lfp_backlight_data_entry { - u8 type:2; - u8 active_low_pwm:1; - u8 obsolete1:5; - u16 pwm_freq_hz; - u8 min_brightness; - u8 obsolete2; - u8 obsolete3; -} __packed; - -struct bdb_lfp_backlight_data { - u8 entry_size; - struct bdb_lfp_backlight_data_entry data[16]; - u8 level[16]; -} __packed; - -struct aimdb_header { - char signature[16]; - char oem_device[20]; - u16 aimdb_version; - u16 aimdb_header_size; - u16 aimdb_size; -} __packed; - -struct aimdb_block { - u8 aimdb_id; - u16 aimdb_size; -} __packed; -struct vch_panel_data { - u16 fp_timing_offset; - u8 fp_timing_size; - u16 dvo_timing_offset; - u8 dvo_timing_size; - u16 text_fitting_offset; - u8 text_fitting_size; - u16 graphics_fitting_offset; - u8 graphics_fitting_size; -} __packed; - -struct vch_bdb_22 { - struct aimdb_block aimdb_block; - struct vch_panel_data panels[16]; -} __packed; - -struct bdb_sdvo_lvds_options { - u8 panel_backlight; - u8 h40_set_panel_type; - u8 panel_type; - u8 ssc_clk_freq; - u16 als_low_trip; - u16 als_high_trip; - u8 sclalarcoeff_tab_row_num; - u8 sclalarcoeff_tab_row_size; - u8 coefficient[8]; - u8 panel_misc_bits_1; - u8 panel_misc_bits_2; - u8 panel_misc_bits_3; - u8 panel_misc_bits_4; -} __packed; - - -#define BDB_DRIVER_FEATURE_NO_LVDS 0 -#define BDB_DRIVER_FEATURE_INT_LVDS 1 -#define BDB_DRIVER_FEATURE_SDVO_LVDS 2 -#define BDB_DRIVER_FEATURE_EDP 3 - -struct bdb_driver_features { - u8 boot_dev_algorithm:1; - u8 block_display_switch:1; - u8 allow_display_switch:1; - u8 hotplug_dvo:1; - u8 dual_view_zoom:1; - u8 int15h_hook:1; - u8 sprite_in_clone:1; - u8 primary_lfp_id:1; - - u16 boot_mode_x; - u16 boot_mode_y; - u8 boot_mode_bpp; - u8 boot_mode_refresh; - - u16 enable_lfp_primary:1; - u16 selective_mode_pruning:1; - u16 dual_frequency:1; - u16 render_clock_freq:1; /* 0: high freq; 1: low freq */ - u16 nt_clone_support:1; - u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */ - u16 sprite_display_assign:1; /* 0: secondary; 1: primary */ - u16 cui_aspect_scaling:1; - u16 preserve_aspect_ratio:1; - u16 sdvo_device_power_down:1; - u16 crt_hotplug:1; - u16 lvds_config:2; - u16 tv_hotplug:1; - u16 hdmi_config:2; - - u8 static_display:1; - u8 reserved2:7; - u16 legacy_crt_max_x; - u16 legacy_crt_max_y; - u8 legacy_crt_max_refresh; - - u8 hdmi_termination; - u8 custom_vbt_version; - /* Driver features data block */ - u16 rmpm_enabled:1; - u16 s2ddt_enabled:1; - u16 dpst_enabled:1; - u16 bltclt_enabled:1; - u16 adb_enabled:1; - u16 drrs_enabled:1; - u16 grs_enabled:1; - u16 gpmt_enabled:1; - u16 tbt_enabled:1; - u16 psr_enabled:1; - u16 ips_enabled:1; - u16 reserved3:4; - u16 pc_feature_valid:1; -} __packed; - -#define EDP_18BPP 0 -#define EDP_24BPP 1 -#define EDP_30BPP 2 -#define EDP_RATE_1_62 0 -#define EDP_RATE_2_7 1 -#define EDP_LANE_1 0 -#define EDP_LANE_2 1 -#define EDP_LANE_4 3 -#define EDP_PREEMPHASIS_NONE 0 -#define EDP_PREEMPHASIS_3_5dB 1 -#define EDP_PREEMPHASIS_6dB 2 -#define EDP_PREEMPHASIS_9_5dB 3 -#define EDP_VSWING_0_4V 0 -#define EDP_VSWING_0_6V 1 -#define EDP_VSWING_0_8V 2 -#define EDP_VSWING_1_2V 3 +#ifndef _INTEL_BIOS_H_ +#define _INTEL_BIOS_H_ struct edp_power_seq { u16 t1_t3; @@ -565,245 +38,37 @@ struct edp_power_seq { u16 t11_t12; } __packed; -struct edp_link_params { - u8 rate:4; - u8 lanes:4; - u8 preemphasis:4; - u8 vswing:4; -} __packed; - -struct bdb_edp { - struct edp_power_seq power_seqs[16]; - u32 color_depth; - struct edp_link_params link_params[16]; - u32 sdrrs_msa_timing_delay; - - /* ith bit indicates enabled/disabled for (i+1)th panel */ - u16 edp_s3d_feature; - u16 edp_t3_optimization; - u64 edp_vswing_preemph; /* v173 */ -} __packed; - -struct psr_table { - /* Feature bits */ - u8 full_link:1; - u8 require_aux_to_wakeup:1; - u8 feature_bits_rsvd:6; - - /* Wait times */ - u8 idle_frames:4; - u8 lines_to_wait:3; - u8 wait_times_rsvd:1; - - /* TP wake up time in multiple of 100 */ - u16 tp1_wakeup_time; - u16 tp2_tp3_wakeup_time; -} __packed; - -struct bdb_psr { - struct psr_table psr_table[16]; -} __packed; - -/* - * Driver<->VBIOS interaction occurs through scratch bits in - * GR18 & SWF*. - */ - -/* GR18 bits are set on display switch and hotkey events */ -#define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */ -#define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */ -#define GR18_HK_NONE (0x0<<3) -#define GR18_HK_LFP_STRETCH (0x1<<3) -#define GR18_HK_TOGGLE_DISP (0x2<<3) -#define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */ -#define GR18_HK_POPUP_DISABLED (0x6<<3) -#define GR18_HK_POPUP_ENABLED (0x7<<3) -#define GR18_HK_PFIT (0x8<<3) -#define GR18_HK_APM_CHANGE (0xa<<3) -#define GR18_HK_MULTIPLE (0xc<<3) -#define GR18_USER_INT_EN (1<<2) -#define GR18_A0000_FLUSH_EN (1<<1) -#define GR18_SMM_EN (1<<0) - -/* Set by driver, cleared by VBIOS */ -#define SWF00_YRES_SHIFT 16 -#define SWF00_XRES_SHIFT 0 -#define SWF00_RES_MASK 0xffff - -/* Set by VBIOS at boot time and driver at runtime */ -#define SWF01_TV2_FORMAT_SHIFT 8 -#define SWF01_TV1_FORMAT_SHIFT 0 -#define SWF01_TV_FORMAT_MASK 0xffff - -#define SWF10_VBIOS_BLC_I2C_EN (1<<29) -#define SWF10_GTT_OVERRIDE_EN (1<<28) -#define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */ -#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24) -#define SWF10_OLD_TOGGLE 0x0 -#define SWF10_TOGGLE_LIST_1 0x1 -#define SWF10_TOGGLE_LIST_2 0x2 -#define SWF10_TOGGLE_LIST_3 0x3 -#define SWF10_TOGGLE_LIST_4 0x4 -#define SWF10_PANNING_EN (1<<23) -#define SWF10_DRIVER_LOADED (1<<22) -#define SWF10_EXTENDED_DESKTOP (1<<21) -#define SWF10_EXCLUSIVE_MODE (1<<20) -#define SWF10_OVERLAY_EN (1<<19) -#define SWF10_PLANEB_HOLDOFF (1<<18) -#define SWF10_PLANEA_HOLDOFF (1<<17) -#define SWF10_VGA_HOLDOFF (1<<16) -#define SWF10_ACTIVE_DISP_MASK 0xffff -#define SWF10_PIPEB_LFP2 (1<<15) -#define SWF10_PIPEB_EFP2 (1<<14) -#define SWF10_PIPEB_TV2 (1<<13) -#define SWF10_PIPEB_CRT2 (1<<12) -#define SWF10_PIPEB_LFP (1<<11) -#define SWF10_PIPEB_EFP (1<<10) -#define SWF10_PIPEB_TV (1<<9) -#define SWF10_PIPEB_CRT (1<<8) -#define SWF10_PIPEA_LFP2 (1<<7) -#define SWF10_PIPEA_EFP2 (1<<6) -#define SWF10_PIPEA_TV2 (1<<5) -#define SWF10_PIPEA_CRT2 (1<<4) -#define SWF10_PIPEA_LFP (1<<3) -#define SWF10_PIPEA_EFP (1<<2) -#define SWF10_PIPEA_TV (1<<1) -#define SWF10_PIPEA_CRT (1<<0) - -#define SWF11_MEMORY_SIZE_SHIFT 16 -#define SWF11_SV_TEST_EN (1<<15) -#define SWF11_IS_AGP (1<<14) -#define SWF11_DISPLAY_HOLDOFF (1<<13) -#define SWF11_DPMS_REDUCED (1<<12) -#define SWF11_IS_VBE_MODE (1<<11) -#define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */ -#define SWF11_DPMS_MASK 0x07 -#define SWF11_DPMS_OFF (1<<2) -#define SWF11_DPMS_SUSPEND (1<<1) -#define SWF11_DPMS_STANDBY (1<<0) -#define SWF11_DPMS_ON 0 - -#define SWF14_GFX_PFIT_EN (1<<31) -#define SWF14_TEXT_PFIT_EN (1<<30) -#define SWF14_LID_STATUS_CLOSED (1<<29) /* 0 here means open */ -#define SWF14_POPUP_EN (1<<28) -#define SWF14_DISPLAY_HOLDOFF (1<<27) -#define SWF14_DISP_DETECT_EN (1<<26) -#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */ -#define SWF14_DRIVER_STATUS (1<<24) -#define SWF14_OS_TYPE_WIN9X (1<<23) -#define SWF14_OS_TYPE_WINNT (1<<22) -/* 21:19 rsvd */ -#define SWF14_PM_TYPE_MASK 0x00070000 -#define SWF14_PM_ACPI_VIDEO (0x4 << 16) -#define SWF14_PM_ACPI (0x3 << 16) -#define SWF14_PM_APM_12 (0x2 << 16) -#define SWF14_PM_APM_11 (0x1 << 16) -#define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */ - /* if GR18 indicates a display switch */ -#define SWF14_DS_PIPEB_LFP2_EN (1<<15) -#define SWF14_DS_PIPEB_EFP2_EN (1<<14) -#define SWF14_DS_PIPEB_TV2_EN (1<<13) -#define SWF14_DS_PIPEB_CRT2_EN (1<<12) -#define SWF14_DS_PIPEB_LFP_EN (1<<11) -#define SWF14_DS_PIPEB_EFP_EN (1<<10) -#define SWF14_DS_PIPEB_TV_EN (1<<9) -#define SWF14_DS_PIPEB_CRT_EN (1<<8) -#define SWF14_DS_PIPEA_LFP2_EN (1<<7) -#define SWF14_DS_PIPEA_EFP2_EN (1<<6) -#define SWF14_DS_PIPEA_TV2_EN (1<<5) -#define SWF14_DS_PIPEA_CRT2_EN (1<<4) -#define SWF14_DS_PIPEA_LFP_EN (1<<3) -#define SWF14_DS_PIPEA_EFP_EN (1<<2) -#define SWF14_DS_PIPEA_TV_EN (1<<1) -#define SWF14_DS_PIPEA_CRT_EN (1<<0) - /* if GR18 indicates a panel fitting request */ -#define SWF14_PFIT_EN (1<<0) /* 0 means disable */ - /* if GR18 indicates an APM change request */ -#define SWF14_APM_HIBERNATE 0x4 -#define SWF14_APM_SUSPEND 0x3 -#define SWF14_APM_STANDBY 0x1 -#define SWF14_APM_RESTORE 0x0 - -/* Add the device class for LFP, TV, HDMI */ -#define DEVICE_TYPE_INT_LFP 0x1022 -#define DEVICE_TYPE_INT_TV 0x1009 -#define DEVICE_TYPE_HDMI 0x60D2 -#define DEVICE_TYPE_DP 0x68C6 -#define DEVICE_TYPE_eDP 0x78C6 - -#define DEVICE_TYPE_CLASS_EXTENSION (1 << 15) -#define DEVICE_TYPE_POWER_MANAGEMENT (1 << 14) -#define DEVICE_TYPE_HOTPLUG_SIGNALING (1 << 13) -#define DEVICE_TYPE_INTERNAL_CONNECTOR (1 << 12) -#define DEVICE_TYPE_NOT_HDMI_OUTPUT (1 << 11) -#define DEVICE_TYPE_MIPI_OUTPUT (1 << 10) -#define DEVICE_TYPE_COMPOSITE_OUTPUT (1 << 9) -#define DEVICE_TYPE_DUAL_CHANNEL (1 << 8) -#define DEVICE_TYPE_HIGH_SPEED_LINK (1 << 6) -#define DEVICE_TYPE_LVDS_SINGALING (1 << 5) -#define DEVICE_TYPE_TMDS_DVI_SIGNALING (1 << 4) -#define DEVICE_TYPE_VIDEO_SIGNALING (1 << 3) -#define DEVICE_TYPE_DISPLAYPORT_OUTPUT (1 << 2) -#define DEVICE_TYPE_DIGITAL_OUTPUT (1 << 1) -#define DEVICE_TYPE_ANALOG_OUTPUT (1 << 0) - -/* - * Bits we care about when checking for DEVICE_TYPE_eDP - * Depending on the system, the other bits may or may not - * be set for eDP outputs. - */ -#define DEVICE_TYPE_eDP_BITS \ - (DEVICE_TYPE_INTERNAL_CONNECTOR | \ - DEVICE_TYPE_MIPI_OUTPUT | \ - DEVICE_TYPE_COMPOSITE_OUTPUT | \ - DEVICE_TYPE_DUAL_CHANNEL | \ - DEVICE_TYPE_LVDS_SINGALING | \ - DEVICE_TYPE_TMDS_DVI_SIGNALING | \ - DEVICE_TYPE_VIDEO_SIGNALING | \ - DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ - DEVICE_TYPE_ANALOG_OUTPUT) - -/* define the DVO port for HDMI output type */ -#define DVO_B 1 -#define DVO_C 2 -#define DVO_D 3 - -/* Possible values for the "DVO Port" field for versions >= 155: */ -#define DVO_PORT_HDMIA 0 -#define DVO_PORT_HDMIB 1 -#define DVO_PORT_HDMIC 2 -#define DVO_PORT_HDMID 3 -#define DVO_PORT_LVDS 4 -#define DVO_PORT_TV 5 -#define DVO_PORT_CRT 6 -#define DVO_PORT_DPB 7 -#define DVO_PORT_DPC 8 -#define DVO_PORT_DPD 9 -#define DVO_PORT_DPA 10 -#define DVO_PORT_DPE 11 -#define DVO_PORT_HDMIE 12 -#define DVO_PORT_MIPIA 21 -#define DVO_PORT_MIPIB 22 -#define DVO_PORT_MIPIC 23 -#define DVO_PORT_MIPID 24 +/* MIPI Sequence Block definitions */ +enum mipi_seq { + MIPI_SEQ_END = 0, + MIPI_SEQ_ASSERT_RESET, + MIPI_SEQ_INIT_OTP, + MIPI_SEQ_DISPLAY_ON, + MIPI_SEQ_DISPLAY_OFF, + MIPI_SEQ_DEASSERT_RESET, + MIPI_SEQ_BACKLIGHT_ON, /* sequence block v2+ */ + MIPI_SEQ_BACKLIGHT_OFF, /* sequence block v2+ */ + MIPI_SEQ_TEAR_ON, /* sequence block v2+ */ + MIPI_SEQ_TEAR_OFF, /* sequence block v3+ */ + MIPI_SEQ_POWER_ON, /* sequence block v3+ */ + MIPI_SEQ_POWER_OFF, /* sequence block v3+ */ + MIPI_SEQ_MAX +}; -/* Block 52 contains MIPI Panel info - * 6 such enteries will there. Index into correct - * entery is based on the panel_index in #40 LFP - */ -#define MAX_MIPI_CONFIGURATIONS 6 +enum mipi_seq_element { + MIPI_SEQ_ELEM_END = 0, + MIPI_SEQ_ELEM_SEND_PKT, + MIPI_SEQ_ELEM_DELAY, + MIPI_SEQ_ELEM_GPIO, + MIPI_SEQ_ELEM_I2C, /* sequence block v2+ */ + MIPI_SEQ_ELEM_SPI, /* sequence block v3+ */ + MIPI_SEQ_ELEM_PMIC, /* sequence block v3+ */ + MIPI_SEQ_ELEM_MAX +}; #define MIPI_DSI_UNDEFINED_PANEL_ID 0 #define MIPI_DSI_GENERIC_PANEL_ID 1 -/* - * PMIC vs SoC Backlight support specified in pwm_blc - * field in mipi_config block below. -*/ -#define PPS_BLC_PMIC 0 -#define PPS_BLC_SOC 1 - struct mipi_config { u16 panel_id; @@ -821,6 +86,8 @@ struct mipi_config { u32 video_transfer_mode:2; u32 cabc_supported:1; +#define PPS_BLC_PMIC 0 +#define PPS_BLC_SOC 1 u32 pwm_blc:1; /* Bit 13:10 */ @@ -924,12 +191,7 @@ struct mipi_config { } __packed; -/* Block 52 contains MIPI configuration block - * 6 * bdb_mipi_config, followed by 6 pps data - * block below - * - * all delays has a unit of 100us - */ +/* all delays have a unit of 100us */ struct mipi_pps_data { u16 panel_on_delay; u16 bl_enable_delay; @@ -938,57 +200,4 @@ struct mipi_pps_data { u16 panel_power_cycle_delay; } __packed; -struct bdb_mipi_config { - struct mipi_config config[MAX_MIPI_CONFIGURATIONS]; - struct mipi_pps_data pps[MAX_MIPI_CONFIGURATIONS]; -} __packed; - -/* Block 53 contains MIPI sequences as needed by the panel - * for enabling it. This block can be variable in size and - * can be maximum of 6 blocks - */ -struct bdb_mipi_sequence { - u8 version; - u8 data[0]; -} __packed; - -/* MIPI Sequnece Block definitions */ -enum mipi_seq { - MIPI_SEQ_END = 0, - MIPI_SEQ_ASSERT_RESET, - MIPI_SEQ_INIT_OTP, - MIPI_SEQ_DISPLAY_ON, - MIPI_SEQ_DISPLAY_OFF, - MIPI_SEQ_DEASSERT_RESET, - MIPI_SEQ_BACKLIGHT_ON, /* sequence block v2+ */ - MIPI_SEQ_BACKLIGHT_OFF, /* sequence block v2+ */ - MIPI_SEQ_TEAR_ON, /* sequence block v2+ */ - MIPI_SEQ_TEAR_OFF, /* sequence block v3+ */ - MIPI_SEQ_POWER_ON, /* sequence block v3+ */ - MIPI_SEQ_POWER_OFF, /* sequence block v3+ */ - MIPI_SEQ_MAX -}; - -enum mipi_seq_element { - MIPI_SEQ_ELEM_END = 0, - MIPI_SEQ_ELEM_SEND_PKT, - MIPI_SEQ_ELEM_DELAY, - MIPI_SEQ_ELEM_GPIO, - MIPI_SEQ_ELEM_I2C, /* sequence block v2+ */ - MIPI_SEQ_ELEM_SPI, /* sequence block v3+ */ - MIPI_SEQ_ELEM_PMIC, /* sequence block v3+ */ - MIPI_SEQ_ELEM_MAX -}; - -enum mipi_gpio_pin_index { - MIPI_GPIO_UNDEFINED = 0, - MIPI_GPIO_PANEL_ENABLE, - MIPI_GPIO_BL_ENABLE, - MIPI_GPIO_PWM_ENABLE, - MIPI_GPIO_RESET_N, - MIPI_GPIO_PWR_DOWN_R, - MIPI_GPIO_STDBY_RST_N, - MIPI_GPIO_MAX -}; - #endif /* _INTEL_BIOS_H_ */ diff --git a/drivers/gpu/drm/i915/intel_vbt_defs.h b/drivers/gpu/drm/i915/intel_vbt_defs.h new file mode 100644 index 0000000..749dcea --- /dev/null +++ b/drivers/gpu/drm/i915/intel_vbt_defs.h @@ -0,0 +1,826 @@ +/* + * Copyright © 2006-2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: + * Eric Anholt + * + */ + +/* + * This information is private to VBT parsing in intel_bios.c. + * + * Please do NOT include anywhere else. + */ +#ifndef _INTEL_BIOS_PRIVATE +#error "intel_vbt_defs.h is private to intel_bios.c" +#endif + +#ifndef _INTEL_VBT_DEFS_H_ +#define _INTEL_VBT_DEFS_H_ + +#include "intel_bios.h" + +/** + * struct vbt_header - VBT Header structure + * @signature: VBT signature, always starts with "$VBT" + * @version: Version of this structure + * @header_size: Size of this structure + * @vbt_size: Size of VBT (VBT Header, BDB Header and data blocks) + * @vbt_checksum: Checksum + * @reserved0: Reserved + * @bdb_offset: Offset of &struct bdb_header from beginning of VBT + * @aim_offset: Offsets of add-in data blocks from beginning of VBT + */ +struct vbt_header { + u8 signature[20]; + u16 version; + u16 header_size; + u16 vbt_size; + u8 vbt_checksum; + u8 reserved0; + u32 bdb_offset; + u32 aim_offset[4]; +} __packed; + +/** + * struct bdb_header - BDB Header structure + * @signature: BDB signature "BIOS_DATA_BLOCK" + * @version: Version of the data block definitions + * @header_size: Size of this structure + * @bdb_size: Size of BDB (BDB Header and data blocks) + */ +struct bdb_header { + u8 signature[16]; + u16 version; + u16 header_size; + u16 bdb_size; +} __packed; + +/* strictly speaking, this is a "skip" block, but it has interesting info */ +struct vbios_data { + u8 type; /* 0 == desktop, 1 == mobile */ + u8 relstage; + u8 chipset; + u8 lvds_present:1; + u8 tv_present:1; + u8 rsvd2:6; /* finish byte */ + u8 rsvd3[4]; + u8 signon[155]; + u8 copyright[61]; + u16 code_segment; + u8 dos_boot_mode; + u8 bandwidth_percent; + u8 rsvd4; /* popup memory size */ + u8 resize_pci_bios; + u8 rsvd5; /* is crt already on ddc2 */ +} __packed; + +/* + * There are several types of BIOS data blocks (BDBs), each block has + * an ID and size in the first 3 bytes (ID in first, size in next 2). + * Known types are listed below. + */ +#define BDB_GENERAL_FEATURES 1 +#define BDB_GENERAL_DEFINITIONS 2 +#define BDB_OLD_TOGGLE_LIST 3 +#define BDB_MODE_SUPPORT_LIST 4 +#define BDB_GENERIC_MODE_TABLE 5 +#define BDB_EXT_MMIO_REGS 6 +#define BDB_SWF_IO 7 +#define BDB_SWF_MMIO 8 +#define BDB_PSR 9 +#define BDB_MODE_REMOVAL_TABLE 10 +#define BDB_CHILD_DEVICE_TABLE 11 +#define BDB_DRIVER_FEATURES 12 +#define BDB_DRIVER_PERSISTENCE 13 +#define BDB_EXT_TABLE_PTRS 14 +#define BDB_DOT_CLOCK_OVERRIDE 15 +#define BDB_DISPLAY_SELECT 16 +/* 17 rsvd */ +#define BDB_DRIVER_ROTATION 18 +#define BDB_DISPLAY_REMOVE 19 +#define BDB_OEM_CUSTOM 20 +#define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */ +#define BDB_SDVO_LVDS_OPTIONS 22 +#define BDB_SDVO_PANEL_DTDS 23 +#define BDB_SDVO_LVDS_PNP_IDS 24 +#define BDB_SDVO_LVDS_POWER_SEQ 25 +#define BDB_TV_OPTIONS 26 +#define BDB_EDP 27 +#define BDB_LVDS_OPTIONS 40 +#define BDB_LVDS_LFP_DATA_PTRS 41 +#define BDB_LVDS_LFP_DATA 42 +#define BDB_LVDS_BACKLIGHT 43 +#define BDB_LVDS_POWER 44 +#define BDB_MIPI_CONFIG 52 +#define BDB_MIPI_SEQUENCE 53 +#define BDB_SKIP 254 /* VBIOS private block, ignore */ + +struct bdb_general_features { + /* bits 1 */ + u8 panel_fitting:2; + u8 flexaim:1; + u8 msg_enable:1; + u8 clear_screen:3; + u8 color_flip:1; + + /* bits 2 */ + u8 download_ext_vbt:1; + u8 enable_ssc:1; + u8 ssc_freq:1; + u8 enable_lfp_on_override:1; + u8 disable_ssc_ddt:1; + u8 rsvd7:1; + u8 display_clock_mode:1; + u8 rsvd8:1; /* finish byte */ + + /* bits 3 */ + u8 disable_smooth_vision:1; + u8 single_dvi:1; + u8 rsvd9:1; + u8 fdi_rx_polarity_inverted:1; + u8 rsvd10:4; /* finish byte */ + + /* bits 4 */ + u8 legacy_monitor_detect; + + /* bits 5 */ + u8 int_crt_support:1; + u8 int_tv_support:1; + u8 int_efp_support:1; + u8 dp_ssc_enb:1; /* PCH attached eDP supports SSC */ + u8 dp_ssc_freq:1; /* SSC freq for PCH attached eDP */ + u8 rsvd11:3; /* finish byte */ +} __packed; + +/* pre-915 */ +#define GPIO_PIN_DVI_LVDS 0x03 /* "DVI/LVDS DDC GPIO pins" */ +#define GPIO_PIN_ADD_I2C 0x05 /* "ADDCARD I2C GPIO pins" */ +#define GPIO_PIN_ADD_DDC 0x04 /* "ADDCARD DDC GPIO pins" */ +#define GPIO_PIN_ADD_DDC_I2C 0x06 /* "ADDCARD DDC/I2C GPIO pins" */ + +/* Pre 915 */ +#define DEVICE_TYPE_NONE 0x00 +#define DEVICE_TYPE_CRT 0x01 +#define DEVICE_TYPE_TV 0x09 +#define DEVICE_TYPE_EFP 0x12 +#define DEVICE_TYPE_LFP 0x22 +/* On 915+ */ +#define DEVICE_TYPE_CRT_DPMS 0x6001 +#define DEVICE_TYPE_CRT_DPMS_HOTPLUG 0x4001 +#define DEVICE_TYPE_TV_COMPOSITE 0x0209 +#define DEVICE_TYPE_TV_MACROVISION 0x0289 +#define DEVICE_TYPE_TV_RF_COMPOSITE 0x020c +#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE 0x0609 +#define DEVICE_TYPE_TV_SCART 0x0209 +#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009 +#define DEVICE_TYPE_EFP_HOTPLUG_PWR 0x6012 +#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR 0x6052 +#define DEVICE_TYPE_EFP_DVI_I 0x6053 +#define DEVICE_TYPE_EFP_DVI_D_DUAL 0x6152 +#define DEVICE_TYPE_EFP_DVI_D_HDCP 0x60d2 +#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR 0x6062 +#define DEVICE_TYPE_OPENLDI_DUALPIX 0x6162 +#define DEVICE_TYPE_LFP_PANELLINK 0x5012 +#define DEVICE_TYPE_LFP_CMOS_PWR 0x5042 +#define DEVICE_TYPE_LFP_LVDS_PWR 0x5062 +#define DEVICE_TYPE_LFP_LVDS_DUAL 0x5162 +#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP 0x51e2 + +#define DEVICE_CFG_NONE 0x00 +#define DEVICE_CFG_12BIT_DVOB 0x01 +#define DEVICE_CFG_12BIT_DVOC 0x02 +#define DEVICE_CFG_24BIT_DVOBC 0x09 +#define DEVICE_CFG_24BIT_DVOCB 0x0a +#define DEVICE_CFG_DUAL_DVOB 0x11 +#define DEVICE_CFG_DUAL_DVOC 0x12 +#define DEVICE_CFG_DUAL_DVOBC 0x13 +#define DEVICE_CFG_DUAL_LINK_DVOBC 0x19 +#define DEVICE_CFG_DUAL_LINK_DVOCB 0x1a + +#define DEVICE_WIRE_NONE 0x00 +#define DEVICE_WIRE_DVOB 0x01 +#define DEVICE_WIRE_DVOC 0x02 +#define DEVICE_WIRE_DVOBC 0x03 +#define DEVICE_WIRE_DVOBB 0x05 +#define DEVICE_WIRE_DVOCC 0x06 +#define DEVICE_WIRE_DVOB_MASTER 0x0d +#define DEVICE_WIRE_DVOC_MASTER 0x0e + +#define DEVICE_PORT_DVOA 0x00 /* none on 845+ */ +#define DEVICE_PORT_DVOB 0x01 +#define DEVICE_PORT_DVOC 0x02 + +/* + * We used to keep this struct but without any version control. We should avoid + * using it in the future, but it should be safe to keep using it in the old + * code. Do not change; we rely on its size. + */ +struct old_child_dev_config { + u16 handle; + u16 device_type; + u8 device_id[10]; /* ascii string */ + u16 addin_offset; + u8 dvo_port; /* See Device_PORT_* above */ + u8 i2c_pin; + u8 slave_addr; + u8 ddc_pin; + u16 edid_ptr; + u8 dvo_cfg; /* See DEVICE_CFG_* above */ + u8 dvo2_port; + u8 i2c2_pin; + u8 slave2_addr; + u8 ddc2_pin; + u8 capabilities; + u8 dvo_wiring;/* See DEVICE_WIRE_* above */ + u8 dvo2_wiring; + u16 extended_type; + u8 dvo_function; +} __packed; + +/* This one contains field offsets that are known to be common for all BDB + * versions. Notice that the meaning of the contents contents may still change, + * but at least the offsets are consistent. */ + +/* Definitions for flags_1 */ +#define IBOOST_ENABLE (1<<3) + +struct common_child_dev_config { + u16 handle; + u16 device_type; + u8 not_common1[12]; + u8 dvo_port; + u8 not_common2[2]; + u8 ddc_pin; + u16 edid_ptr; + u8 obsolete; + u8 flags_1; + u8 not_common3[13]; + u8 iboost_level; +} __packed; + + +/* This field changes depending on the BDB version, so the most reliable way to + * read it is by checking the BDB version and reading the raw pointer. */ +union child_device_config { + /* This one is safe to be used anywhere, but the code should still check + * the BDB version. */ + u8 raw[33]; + /* This one should only be kept for legacy code. */ + struct old_child_dev_config old; + /* This one should also be safe to use anywhere, even without version + * checks. */ + struct common_child_dev_config common; +} __packed; + +struct bdb_general_definitions { + /* DDC GPIO */ + u8 crt_ddc_gmbus_pin; + + /* DPMS bits */ + u8 dpms_acpi:1; + u8 skip_boot_crt_detect:1; + u8 dpms_aim:1; + u8 rsvd1:5; /* finish byte */ + + /* boot device bits */ + u8 boot_display[2]; + u8 child_dev_size; + + /* + * Device info: + * If TV is present, it'll be at devices[0]. + * LVDS will be next, either devices[0] or [1], if present. + * On some platforms the number of device is 6. But could be as few as + * 4 if both TV and LVDS are missing. + * And the device num is related with the size of general definition + * block. It is obtained by using the following formula: + * number = (block_size - sizeof(bdb_general_definitions))/ + * defs->child_dev_size; + */ + uint8_t devices[0]; +} __packed; + +/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */ +#define MODE_MASK 0x3 + +struct bdb_lvds_options { + u8 panel_type; + u8 rsvd1; + /* LVDS capabilities, stored in a dword */ + u8 pfit_mode:2; + u8 pfit_text_mode_enhanced:1; + u8 pfit_gfx_mode_enhanced:1; + u8 pfit_ratio_auto:1; + u8 pixel_dither:1; + u8 lvds_edid:1; + u8 rsvd2:1; + u8 rsvd4; + /* LVDS Panel channel bits stored here */ + u32 lvds_panel_channel_bits; + /* LVDS SSC (Spread Spectrum Clock) bits stored here. */ + u16 ssc_bits; + u16 ssc_freq; + u16 ssc_ddt; + /* Panel color depth defined here */ + u16 panel_color_depth; + /* LVDS panel type bits stored here */ + u32 dps_panel_type_bits; + /* LVDS backlight control type bits stored here */ + u32 blt_control_type_bits; +} __packed; + +/* LFP pointer table contains entries to the struct below */ +struct bdb_lvds_lfp_data_ptr { + u16 fp_timing_offset; /* offsets are from start of bdb */ + u8 fp_table_size; + u16 dvo_timing_offset; + u8 dvo_table_size; + u16 panel_pnp_id_offset; + u8 pnp_table_size; +} __packed; + +struct bdb_lvds_lfp_data_ptrs { + u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */ + struct bdb_lvds_lfp_data_ptr ptr[16]; +} __packed; + +/* LFP data has 3 blocks per entry */ +struct lvds_fp_timing { + u16 x_res; + u16 y_res; + u32 lvds_reg; + u32 lvds_reg_val; + u32 pp_on_reg; + u32 pp_on_reg_val; + u32 pp_off_reg; + u32 pp_off_reg_val; + u32 pp_cycle_reg; + u32 pp_cycle_reg_val; + u32 pfit_reg; + u32 pfit_reg_val; + u16 terminator; +} __packed; + +struct lvds_dvo_timing { + u16 clock; /**< In 10khz */ + u8 hactive_lo; + u8 hblank_lo; + u8 hblank_hi:4; + u8 hactive_hi:4; + u8 vactive_lo; + u8 vblank_lo; + u8 vblank_hi:4; + u8 vactive_hi:4; + u8 hsync_off_lo; + u8 hsync_pulse_width; + u8 vsync_pulse_width:4; + u8 vsync_off:4; + u8 rsvd0:6; + u8 hsync_off_hi:2; + u8 h_image; + u8 v_image; + u8 max_hv; + u8 h_border; + u8 v_border; + u8 rsvd1:3; + u8 digital:2; + u8 vsync_positive:1; + u8 hsync_positive:1; + u8 rsvd2:1; +} __packed; + +struct lvds_pnp_id { + u16 mfg_name; + u16 product_code; + u32 serial; + u8 mfg_week; + u8 mfg_year; +} __packed; + +struct bdb_lvds_lfp_data_entry { + struct lvds_fp_timing fp_timing; + struct lvds_dvo_timing dvo_timing; + struct lvds_pnp_id pnp_id; +} __packed; + +struct bdb_lvds_lfp_data { + struct bdb_lvds_lfp_data_entry data[16]; +} __packed; + +#define BDB_BACKLIGHT_TYPE_NONE 0 +#define BDB_BACKLIGHT_TYPE_PWM 2 + +struct bdb_lfp_backlight_data_entry { + u8 type:2; + u8 active_low_pwm:1; + u8 obsolete1:5; + u16 pwm_freq_hz; + u8 min_brightness; + u8 obsolete2; + u8 obsolete3; +} __packed; + +struct bdb_lfp_backlight_data { + u8 entry_size; + struct bdb_lfp_backlight_data_entry data[16]; + u8 level[16]; +} __packed; + +struct aimdb_header { + char signature[16]; + char oem_device[20]; + u16 aimdb_version; + u16 aimdb_header_size; + u16 aimdb_size; +} __packed; + +struct aimdb_block { + u8 aimdb_id; + u16 aimdb_size; +} __packed; + +struct vch_panel_data { + u16 fp_timing_offset; + u8 fp_timing_size; + u16 dvo_timing_offset; + u8 dvo_timing_size; + u16 text_fitting_offset; + u8 text_fitting_size; + u16 graphics_fitting_offset; + u8 graphics_fitting_size; +} __packed; + +struct vch_bdb_22 { + struct aimdb_block aimdb_block; + struct vch_panel_data panels[16]; +} __packed; + +struct bdb_sdvo_lvds_options { + u8 panel_backlight; + u8 h40_set_panel_type; + u8 panel_type; + u8 ssc_clk_freq; + u16 als_low_trip; + u16 als_high_trip; + u8 sclalarcoeff_tab_row_num; + u8 sclalarcoeff_tab_row_size; + u8 coefficient[8]; + u8 panel_misc_bits_1; + u8 panel_misc_bits_2; + u8 panel_misc_bits_3; + u8 panel_misc_bits_4; +} __packed; + + +#define BDB_DRIVER_FEATURE_NO_LVDS 0 +#define BDB_DRIVER_FEATURE_INT_LVDS 1 +#define BDB_DRIVER_FEATURE_SDVO_LVDS 2 +#define BDB_DRIVER_FEATURE_EDP 3 + +struct bdb_driver_features { + u8 boot_dev_algorithm:1; + u8 block_display_switch:1; + u8 allow_display_switch:1; + u8 hotplug_dvo:1; + u8 dual_view_zoom:1; + u8 int15h_hook:1; + u8 sprite_in_clone:1; + u8 primary_lfp_id:1; + + u16 boot_mode_x; + u16 boot_mode_y; + u8 boot_mode_bpp; + u8 boot_mode_refresh; + + u16 enable_lfp_primary:1; + u16 selective_mode_pruning:1; + u16 dual_frequency:1; + u16 render_clock_freq:1; /* 0: high freq; 1: low freq */ + u16 nt_clone_support:1; + u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */ + u16 sprite_display_assign:1; /* 0: secondary; 1: primary */ + u16 cui_aspect_scaling:1; + u16 preserve_aspect_ratio:1; + u16 sdvo_device_power_down:1; + u16 crt_hotplug:1; + u16 lvds_config:2; + u16 tv_hotplug:1; + u16 hdmi_config:2; + + u8 static_display:1; + u8 reserved2:7; + u16 legacy_crt_max_x; + u16 legacy_crt_max_y; + u8 legacy_crt_max_refresh; + + u8 hdmi_termination; + u8 custom_vbt_version; + /* Driver features data block */ + u16 rmpm_enabled:1; + u16 s2ddt_enabled:1; + u16 dpst_enabled:1; + u16 bltclt_enabled:1; + u16 adb_enabled:1; + u16 drrs_enabled:1; + u16 grs_enabled:1; + u16 gpmt_enabled:1; + u16 tbt_enabled:1; + u16 psr_enabled:1; + u16 ips_enabled:1; + u16 reserved3:4; + u16 pc_feature_valid:1; +} __packed; + +#define EDP_18BPP 0 +#define EDP_24BPP 1 +#define EDP_30BPP 2 +#define EDP_RATE_1_62 0 +#define EDP_RATE_2_7 1 +#define EDP_LANE_1 0 +#define EDP_LANE_2 1 +#define EDP_LANE_4 3 +#define EDP_PREEMPHASIS_NONE 0 +#define EDP_PREEMPHASIS_3_5dB 1 +#define EDP_PREEMPHASIS_6dB 2 +#define EDP_PREEMPHASIS_9_5dB 3 +#define EDP_VSWING_0_4V 0 +#define EDP_VSWING_0_6V 1 +#define EDP_VSWING_0_8V 2 +#define EDP_VSWING_1_2V 3 + + +struct edp_link_params { + u8 rate:4; + u8 lanes:4; + u8 preemphasis:4; + u8 vswing:4; +} __packed; + +struct bdb_edp { + struct edp_power_seq power_seqs[16]; + u32 color_depth; + struct edp_link_params link_params[16]; + u32 sdrrs_msa_timing_delay; + + /* ith bit indicates enabled/disabled for (i+1)th panel */ + u16 edp_s3d_feature; + u16 edp_t3_optimization; + u64 edp_vswing_preemph; /* v173 */ +} __packed; + +struct psr_table { + /* Feature bits */ + u8 full_link:1; + u8 require_aux_to_wakeup:1; + u8 feature_bits_rsvd:6; + + /* Wait times */ + u8 idle_frames:4; + u8 lines_to_wait:3; + u8 wait_times_rsvd:1; + + /* TP wake up time in multiple of 100 */ + u16 tp1_wakeup_time; + u16 tp2_tp3_wakeup_time; +} __packed; + +struct bdb_psr { + struct psr_table psr_table[16]; +} __packed; + +/* + * Driver<->VBIOS interaction occurs through scratch bits in + * GR18 & SWF*. + */ + +/* GR18 bits are set on display switch and hotkey events */ +#define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */ +#define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */ +#define GR18_HK_NONE (0x0<<3) +#define GR18_HK_LFP_STRETCH (0x1<<3) +#define GR18_HK_TOGGLE_DISP (0x2<<3) +#define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */ +#define GR18_HK_POPUP_DISABLED (0x6<<3) +#define GR18_HK_POPUP_ENABLED (0x7<<3) +#define GR18_HK_PFIT (0x8<<3) +#define GR18_HK_APM_CHANGE (0xa<<3) +#define GR18_HK_MULTIPLE (0xc<<3) +#define GR18_USER_INT_EN (1<<2) +#define GR18_A0000_FLUSH_EN (1<<1) +#define GR18_SMM_EN (1<<0) + +/* Set by driver, cleared by VBIOS */ +#define SWF00_YRES_SHIFT 16 +#define SWF00_XRES_SHIFT 0 +#define SWF00_RES_MASK 0xffff + +/* Set by VBIOS at boot time and driver at runtime */ +#define SWF01_TV2_FORMAT_SHIFT 8 +#define SWF01_TV1_FORMAT_SHIFT 0 +#define SWF01_TV_FORMAT_MASK 0xffff + +#define SWF10_VBIOS_BLC_I2C_EN (1<<29) +#define SWF10_GTT_OVERRIDE_EN (1<<28) +#define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */ +#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24) +#define SWF10_OLD_TOGGLE 0x0 +#define SWF10_TOGGLE_LIST_1 0x1 +#define SWF10_TOGGLE_LIST_2 0x2 +#define SWF10_TOGGLE_LIST_3 0x3 +#define SWF10_TOGGLE_LIST_4 0x4 +#define SWF10_PANNING_EN (1<<23) +#define SWF10_DRIVER_LOADED (1<<22) +#define SWF10_EXTENDED_DESKTOP (1<<21) +#define SWF10_EXCLUSIVE_MODE (1<<20) +#define SWF10_OVERLAY_EN (1<<19) +#define SWF10_PLANEB_HOLDOFF (1<<18) +#define SWF10_PLANEA_HOLDOFF (1<<17) +#define SWF10_VGA_HOLDOFF (1<<16) +#define SWF10_ACTIVE_DISP_MASK 0xffff +#define SWF10_PIPEB_LFP2 (1<<15) +#define SWF10_PIPEB_EFP2 (1<<14) +#define SWF10_PIPEB_TV2 (1<<13) +#define SWF10_PIPEB_CRT2 (1<<12) +#define SWF10_PIPEB_LFP (1<<11) +#define SWF10_PIPEB_EFP (1<<10) +#define SWF10_PIPEB_TV (1<<9) +#define SWF10_PIPEB_CRT (1<<8) +#define SWF10_PIPEA_LFP2 (1<<7) +#define SWF10_PIPEA_EFP2 (1<<6) +#define SWF10_PIPEA_TV2 (1<<5) +#define SWF10_PIPEA_CRT2 (1<<4) +#define SWF10_PIPEA_LFP (1<<3) +#define SWF10_PIPEA_EFP (1<<2) +#define SWF10_PIPEA_TV (1<<1) +#define SWF10_PIPEA_CRT (1<<0) + +#define SWF11_MEMORY_SIZE_SHIFT 16 +#define SWF11_SV_TEST_EN (1<<15) +#define SWF11_IS_AGP (1<<14) +#define SWF11_DISPLAY_HOLDOFF (1<<13) +#define SWF11_DPMS_REDUCED (1<<12) +#define SWF11_IS_VBE_MODE (1<<11) +#define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */ +#define SWF11_DPMS_MASK 0x07 +#define SWF11_DPMS_OFF (1<<2) +#define SWF11_DPMS_SUSPEND (1<<1) +#define SWF11_DPMS_STANDBY (1<<0) +#define SWF11_DPMS_ON 0 + +#define SWF14_GFX_PFIT_EN (1<<31) +#define SWF14_TEXT_PFIT_EN (1<<30) +#define SWF14_LID_STATUS_CLOSED (1<<29) /* 0 here means open */ +#define SWF14_POPUP_EN (1<<28) +#define SWF14_DISPLAY_HOLDOFF (1<<27) +#define SWF14_DISP_DETECT_EN (1<<26) +#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */ +#define SWF14_DRIVER_STATUS (1<<24) +#define SWF14_OS_TYPE_WIN9X (1<<23) +#define SWF14_OS_TYPE_WINNT (1<<22) +/* 21:19 rsvd */ +#define SWF14_PM_TYPE_MASK 0x00070000 +#define SWF14_PM_ACPI_VIDEO (0x4 << 16) +#define SWF14_PM_ACPI (0x3 << 16) +#define SWF14_PM_APM_12 (0x2 << 16) +#define SWF14_PM_APM_11 (0x1 << 16) +#define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */ + /* if GR18 indicates a display switch */ +#define SWF14_DS_PIPEB_LFP2_EN (1<<15) +#define SWF14_DS_PIPEB_EFP2_EN (1<<14) +#define SWF14_DS_PIPEB_TV2_EN (1<<13) +#define SWF14_DS_PIPEB_CRT2_EN (1<<12) +#define SWF14_DS_PIPEB_LFP_EN (1<<11) +#define SWF14_DS_PIPEB_EFP_EN (1<<10) +#define SWF14_DS_PIPEB_TV_EN (1<<9) +#define SWF14_DS_PIPEB_CRT_EN (1<<8) +#define SWF14_DS_PIPEA_LFP2_EN (1<<7) +#define SWF14_DS_PIPEA_EFP2_EN (1<<6) +#define SWF14_DS_PIPEA_TV2_EN (1<<5) +#define SWF14_DS_PIPEA_CRT2_EN (1<<4) +#define SWF14_DS_PIPEA_LFP_EN (1<<3) +#define SWF14_DS_PIPEA_EFP_EN (1<<2) +#define SWF14_DS_PIPEA_TV_EN (1<<1) +#define SWF14_DS_PIPEA_CRT_EN (1<<0) + /* if GR18 indicates a panel fitting request */ +#define SWF14_PFIT_EN (1<<0) /* 0 means disable */ + /* if GR18 indicates an APM change request */ +#define SWF14_APM_HIBERNATE 0x4 +#define SWF14_APM_SUSPEND 0x3 +#define SWF14_APM_STANDBY 0x1 +#define SWF14_APM_RESTORE 0x0 + +/* Add the device class for LFP, TV, HDMI */ +#define DEVICE_TYPE_INT_LFP 0x1022 +#define DEVICE_TYPE_INT_TV 0x1009 +#define DEVICE_TYPE_HDMI 0x60D2 +#define DEVICE_TYPE_DP 0x68C6 +#define DEVICE_TYPE_eDP 0x78C6 + +#define DEVICE_TYPE_CLASS_EXTENSION (1 << 15) +#define DEVICE_TYPE_POWER_MANAGEMENT (1 << 14) +#define DEVICE_TYPE_HOTPLUG_SIGNALING (1 << 13) +#define DEVICE_TYPE_INTERNAL_CONNECTOR (1 << 12) +#define DEVICE_TYPE_NOT_HDMI_OUTPUT (1 << 11) +#define DEVICE_TYPE_MIPI_OUTPUT (1 << 10) +#define DEVICE_TYPE_COMPOSITE_OUTPUT (1 << 9) +#define DEVICE_TYPE_DUAL_CHANNEL (1 << 8) +#define DEVICE_TYPE_HIGH_SPEED_LINK (1 << 6) +#define DEVICE_TYPE_LVDS_SINGALING (1 << 5) +#define DEVICE_TYPE_TMDS_DVI_SIGNALING (1 << 4) +#define DEVICE_TYPE_VIDEO_SIGNALING (1 << 3) +#define DEVICE_TYPE_DISPLAYPORT_OUTPUT (1 << 2) +#define DEVICE_TYPE_DIGITAL_OUTPUT (1 << 1) +#define DEVICE_TYPE_ANALOG_OUTPUT (1 << 0) + +/* + * Bits we care about when checking for DEVICE_TYPE_eDP + * Depending on the system, the other bits may or may not + * be set for eDP outputs. + */ +#define DEVICE_TYPE_eDP_BITS \ + (DEVICE_TYPE_INTERNAL_CONNECTOR | \ + DEVICE_TYPE_MIPI_OUTPUT | \ + DEVICE_TYPE_COMPOSITE_OUTPUT | \ + DEVICE_TYPE_DUAL_CHANNEL | \ + DEVICE_TYPE_LVDS_SINGALING | \ + DEVICE_TYPE_TMDS_DVI_SIGNALING | \ + DEVICE_TYPE_VIDEO_SIGNALING | \ + DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ + DEVICE_TYPE_ANALOG_OUTPUT) + +/* define the DVO port for HDMI output type */ +#define DVO_B 1 +#define DVO_C 2 +#define DVO_D 3 + +/* Possible values for the "DVO Port" field for versions >= 155: */ +#define DVO_PORT_HDMIA 0 +#define DVO_PORT_HDMIB 1 +#define DVO_PORT_HDMIC 2 +#define DVO_PORT_HDMID 3 +#define DVO_PORT_LVDS 4 +#define DVO_PORT_TV 5 +#define DVO_PORT_CRT 6 +#define DVO_PORT_DPB 7 +#define DVO_PORT_DPC 8 +#define DVO_PORT_DPD 9 +#define DVO_PORT_DPA 10 +#define DVO_PORT_DPE 11 +#define DVO_PORT_HDMIE 12 +#define DVO_PORT_MIPIA 21 +#define DVO_PORT_MIPIB 22 +#define DVO_PORT_MIPIC 23 +#define DVO_PORT_MIPID 24 + +/* Block 52 contains MIPI configuration block + * 6 * bdb_mipi_config, followed by 6 pps data block + * block below + */ +#define MAX_MIPI_CONFIGURATIONS 6 + +struct bdb_mipi_config { + struct mipi_config config[MAX_MIPI_CONFIGURATIONS]; + struct mipi_pps_data pps[MAX_MIPI_CONFIGURATIONS]; +} __packed; + +/* Block 53 contains MIPI sequences as needed by the panel + * for enabling it. This block can be variable in size and + * can be maximum of 6 blocks + */ +struct bdb_mipi_sequence { + u8 version; + u8 data[0]; +} __packed; + +enum mipi_gpio_pin_index { + MIPI_GPIO_UNDEFINED = 0, + MIPI_GPIO_PANEL_ENABLE, + MIPI_GPIO_BL_ENABLE, + MIPI_GPIO_PWM_ENABLE, + MIPI_GPIO_RESET_N, + MIPI_GPIO_PWR_DOWN_R, + MIPI_GPIO_STDBY_RST_N, + MIPI_GPIO_MAX +}; + +#endif /* _INTEL_VBT_DEFS_H_ */ -- cgit v0.10.2 From ee4b6faf96a990d2acc30084f4edf015ca21b9c4 Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 16 Mar 2016 17:54:00 +0200 Subject: drm/i915: Modify reset func to handle per engine resets In full gpu reset we prime all engines and reset domains corresponding to each engine. Per engine reset is just a special case of this process wherein only a single engine is reset. This change is aimed to modify relevant functions to achieve this. There are some other steps we carry out in case of engine reset which are addressed in later patches. Reset func now accepts a mask of all engines that need to be reset. Where per engine resets are supported, error handler populates the mask accordingly otherwise all engines are specified. v2: ALL_ENGINES mask fixup, better for_each_ring_masked (Chris) v3: Whitespace fixes (Chris) v4: Rebase due to s/ring/engine Cc: Chris Wilson Signed-off-by: Mika Kuoppala Signed-off-by: Arun Siluvery Reviewed-by: Chris Wilson Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1458143640-20563-1-git-send-email-mika.kuoppala@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 20e8200..3648b73 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -881,7 +881,7 @@ int i915_reset(struct drm_device *dev) simulated = dev_priv->gpu_error.stop_rings != 0; - ret = intel_gpu_reset(dev); + ret = intel_gpu_reset(dev, ALL_ENGINES); /* Also reset the gpu hangman. */ if (simulated) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8a10c4b..f2ab545 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1988,6 +1988,10 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) for ((i__) = 0; (i__) < I915_NUM_ENGINES; (i__)++) \ for_each_if ((((ring__) = &(dev_priv__)->engine[(i__)]), intel_engine_initialized((ring__)))) +#define for_each_engine_masked(engine__, dev_priv__, mask__) \ + for ((engine__) = &dev_priv->engine[0]; (engine__) < &dev_priv->engine[I915_NUM_ENGINES]; (engine__)++) \ + for_each_if (intel_engine_flag((engine__)) & (mask__) && intel_engine_initialized((engine__))) + enum hdmi_force_audio { HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ HDMI_AUDIO_OFF, /* force turn off HDMI audio */ @@ -2570,6 +2574,8 @@ struct drm_i915_cmd_table { #define BLT_RING (1<ring_mask & BSD_RING) #define HAS_BSD2(dev) (INTEL_INFO(dev)->ring_mask & BSD2_RING) #define HAS_BLT(dev) (INTEL_INFO(dev)->ring_mask & BLT_RING) @@ -2698,7 +2704,7 @@ extern void i915_driver_postclose(struct drm_device *dev, extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); #endif -extern int intel_gpu_reset(struct drm_device *dev); +extern int intel_gpu_reset(struct drm_device *dev, u32 engine_mask); extern bool intel_has_gpu_reset(struct drm_device *dev); extern int i915_reset(struct drm_device *dev); extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 31652c1..a25109a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5012,13 +5012,13 @@ i915_gem_cleanup_engines(struct drm_device *dev) for_each_engine(engine, dev_priv, i) dev_priv->gt.cleanup_engine(engine); - if (i915.enable_execlists) - /* - * Neither the BIOS, ourselves or any other kernel - * expects the system to be in execlists mode on startup, - * so we need to reset the GPU back to legacy mode. - */ - intel_gpu_reset(dev); + if (i915.enable_execlists) + /* + * Neither the BIOS, ourselves or any other kernel + * expects the system to be in execlists mode on startup, + * so we need to reset the GPU back to legacy mode. + */ + intel_gpu_reset(dev, ALL_ENGINES); } static void diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 1993449..c114665 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -413,7 +413,7 @@ void i915_gem_context_fini(struct drm_device *dev) /* The only known way to stop the gpu from accessing the hw context is * to reset it. Do this as the very last operation to avoid confusing * other code, leading to spurious errors. */ - intel_gpu_reset(dev); + intel_gpu_reset(dev, ALL_ENGINES); /* When default context is created and switched to, base object refcount * will be 2 (+1 from object creation and +1 from do_switch()). diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d4a298f..07e0449 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -164,6 +164,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define GEN6_GRDOM_RENDER (1 << 1) #define GEN6_GRDOM_MEDIA (1 << 2) #define GEN6_GRDOM_BLT (1 << 3) +#define GEN6_GRDOM_VECS (1 << 4) +#define GEN8_GRDOM_MEDIA2 (1 << 7) #define RING_PP_DIR_BASE(ring) _MMIO((ring)->mmio_base+0x228) #define RING_PP_DIR_BASE_READ(ring) _MMIO((ring)->mmio_base+0x518) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 02add02..512b7fa 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1433,7 +1433,7 @@ static int i915_reset_complete(struct drm_device *dev) return (gdrst & GRDOM_RESET_STATUS) == 0; } -static int i915_do_reset(struct drm_device *dev) +static int i915_do_reset(struct drm_device *dev, unsigned engine_mask) { /* assert reset for at least 20 usec */ pci_write_config_byte(dev->pdev, I915_GDRST, GRDOM_RESET_ENABLE); @@ -1450,13 +1450,13 @@ static int g4x_reset_complete(struct drm_device *dev) return (gdrst & GRDOM_RESET_ENABLE) == 0; } -static int g33_do_reset(struct drm_device *dev) +static int g33_do_reset(struct drm_device *dev, unsigned engine_mask) { pci_write_config_byte(dev->pdev, I915_GDRST, GRDOM_RESET_ENABLE); return wait_for(g4x_reset_complete(dev), 500); } -static int g4x_do_reset(struct drm_device *dev) +static int g4x_do_reset(struct drm_device *dev, unsigned engine_mask) { struct drm_i915_private *dev_priv = dev->dev_private; int ret; @@ -1486,7 +1486,7 @@ static int g4x_do_reset(struct drm_device *dev) return 0; } -static int ironlake_do_reset(struct drm_device *dev) +static int ironlake_do_reset(struct drm_device *dev, unsigned engine_mask) { struct drm_i915_private *dev_priv = dev->dev_private; int ret; @@ -1510,21 +1510,62 @@ static int ironlake_do_reset(struct drm_device *dev) return 0; } -static int gen6_do_reset(struct drm_device *dev) +/* Reset the hardware domains (GENX_GRDOM_*) specified by mask */ +static int gen6_hw_domain_reset(struct drm_i915_private *dev_priv, + u32 hw_domain_mask) { - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; - - /* Reset the chip */ + int ret; /* GEN6_GDRST is not in the gt power well, no need to check * for fifo space for the write or forcewake the chip for * the read */ - __raw_i915_write32(dev_priv, GEN6_GDRST, GEN6_GRDOM_FULL); + __raw_i915_write32(dev_priv, GEN6_GDRST, hw_domain_mask); - /* Spin waiting for the device to ack the reset request */ - ret = wait_for((__raw_i915_read32(dev_priv, GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500); +#define ACKED ((__raw_i915_read32(dev_priv, GEN6_GDRST) & hw_domain_mask) == 0) + /* Spin waiting for the device to ack the reset requests */ + ret = wait_for(ACKED, 500); +#undef ACKED + + return ret; +} + +/** + * gen6_reset_engines - reset individual engines + * @dev: DRM device + * @engine_mask: mask of intel_ring_flag() engines or ALL_ENGINES for full reset + * + * This function will reset the individual engines that are set in engine_mask. + * If you provide ALL_ENGINES as mask, full global domain reset will be issued. + * + * Note: It is responsibility of the caller to handle the difference between + * asking full domain reset versus reset for all available individual engines. + * + * Returns 0 on success, nonzero on error. + */ +static int gen6_reset_engines(struct drm_device *dev, unsigned engine_mask) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_engine_cs *engine; + const u32 hw_engine_mask[I915_NUM_ENGINES] = { + [RCS] = GEN6_GRDOM_RENDER, + [BCS] = GEN6_GRDOM_BLT, + [VCS] = GEN6_GRDOM_MEDIA, + [VCS2] = GEN8_GRDOM_MEDIA2, + [VECS] = GEN6_GRDOM_VECS, + }; + u32 hw_mask; + int ret; + + if (engine_mask == ALL_ENGINES) { + hw_mask = GEN6_GRDOM_FULL; + } else { + hw_mask = 0; + for_each_engine_masked(engine, dev_priv, engine_mask) + hw_mask |= hw_engine_mask[engine->id]; + } + + ret = gen6_hw_domain_reset(dev_priv, hw_mask); intel_uncore_forcewake_reset(dev, true); @@ -1567,34 +1608,34 @@ static void gen8_unrequest_engine_reset(struct intel_engine_cs *engine) _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET)); } -static int gen8_do_reset(struct drm_device *dev) +static int gen8_reset_engines(struct drm_device *dev, unsigned engine_mask) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int i; - for_each_engine(engine, dev_priv, i) + for_each_engine_masked(engine, dev_priv, engine_mask) if (gen8_request_engine_reset(engine)) goto not_ready; - return gen6_do_reset(dev); + return gen6_reset_engines(dev, engine_mask); not_ready: - for_each_engine(engine, dev_priv, i) + for_each_engine_masked(engine, dev_priv, engine_mask) gen8_unrequest_engine_reset(engine); return -EIO; } -static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *) +static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *, + unsigned engine_mask) { if (!i915.reset) return NULL; if (INTEL_INFO(dev)->gen >= 8) - return gen8_do_reset; + return gen8_reset_engines; else if (INTEL_INFO(dev)->gen >= 6) - return gen6_do_reset; + return gen6_reset_engines; else if (IS_GEN5(dev)) return ironlake_do_reset; else if (IS_G4X(dev)) @@ -1607,10 +1648,10 @@ static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *) return NULL; } -int intel_gpu_reset(struct drm_device *dev) +int intel_gpu_reset(struct drm_device *dev, unsigned engine_mask) { struct drm_i915_private *dev_priv = to_i915(dev); - int (*reset)(struct drm_device *); + int (*reset)(struct drm_device *, unsigned); int ret; reset = intel_get_gpu_reset(dev); @@ -1621,7 +1662,7 @@ int intel_gpu_reset(struct drm_device *dev) * request may be dropped and never completes (causing -EIO). */ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); - ret = reset(dev); + ret = reset(dev, engine_mask); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); return ret; -- cgit v0.10.2 From 066de1aadf6aba1911560cf90a5bc8e25ca1aae9 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:38:50 +0200 Subject: Fix MCHBAR cleanup on the driver init error path MCHBAR is cleaned up in i915_mmio_cleanup(), so the separate call in i915_driver_load() is incorrect. CC: David Weinehall Fixes: ad5c3d3ffbb2 ("drm/i915: Move MCHBAR setup earlier during init") Signed-off-by: Imre Deak Reviewed-by: David Weinehall Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-2-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 85b3130..1cbd995 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1175,7 +1175,6 @@ out_gem_unload: if (dev->pdev->msi_enabled) pci_disable_msi(dev->pdev); - intel_teardown_mchbar(dev); pm_qos_remove_request(&dev_priv->pm_qos); arch_phys_wc_del(dev_priv->gtt.mtrr); io_mapping_free(dev_priv->gtt.mappable); -- cgit v0.10.2 From 861f878e6a7a8bc152c92de358b96eb3bd086f78 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:38:51 +0200 Subject: drm/i915: Move load time PCH detect, DPIO, power domain SW init earlier These are all SW only init steps not accessing the device and they only need the platform identification macros to work, which are already available earlier, so move these init steps earlier. Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-3-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 1cbd995..c79f532 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1020,7 +1020,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (ret < 0) goto out_free_priv; + /* This must be called before any calls to HAS_PCH_* */ + intel_detect_pch(dev); + intel_pm_setup(dev); + intel_init_dpio(dev_priv); + intel_power_domains_init(dev_priv); intel_runtime_pm_get(dev_priv); @@ -1045,9 +1050,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (ret < 0) goto put_bridge; - /* This must be called before any calls to HAS_PCH_* */ - intel_detect_pch(dev); - intel_uncore_init(dev); ret = i915_gem_gtt_init(dev); @@ -1124,16 +1126,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_device_info_runtime_init(dev); - intel_init_dpio(dev_priv); - if (INTEL_INFO(dev)->num_pipes) { ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes); if (ret) goto out_gem_unload; } - intel_power_domains_init(dev_priv); - ret = i915_load_modeset_init(dev); if (ret < 0) { DRM_ERROR("failed to init modeset\n"); -- cgit v0.10.2 From bd39ec5ddae8807644196cadbb62bb2b3d88607b Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:38:52 +0200 Subject: drm/i915: Move load time IRQ SW init earlier Most of the IRQ init is setting up hooks so move that part earlier. Leave the pm_qos_add_request() call in place. Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-4-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c79f532..e23cdad 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1026,6 +1026,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_pm_setup(dev); intel_init_dpio(dev_priv); intel_power_domains_init(dev_priv); + intel_irq_init(dev_priv); intel_runtime_pm_get(dev_priv); @@ -1100,7 +1101,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->gtt.mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base, aperture_size); - intel_irq_init(dev_priv); + pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); + intel_uncore_sanitize(dev); intel_opregion_setup(dev); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0f61ae0..8f3e330 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -4565,8 +4565,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv) INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work, i915_hangcheck_elapsed); - pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); - if (IS_GEN2(dev_priv)) { dev->max_vblank_count = 0; dev->driver->get_vblank_counter = i8xx_get_vblank_counter; -- cgit v0.10.2 From 8821294172f0f807b7928909aeadd4e7467d2ed0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:38:53 +0200 Subject: drm/i915: Move load time init of display/audio hooks earlier All of this is SW only initialization so we can move them earlier. Move the mutex init where the rest of the locks are inited. While at it also convert dev to dev_priv. v2: - use the term hook instead of callback for these functions (Jani) CC: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-5-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index e23cdad..b90d2d9 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1015,6 +1015,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) mutex_init(&dev_priv->modeset_restore_lock); mutex_init(&dev_priv->av_mutex); mutex_init(&dev_priv->wm.wm_mutex); + mutex_init(&dev_priv->pps_mutex); ret = i915_workqueues_init(dev_priv); if (ret < 0) @@ -1027,6 +1028,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_init_dpio(dev_priv); intel_power_domains_init(dev_priv); intel_irq_init(dev_priv); + intel_init_display_hooks(dev_priv); + intel_init_audio_hooks(dev_priv); intel_runtime_pm_get(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 30f9214..fdc8b2a 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -564,23 +564,21 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder) } /** - * intel_init_audio - Set up chip specific audio functions - * @dev: drm device + * intel_init_audio_hooks - Set up chip specific audio hooks + * @dev_priv: device private */ -void intel_init_audio(struct drm_device *dev) +void intel_init_audio_hooks(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; - - if (IS_G4X(dev)) { + if (IS_G4X(dev_priv)) { dev_priv->display.audio_codec_enable = g4x_audio_codec_enable; dev_priv->display.audio_codec_disable = g4x_audio_codec_disable; - } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { dev_priv->display.audio_codec_enable = ilk_audio_codec_enable; dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; - } else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) { + } else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) { dev_priv->display.audio_codec_enable = hsw_audio_codec_enable; dev_priv->display.audio_codec_disable = hsw_audio_codec_disable; - } else if (HAS_PCH_SPLIT(dev)) { + } else if (HAS_PCH_SPLIT(dev_priv)) { dev_priv->display.audio_codec_enable = ilk_audio_codec_enable; dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e3e1581..ab1ec8d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14824,23 +14824,24 @@ static const struct drm_mode_config_funcs intel_mode_funcs = { .atomic_state_clear = intel_atomic_state_clear, }; -/* Set up chip specific display functions */ -static void intel_init_display(struct drm_device *dev) +/** + * intel_init_display_hooks - initialize the display modesetting hooks + * @dev_priv: device private + */ +void intel_init_display_hooks(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; - - if (HAS_PCH_SPLIT(dev) || IS_G4X(dev)) + if (HAS_PCH_SPLIT(dev_priv) || IS_G4X(dev_priv)) dev_priv->display.find_dpll = g4x_find_best_dpll; - else if (IS_CHERRYVIEW(dev)) + else if (IS_CHERRYVIEW(dev_priv)) dev_priv->display.find_dpll = chv_find_best_dpll; - else if (IS_VALLEYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv)) dev_priv->display.find_dpll = vlv_find_best_dpll; - else if (IS_PINEVIEW(dev)) + else if (IS_PINEVIEW(dev_priv)) dev_priv->display.find_dpll = pnv_find_best_dpll; else dev_priv->display.find_dpll = i9xx_find_best_dpll; - if (INTEL_INFO(dev)->gen >= 9) { + if (INTEL_INFO(dev_priv)->gen >= 9) { dev_priv->display.get_pipe_config = haswell_get_pipe_config; dev_priv->display.get_initial_plane_config = skylake_get_initial_plane_config; @@ -14848,7 +14849,7 @@ static void intel_init_display(struct drm_device *dev) haswell_crtc_compute_clock; dev_priv->display.crtc_enable = haswell_crtc_enable; dev_priv->display.crtc_disable = haswell_crtc_disable; - } else if (HAS_DDI(dev)) { + } else if (HAS_DDI(dev_priv)) { dev_priv->display.get_pipe_config = haswell_get_pipe_config; dev_priv->display.get_initial_plane_config = ironlake_get_initial_plane_config; @@ -14856,7 +14857,7 @@ static void intel_init_display(struct drm_device *dev) haswell_crtc_compute_clock; dev_priv->display.crtc_enable = haswell_crtc_enable; dev_priv->display.crtc_disable = haswell_crtc_disable; - } else if (HAS_PCH_SPLIT(dev)) { + } else if (HAS_PCH_SPLIT(dev_priv)) { dev_priv->display.get_pipe_config = ironlake_get_pipe_config; dev_priv->display.get_initial_plane_config = ironlake_get_initial_plane_config; @@ -14864,7 +14865,7 @@ static void intel_init_display(struct drm_device *dev) ironlake_crtc_compute_clock; dev_priv->display.crtc_enable = ironlake_crtc_enable; dev_priv->display.crtc_disable = ironlake_crtc_disable; - } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.get_initial_plane_config = i9xx_get_initial_plane_config; @@ -14881,89 +14882,89 @@ static void intel_init_display(struct drm_device *dev) } /* Returns the core display clock speed */ - if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) + if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) dev_priv->display.get_display_clock_speed = skylake_get_display_clock_speed; - else if (IS_BROXTON(dev)) + else if (IS_BROXTON(dev_priv)) dev_priv->display.get_display_clock_speed = broxton_get_display_clock_speed; - else if (IS_BROADWELL(dev)) + else if (IS_BROADWELL(dev_priv)) dev_priv->display.get_display_clock_speed = broadwell_get_display_clock_speed; - else if (IS_HASWELL(dev)) + else if (IS_HASWELL(dev_priv)) dev_priv->display.get_display_clock_speed = haswell_get_display_clock_speed; - else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) + else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) dev_priv->display.get_display_clock_speed = valleyview_get_display_clock_speed; - else if (IS_GEN5(dev)) + else if (IS_GEN5(dev_priv)) dev_priv->display.get_display_clock_speed = ilk_get_display_clock_speed; - else if (IS_I945G(dev) || IS_BROADWATER(dev) || - IS_GEN6(dev) || IS_IVYBRIDGE(dev)) + else if (IS_I945G(dev_priv) || IS_BROADWATER(dev_priv) || + IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) dev_priv->display.get_display_clock_speed = i945_get_display_clock_speed; - else if (IS_GM45(dev)) + else if (IS_GM45(dev_priv)) dev_priv->display.get_display_clock_speed = gm45_get_display_clock_speed; - else if (IS_CRESTLINE(dev)) + else if (IS_CRESTLINE(dev_priv)) dev_priv->display.get_display_clock_speed = i965gm_get_display_clock_speed; - else if (IS_PINEVIEW(dev)) + else if (IS_PINEVIEW(dev_priv)) dev_priv->display.get_display_clock_speed = pnv_get_display_clock_speed; - else if (IS_G33(dev) || IS_G4X(dev)) + else if (IS_G33(dev_priv) || IS_G4X(dev_priv)) dev_priv->display.get_display_clock_speed = g33_get_display_clock_speed; - else if (IS_I915G(dev)) + else if (IS_I915G(dev_priv)) dev_priv->display.get_display_clock_speed = i915_get_display_clock_speed; - else if (IS_I945GM(dev) || IS_845G(dev)) + else if (IS_I945GM(dev_priv) || IS_845G(dev_priv)) dev_priv->display.get_display_clock_speed = i9xx_misc_get_display_clock_speed; - else if (IS_I915GM(dev)) + else if (IS_I915GM(dev_priv)) dev_priv->display.get_display_clock_speed = i915gm_get_display_clock_speed; - else if (IS_I865G(dev)) + else if (IS_I865G(dev_priv)) dev_priv->display.get_display_clock_speed = i865_get_display_clock_speed; - else if (IS_I85X(dev)) + else if (IS_I85X(dev_priv)) dev_priv->display.get_display_clock_speed = i85x_get_display_clock_speed; else { /* 830 */ - WARN(!IS_I830(dev), "Unknown platform. Assuming 133 MHz CDCLK\n"); + WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz CDCLK\n"); dev_priv->display.get_display_clock_speed = i830_get_display_clock_speed; } - if (IS_GEN5(dev)) { + if (IS_GEN5(dev_priv)) { dev_priv->display.fdi_link_train = ironlake_fdi_link_train; - } else if (IS_GEN6(dev)) { + } else if (IS_GEN6(dev_priv)) { dev_priv->display.fdi_link_train = gen6_fdi_link_train; - } else if (IS_IVYBRIDGE(dev)) { + } else if (IS_IVYBRIDGE(dev_priv)) { /* FIXME: detect B0+ stepping and use auto training */ dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; - } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { dev_priv->display.fdi_link_train = hsw_fdi_link_train; - if (IS_BROADWELL(dev)) { + if (IS_BROADWELL(dev_priv)) { dev_priv->display.modeset_commit_cdclk = broadwell_modeset_commit_cdclk; dev_priv->display.modeset_calc_cdclk = broadwell_modeset_calc_cdclk; } - } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { dev_priv->display.modeset_commit_cdclk = valleyview_modeset_commit_cdclk; dev_priv->display.modeset_calc_cdclk = valleyview_modeset_calc_cdclk; - } else if (IS_BROXTON(dev)) { + } else if (IS_BROXTON(dev_priv)) { dev_priv->display.modeset_commit_cdclk = broxton_modeset_commit_cdclk; dev_priv->display.modeset_calc_cdclk = broxton_modeset_calc_cdclk; } - switch (INTEL_INFO(dev)->gen) { + switch (INTEL_INFO(dev_priv)->gen) { case 2: dev_priv->display.queue_flip = intel_gen2_queue_flip; break; @@ -14990,8 +14991,6 @@ static void intel_init_display(struct drm_device *dev) /* Default just returns -ENODEV to indicate unsupported */ dev_priv->display.queue_flip = intel_default_queue_flip; } - - mutex_init(&dev_priv->pps_mutex); } /* @@ -15318,9 +15317,6 @@ void intel_modeset_init(struct drm_device *dev) } } - intel_init_display(dev); - intel_init_audio(dev); - if (IS_GEN2(dev)) { dev->mode_config.max_width = 2048; dev->mode_config.max_height = 2048; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0786246..7c0d12d 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1091,7 +1091,7 @@ u32 intel_fb_stride_alignment(const struct drm_i915_private *dev_priv, uint64_t fb_modifier, uint32_t pixel_format); /* intel_audio.c */ -void intel_init_audio(struct drm_device *dev); +void intel_init_audio_hooks(struct drm_i915_private *dev_priv); void intel_audio_codec_enable(struct intel_encoder *encoder); void intel_audio_codec_disable(struct intel_encoder *encoder); void i915_audio_component_init(struct drm_i915_private *dev_priv); @@ -1099,6 +1099,7 @@ void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); /* intel_display.c */ extern const struct drm_plane_funcs intel_plane_funcs; +void intel_init_display_hooks(struct drm_i915_private *dev_priv); unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info); bool intel_has_pending_fb_unpin(struct drm_device *dev); void intel_mark_busy(struct drm_device *dev); -- cgit v0.10.2 From bb400da99836793ade6f1a007db58af2f1b57e9e Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:38:54 +0200 Subject: drm/i915: Move load time init of clock gating hooks earlier Split out the part initing the clock gating hooks and move it earlier. Add a new NOP hook for platforms without the need to apply clockgating or workaround settings, so that the hook can be called unconditionally. Also add a WARN for future platforms that forget to add a hook. The rest of the hooks in intel_init_pm() should be inited in the same way, but atm some of the hooks are set only conditionally, so before doing this we need to make the setup unconditional and use instead some flags. v2: - add a NOP hook and WARN if no hook is set for the platform (Chris) - use the term hook instead of callback for these functions (Jani) v3: - remove the GEN4() check it's already covered by earlier platform checks (Chris) CC: Jani Nikula CC: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-6-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index b90d2d9..a3c5621 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1029,6 +1029,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_power_domains_init(dev_priv); intel_irq_init(dev_priv); intel_init_display_hooks(dev_priv); + intel_init_clock_gating_hooks(dev_priv); intel_init_audio_hooks(dev_priv); intel_runtime_pm_get(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7c0d12d..5136eef 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1569,6 +1569,7 @@ void intel_suspend_hw(struct drm_device *dev); int ilk_wm_max_level(const struct drm_device *dev); void intel_update_watermarks(struct drm_crtc *crtc); void intel_init_pm(struct drm_device *dev); +void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv); void intel_pm_setup(struct drm_device *dev); void intel_gpu_ips_init(struct drm_i915_private *dev_priv); void intel_gpu_ips_teardown(void); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 20c8243..a539fbc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7097,8 +7097,7 @@ void intel_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - if (dev_priv->display.init_clock_gating) - dev_priv->display.init_clock_gating(dev); + dev_priv->display.init_clock_gating(dev); } void intel_suspend_hw(struct drm_device *dev) @@ -7107,6 +7106,60 @@ void intel_suspend_hw(struct drm_device *dev) lpt_suspend_hw(dev); } +static void nop_init_clock_gating(struct drm_device *dev) +{ + DRM_DEBUG_KMS("No clock gating settings or workarounds applied.\n"); +} + +/** + * intel_init_clock_gating_hooks - setup the clock gating hooks + * @dev_priv: device private + * + * Setup the hooks that configure which clocks of a given platform can be + * gated and also apply various GT and display specific workarounds for these + * platforms. Note that some GT specific workarounds are applied separately + * when GPU contexts or batchbuffers start their execution. + */ +void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv) +{ + if (IS_SKYLAKE(dev_priv)) + dev_priv->display.init_clock_gating = nop_init_clock_gating; + else if (IS_KABYLAKE(dev_priv)) + dev_priv->display.init_clock_gating = nop_init_clock_gating; + else if (IS_BROXTON(dev_priv)) + dev_priv->display.init_clock_gating = bxt_init_clock_gating; + else if (IS_BROADWELL(dev_priv)) + dev_priv->display.init_clock_gating = broadwell_init_clock_gating; + else if (IS_CHERRYVIEW(dev_priv)) + dev_priv->display.init_clock_gating = cherryview_init_clock_gating; + else if (IS_HASWELL(dev_priv)) + dev_priv->display.init_clock_gating = haswell_init_clock_gating; + else if (IS_IVYBRIDGE(dev_priv)) + dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; + else if (IS_VALLEYVIEW(dev_priv)) + dev_priv->display.init_clock_gating = valleyview_init_clock_gating; + else if (IS_GEN6(dev_priv)) + dev_priv->display.init_clock_gating = gen6_init_clock_gating; + else if (IS_GEN5(dev_priv)) + dev_priv->display.init_clock_gating = ironlake_init_clock_gating; + else if (IS_G4X(dev_priv)) + dev_priv->display.init_clock_gating = g4x_init_clock_gating; + else if (IS_CRESTLINE(dev_priv)) + dev_priv->display.init_clock_gating = crestline_init_clock_gating; + else if (IS_BROADWATER(dev_priv)) + dev_priv->display.init_clock_gating = broadwater_init_clock_gating; + else if (IS_GEN3(dev_priv)) + dev_priv->display.init_clock_gating = gen3_init_clock_gating; + else if (IS_I85X(dev_priv) || IS_I865G(dev_priv)) + dev_priv->display.init_clock_gating = i85x_init_clock_gating; + else if (IS_GEN2(dev_priv)) + dev_priv->display.init_clock_gating = i830_init_clock_gating; + else { + MISSING_CASE(INTEL_DEVID(dev_priv)); + dev_priv->display.init_clock_gating = nop_init_clock_gating; + } +} + /* Set up chip specific power management-related functions */ void intel_init_pm(struct drm_device *dev) { @@ -7123,10 +7176,6 @@ void intel_init_pm(struct drm_device *dev) /* For FIFO watermark updates */ if (INTEL_INFO(dev)->gen >= 9) { skl_setup_wm_latency(dev); - - if (IS_BROXTON(dev)) - dev_priv->display.init_clock_gating = - bxt_init_clock_gating; dev_priv->display.update_wm = skl_update_wm; } else if (HAS_PCH_SPLIT(dev)) { ilk_setup_wm_latency(dev); @@ -7146,29 +7195,12 @@ void intel_init_pm(struct drm_device *dev) DRM_DEBUG_KMS("Failed to read display plane latency. " "Disable CxSR\n"); } - - if (IS_GEN5(dev)) - dev_priv->display.init_clock_gating = ironlake_init_clock_gating; - else if (IS_GEN6(dev)) - dev_priv->display.init_clock_gating = gen6_init_clock_gating; - else if (IS_IVYBRIDGE(dev)) - dev_priv->display.init_clock_gating = ivybridge_init_clock_gating; - else if (IS_HASWELL(dev)) - dev_priv->display.init_clock_gating = haswell_init_clock_gating; - else if (INTEL_INFO(dev)->gen == 8) - dev_priv->display.init_clock_gating = broadwell_init_clock_gating; } else if (IS_CHERRYVIEW(dev)) { vlv_setup_wm_latency(dev); - dev_priv->display.update_wm = vlv_update_wm; - dev_priv->display.init_clock_gating = - cherryview_init_clock_gating; } else if (IS_VALLEYVIEW(dev)) { vlv_setup_wm_latency(dev); - dev_priv->display.update_wm = vlv_update_wm; - dev_priv->display.init_clock_gating = - valleyview_init_clock_gating; } else if (IS_PINEVIEW(dev)) { if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, @@ -7184,20 +7216,13 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.update_wm = NULL; } else dev_priv->display.update_wm = pineview_update_wm; - dev_priv->display.init_clock_gating = gen3_init_clock_gating; } else if (IS_G4X(dev)) { dev_priv->display.update_wm = g4x_update_wm; - dev_priv->display.init_clock_gating = g4x_init_clock_gating; } else if (IS_GEN4(dev)) { dev_priv->display.update_wm = i965_update_wm; - if (IS_CRESTLINE(dev)) - dev_priv->display.init_clock_gating = crestline_init_clock_gating; - else if (IS_BROADWATER(dev)) - dev_priv->display.init_clock_gating = broadwater_init_clock_gating; } else if (IS_GEN3(dev)) { dev_priv->display.update_wm = i9xx_update_wm; dev_priv->display.get_fifo_size = i9xx_get_fifo_size; - dev_priv->display.init_clock_gating = gen3_init_clock_gating; } else if (IS_GEN2(dev)) { if (INTEL_INFO(dev)->num_pipes == 1) { dev_priv->display.update_wm = i845_update_wm; @@ -7206,11 +7231,6 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.update_wm = i9xx_update_wm; dev_priv->display.get_fifo_size = i830_get_fifo_size; } - - if (IS_I85X(dev) || IS_I865G(dev)) - dev_priv->display.init_clock_gating = i85x_init_clock_gating; - else - dev_priv->display.init_clock_gating = i830_init_clock_gating; } else { DRM_ERROR("unexpected fall-through in intel_init_pm\n"); } -- cgit v0.10.2 From 13c8f4c8cd481ec80bfe3b71f1f21e18bad98efb Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:38:55 +0200 Subject: drm/i915: Move load time runtime device info init earlier This init step accesses the device, but doesn't have any device specific side effect. It also sets up some platform specific attributes that may be required early, so move it earlier. Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-7-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a3c5621..a94610a 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1057,6 +1057,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_uncore_init(dev); + intel_device_info_runtime_init(dev); + ret = i915_gem_gtt_init(dev); if (ret) goto out_uncore_fini; @@ -1131,8 +1133,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) DRM_DEBUG_DRIVER("can't enable MSI"); } - intel_device_info_runtime_init(dev); - if (INTEL_INFO(dev)->num_pipes) { ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes); if (ret) -- cgit v0.10.2 From 40ae4e1661cd2ef67ca888b36ea636999bd0be73 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 14:54:03 +0200 Subject: drm/i915: Move load time gem_load_init earlier The only steps requiring device access is the fence and swizzling initialization, so split these out keeping them in their current place and move the rest of init steps earlier. v2-v3: - unchanged v4: - move call to i915_gem_detect_bit_6_swizzle() to i915_gem_load_init_fences() and preserve the original order of the detection of HW fence capailities wrt. swizzling (Chris) CC: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458132843-21860-1-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a94610a..b89fa73 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1031,6 +1031,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_init_display_hooks(dev_priv); intel_init_clock_gating_hooks(dev_priv); intel_init_audio_hooks(dev_priv); + i915_gem_load_init(dev); intel_runtime_pm_get(dev_priv); @@ -1114,7 +1115,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_opregion_setup(dev); - i915_gem_load_init(dev); + i915_gem_load_init_fences(dev_priv); + i915_gem_shrinker_init(dev_priv); /* On the 945G/GM, the chipset reports the MSI capability on the @@ -1136,7 +1138,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (INTEL_INFO(dev)->num_pipes) { ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes); if (ret) - goto out_gem_unload; + goto out_cleanup_shrinker; } ret = i915_load_modeset_init(dev); @@ -1174,7 +1176,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) out_power_well: intel_power_domains_fini(dev_priv); drm_vblank_cleanup(dev); -out_gem_unload: +out_cleanup_shrinker: i915_gem_shrinker_cleanup(dev_priv); if (dev->pdev->msi_enabled) @@ -1190,9 +1192,9 @@ out_uncore_fini: i915_mmio_cleanup(dev); put_bridge: pci_dev_put(dev_priv->bridge_dev); - i915_gem_load_cleanup(dev); out_runtime_pm_put: intel_runtime_pm_put(dev_priv); + i915_gem_load_cleanup(dev); i915_workqueues_cleanup(dev_priv); out_free_priv: kfree(dev_priv); @@ -1277,8 +1279,8 @@ int i915_driver_unload(struct drm_device *dev) intel_uncore_fini(dev); i915_mmio_cleanup(dev); - i915_gem_load_cleanup(dev); pci_dev_put(dev_priv->bridge_dev); + i915_gem_load_cleanup(dev); i915_workqueues_cleanup(dev_priv); kfree(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f2ab545..e6d4b1c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2859,6 +2859,7 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); void i915_gem_load_init(struct drm_device *dev); void i915_gem_load_cleanup(struct drm_device *dev); +void i915_gem_load_init_fences(struct drm_i915_private *dev_priv); void *i915_gem_object_alloc(struct drm_device *dev); void i915_gem_object_free(struct drm_i915_gem_object *obj); void i915_gem_object_init(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a25109a..a4e0155 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5029,6 +5029,30 @@ init_engine_lists(struct intel_engine_cs *engine) } void +i915_gem_load_init_fences(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + + if (INTEL_INFO(dev_priv)->gen >= 7 && !IS_VALLEYVIEW(dev_priv) && + !IS_CHERRYVIEW(dev_priv)) + dev_priv->num_fence_regs = 32; + else if (INTEL_INFO(dev_priv)->gen >= 4 || IS_I945G(dev_priv) || + IS_I945GM(dev_priv) || IS_G33(dev_priv)) + dev_priv->num_fence_regs = 16; + else + dev_priv->num_fence_regs = 8; + + if (intel_vgpu_active(dev)) + dev_priv->num_fence_regs = + I915_READ(vgtif_reg(avail_rs.fence_num)); + + /* Initialize fence registers to zero */ + i915_gem_restore_fences(dev); + + i915_gem_detect_bit_6_swizzle(dev); +} + +void i915_gem_load_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5067,17 +5091,6 @@ i915_gem_load_init(struct drm_device *dev) dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL; - if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) - dev_priv->num_fence_regs = 32; - else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) - dev_priv->num_fence_regs = 16; - else - dev_priv->num_fence_regs = 8; - - if (intel_vgpu_active(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, @@ -5086,11 +5099,8 @@ i915_gem_load_init(struct drm_device *dev) 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); - i915_gem_detect_bit_6_swizzle(dev); init_waitqueue_head(&dev_priv->pending_flip_queue); dev_priv->mm.interruptible = true; -- cgit v0.10.2 From 802cbbc09b96eed654233020d8f6d486ddc5123b Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:38:57 +0200 Subject: drm/i915: Move load time runtime PM get later We require the device to be powered only before accessing it, so we can move this call later. Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-9-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index b89fa73..a07e359 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1033,8 +1033,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_init_audio_hooks(dev_priv); i915_gem_load_init(dev); - intel_runtime_pm_get(dev_priv); - intel_display_crc_init(dev); i915_dump_device_info(dev_priv); @@ -1047,6 +1045,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) DRM_INFO("This is an early pre-production Haswell machine. " "It may not be fully functional.\n"); + intel_runtime_pm_get(dev_priv); + if (i915_get_bridge_dev(dev)) { ret = -EIO; goto out_runtime_pm_put; -- cgit v0.10.2 From 80741e99282a3672a2259386f3f1dc4c3ef3d54f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:38:58 +0200 Subject: drm/i915: Move load time shrinker registration later According to the new init phases scheme we should register the driver with frameworks/userspace only one the device is setup fully. So move the shrinker registration later accordingly. Also fix the shrinker unregistration order wrt. the acpi unregistration to fix the corresponding init order. Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-10-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a07e359..2d279a6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1117,8 +1117,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) i915_gem_load_init_fences(dev_priv); - i915_gem_shrinker_init(dev_priv); - /* On the 945G/GM, the chipset reports the MSI capability on the * integrated graphics even though the support isn't actually there * according to the published specs. It doesn't appear to function @@ -1138,7 +1136,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (INTEL_INFO(dev)->num_pipes) { ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes); if (ret) - goto out_cleanup_shrinker; + goto out_disable_msi; } ret = i915_load_modeset_init(dev); @@ -1147,6 +1145,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto out_power_well; } + i915_gem_shrinker_init(dev_priv); /* * Notify a valid surface after modesetting, * when running inside a VM. @@ -1176,9 +1175,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) out_power_well: intel_power_domains_fini(dev_priv); drm_vblank_cleanup(dev); -out_cleanup_shrinker: - i915_gem_shrinker_cleanup(dev_priv); - +out_disable_msi: if (dev->pdev->msi_enabled) pci_disable_msi(dev->pdev); @@ -1223,12 +1220,11 @@ int i915_driver_unload(struct drm_device *dev) i915_teardown_sysfs(dev); - i915_gem_shrinker_cleanup(dev_priv); - io_mapping_free(dev_priv->gtt.mappable); arch_phys_wc_del(dev_priv->gtt.mtrr); acpi_video_unregister(); + i915_gem_shrinker_cleanup(dev_priv); drm_vblank_cleanup(dev); -- cgit v0.10.2 From 3487b66ba13c1a7ba1185028ad0dae95e97bd4d2 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:38:59 +0200 Subject: drm/i915: Move load time audio component registration earlier We should register all the interfaces before we enable runtime PM. Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-11-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2d279a6..2bdafa9 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1164,10 +1164,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (IS_GEN5(dev)) intel_gpu_ips_init(dev_priv); - intel_runtime_pm_enable(dev_priv); - i915_audio_component_init(dev_priv); + intel_runtime_pm_enable(dev_priv); + intel_runtime_pm_put(dev_priv); return 0; @@ -1206,8 +1206,6 @@ int i915_driver_unload(struct drm_device *dev) intel_fbdev_fini(dev); - i915_audio_component_cleanup(dev_priv); - ret = i915_gem_suspend(dev); if (ret) { DRM_ERROR("failed to idle hardware: %d\n", ret); @@ -1216,6 +1214,8 @@ int i915_driver_unload(struct drm_device *dev) intel_power_domains_fini(dev_priv); + i915_audio_component_cleanup(dev_priv); + intel_gpu_ips_teardown(); i915_teardown_sysfs(dev); -- cgit v0.10.2 From 250ad48e2e2f2aeebafd52d67768392eca5077ad Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:39:00 +0200 Subject: drm/i915: Move unload time display power domain uninit later Move the power domain uninitialization later so that it matches its corresponding init order. Since we access the HW during the later unitialization steps keep a wake reference until after the last such step. Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-12-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2bdafa9..40a5af4 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1212,7 +1212,7 @@ int i915_driver_unload(struct drm_device *dev) return ret; } - intel_power_domains_fini(dev_priv); + intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); i915_audio_component_cleanup(dev_priv); @@ -1268,6 +1268,8 @@ int i915_driver_unload(struct drm_device *dev) mutex_unlock(&dev->struct_mutex); intel_fbc_cleanup_cfb(dev_priv); + intel_power_domains_fini(dev_priv); + pm_qos_remove_request(&dev_priv->pm_qos); i915_global_gtt_cleanup(dev); @@ -1276,6 +1278,9 @@ int i915_driver_unload(struct drm_device *dev) i915_mmio_cleanup(dev); pci_dev_put(dev_priv->bridge_dev); + + intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); + i915_gem_load_cleanup(dev); i915_workqueues_cleanup(dev_priv); kfree(dev_priv); -- cgit v0.10.2 From 882c5a83b5116bff597aefec16ad016641dfea05 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:39:01 +0200 Subject: drm/i915: Move unload time GTT, MSI IRQ cleanup later Move the GTT,MSI IRQ cleanup later so that it matches their corresponding init order. Also fix the order of these calls wrt. each other to match their corresponding init order. Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-13-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 40a5af4..fb28a03 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1220,9 +1220,6 @@ int i915_driver_unload(struct drm_device *dev) i915_teardown_sysfs(dev); - io_mapping_free(dev_priv->gtt.mappable); - arch_phys_wc_del(dev_priv->gtt.mtrr); - acpi_video_unregister(); i915_gem_shrinker_cleanup(dev_priv); @@ -1253,9 +1250,6 @@ int i915_driver_unload(struct drm_device *dev) cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work); i915_destroy_error_state(dev); - if (dev->pdev->msi_enabled) - pci_disable_msi(dev->pdev); - intel_opregion_fini(dev); /* Flush any outstanding unpin_work. */ @@ -1270,8 +1264,11 @@ int i915_driver_unload(struct drm_device *dev) intel_power_domains_fini(dev_priv); + if (dev->pdev->msi_enabled) + pci_disable_msi(dev->pdev); pm_qos_remove_request(&dev_priv->pm_qos); - + arch_phys_wc_del(dev_priv->gtt.mtrr); + io_mapping_free(dev_priv->gtt.mappable); i915_global_gtt_cleanup(dev); intel_uncore_fini(dev); -- cgit v0.10.2 From fbf107bdbd449494e6b17589f0a8a02094b52a19 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:39:02 +0200 Subject: drm/i915: Move unload time opregion unregistration earlier Move the opregion unregistration earlier to match its corresponding registration order. Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-14-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index fb28a03..7618a3f 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1221,6 +1221,7 @@ int i915_driver_unload(struct drm_device *dev) i915_teardown_sysfs(dev); acpi_video_unregister(); + intel_opregion_fini(dev); i915_gem_shrinker_cleanup(dev_priv); drm_vblank_cleanup(dev); @@ -1250,8 +1251,6 @@ int i915_driver_unload(struct drm_device *dev) cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work); i915_destroy_error_state(dev); - intel_opregion_fini(dev); - /* Flush any outstanding unpin_work. */ flush_workqueue(dev_priv->wq); -- cgit v0.10.2 From 5d7a6eefc3b025725dd1b5a643e90ce068e9dbd4 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:39:03 +0200 Subject: drm/i915: Split out load time early initialization According to the new init phases scheme we should initialize "SW-only" state not requiring accessing the device as the very first step, so that the reasoning about dependencies of later steps becomes easier. So move these init steps into a separate function. This also has the benefit of making the error path cleaner both in the new function and int i915_driver_load()/unload(). No functional change. Suggested by Chris. CC: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-15-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 7618a3f..182770d 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -933,6 +933,83 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) destroy_workqueue(dev_priv->wq); } +/** + * i915_driver_init_early - setup state not requiring device access + * @dev_priv: device private + * + * Initialize everything that is a "SW-only" state, that is state not + * requiring accessing the device or exposing the driver via kernel internal + * or userspace interfaces. Example steps belonging here: lock initialization, + * system memory allocation, setting up device specific attributes and + * function hooks not requiring accessing the device. + */ +static int i915_driver_init_early(struct drm_i915_private *dev_priv, + struct drm_device *dev, + struct intel_device_info *info) +{ + struct intel_device_info *device_info; + int ret = 0; + + dev_priv->dev = dev; + + /* Setup the write-once "constant" device info */ + device_info = (struct intel_device_info *)&dev_priv->info; + memcpy(device_info, info, sizeof(dev_priv->info)); + device_info->device_id = dev->pdev->device; + + spin_lock_init(&dev_priv->irq_lock); + spin_lock_init(&dev_priv->gpu_error.lock); + mutex_init(&dev_priv->backlight_lock); + spin_lock_init(&dev_priv->uncore.lock); + spin_lock_init(&dev_priv->mm.object_stat_lock); + spin_lock_init(&dev_priv->mmio_flip_lock); + mutex_init(&dev_priv->sb_lock); + mutex_init(&dev_priv->modeset_restore_lock); + mutex_init(&dev_priv->av_mutex); + mutex_init(&dev_priv->wm.wm_mutex); + mutex_init(&dev_priv->pps_mutex); + + ret = i915_workqueues_init(dev_priv); + if (ret < 0) + return ret; + + /* This must be called before any calls to HAS_PCH_* */ + intel_detect_pch(dev); + + intel_pm_setup(dev); + intel_init_dpio(dev_priv); + intel_power_domains_init(dev_priv); + intel_irq_init(dev_priv); + intel_init_display_hooks(dev_priv); + intel_init_clock_gating_hooks(dev_priv); + intel_init_audio_hooks(dev_priv); + i915_gem_load_init(dev); + + intel_display_crc_init(dev); + + i915_dump_device_info(dev_priv); + + /* Not all pre-production machines fall into this category, only the + * very first ones. Almost everything should work, except for maybe + * suspend/resume. And we don't implement workarounds that affect only + * pre-production machines. */ + if (IS_HSW_EARLY_SDV(dev)) + DRM_INFO("This is an early pre-production Haswell machine. " + "It may not be fully functional.\n"); + + return 0; +} + +/** + * i915_driver_cleanup_early - cleanup the setup done in i915_driver_init_early() + * @dev_priv: device private + */ +static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv) +{ + i915_gem_load_cleanup(dev_priv->dev); + i915_workqueues_cleanup(dev_priv); +} + static int i915_mmio_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -987,64 +1064,21 @@ static void i915_mmio_cleanup(struct drm_device *dev) int i915_driver_load(struct drm_device *dev, unsigned long flags) { struct drm_i915_private *dev_priv; - struct intel_device_info *info, *device_info; int ret = 0; uint32_t aperture_size; - info = (struct intel_device_info *) flags; - dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); if (dev_priv == NULL) return -ENOMEM; dev->dev_private = dev_priv; - dev_priv->dev = dev; - /* Setup the write-once "constant" device info */ - device_info = (struct intel_device_info *)&dev_priv->info; - memcpy(device_info, info, sizeof(dev_priv->info)); - device_info->device_id = dev->pdev->device; + ret = i915_driver_init_early(dev_priv, dev, + (struct intel_device_info *)flags); - spin_lock_init(&dev_priv->irq_lock); - spin_lock_init(&dev_priv->gpu_error.lock); - mutex_init(&dev_priv->backlight_lock); - spin_lock_init(&dev_priv->uncore.lock); - spin_lock_init(&dev_priv->mm.object_stat_lock); - spin_lock_init(&dev_priv->mmio_flip_lock); - mutex_init(&dev_priv->sb_lock); - mutex_init(&dev_priv->modeset_restore_lock); - mutex_init(&dev_priv->av_mutex); - mutex_init(&dev_priv->wm.wm_mutex); - mutex_init(&dev_priv->pps_mutex); - - ret = i915_workqueues_init(dev_priv); if (ret < 0) goto out_free_priv; - /* This must be called before any calls to HAS_PCH_* */ - intel_detect_pch(dev); - - intel_pm_setup(dev); - intel_init_dpio(dev_priv); - intel_power_domains_init(dev_priv); - intel_irq_init(dev_priv); - intel_init_display_hooks(dev_priv); - intel_init_clock_gating_hooks(dev_priv); - intel_init_audio_hooks(dev_priv); - i915_gem_load_init(dev); - - intel_display_crc_init(dev); - - i915_dump_device_info(dev_priv); - - /* Not all pre-production machines fall into this category, only the - * very first ones. Almost everything should work, except for maybe - * suspend/resume. And we don't implement workarounds that affect only - * pre-production machines. */ - if (IS_HSW_EARLY_SDV(dev)) - DRM_INFO("This is an early pre-production Haswell machine. " - "It may not be fully functional.\n"); - intel_runtime_pm_get(dev_priv); if (i915_get_bridge_dev(dev)) { @@ -1191,8 +1225,7 @@ put_bridge: pci_dev_put(dev_priv->bridge_dev); out_runtime_pm_put: intel_runtime_pm_put(dev_priv); - i915_gem_load_cleanup(dev); - i915_workqueues_cleanup(dev_priv); + i915_driver_cleanup_early(dev_priv); out_free_priv: kfree(dev_priv); @@ -1277,8 +1310,7 @@ int i915_driver_unload(struct drm_device *dev) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); - i915_gem_load_cleanup(dev); - i915_workqueues_cleanup(dev_priv); + i915_driver_cleanup_early(dev_priv); kfree(dev_priv); return 0; -- cgit v0.10.2 From f28cea45e5a9e1680753ce1b91f033dc3ceda7d0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:39:04 +0200 Subject: drm/i915: Split out load time MMIO initialization According to the new init phases scheme we should have a definite step in the init sequence where MMIO access is setup, so move the corresponding code to a separate function. This also has the benefit of making the error path cleaner both in the new function and in i915_driver_load()/unload(). No functional change. Suggested by Chris. Cc: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-16-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 182770d..142d59a 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1051,6 +1051,50 @@ static void i915_mmio_cleanup(struct drm_device *dev) } /** + * i915_driver_init_mmio - setup device MMIO + * @dev_priv: device private + * + * Setup minimal device state necessary for MMIO accesses later in the + * initialization sequence. The setup here should avoid any other device-wide + * side effects or exposing the driver via kernel internal or user space + * interfaces. + */ +static int i915_driver_init_mmio(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + int ret; + + if (i915_get_bridge_dev(dev)) + return -EIO; + + ret = i915_mmio_setup(dev); + if (ret < 0) + goto put_bridge; + + intel_uncore_init(dev); + + return 0; + +put_bridge: + pci_dev_put(dev_priv->bridge_dev); + + return ret; +} + +/** + * i915_driver_cleanup_mmio - cleanup the setup done in i915_driver_init_mmio() + * @dev_priv: device private + */ +static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + + intel_uncore_fini(dev); + i915_mmio_cleanup(dev); + pci_dev_put(dev_priv->bridge_dev); +} + +/** * i915_driver_load - setup chip and create an initial config * @dev: DRM device * @flags: startup flags @@ -1081,22 +1125,15 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) intel_runtime_pm_get(dev_priv); - if (i915_get_bridge_dev(dev)) { - ret = -EIO; - goto out_runtime_pm_put; - } - - ret = i915_mmio_setup(dev); + ret = i915_driver_init_mmio(dev_priv); if (ret < 0) - goto put_bridge; - - intel_uncore_init(dev); + goto out_runtime_pm_put; intel_device_info_runtime_init(dev); ret = i915_gem_gtt_init(dev); if (ret) - goto out_uncore_fini; + goto out_cleanup_mmio; /* WARNING: Apparently we must kick fbdev drivers before vgacon, * otherwise the vga fbdev driver falls over. */ @@ -1218,11 +1255,8 @@ out_disable_msi: io_mapping_free(dev_priv->gtt.mappable); out_gtt: i915_global_gtt_cleanup(dev); -out_uncore_fini: - intel_uncore_fini(dev); - i915_mmio_cleanup(dev); -put_bridge: - pci_dev_put(dev_priv->bridge_dev); +out_cleanup_mmio: + i915_driver_cleanup_mmio(dev_priv); out_runtime_pm_put: intel_runtime_pm_put(dev_priv); i915_driver_cleanup_early(dev_priv); @@ -1303,10 +1337,7 @@ int i915_driver_unload(struct drm_device *dev) io_mapping_free(dev_priv->gtt.mappable); i915_global_gtt_cleanup(dev); - intel_uncore_fini(dev); - i915_mmio_cleanup(dev); - - pci_dev_put(dev_priv->bridge_dev); + i915_driver_cleanup_mmio(dev_priv); intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); -- cgit v0.10.2 From 09cfcb456941222021f378131b1b2fa4c59cc495 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:39:05 +0200 Subject: drm/i915: Split out load time HW initialization According to the new init phases scheme we should have a definite step in the init sequence where we setup things requiring accessing the device, so move the corresponding code to separate function. The steps in this init phase should avoid exposing the driver via some interface, which is done in the last registration init phase. This changae also has the benefit of making the error path cleaner both in the new function and i915_driver_load()/unload(). No functional change. Suggested by Chris. CC: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-17-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 142d59a..ec8ad5e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1095,45 +1095,23 @@ static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv) } /** - * i915_driver_load - setup chip and create an initial config - * @dev: DRM device - * @flags: startup flags + * i915_driver_init_hw - setup state requiring device access + * @dev_priv: device private * - * The driver load routine has to do several things: - * - drive output discovery via intel_modeset_init() - * - initialize the memory manager - * - allocate initial config memory - * - setup the DRM framebuffer with the allocated memory + * Setup state that requires accessing the device, but doesn't require + * exposing the driver via kernel internal or userspace interfaces. */ -int i915_driver_load(struct drm_device *dev, unsigned long flags) +static int i915_driver_init_hw(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv; - int ret = 0; + struct drm_device *dev = dev_priv->dev; uint32_t aperture_size; - - dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); - if (dev_priv == NULL) - return -ENOMEM; - - dev->dev_private = dev_priv; - - ret = i915_driver_init_early(dev_priv, dev, - (struct intel_device_info *)flags); - - if (ret < 0) - goto out_free_priv; - - intel_runtime_pm_get(dev_priv); - - ret = i915_driver_init_mmio(dev_priv); - if (ret < 0) - goto out_runtime_pm_put; + int ret; intel_device_info_runtime_init(dev); ret = i915_gem_gtt_init(dev); if (ret) - goto out_cleanup_mmio; + return ret; /* WARNING: Apparently we must kick fbdev drivers before vgacon, * otherwise the vga fbdev driver falls over. */ @@ -1204,10 +1182,73 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) DRM_DEBUG_DRIVER("can't enable MSI"); } + return 0; + +out_gtt: + i915_global_gtt_cleanup(dev); + + return ret; +} + +/** + * i915_driver_cleanup_hw - cleanup the setup done in i915_driver_init_hw() + * @dev_priv: device private + */ +static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + + if (dev->pdev->msi_enabled) + pci_disable_msi(dev->pdev); + + pm_qos_remove_request(&dev_priv->pm_qos); + arch_phys_wc_del(dev_priv->gtt.mtrr); + io_mapping_free(dev_priv->gtt.mappable); + i915_global_gtt_cleanup(dev); +} + +/** + * i915_driver_load - setup chip and create an initial config + * @dev: DRM device + * @flags: startup flags + * + * The driver load routine has to do several things: + * - drive output discovery via intel_modeset_init() + * - initialize the memory manager + * - allocate initial config memory + * - setup the DRM framebuffer with the allocated memory + */ +int i915_driver_load(struct drm_device *dev, unsigned long flags) +{ + struct drm_i915_private *dev_priv; + int ret = 0; + + dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); + if (dev_priv == NULL) + return -ENOMEM; + + dev->dev_private = dev_priv; + + ret = i915_driver_init_early(dev_priv, dev, + (struct intel_device_info *)flags); + + if (ret < 0) + goto out_free_priv; + + intel_runtime_pm_get(dev_priv); + + ret = i915_driver_init_mmio(dev_priv); + if (ret < 0) + goto out_runtime_pm_put; + + ret = i915_driver_init_hw(dev_priv); + if (ret < 0) + goto out_cleanup_mmio; + if (INTEL_INFO(dev)->num_pipes) { ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes); if (ret) - goto out_disable_msi; + goto out_cleanup_hw; } ret = i915_load_modeset_init(dev); @@ -1246,15 +1287,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) out_power_well: intel_power_domains_fini(dev_priv); drm_vblank_cleanup(dev); -out_disable_msi: - if (dev->pdev->msi_enabled) - pci_disable_msi(dev->pdev); - - pm_qos_remove_request(&dev_priv->pm_qos); - arch_phys_wc_del(dev_priv->gtt.mtrr); - io_mapping_free(dev_priv->gtt.mappable); -out_gtt: - i915_global_gtt_cleanup(dev); +out_cleanup_hw: + i915_driver_cleanup_hw(dev_priv); out_cleanup_mmio: i915_driver_cleanup_mmio(dev_priv); out_runtime_pm_put: @@ -1330,13 +1364,7 @@ int i915_driver_unload(struct drm_device *dev) intel_power_domains_fini(dev_priv); - if (dev->pdev->msi_enabled) - pci_disable_msi(dev->pdev); - pm_qos_remove_request(&dev_priv->pm_qos); - arch_phys_wc_del(dev_priv->gtt.mtrr); - io_mapping_free(dev_priv->gtt.mappable); - i915_global_gtt_cleanup(dev); - + i915_driver_cleanup_hw(dev_priv); i915_driver_cleanup_mmio(dev_priv); intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); -- cgit v0.10.2 From 432f856d8b4963f2f1d95844794266d7c9a9ca97 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:39:06 +0200 Subject: drm/i915: Split out load time interface registration According to the new init phases scheme we should register the device making it available via some kernel internal or user space interface as the last step in the init sequence, so move the corresponding code to a separate function. Also add a TODO comment about code that still needs to be moved around to one of the init phases functions depending on what the role and effect of that code is. No functional change, except for the reordering of the unload time unregistration steps of sysfs wrt. acpi and opregion. Suggested by Chris. v3: - rename i915_driver_init_register to i915_driver_init_frameworks (Chris) - rename i915_driver_init_frameworks to i915_driver_register (Daniel) CC: Chris Wilson CC: Daniel Vetter Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-18-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ec8ad5e..b8c5fd0 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1208,6 +1208,53 @@ static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv) } /** + * i915_driver_register - register the driver with the rest of the system + * @dev_priv: device private + * + * Perform any steps necessary to make the driver available via kernel + * internal or userspace interfaces. + */ +static void i915_driver_register(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + + i915_gem_shrinker_init(dev_priv); + /* + * Notify a valid surface after modesetting, + * when running inside a VM. + */ + if (intel_vgpu_active(dev)) + I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY); + + i915_setup_sysfs(dev); + + if (INTEL_INFO(dev_priv)->num_pipes) { + /* Must be done after probing outputs */ + intel_opregion_init(dev); + acpi_video_register(); + } + + if (IS_GEN5(dev_priv)) + intel_gpu_ips_init(dev_priv); + + i915_audio_component_init(dev_priv); +} + +/** + * i915_driver_unregister - cleanup the registration done in i915_driver_regiser() + * @dev_priv: device private + */ +static void i915_driver_unregister(struct drm_i915_private *dev_priv) +{ + i915_audio_component_cleanup(dev_priv); + intel_gpu_ips_teardown(); + acpi_video_unregister(); + intel_opregion_fini(dev_priv->dev); + i915_teardown_sysfs(dev_priv->dev); + i915_gem_shrinker_cleanup(dev_priv); +} + +/** * i915_driver_load - setup chip and create an initial config * @dev: DRM device * @flags: startup flags @@ -1245,6 +1292,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (ret < 0) goto out_cleanup_mmio; + /* + * TODO: move the vblank init and parts of modeset init steps into one + * of the i915_driver_init_/i915_driver_register functions according + * to the role/effect of the given init step. + */ if (INTEL_INFO(dev)->num_pipes) { ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes); if (ret) @@ -1257,26 +1309,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto out_power_well; } - i915_gem_shrinker_init(dev_priv); - /* - * Notify a valid surface after modesetting, - * when running inside a VM. - */ - if (intel_vgpu_active(dev)) - I915_WRITE(vgtif_reg(display_ready), VGT_DRV_DISPLAY_READY); - - i915_setup_sysfs(dev); - - if (INTEL_INFO(dev)->num_pipes) { - /* Must be done after probing outputs */ - intel_opregion_init(dev); - acpi_video_register(); - } - - if (IS_GEN5(dev)) - intel_gpu_ips_init(dev_priv); - - i915_audio_component_init(dev_priv); + i915_driver_register(dev_priv); intel_runtime_pm_enable(dev_priv); @@ -1315,15 +1348,7 @@ int i915_driver_unload(struct drm_device *dev) intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); - i915_audio_component_cleanup(dev_priv); - - intel_gpu_ips_teardown(); - - i915_teardown_sysfs(dev); - - acpi_video_unregister(); - intel_opregion_fini(dev); - i915_gem_shrinker_cleanup(dev_priv); + i915_driver_unregister(dev_priv); drm_vblank_cleanup(dev); -- cgit v0.10.2 From 65ff442f6bca0e2247ff7acac6014bcea69d1f7e Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:39:07 +0200 Subject: drm/i915: Fix power domain HW state cleanup on error path Move the cleanup of the power domain HW state on the error path to the same function where the corresponding init call was called from. I noticed this problem when loading the module with load failure injection enabled, making i915_load_modeset_init() fail. CC: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458128348-15730-19-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index b8c5fd0..7466e73 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -453,6 +453,7 @@ cleanup_irq: intel_teardown_gmbus(dev); cleanup_csr: intel_csr_ucode_fini(dev_priv); + intel_power_domains_fini(dev_priv); vga_switcheroo_unregister_client(dev->pdev); cleanup_vga_client: vga_client_register(dev->pdev, NULL, NULL, NULL); @@ -1306,7 +1307,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ret = i915_load_modeset_init(dev); if (ret < 0) { DRM_ERROR("failed to init modeset\n"); - goto out_power_well; + goto out_cleanup_vblank; } i915_driver_register(dev_priv); @@ -1317,8 +1318,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return 0; -out_power_well: - intel_power_domains_fini(dev_priv); +out_cleanup_vblank: drm_vblank_cleanup(dev); out_cleanup_hw: i915_driver_cleanup_hw(dev_priv); -- cgit v0.10.2 From 4fec15d1bd8352b6fc1edd71ae35ab138df010fc Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Mar 2016 13:39:08 +0200 Subject: drm/i915: Add fault injection support Add support for forcing an error at selected places in the driver. As an example add 4 options to fail during driver loading. Requested by Chris. v2: - Add fault point for modeset initialization - Print debug message when injecting an error v3: - Rename inject_fault to inject_load_failure, rename the related macros and helper accordingly (Chris) - Use a counter instead of a mask to identify the failure point (Daniel) - Mark the module option as _unsafe and keep i915_params ordered (Joonas) v4: - Rebase on latest -nightly v5: - Use DRM_INFO instead of DRM_DEBUG_DRIVER, making it clearer in CI reports that a following error message is expected (IRC r-b from Chris on v5) CC: Chris Wilson CC: Daniel Vetter CC: Joonas Lahtinen Signed-off-by: Imre Deak Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 7466e73..68592b0 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -50,6 +50,21 @@ #include #include +static unsigned int i915_load_fail_count; + +bool __i915_inject_load_failure(const char *func, int line) +{ + if (i915_load_fail_count >= i915.inject_load_failure) + return false; + + if (++i915_load_fail_count == i915.inject_load_failure) { + DRM_INFO("Injecting failure at checkpoint %u [%s:%d]\n", + i915.inject_load_failure, func, line); + return true; + } + + return false; +} static int i915_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -370,6 +385,9 @@ static int i915_load_modeset_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret; + if (i915_inject_load_failure()) + return -ENODEV; + ret = intel_bios_init(dev_priv); if (ret) DRM_INFO("failed to find VBIOS tables\n"); @@ -951,6 +969,9 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, struct intel_device_info *device_info; int ret = 0; + if (i915_inject_load_failure()) + return -ENODEV; + dev_priv->dev = dev; /* Setup the write-once "constant" device info */ @@ -1065,6 +1086,9 @@ static int i915_driver_init_mmio(struct drm_i915_private *dev_priv) struct drm_device *dev = dev_priv->dev; int ret; + if (i915_inject_load_failure()) + return -ENODEV; + if (i915_get_bridge_dev(dev)) return -EIO; @@ -1108,6 +1132,9 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) uint32_t aperture_size; int ret; + if (i915_inject_load_failure()) + return -ENODEV; + intel_device_info_runtime_init(dev); ret = i915_gem_gtt_init(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e6d4b1c..00c41a4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -98,6 +98,10 @@ #define I915_STATE_WARN_ON(x) \ I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")") +bool __i915_inject_load_failure(const char *func, int line); +#define i915_inject_load_failure() \ + __i915_inject_load_failure(__func__, __LINE__) + static inline const char *yesno(bool v) { return v ? "yes" : "no"; diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 97691f1..1779f02 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -57,6 +57,7 @@ struct i915_params i915 __read_mostly = { .enable_guc_submission = false, .guc_log_level = -1, .enable_dp_mst = true, + .inject_load_failure = 0, }; module_param_named(modeset, i915.modeset, int, 0400); @@ -206,3 +207,6 @@ MODULE_PARM_DESC(guc_log_level, module_param_named_unsafe(enable_dp_mst, i915.enable_dp_mst, bool, 0600); MODULE_PARM_DESC(enable_dp_mst, "Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)"); +module_param_named_unsafe(inject_load_failure, i915.inject_load_failure, uint, 0400); +MODULE_PARM_DESC(inject_load_failure, + "Force an error after a number of failure check points (0:disabled (default), N:force failure at the Nth failure check point)"); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 87153b0..02bc278 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -49,6 +49,7 @@ struct i915_params { int use_mmio_flip; int mmio_debug; int edp_vswing; + unsigned int inject_load_failure; /* leave bools at the end to not create holes */ bool enable_hangcheck; bool fastboot; -- cgit v0.10.2 From a112dbad44c4584ca565333d58d1bbb38799c12d Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 17 Mar 2016 13:04:09 +0000 Subject: drm/i915: Remove unused variable in i915_gem_request_add_to_client Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a4e0155..85963b0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1370,7 +1370,6 @@ out: int i915_gem_request_add_to_client(struct drm_i915_gem_request *req, struct drm_file *file) { - struct drm_i915_private *dev_private; struct drm_i915_file_private *file_priv; WARN_ON(!req || !file || req->file_priv); @@ -1381,7 +1380,6 @@ int i915_gem_request_add_to_client(struct drm_i915_gem_request *req, if (req->file_priv) return -EINVAL; - dev_private = req->engine->dev->dev_private; file_priv = file->driver_priv; spin_lock(&file_priv->mm.lock); -- cgit v0.10.2 From 39dabecd991b0a914f044af5824774825fb0923e Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 17 Mar 2016 13:04:10 +0000 Subject: drm/i915: Use shorter route to dev_private where possible Where we have a request we can use req->i915 directly instead of going through the engine and device. Coccinelle script: @@ function f; identifier r; @@ f(..., struct drm_i915_gem_request *r, ...) { ... - engine->dev->dev_private + r->i915 ... } @@ struct drm_i915_gem_request *req; @@ ( req-> - engine->dev->dev_private + i915 ) Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458219850-21007-1-git-send-email-tvrtko.ursulin@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 85963b0..f45856d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2550,7 +2550,7 @@ void __i915_add_request(struct drm_i915_gem_request *request, return; engine = request->engine; - dev_priv = engine->dev->dev_private; + dev_priv = request->i915; ringbuf = request->ringbuf; /* diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index c114665..6627bbe 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -656,7 +656,7 @@ static int do_switch(struct drm_i915_gem_request *req) { struct intel_context *to = req->ctx; struct intel_engine_cs *engine = req->engine; - struct drm_i915_private *dev_priv = engine->dev->dev_private; + struct drm_i915_private *dev_priv = req->i915; struct intel_context *from = engine->last_context; u32 hw_flags = 0; bool uninitialized = false; @@ -829,7 +829,7 @@ unpin_out: int i915_switch_context(struct drm_i915_gem_request *req) { struct intel_engine_cs *engine = req->engine; - struct drm_i915_private *dev_priv = engine->dev->dev_private; + struct drm_i915_private *dev_priv = req->i915; WARN_ON(i915.enable_execlists); WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9c752fe..fb0f963 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2192,7 +2192,7 @@ int i915_ppgtt_init_hw(struct drm_device *dev) int i915_ppgtt_init_ring(struct drm_i915_gem_request *req) { - struct drm_i915_private *dev_priv = req->engine->dev->dev_private; + struct drm_i915_private *dev_priv = req->i915; struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; if (i915.enable_execlists) diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index f727822..7c636b3 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -897,7 +897,7 @@ int intel_logical_ring_begin(struct drm_i915_gem_request *req, int num_dwords) int ret; WARN_ON(req == NULL); - dev_priv = req->engine->dev->dev_private; + dev_priv = req->i915; ret = i915_gem_check_wedge(&dev_priv->gpu_error, dev_priv->mm.interruptible); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 015dc7d..b7c8fc1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2499,7 +2499,7 @@ int intel_ring_begin(struct drm_i915_gem_request *req, WARN_ON(req == NULL); engine = req->engine; - dev_priv = engine->dev->dev_private; + dev_priv = req->i915; ret = i915_gem_check_wedge(&dev_priv->gpu_error, dev_priv->mm.interruptible); -- cgit v0.10.2 From 26720ab97feac7153a7b5c3c79cf5d53a8531126 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Thu, 17 Mar 2016 12:59:46 +0000 Subject: drm/i915: Move CSB MMIO reads out of the execlists lock By reading the CSB (slow MMIO accesses) into a temporary local buffer we can decrease the duration of holding the execlist lock. Main advantage is that during heavy batch buffer submission we reduce the execlist lock contention, which should decrease the latency and CPU usage between the submitting userspace process and interrupt handling. Downside is that we need to grab and relase the forcewake twice, but as the below numbers will show this is completely hidden by the primary gains. Testing with "gem_latency -n 100" (submit batch buffers with a hundred nops each) shows more than doubling of the throughput and more than halving of the dispatch latency, overall latency and CPU time spend in the submitting process. Submitting empty batches ("gem_latency -n 0") does not seem significantly affected by this change with throughput and CPU time improving by half a percent, and overall latency worsening by the same amount. Above tests were done in a hundred runs on a big core Broadwell. v2: * Overflow protection to local CSB buffer. * Use closer dev_priv in execlists_submit_requests. (Chris Wilson) v3: Rebase. v4: Added commend about irq needed to be disabled in execlists_submit_request. (Chris Wilson) Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Reviewed-by: Chris Wilsno Link: http://patchwork.freedesktop.org/patch/msgid/1458219586-20452-1-git-send-email-tvrtko.ursulin@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 7c636b3..3a23b95 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -416,15 +416,25 @@ static void execlists_update_context(struct drm_i915_gem_request *rq) static void execlists_submit_requests(struct drm_i915_gem_request *rq0, struct drm_i915_gem_request *rq1) { + struct drm_i915_private *dev_priv = rq0->i915; + + /* BUG_ON(!irqs_disabled()); */ + execlists_update_context(rq0); if (rq1) execlists_update_context(rq1); + spin_lock(&dev_priv->uncore.lock); + intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); + execlists_elsp_write(rq0, rq1); + + intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); + spin_unlock(&dev_priv->uncore.lock); } -static void execlists_context_unqueue__locked(struct intel_engine_cs *engine) +static void execlists_context_unqueue(struct intel_engine_cs *engine) { struct drm_i915_gem_request *req0 = NULL, *req1 = NULL; struct drm_i915_gem_request *cursor, *tmp; @@ -478,19 +488,6 @@ static void execlists_context_unqueue__locked(struct intel_engine_cs *engine) execlists_submit_requests(req0, req1); } -static void execlists_context_unqueue(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->dev->dev_private; - - spin_lock(&dev_priv->uncore.lock); - intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); - - execlists_context_unqueue__locked(engine); - - intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); - spin_unlock(&dev_priv->uncore.lock); -} - static unsigned int execlists_check_remove_request(struct intel_engine_cs *engine, u32 request_id) { @@ -551,12 +548,10 @@ void intel_lrc_irq_handler(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = engine->dev->dev_private; u32 status_pointer; unsigned int read_pointer, write_pointer; - u32 status = 0; - u32 status_id; + u32 csb[GEN8_CSB_ENTRIES][2]; + unsigned int csb_read = 0, i; unsigned int submit_contexts = 0; - spin_lock(&engine->execlist_lock); - spin_lock(&dev_priv->uncore.lock); intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); @@ -568,41 +563,47 @@ void intel_lrc_irq_handler(struct intel_engine_cs *engine) write_pointer += GEN8_CSB_ENTRIES; while (read_pointer < write_pointer) { - status = get_context_status(engine, ++read_pointer, - &status_id); + if (WARN_ON_ONCE(csb_read == GEN8_CSB_ENTRIES)) + break; + csb[csb_read][0] = get_context_status(engine, ++read_pointer, + &csb[csb_read][1]); + csb_read++; + } - if (unlikely(status & GEN8_CTX_STATUS_PREEMPTED)) { - if (status & GEN8_CTX_STATUS_LITE_RESTORE) { - if (execlists_check_remove_request(engine, status_id)) + engine->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES; + + /* Update the read pointer to the old write pointer. Manual ringbuffer + * management ftw */ + I915_WRITE_FW(RING_CONTEXT_STATUS_PTR(engine), + _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, + engine->next_context_status_buffer << 8)); + + intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); + spin_unlock(&dev_priv->uncore.lock); + + spin_lock(&engine->execlist_lock); + + for (i = 0; i < csb_read; i++) { + if (unlikely(csb[i][0] & GEN8_CTX_STATUS_PREEMPTED)) { + if (csb[i][0] & GEN8_CTX_STATUS_LITE_RESTORE) { + if (execlists_check_remove_request(engine, csb[i][1])) WARN(1, "Lite Restored request removed from queue\n"); } else WARN(1, "Preemption without Lite Restore\n"); } - if (status & (GEN8_CTX_STATUS_ACTIVE_IDLE | + if (csb[i][0] & (GEN8_CTX_STATUS_ACTIVE_IDLE | GEN8_CTX_STATUS_ELEMENT_SWITCH)) submit_contexts += - execlists_check_remove_request(engine, - status_id); + execlists_check_remove_request(engine, csb[i][1]); } if (submit_contexts) { if (!engine->disable_lite_restore_wa || - (status & GEN8_CTX_STATUS_ACTIVE_IDLE)) - execlists_context_unqueue__locked(engine); + (csb[i][0] & GEN8_CTX_STATUS_ACTIVE_IDLE)) + execlists_context_unqueue(engine); } - engine->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES; - - /* Update the read pointer to the old write pointer. Manual ringbuffer - * management ftw */ - I915_WRITE_FW(RING_CONTEXT_STATUS_PTR(engine), - _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, - engine->next_context_status_buffer << 8)); - - intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); - spin_unlock(&dev_priv->uncore.lock); - spin_unlock(&engine->execlist_lock); if (unlikely(submit_contexts > 2)) -- cgit v0.10.2 From 950b2aaeea6960561425fc80adfb5b2fc0ac020f Mon Sep 17 00:00:00 2001 From: Tim Gore Date: Wed, 16 Mar 2016 16:13:46 +0000 Subject: drm/i915/gen9: add WaClearFlowControlGpgpuContextSave This allows writes to EU flow control registers. Together with SIP code from the user-mode driver this resolves a hang seen in some pre-emption scenarios. Note that this patch is just the kernel mode part of this workaround. v2. Oops, add FLOW_CONTROL_ENABLE macro to i915_reg.h. Signed-off-by: Tim Gore Reviewed-by: Arun Siluvery Signed-off-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/1458144826-17269-1-git-send-email-tim.gore@intel.com diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 07e0449..264885f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7105,6 +7105,7 @@ enum skl_disp_power_wells { #define GEN9_CCS_TLB_PREFETCH_ENABLE (1<<3) #define GEN8_ROW_CHICKEN _MMIO(0xe4f0) +#define FLOW_CONTROL_ENABLE (1<<15) #define PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE (1<<8) #define STALL_DOP_GATING_DISABLE (1<<5) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b7c8fc1..9c59ede 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -925,8 +925,10 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | ECOCHK_DIS_TLB); + /* WaClearFlowControlGpgpuContextSave:skl,bxt */ /* WaDisablePartialInstShootdown:skl,bxt */ WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, + FLOW_CONTROL_ENABLE | PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); /* Syncing dependencies between camera and graphics:skl,bxt */ -- cgit v0.10.2 From dc3b04fbf43227e21fa95dbe6c7a13def655c891 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Fri, 18 Mar 2016 10:42:56 +0200 Subject: drm/i915/gtt: Reference mappable_end variable from pointer Reference variable value from pointer, not assumed pointer destination. Since: commit c44ef60e437019b8ca1dab8b4d2e8761fd4ce1e9 Author: Mika Kuoppala Date: Thu Jun 25 18:35:05 2015 +0300 drm/i915/gtt: Allow >= 4GB sizes for vm. Cc: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen Reviewed-by: Tvrtko Ursulin diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index fb0f963..be20407 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3103,8 +3103,7 @@ static int gen6_gmch_probe(struct drm_device *dev, * a coarse sanity check. */ if ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) { - DRM_ERROR("Unknown GMADR size (%llx)\n", - dev_priv->gtt.mappable_end); + DRM_ERROR("Unknown GMADR size (%llx)\n", *mappable_end); return -ENXIO; } -- cgit v0.10.2 From 62106b4f6b9118073ec59e3e34ec393ed76cf24f Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Fri, 18 Mar 2016 10:42:57 +0200 Subject: drm/i915: Rename dev_priv->gtt to dev_priv->ggtt Refer to Global GTT consistently as GGTT, thus rename dev_priv->gtt to dev_priv->ggtt and struct i915_gtt to struct i915_ggtt. Fix a couple of whitespace problems while at it. v2: - Fix a typo in commit message. Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ccdca2c..e0ba3e3 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -203,7 +203,7 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) struct list_head *head; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_address_space *vm = &dev_priv->gtt.base; + struct i915_address_space *vm = &dev_priv->ggtt.base; struct i915_vma *vma; u64 total_obj_size, total_gtt_size; int count, ret; @@ -433,7 +433,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) u32 count, mappable_count, purgeable_count; u64 size, mappable_size, purgeable_size; struct drm_i915_gem_object *obj; - struct i915_address_space *vm = &dev_priv->gtt.base; + struct i915_address_space *vm = &dev_priv->ggtt.base; struct drm_file *file; struct i915_vma *vma; int ret; @@ -492,8 +492,8 @@ static int i915_gem_object_info(struct seq_file *m, void* data) count, size); seq_printf(m, "%llu [%llu] gtt total\n", - dev_priv->gtt.base.total, - (u64)dev_priv->gtt.mappable_end - dev_priv->gtt.base.start); + dev_priv->ggtt.base.total, + (u64)dev_priv->ggtt.mappable_end - dev_priv->ggtt.base.start); seq_putc(m, '\n'); print_batch_pool_stats(m, dev_priv); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 68592b0..3565163 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -491,8 +491,8 @@ static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) if (!ap) return -ENOMEM; - ap->ranges[0].base = dev_priv->gtt.mappable_base; - ap->ranges[0].size = dev_priv->gtt.mappable_end; + ap->ranges[0].base = dev_priv->ggtt.mappable_base; + ap->ranges[0].size = dev_priv->ggtt.mappable_end; primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; @@ -1172,17 +1172,17 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32)); - aperture_size = dev_priv->gtt.mappable_end; + aperture_size = dev_priv->ggtt.mappable_end; - dev_priv->gtt.mappable = - io_mapping_create_wc(dev_priv->gtt.mappable_base, + dev_priv->ggtt.mappable = + io_mapping_create_wc(dev_priv->ggtt.mappable_base, aperture_size); - if (dev_priv->gtt.mappable == NULL) { + if (dev_priv->ggtt.mappable == NULL) { ret = -EIO; goto out_gtt; } - dev_priv->gtt.mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base, + dev_priv->ggtt.mtrr = arch_phys_wc_add(dev_priv->ggtt.mappable_base, aperture_size); pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, @@ -1230,8 +1230,8 @@ static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv) pci_disable_msi(dev->pdev); pm_qos_remove_request(&dev_priv->pm_qos); - arch_phys_wc_del(dev_priv->gtt.mtrr); - io_mapping_free(dev_priv->gtt.mappable); + arch_phys_wc_del(dev_priv->ggtt.mtrr); + io_mapping_free(dev_priv->ggtt.mappable); i915_global_gtt_cleanup(dev); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 00c41a4..b1d6554 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1810,7 +1810,7 @@ struct drm_i915_private { struct drm_atomic_state *modeset_restore_state; struct list_head vm_list; /* Global list of all address spaces */ - struct i915_gtt gtt; /* VM representing the global address space */ + struct i915_ggtt ggtt; /* VM representing the global address space */ struct i915_gem_mm mm; DECLARE_HASHTABLE(mm_structs, 7); @@ -3126,7 +3126,7 @@ bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj); /* Some GGTT VM helpers */ #define i915_obj_to_ggtt(obj) \ - (&((struct drm_i915_private *)(obj)->base.dev->dev_private)->gtt.base) + (&((struct drm_i915_private *)(obj)->base.dev->dev_private)->ggtt.base) static inline struct i915_hw_ppgtt * i915_vm_to_ppgtt(struct i915_address_space *vm) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f45856d..8588c83 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -132,7 +132,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_get_aperture *args = data; - struct i915_gtt *ggtt = &dev_priv->gtt; + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_vma *vma; size_t pinned; @@ -146,7 +146,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, pinned += vma->node.size; mutex_unlock(&dev->struct_mutex); - args->aper_size = dev_priv->gtt.base.total; + args->aper_size = dev_priv->ggtt.base.total; args->aper_available_size = args->aper_size - pinned; return 0; @@ -807,7 +807,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, * source page isn't available. Return the error and we'll * retry in the slow path. */ - if (fast_user_write(dev_priv->gtt.mappable, page_base, + if (fast_user_write(dev_priv->ggtt.mappable, page_base, page_offset, user_data, page_length)) { ret = -EFAULT; goto out_flush; @@ -1825,7 +1825,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } /* Use a partial view if the object is bigger than the aperture. */ - if (obj->base.size >= dev_priv->gtt.mappable_end && + if (obj->base.size >= dev_priv->ggtt.mappable_end && obj->tiling_mode == I915_TILING_NONE) { static const unsigned int chunk_size = 256; // 1 MiB @@ -1853,7 +1853,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) goto unpin; /* Finally, remap it using the new GTT offset */ - pfn = dev_priv->gtt.mappable_base + + pfn = dev_priv->ggtt.mappable_base + i915_gem_obj_ggtt_offset_view(obj, &view); pfn >>= PAGE_SHIFT; @@ -3511,7 +3511,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0; end = vm->total; if (flags & PIN_MAPPABLE) - end = min_t(u64, end, dev_priv->gtt.mappable_end); + end = min_t(u64, end, dev_priv->ggtt.mappable_end); if (flags & PIN_ZONE_4G) end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE); @@ -3772,7 +3772,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) vma = i915_gem_obj_to_ggtt(obj); if (vma && drm_mm_node_allocated(&vma->node) && !obj->active) list_move_tail(&vma->vm_link, - &to_i915(obj->base.dev)->gtt.base.inactive_list); + &to_i915(obj->base.dev)->ggtt.base.inactive_list); return 0; } @@ -4209,7 +4209,7 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma) (vma->node.start & (fence_alignment - 1)) == 0); mappable = (vma->node.start + fence_size <= - to_i915(obj->base.dev)->gtt.mappable_end); + to_i915(obj->base.dev)->ggtt.mappable_end); obj->map_and_fenceable = mappable && fenceable; } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6627bbe..394e525 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -945,7 +945,7 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, else if (to_i915(dev)->mm.aliasing_ppgtt) args->value = to_i915(dev)->mm.aliasing_ppgtt->base.total; else - args->value = to_i915(dev)->gtt.base.total; + args->value = to_i915(dev)->ggtt.base.total; break; default: ret = -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index dac01ee..374a0cb 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -330,7 +330,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, /* Map the page containing the relocation we're going to perform. */ offset = i915_gem_obj_ggtt_offset(obj); offset += reloc->offset; - reloc_page = io_mapping_map_atomic_wc(dev_priv->gtt.mappable, + reloc_page = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable, offset & PAGE_MASK); iowrite32(lower_32_bits(delta), reloc_page + offset_in_page(offset)); @@ -340,7 +340,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, if (offset_in_page(offset) == 0) { io_mapping_unmap_atomic(reloc_page); reloc_page = - io_mapping_map_atomic_wc(dev_priv->gtt.mappable, + io_mapping_map_atomic_wc(dev_priv->ggtt.mappable, offset); } @@ -1504,7 +1504,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (ctx->ppgtt) vm = &ctx->ppgtt->base; else - vm = &dev_priv->gtt.base; + vm = &dev_priv->ggtt.base; memset(¶ms_master, 0x00, sizeof(params_master)); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index be20407..41b4606 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1637,7 +1637,7 @@ static void gen6_write_page_range(struct drm_i915_private *dev_priv, /* Make sure write is complete before other code can use this page * table. Also require for WC mapped PTEs */ - readl(dev_priv->gtt.gsm); + readl(dev_priv->ggtt.gsm); } static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt) @@ -1932,7 +1932,7 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, /* Make sure write is complete before other code can use this page * table. Also require for WC mapped PTEs */ - readl(dev_priv->gtt.gsm); + readl(dev_priv->ggtt.gsm); mark_tlbs_dirty(ppgtt); return 0; @@ -2005,23 +2005,23 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt) * allocator works in address space sizes, so it's multiplied by page * size. We allocate at the top of the GTT to avoid fragmentation. */ - BUG_ON(!drm_mm_initialized(&dev_priv->gtt.base.mm)); + BUG_ON(!drm_mm_initialized(&dev_priv->ggtt.base.mm)); ret = gen6_init_scratch(vm); if (ret) return ret; alloc: - ret = drm_mm_insert_node_in_range_generic(&dev_priv->gtt.base.mm, + ret = drm_mm_insert_node_in_range_generic(&dev_priv->ggtt.base.mm, &ppgtt->node, GEN6_PD_SIZE, GEN6_PD_ALIGN, 0, - 0, dev_priv->gtt.base.total, + 0, dev_priv->ggtt.base.total, DRM_MM_TOPDOWN); if (ret == -ENOSPC && !retried) { - ret = i915_gem_evict_something(dev, &dev_priv->gtt.base, + ret = i915_gem_evict_something(dev, &dev_priv->ggtt.base, GEN6_PD_SIZE, GEN6_PD_ALIGN, I915_CACHE_NONE, - 0, dev_priv->gtt.base.total, + 0, dev_priv->ggtt.base.total, 0); if (ret) goto err_out; @@ -2034,7 +2034,7 @@ alloc: goto err_out; - if (ppgtt->node.start < dev_priv->gtt.mappable_end) + if (ppgtt->node.start < dev_priv->ggtt.mappable_end) DRM_DEBUG("Forced to use aperture for PDEs\n"); return 0; @@ -2065,7 +2065,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) struct drm_i915_private *dev_priv = dev->dev_private; int ret; - ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode; + ppgtt->base.pte_encode = dev_priv->ggtt.base.pte_encode; if (IS_GEN6(dev)) { ppgtt->switch_mm = gen6_mm_switch; } else if (IS_HASWELL(dev)) { @@ -2095,7 +2095,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->pd.base.ggtt_offset = ppgtt->node.start / PAGE_SIZE * sizeof(gen6_pte_t); - ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->gtt.gsm + + ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->ggtt.gsm + ppgtt->pd.base.ggtt_offset / sizeof(gen6_pte_t); gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total); @@ -2265,7 +2265,7 @@ static bool do_idling(struct drm_i915_private *dev_priv) { bool ret = dev_priv->mm.interruptible; - if (unlikely(dev_priv->gtt.do_idle_maps)) { + if (unlikely(dev_priv->ggtt.do_idle_maps)) { dev_priv->mm.interruptible = false; if (i915_gpu_idle(dev_priv->dev)) { DRM_ERROR("Couldn't idle GPU\n"); @@ -2279,7 +2279,7 @@ static bool do_idling(struct drm_i915_private *dev_priv) static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) { - if (unlikely(dev_priv->gtt.do_idle_maps)) + if (unlikely(dev_priv->ggtt.do_idle_maps)) dev_priv->mm.interruptible = interruptible; } @@ -2334,9 +2334,9 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) i915_check_and_clear_faults(dev); - dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, - dev_priv->gtt.base.start, - dev_priv->gtt.base.total, + dev_priv->ggtt.base.clear_range(&dev_priv->ggtt.base, + dev_priv->ggtt.base.start, + dev_priv->ggtt.base.total, true); i915_ggtt_flush(dev_priv); @@ -2370,7 +2370,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, struct drm_i915_private *dev_priv = vm->dev->dev_private; unsigned first_entry = start >> PAGE_SHIFT; gen8_pte_t __iomem *gtt_entries = - (gen8_pte_t __iomem *)dev_priv->gtt.gsm + first_entry; + (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + first_entry; int i = 0; struct sg_page_iter sg_iter; dma_addr_t addr = 0; /* shut up gcc */ @@ -2447,7 +2447,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, struct drm_i915_private *dev_priv = vm->dev->dev_private; unsigned first_entry = start >> PAGE_SHIFT; gen6_pte_t __iomem *gtt_entries = - (gen6_pte_t __iomem *)dev_priv->gtt.gsm + first_entry; + (gen6_pte_t __iomem *)dev_priv->ggtt.gsm + first_entry; int i = 0; struct sg_page_iter sg_iter; dma_addr_t addr = 0; @@ -2491,8 +2491,8 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, unsigned first_entry = start >> PAGE_SHIFT; unsigned num_entries = length >> PAGE_SHIFT; gen8_pte_t scratch_pte, __iomem *gtt_base = - (gen8_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; - const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; + (gen8_pte_t __iomem *) dev_priv->ggtt.gsm + first_entry; + const int max_entries = gtt_total_entries(dev_priv->ggtt) - first_entry; int i; int rpm_atomic_seq; @@ -2522,8 +2522,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, unsigned first_entry = start >> PAGE_SHIFT; unsigned num_entries = length >> PAGE_SHIFT; gen6_pte_t scratch_pte, __iomem *gtt_base = - (gen6_pte_t __iomem *) dev_priv->gtt.gsm + first_entry; - const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry; + (gen6_pte_t __iomem *) dev_priv->ggtt.gsm + first_entry; + const int max_entries = gtt_total_entries(dev_priv->ggtt) - first_entry; int i; int rpm_atomic_seq; @@ -2718,7 +2718,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, * of the aperture. */ struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_address_space *ggtt_vm = &dev_priv->gtt.base; + struct i915_address_space *ggtt_vm = &dev_priv->ggtt.base; struct drm_mm_node *entry; struct drm_i915_gem_object *obj; unsigned long hole_start, hole_end; @@ -2801,8 +2801,8 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, true); dev_priv->mm.aliasing_ppgtt = ppgtt; - WARN_ON(dev_priv->gtt.base.bind_vma != ggtt_bind_vma); - dev_priv->gtt.base.bind_vma = aliasing_gtt_bind_vma; + WARN_ON(dev_priv->ggtt.base.bind_vma != ggtt_bind_vma); + dev_priv->ggtt.base.bind_vma = aliasing_gtt_bind_vma; } return 0; @@ -2813,8 +2813,8 @@ void i915_gem_init_global_gtt(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; u64 gtt_size, mappable_size; - gtt_size = dev_priv->gtt.base.total; - mappable_size = dev_priv->gtt.mappable_end; + gtt_size = dev_priv->ggtt.base.total; + mappable_size = dev_priv->ggtt.mappable_end; i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size); } @@ -2822,7 +2822,7 @@ void i915_gem_init_global_gtt(struct drm_device *dev) void i915_global_gtt_cleanup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_address_space *vm = &dev_priv->gtt.base; + struct i915_address_space *vm = &dev_priv->ggtt.base; if (dev_priv->mm.aliasing_ppgtt) { struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; @@ -2940,10 +2940,10 @@ static int ggtt_probe_common(struct drm_device *dev, * readback check when writing GTT PTE entries. */ if (IS_BROXTON(dev)) - dev_priv->gtt.gsm = ioremap_nocache(gtt_phys_addr, gtt_size); + dev_priv->ggtt.gsm = ioremap_nocache(gtt_phys_addr, gtt_size); else - dev_priv->gtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size); - if (!dev_priv->gtt.gsm) { + dev_priv->ggtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size); + if (!dev_priv->ggtt.gsm) { DRM_ERROR("Failed to map the gtt page table\n"); return -ENOMEM; } @@ -2952,11 +2952,11 @@ static int ggtt_probe_common(struct drm_device *dev, if (IS_ERR(scratch_page)) { DRM_ERROR("Scratch setup failed\n"); /* iounmap will also get called at remove, but meh */ - iounmap(dev_priv->gtt.gsm); + iounmap(dev_priv->ggtt.gsm); return PTR_ERR(scratch_page); } - dev_priv->gtt.base.scratch_page = scratch_page; + dev_priv->ggtt.base.scratch_page = scratch_page; return 0; } @@ -3074,13 +3074,13 @@ static int gen8_gmch_probe(struct drm_device *dev, ret = ggtt_probe_common(dev, gtt_size); - dev_priv->gtt.base.clear_range = gen8_ggtt_clear_range; - dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries; - dev_priv->gtt.base.bind_vma = ggtt_bind_vma; - dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; + dev_priv->ggtt.base.clear_range = gen8_ggtt_clear_range; + dev_priv->ggtt.base.insert_entries = gen8_ggtt_insert_entries; + dev_priv->ggtt.base.bind_vma = ggtt_bind_vma; + dev_priv->ggtt.base.unbind_vma = ggtt_unbind_vma; if (IS_CHERRYVIEW(dev_priv)) - dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries__BKL; + dev_priv->ggtt.base.insert_entries = gen8_ggtt_insert_entries__BKL; return ret; } @@ -3118,20 +3118,19 @@ static int gen6_gmch_probe(struct drm_device *dev, ret = ggtt_probe_common(dev, gtt_size); - dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range; - dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries; - dev_priv->gtt.base.bind_vma = ggtt_bind_vma; - dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; + dev_priv->ggtt.base.clear_range = gen6_ggtt_clear_range; + dev_priv->ggtt.base.insert_entries = gen6_ggtt_insert_entries; + dev_priv->ggtt.base.bind_vma = ggtt_bind_vma; + dev_priv->ggtt.base.unbind_vma = ggtt_unbind_vma; return ret; } static void gen6_gmch_remove(struct i915_address_space *vm) { + struct i915_ggtt *ggtt = container_of(vm, struct i915_ggtt, base); - struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base); - - iounmap(gtt->gsm); + iounmap(ggtt->gsm); free_scratch_page(vm->dev, vm->scratch_page); } @@ -3152,13 +3151,13 @@ static int i915_gmch_probe(struct drm_device *dev, intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end); - dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev); - dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries; - dev_priv->gtt.base.clear_range = i915_ggtt_clear_range; - dev_priv->gtt.base.bind_vma = ggtt_bind_vma; - dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma; + dev_priv->ggtt.do_idle_maps = needs_idle_maps(dev_priv->dev); + dev_priv->ggtt.base.insert_entries = i915_ggtt_insert_entries; + dev_priv->ggtt.base.clear_range = i915_ggtt_clear_range; + dev_priv->ggtt.base.bind_vma = ggtt_bind_vma; + dev_priv->ggtt.base.unbind_vma = ggtt_unbind_vma; - if (unlikely(dev_priv->gtt.do_idle_maps)) + if (unlikely(dev_priv->ggtt.do_idle_maps)) DRM_INFO("applying Ironlake quirks for intel_iommu\n"); return 0; @@ -3172,35 +3171,35 @@ static void i915_gmch_remove(struct i915_address_space *vm) int i915_gem_gtt_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_gtt *gtt = &dev_priv->gtt; + struct i915_ggtt *ggtt = &dev_priv->ggtt; int ret; if (INTEL_INFO(dev)->gen <= 5) { - gtt->gtt_probe = i915_gmch_probe; - gtt->base.cleanup = i915_gmch_remove; + ggtt->probe = i915_gmch_probe; + ggtt->base.cleanup = i915_gmch_remove; } else if (INTEL_INFO(dev)->gen < 8) { - gtt->gtt_probe = gen6_gmch_probe; - gtt->base.cleanup = gen6_gmch_remove; + ggtt->probe = gen6_gmch_probe; + ggtt->base.cleanup = gen6_gmch_remove; if (IS_HASWELL(dev) && dev_priv->ellc_size) - gtt->base.pte_encode = iris_pte_encode; + ggtt->base.pte_encode = iris_pte_encode; else if (IS_HASWELL(dev)) - gtt->base.pte_encode = hsw_pte_encode; + ggtt->base.pte_encode = hsw_pte_encode; else if (IS_VALLEYVIEW(dev)) - gtt->base.pte_encode = byt_pte_encode; + ggtt->base.pte_encode = byt_pte_encode; else if (INTEL_INFO(dev)->gen >= 7) - gtt->base.pte_encode = ivb_pte_encode; + ggtt->base.pte_encode = ivb_pte_encode; else - gtt->base.pte_encode = snb_pte_encode; + ggtt->base.pte_encode = snb_pte_encode; } else { - dev_priv->gtt.gtt_probe = gen8_gmch_probe; - dev_priv->gtt.base.cleanup = gen6_gmch_remove; + ggtt->probe = gen8_gmch_probe; + ggtt->base.cleanup = gen6_gmch_remove; } - gtt->base.dev = dev; - gtt->base.is_ggtt = true; + ggtt->base.dev = dev; + ggtt->base.is_ggtt = true; - ret = gtt->gtt_probe(dev, >t->base.total, >t->stolen_size, - >t->mappable_base, >t->mappable_end); + ret = ggtt->probe(dev, &ggtt->base.total, &ggtt->stolen_size, + &ggtt->mappable_base, &ggtt->mappable_end); if (ret) return ret; @@ -3214,9 +3213,9 @@ int i915_gem_gtt_init(struct drm_device *dev) /* GMADR is the PCI mmio aperture into the global GTT. */ DRM_INFO("Memory usable by graphics device = %lluM\n", - gtt->base.total >> 20); - DRM_DEBUG_DRIVER("GMADR size = %lldM\n", gtt->mappable_end >> 20); - DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20); + ggtt->base.total >> 20); + DRM_DEBUG_DRIVER("GMADR size = %lldM\n", ggtt->mappable_end >> 20); + DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", ggtt->stolen_size >> 20); #ifdef CONFIG_INTEL_IOMMU if (intel_iommu_gfx_mapped) DRM_INFO("VT-d active for gfx access\n"); @@ -3233,7 +3232,7 @@ int i915_gem_gtt_init(struct drm_device *dev) return 0; out_gtt_cleanup: - gtt->base.cleanup(&dev_priv->gtt.base); + ggtt->base.cleanup(&dev_priv->ggtt.base); return ret; } @@ -3249,13 +3248,13 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) i915_check_and_clear_faults(dev); /* First fill our portion of the GTT with scratch pages */ - dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, - dev_priv->gtt.base.start, - dev_priv->gtt.base.total, + dev_priv->ggtt.base.clear_range(&dev_priv->ggtt.base, + dev_priv->ggtt.base.start, + dev_priv->ggtt.base.total, true); /* Cache flush objects bound into GGTT and rebind them. */ - vm = &dev_priv->gtt.base; + vm = &dev_priv->ggtt.base; list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { flush = false; list_for_each_entry(vma, &obj->vma_list, obj_link) { diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index dc208c0..2906bb1 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -339,7 +339,7 @@ struct i915_address_space { * and correct (in cases like swizzling). That region is referred to as GMADR in * the spec. */ -struct i915_gtt { +struct i915_ggtt { struct i915_address_space base; size_t stolen_size; /* Total size of stolen memory */ @@ -357,10 +357,9 @@ struct i915_gtt { int mtrr; - /* global gtt ops */ - int (*gtt_probe)(struct drm_device *dev, u64 *gtt_total, - size_t *stolen, phys_addr_t *mappable_base, - u64 *mappable_end); + int (*probe)(struct drm_device *dev, u64 *gtt_total, + size_t *stolen, phys_addr_t *mappable_base, + u64 *mappable_end); }; struct i915_hw_ppgtt { diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 2e6e9fb..de891c9 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -74,7 +74,7 @@ int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, { return i915_gem_stolen_insert_node_in_range(dev_priv, node, size, alignment, 0, - dev_priv->gtt.stolen_usable_size); + dev_priv->ggtt.stolen_usable_size); } void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, @@ -134,7 +134,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) I85X_DRB3, &tmp); tom = tmp * MB(32); - base = tom - tseg_size - dev_priv->gtt.stolen_size; + base = tom - tseg_size - dev_priv->ggtt.stolen_size; } else if (IS_845G(dev)) { u32 tseg_size = 0; u32 tom; @@ -158,7 +158,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) I830_DRB3, &tmp); tom = tmp * MB(32); - base = tom - tseg_size - dev_priv->gtt.stolen_size; + base = tom - tseg_size - dev_priv->ggtt.stolen_size; } else if (IS_I830(dev)) { u32 tseg_size = 0; u32 tom; @@ -178,7 +178,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) I830_DRB3, &tmp); tom = tmp * MB(32); - base = tom - tseg_size - dev_priv->gtt.stolen_size; + base = tom - tseg_size - dev_priv->ggtt.stolen_size; } if (base == 0) @@ -189,8 +189,8 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) struct { u32 start, end; } stolen[2] = { - { .start = base, .end = base + dev_priv->gtt.stolen_size, }, - { .start = base, .end = base + dev_priv->gtt.stolen_size, }, + { .start = base, .end = base + dev_priv->ggtt.stolen_size, }, + { .start = base, .end = base + dev_priv->ggtt.stolen_size, }, }; u64 gtt_start, gtt_end; @@ -200,7 +200,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) (gtt_start & PGTBL_ADDRESS_HI_MASK) << 28; else gtt_start &= PGTBL_ADDRESS_LO_MASK; - gtt_end = gtt_start + gtt_total_entries(dev_priv->gtt) * 4; + gtt_end = gtt_start + gtt_total_entries(dev_priv->ggtt) * 4; if (gtt_start >= stolen[0].start && gtt_start < stolen[0].end) stolen[0].end = gtt_start; @@ -211,10 +211,10 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) if (stolen[0].end - stolen[0].start > stolen[1].end - stolen[1].start) { base = stolen[0].start; - dev_priv->gtt.stolen_size = stolen[0].end - stolen[0].start; + dev_priv->ggtt.stolen_size = stolen[0].end - stolen[0].start; } else { base = stolen[1].start; - dev_priv->gtt.stolen_size = stolen[1].end - stolen[1].start; + dev_priv->ggtt.stolen_size = stolen[1].end - stolen[1].start; } if (stolen[0].start != stolen[1].start || @@ -223,7 +223,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) (unsigned long long) gtt_start, (unsigned long long) gtt_end - 1); DRM_DEBUG_KMS("Stolen memory adjusted to 0x%x-0x%x\n", - base, base + (u32) dev_priv->gtt.stolen_size - 1); + base, base + (u32) dev_priv->ggtt.stolen_size - 1); } } @@ -233,7 +233,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) * kernel. So if the region is already marked as busy, something * is seriously wrong. */ - r = devm_request_mem_region(dev->dev, base, dev_priv->gtt.stolen_size, + r = devm_request_mem_region(dev->dev, base, dev_priv->ggtt.stolen_size, "Graphics Stolen Memory"); if (r == NULL) { /* @@ -245,7 +245,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) * reservation starting from 1 instead of 0. */ r = devm_request_mem_region(dev->dev, base + 1, - dev_priv->gtt.stolen_size - 1, + dev_priv->ggtt.stolen_size - 1, "Graphics Stolen Memory"); /* * GEN3 firmware likes to smash pci bridges into the stolen @@ -253,7 +253,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) */ if (r == NULL && !IS_GEN3(dev)) { DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n", - base, base + (uint32_t)dev_priv->gtt.stolen_size); + base, base + (uint32_t)dev_priv->ggtt.stolen_size); base = 0; } } @@ -278,7 +278,7 @@ static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, CTG_STOLEN_RESERVED : ELK_STOLEN_RESERVED); unsigned long stolen_top = dev_priv->mm.stolen_base + - dev_priv->gtt.stolen_size; + dev_priv->ggtt.stolen_size; *base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16; @@ -372,7 +372,7 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv, uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); unsigned long stolen_top; - stolen_top = dev_priv->mm.stolen_base + dev_priv->gtt.stolen_size; + stolen_top = dev_priv->mm.stolen_base + dev_priv->ggtt.stolen_size; *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; @@ -401,14 +401,14 @@ int i915_gem_init_stolen(struct drm_device *dev) } #endif - if (dev_priv->gtt.stolen_size == 0) + if (dev_priv->ggtt.stolen_size == 0) return 0; dev_priv->mm.stolen_base = i915_stolen_to_physical(dev); if (dev_priv->mm.stolen_base == 0) return 0; - stolen_top = dev_priv->mm.stolen_base + dev_priv->gtt.stolen_size; + stolen_top = dev_priv->mm.stolen_base + dev_priv->ggtt.stolen_size; switch (INTEL_INFO(dev_priv)->gen) { case 2: @@ -458,18 +458,18 @@ int i915_gem_init_stolen(struct drm_device *dev) return 0; } - dev_priv->gtt.stolen_reserved_base = reserved_base; - dev_priv->gtt.stolen_reserved_size = reserved_size; + dev_priv->ggtt.stolen_reserved_base = reserved_base; + dev_priv->ggtt.stolen_reserved_size = reserved_size; /* It is possible for the reserved area to end before the end of stolen * memory, so just consider the start. */ reserved_total = stolen_top - reserved_base; DRM_DEBUG_KMS("Memory reserved for graphics device: %zuK, usable: %luK\n", - dev_priv->gtt.stolen_size >> 10, - (dev_priv->gtt.stolen_size - reserved_total) >> 10); + dev_priv->ggtt.stolen_size >> 10, + (dev_priv->ggtt.stolen_size - reserved_total) >> 10); - dev_priv->gtt.stolen_usable_size = dev_priv->gtt.stolen_size - + dev_priv->ggtt.stolen_usable_size = dev_priv->ggtt.stolen_size - reserved_total; /* @@ -483,7 +483,7 @@ int i915_gem_init_stolen(struct drm_device *dev) * i915_gem_stolen_insert_node_in_range(). We may want to fix the fbcon * problem later. */ - drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_usable_size); + drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->ggtt.stolen_usable_size); return 0; } @@ -497,7 +497,7 @@ i915_pages_create_for_stolen(struct drm_device *dev, struct scatterlist *sg; DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size); - BUG_ON(offset > dev_priv->gtt.stolen_size - size); + BUG_ON(offset > dev_priv->ggtt.stolen_size - size); /* We hide that we have no struct page backing our stolen object * by wrapping the contiguous physical allocation with a fake @@ -629,7 +629,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, u32 size) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_address_space *ggtt = &dev_priv->gtt.base; + struct i915_address_space *ggtt = &dev_priv->ggtt.base; struct drm_i915_gem_object *obj; struct drm_mm_node *stolen; struct i915_vma *vma; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 34397a6..db8600a 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -653,7 +653,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv, vma = i915_gem_obj_to_ggtt(src); use_ggtt = (src->cache_level == I915_CACHE_NONE && vma && (vma->bound & GLOBAL_BIND) && - reloc_offset + num_pages * PAGE_SIZE <= dev_priv->gtt.mappable_end); + reloc_offset + num_pages * PAGE_SIZE <= dev_priv->ggtt.mappable_end); /* Cannot access stolen address directly, try to use the aperture */ if (src->stolen) { @@ -663,7 +663,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv, goto unwind; reloc_offset = i915_gem_obj_ggtt_offset(src); - if (reloc_offset + num_pages * PAGE_SIZE > dev_priv->gtt.mappable_end) + if (reloc_offset + num_pages * PAGE_SIZE > dev_priv->ggtt.mappable_end) goto unwind; } @@ -689,7 +689,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv, * captures what the GPU read. */ - s = io_mapping_map_atomic_wc(dev_priv->gtt.mappable, + s = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable, reloc_offset); memcpy_fromio(d, s, PAGE_SIZE); io_mapping_unmap_atomic(s); @@ -722,7 +722,7 @@ unwind: return NULL; } #define i915_error_ggtt_object_create(dev_priv, src) \ - i915_error_object_create((dev_priv), (src), &(dev_priv)->gtt.base) + i915_error_object_create((dev_priv), (src), &(dev_priv)->ggtt.base) static void capture_bo(struct drm_i915_error_buffer *err, struct i915_vma *vma) @@ -1038,7 +1038,7 @@ static void i915_gem_record_rings(struct drm_device *dev, vm = request->ctx && request->ctx->ppgtt ? &request->ctx->ppgtt->base : - &dev_priv->gtt.base; + &dev_priv->ggtt.base; /* We need to copy these to an anonymous buffer * as the simplest method to avoid being overwritten diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c index dea7429..2891bcf 100644 --- a/drivers/gpu/drm/i915/i915_vgpu.c +++ b/drivers/gpu/drm/i915/i915_vgpu.c @@ -181,7 +181,7 @@ static int vgt_balloon_space(struct drm_mm *mm, int intel_vgt_balloon(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct i915_address_space *ggtt_vm = &dev_priv->gtt.base; + struct i915_address_space *ggtt_vm = &dev_priv->ggtt.base; unsigned long ggtt_vm_end = ggtt_vm->start + ggtt_vm->total; unsigned long mappable_base, mappable_size, mappable_end; @@ -203,18 +203,18 @@ int intel_vgt_balloon(struct drm_device *dev) unmappable_base, unmappable_size / 1024); if (mappable_base < ggtt_vm->start || - mappable_end > dev_priv->gtt.mappable_end || - unmappable_base < dev_priv->gtt.mappable_end || + mappable_end > dev_priv->ggtt.mappable_end || + unmappable_base < dev_priv->ggtt.mappable_end || unmappable_end > ggtt_vm_end) { DRM_ERROR("Invalid ballooning configuration!\n"); return -EINVAL; } /* Unmappable graphic memory ballooning */ - if (unmappable_base > dev_priv->gtt.mappable_end) { + if (unmappable_base > dev_priv->ggtt.mappable_end) { ret = vgt_balloon_space(&ggtt_vm->mm, &bl_info.space[2], - dev_priv->gtt.mappable_end, + dev_priv->ggtt.mappable_end, unmappable_base); if (ret) @@ -244,11 +244,11 @@ int intel_vgt_balloon(struct drm_device *dev) goto err; } - if (mappable_end < dev_priv->gtt.mappable_end) { + if (mappable_end < dev_priv->ggtt.mappable_end) { ret = vgt_balloon_space(&ggtt_vm->mm, &bl_info.space[1], mappable_end, - dev_priv->gtt.mappable_end); + dev_priv->ggtt.mappable_end); if (ret) goto err; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ab1ec8d..74b0165 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2503,7 +2503,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, /* If the FB is too big, just don't use it since fbdev is not very * important and we should probably use that space with FBC or other * features. */ - if (size_aligned * 2 > dev_priv->gtt.stolen_usable_size) + if (size_aligned * 2 > dev_priv->ggtt.stolen_usable_size) return false; mutex_lock(&dev->struct_mutex); @@ -15339,7 +15339,7 @@ void intel_modeset_init(struct drm_device *dev) dev->mode_config.cursor_height = MAX_CURSOR_HEIGHT; } - dev->mode_config.fb_base = dev_priv->gtt.mappable_base; + dev->mode_config.fb_base = dev_priv->ggtt.mappable_base; DRM_DEBUG_KMS("%d display pipe%s available.\n", INTEL_INFO(dev)->num_pipes, diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 0f0492f..2e571f5 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -516,9 +516,9 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, * underruns, even if that range is not reserved by the BIOS. */ if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) - end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024; + end = dev_priv->ggtt.stolen_size - 8 * 1024 * 1024; else - end = dev_priv->gtt.stolen_usable_size; + end = dev_priv->ggtt.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. diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index ae9cf6f..ea4188a 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -146,7 +146,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper, /* If the FB is too big, just don't use it since fbdev is not very * important and we should probably use that space with FBC or other * features. */ - if (size * 2 < dev_priv->gtt.stolen_usable_size) + if (size * 2 < dev_priv->ggtt.stolen_usable_size) obj = i915_gem_object_create_stolen(dev, size); if (obj == NULL) obj = i915_gem_alloc_object(dev, size); @@ -244,13 +244,13 @@ static int intelfb_create(struct drm_fb_helper *helper, /* setup aperture base/size for vesafb takeover */ info->apertures->ranges[0].base = dev->mode_config.fb_base; - info->apertures->ranges[0].size = dev_priv->gtt.mappable_end; + info->apertures->ranges[0].size = dev_priv->ggtt.mappable_end; info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj); info->fix.smem_len = size; info->screen_base = - ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj), + ioremap_wc(dev_priv->ggtt.mappable_base + i915_gem_obj_ggtt_offset(obj), size); if (!info->screen_base) { DRM_ERROR("Failed to remap framebuffer into virtual memory\n"); diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 13e22f5..e1acb41 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -196,7 +196,7 @@ intel_overlay_map_regs(struct intel_overlay *overlay) if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr; else - regs = io_mapping_map_wc(dev_priv->gtt.mappable, + regs = io_mapping_map_wc(dev_priv->ggtt.mappable, i915_gem_obj_ggtt_offset(overlay->reg_bo)); return regs; @@ -1490,7 +1490,7 @@ intel_overlay_map_regs_atomic(struct intel_overlay *overlay) regs = (struct overlay_registers __iomem *) overlay->reg_bo->phys_handle->vaddr; else - regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable, + regs = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable, i915_gem_obj_ggtt_offset(overlay->reg_bo)); return regs; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a539fbc..521cf45 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4644,9 +4644,9 @@ static bool bxt_check_bios_rc6_setup(const struct drm_device *dev) * for this check. */ rc6_ctx_base = I915_READ(RC6_CTX_BASE) & RC6_CTX_BASE_MASK; - if (!((rc6_ctx_base >= dev_priv->gtt.stolen_reserved_base) && - (rc6_ctx_base + PAGE_SIZE <= dev_priv->gtt.stolen_reserved_base + - dev_priv->gtt.stolen_reserved_size))) { + if (!((rc6_ctx_base >= dev_priv->ggtt.stolen_reserved_base) && + (rc6_ctx_base + PAGE_SIZE <= dev_priv->ggtt.stolen_reserved_base + + dev_priv->ggtt.stolen_reserved_size))) { DRM_DEBUG_KMS("RC6 Base address not as expected.\n"); enable_rc6 = false; } @@ -5291,7 +5291,7 @@ static void cherryview_setup_pctx(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; unsigned long pctx_paddr, paddr; - struct i915_gtt *gtt = &dev_priv->gtt; + struct i915_ggtt *ggtt = &dev_priv->ggtt; u32 pcbr; int pctx_size = 32*1024; @@ -5299,7 +5299,7 @@ static void cherryview_setup_pctx(struct drm_device *dev) if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) { DRM_DEBUG_DRIVER("BIOS didn't set up PCBR, fixing up\n"); paddr = (dev_priv->mm.stolen_base + - (gtt->stolen_size - pctx_size)); + (ggtt->stolen_size - pctx_size)); pctx_paddr = (paddr & (~4095)); I915_WRITE(VLV_PCBR, pctx_paddr); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 9c59ede..df0ef5b 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2136,7 +2136,7 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, /* Access through the GTT requires the device to be awake. */ assert_rpm_wakelock_held(dev_priv); - ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base + + ringbuf->virtual_start = ioremap_wc(dev_priv->ggtt.mappable_base + i915_gem_obj_ggtt_offset(obj), ringbuf->size); if (ringbuf->virtual_start == NULL) { i915_gem_object_ggtt_unpin(obj); -- cgit v0.10.2 From d507d73578ef7aa1ffcd122e51caa59e4492cb46 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Fri, 18 Mar 2016 10:42:58 +0200 Subject: drm/i915/gtt: Clean up GGTT probing code Use less pointers with the probing code, making it much less confusing to read. Cc: Mika Kuoppala Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 41b4606..799576e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3034,20 +3034,16 @@ static void chv_setup_private_ppat(struct drm_i915_private *dev_priv) I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32); } -static int gen8_gmch_probe(struct drm_device *dev, - u64 *gtt_total, - size_t *stolen, - phys_addr_t *mappable_base, - u64 *mappable_end) +static int gen8_gmch_probe(struct i915_ggtt *ggtt) { + struct drm_device *dev = ggtt->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - u64 gtt_size; u16 snb_gmch_ctl; int ret; /* TODO: We're not aware of mappable constraints on gen8 yet */ - *mappable_base = pci_resource_start(dev->pdev, 2); - *mappable_end = pci_resource_len(dev->pdev, 2); + ggtt->mappable_base = pci_resource_start(dev->pdev, 2); + ggtt->mappable_end = pci_resource_len(dev->pdev, 2); if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(39))) pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(39)); @@ -3055,55 +3051,51 @@ static int gen8_gmch_probe(struct drm_device *dev, pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); if (INTEL_INFO(dev)->gen >= 9) { - *stolen = gen9_get_stolen_size(snb_gmch_ctl); - gtt_size = gen8_get_total_gtt_size(snb_gmch_ctl); + ggtt->stolen_size = gen9_get_stolen_size(snb_gmch_ctl); + ggtt->size = gen8_get_total_gtt_size(snb_gmch_ctl); } else if (IS_CHERRYVIEW(dev)) { - *stolen = chv_get_stolen_size(snb_gmch_ctl); - gtt_size = chv_get_total_gtt_size(snb_gmch_ctl); + ggtt->stolen_size = chv_get_stolen_size(snb_gmch_ctl); + ggtt->size = chv_get_total_gtt_size(snb_gmch_ctl); } else { - *stolen = gen8_get_stolen_size(snb_gmch_ctl); - gtt_size = gen8_get_total_gtt_size(snb_gmch_ctl); + ggtt->stolen_size = gen8_get_stolen_size(snb_gmch_ctl); + ggtt->size = gen8_get_total_gtt_size(snb_gmch_ctl); } - *gtt_total = (gtt_size / sizeof(gen8_pte_t)) << PAGE_SHIFT; + ggtt->base.total = (ggtt->size / sizeof(gen8_pte_t)) << PAGE_SHIFT; if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) chv_setup_private_ppat(dev_priv); else bdw_setup_private_ppat(dev_priv); - ret = ggtt_probe_common(dev, gtt_size); - - dev_priv->ggtt.base.clear_range = gen8_ggtt_clear_range; - dev_priv->ggtt.base.insert_entries = gen8_ggtt_insert_entries; - dev_priv->ggtt.base.bind_vma = ggtt_bind_vma; - dev_priv->ggtt.base.unbind_vma = ggtt_unbind_vma; + ret = ggtt_probe_common(dev, ggtt->size); + ggtt->base.clear_range = gen8_ggtt_clear_range; if (IS_CHERRYVIEW(dev_priv)) - dev_priv->ggtt.base.insert_entries = gen8_ggtt_insert_entries__BKL; + ggtt->base.insert_entries = gen8_ggtt_insert_entries__BKL; + else + ggtt->base.insert_entries = gen8_ggtt_insert_entries; + ggtt->base.bind_vma = ggtt_bind_vma; + ggtt->base.unbind_vma = ggtt_unbind_vma; + return ret; } -static int gen6_gmch_probe(struct drm_device *dev, - u64 *gtt_total, - size_t *stolen, - phys_addr_t *mappable_base, - u64 *mappable_end) +static int gen6_gmch_probe(struct i915_ggtt *ggtt) { - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned int gtt_size; + struct drm_device *dev = ggtt->base.dev; u16 snb_gmch_ctl; int ret; - *mappable_base = pci_resource_start(dev->pdev, 2); - *mappable_end = pci_resource_len(dev->pdev, 2); + ggtt->mappable_base = pci_resource_start(dev->pdev, 2); + ggtt->mappable_end = pci_resource_len(dev->pdev, 2); /* 64/512MB is the current min/max we actually know of, but this is just * a coarse sanity check. */ - if ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) { - DRM_ERROR("Unknown GMADR size (%llx)\n", *mappable_end); + if ((ggtt->mappable_end < (64<<20) || (ggtt->mappable_end > (512<<20)))) { + DRM_ERROR("Unknown GMADR size (%llx)\n", ggtt->mappable_end); return -ENXIO; } @@ -3111,17 +3103,16 @@ static int gen6_gmch_probe(struct drm_device *dev, pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40)); pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); - *stolen = gen6_get_stolen_size(snb_gmch_ctl); - - gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); - *gtt_total = (gtt_size / sizeof(gen6_pte_t)) << PAGE_SHIFT; + ggtt->stolen_size = gen6_get_stolen_size(snb_gmch_ctl); + ggtt->size = gen6_get_total_gtt_size(snb_gmch_ctl); + ggtt->base.total = (ggtt->size / sizeof(gen6_pte_t)) << PAGE_SHIFT; - ret = ggtt_probe_common(dev, gtt_size); + ret = ggtt_probe_common(dev, ggtt->size); - dev_priv->ggtt.base.clear_range = gen6_ggtt_clear_range; - dev_priv->ggtt.base.insert_entries = gen6_ggtt_insert_entries; - dev_priv->ggtt.base.bind_vma = ggtt_bind_vma; - dev_priv->ggtt.base.unbind_vma = ggtt_unbind_vma; + ggtt->base.clear_range = gen6_ggtt_clear_range; + ggtt->base.insert_entries = gen6_ggtt_insert_entries; + ggtt->base.bind_vma = ggtt_bind_vma; + ggtt->base.unbind_vma = ggtt_unbind_vma; return ret; } @@ -3134,12 +3125,9 @@ static void gen6_gmch_remove(struct i915_address_space *vm) free_scratch_page(vm->dev, vm->scratch_page); } -static int i915_gmch_probe(struct drm_device *dev, - u64 *gtt_total, - size_t *stolen, - phys_addr_t *mappable_base, - u64 *mappable_end) +static int i915_gmch_probe(struct i915_ggtt *ggtt) { + struct drm_device *dev = ggtt->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int ret; @@ -3149,15 +3137,16 @@ static int i915_gmch_probe(struct drm_device *dev, return -EIO; } - intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end); + intel_gtt_get(&ggtt->base.total, &ggtt->stolen_size, + &ggtt->mappable_base, &ggtt->mappable_end); - dev_priv->ggtt.do_idle_maps = needs_idle_maps(dev_priv->dev); - dev_priv->ggtt.base.insert_entries = i915_ggtt_insert_entries; - dev_priv->ggtt.base.clear_range = i915_ggtt_clear_range; - dev_priv->ggtt.base.bind_vma = ggtt_bind_vma; - dev_priv->ggtt.base.unbind_vma = ggtt_unbind_vma; + ggtt->do_idle_maps = needs_idle_maps(dev_priv->dev); + ggtt->base.insert_entries = i915_ggtt_insert_entries; + ggtt->base.clear_range = i915_ggtt_clear_range; + ggtt->base.bind_vma = ggtt_bind_vma; + ggtt->base.unbind_vma = ggtt_unbind_vma; - if (unlikely(dev_priv->ggtt.do_idle_maps)) + if (unlikely(ggtt->do_idle_maps)) DRM_INFO("applying Ironlake quirks for intel_iommu\n"); return 0; @@ -3198,8 +3187,7 @@ int i915_gem_gtt_init(struct drm_device *dev) ggtt->base.dev = dev; ggtt->base.is_ggtt = true; - ret = ggtt->probe(dev, &ggtt->base.total, &ggtt->stolen_size, - &ggtt->mappable_base, &ggtt->mappable_end); + ret = ggtt->probe(ggtt); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 2906bb1..d804be0 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -346,6 +346,7 @@ struct i915_ggtt { size_t stolen_usable_size; /* Total size minus BIOS reserved */ size_t stolen_reserved_base; size_t stolen_reserved_size; + size_t size; /* Total size of Global GTT */ 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 */ @@ -357,9 +358,7 @@ struct i915_ggtt { int mtrr; - int (*probe)(struct drm_device *dev, u64 *gtt_total, - size_t *stolen, phys_addr_t *mappable_base, - u64 *mappable_end); + int (*probe)(struct i915_ggtt *ggtt); }; struct i915_hw_ppgtt { -- cgit v0.10.2 From c890e2d5313e8e8f4fb54258dc2bbb2c7dd901ce Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 18 Mar 2016 10:42:59 +0200 Subject: drm/i915: Codify our assumption that the Global GTT is <= 4GiB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Throughout the code base, we use u32 for offsets into the global GTT. If we ever see any hardware with a larger GGTT, then we run the real risk of silent corruption. So test for our assumption up front so that we have a nice reminder should the time come when it fails. Signed-off-by: Chris Wilson Cc: Ville Syrjälä Cc: Daniel Vetter Signed-off-by: Joonas Lahtinen [Rebased and changed 1ull -> 1ULL, cut 80 char line] Reviewed-by: Tvrtko Ursulin Reviewed-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1458290579-27783-1-git-send-email-joonas.lahtinen@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 799576e..0715bb7 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3191,6 +3191,14 @@ int i915_gem_gtt_init(struct drm_device *dev) if (ret) return ret; + if ((ggtt->base.total - 1) >> 32) { + DRM_ERROR("We never expected a Global GTT with more than 32bits" + "of address space! Found %lldM!\n", + ggtt->base.total >> 20); + ggtt->base.total = 1ULL << 32; + ggtt->mappable_end = min(ggtt->mappable_end, ggtt->base.total); + } + /* * Initialise stolen early so that we may reserve preallocated * objects for the BIOS to KMS transition. -- cgit v0.10.2 From d15d7538c6d210b2a10df94d131b70b025ee9cd2 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 18 Mar 2016 10:46:10 +0200 Subject: drm/i915: Tune down init error message due to failure injection Atm, in case failure injection forces an error the subsequent "*ERROR* failed to init modeset" error message will make automated tests (CI) report this event as a breakage even though the event is expected. To fix this print the error message with debug log level in this case. While at it print the error message for any init failure and change it to """ Device initialization failed (errno) Please file a bug at https://bugs.freedesktop.org/enter_bug.cgi?product=DRI against DRM/Intel providing the dmesg log by booting with drm.debug=0xf """ and export a helper printing error messages using this same format. A follow-up patch will convert all uses of DRM_ERROR reporting a user facing problem to use this new helper instead. v2: - Include the problematic error message in the commit log, add a request to file an fdo bug to the message (Chris) v3: - Include the new error message too in the commit log, make the fdo link more precise and print part of the message with info log level (Chris) v4: (Chris) - Use dev_printk instead of DRM_ERROR/INFO and use NOTICE instead of INFO loglevel - Export a helper for printing user facing error messages v5: - Keep the DRM_ERROR message prefix used by piglit-igt/CI to filter relevant dmesg lines - Use dev_notice(), instead of dev_printk(KERN_NOTICE,...) v6: - Print the fdo bug link only once (Chris) CC: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458290770-15480-1-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 3565163..3f439a0 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -66,6 +66,47 @@ bool __i915_inject_load_failure(const char *func, int line) return false; } +#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI" +#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \ + "providing the dmesg log by booting with drm.debug=0xf" + +void +__i915_printk(struct drm_i915_private *dev_priv, const char *level, + const char *fmt, ...) +{ + static bool shown_bug_once; + struct device *dev = dev_priv->dev->dev; + bool is_error = level[1] <= KERN_ERR[1]; + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV", + __builtin_return_address(0), &vaf); + + if (is_error && !shown_bug_once) { + dev_notice(dev, "%s", FDO_BUG_MSG); + shown_bug_once = true; + } + + va_end(args); +} + +static bool i915_error_injected(struct drm_i915_private *dev_priv) +{ + return i915.inject_load_failure && + i915_load_fail_count == i915.inject_load_failure; +} + +#define i915_load_error(dev_priv, fmt, ...) \ + __i915_printk(dev_priv, \ + i915_error_injected(dev_priv) ? KERN_DEBUG : KERN_ERR, \ + fmt, ##__VA_ARGS__) + static int i915_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -972,8 +1013,6 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, if (i915_inject_load_failure()) return -ENODEV; - dev_priv->dev = dev; - /* Setup the write-once "constant" device info */ device_info = (struct intel_device_info *)&dev_priv->info; memcpy(device_info, info, sizeof(dev_priv->info)); @@ -1303,6 +1342,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) return -ENOMEM; dev->dev_private = dev_priv; + /* Must be set before calling __i915_printk */ + dev_priv->dev = dev; ret = i915_driver_init_early(dev_priv, dev, (struct intel_device_info *)flags); @@ -1332,10 +1373,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } ret = i915_load_modeset_init(dev); - if (ret < 0) { - DRM_ERROR("failed to init modeset\n"); + if (ret < 0) goto out_cleanup_vblank; - } i915_driver_register(dev_priv); @@ -1357,6 +1396,8 @@ out_runtime_pm_put: out_free_priv: kfree(dev_priv); + i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret); + return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b1d6554..f330a53 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2696,6 +2696,13 @@ extern int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state); extern int i915_resume_switcheroo(struct drm_device *dev); /* i915_dma.c */ +void __printf(3, 4) +__i915_printk(struct drm_i915_private *dev_priv, const char *level, + const char *fmt, ...); + +#define i915_report_error(dev_priv, fmt, ...) \ + __i915_printk(dev_priv, KERN_ERR, fmt, ##__VA_ARGS__) + extern int i915_driver_load(struct drm_device *, unsigned long flags); extern int i915_driver_unload(struct drm_device *); extern int i915_driver_open(struct drm_device *dev, struct drm_file *file); -- cgit v0.10.2 From a6573e1f54b713f837ac08d87961f610c63246ba Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Sun, 6 Mar 2016 23:30:26 -0800 Subject: drm/i915: Add TIMESTAMP to register whitelist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed for the Mesa Vulkan driver on Haswell. Signed-off-by: Jordan Justen Cc: Kristian Høgsberg Cc: Kenneth Graunke Reviewed-by: Francisco Jerez Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1457335830-30923-2-git-send-email-jordan.l.justen@intel.com diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 2c50142..a5ebe9a 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -444,6 +444,7 @@ static const struct drm_i915_reg_descriptor gen7_render_regs[] = { REG64(CL_PRIMITIVES_COUNT), REG64(PS_INVOCATION_COUNT), REG64(PS_DEPTH_COUNT), + REG64_IDX(RING_TIMESTAMP, RENDER_RING_BASE), REG32(OACONTROL), /* Only allowed for LRI and SRM. See below. */ REG64(MI_PREDICATE_SRC0), REG64(MI_PREDICATE_SRC1), -- cgit v0.10.2 From 361b027bc6ae8501756829043ac98e42e40494f8 Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Sun, 6 Mar 2016 23:30:27 -0800 Subject: drm/i915: Use an array of register tables in command parser For Haswell, we will want another table of registers while retaining the large common table of whitelisted registers shared by all gen7 devices. Signed-off-by: Jordan Justen Reviewed-by: Francisco Jerez [danvet: Pipe patch through sed -e 's/\/engine/g' to make it apply.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index a5ebe9a..ce753d3 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -501,6 +501,32 @@ static const struct drm_i915_reg_descriptor hsw_master_regs[] = { #undef REG64 #undef REG32 +struct drm_i915_reg_table { + const struct drm_i915_reg_descriptor *regs; + int num_regs; + bool master; +}; + +static const struct drm_i915_reg_table ivb_render_reg_tables[] = { + { gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false }, + { ivb_master_regs, ARRAY_SIZE(ivb_master_regs), true }, +}; + +static const struct drm_i915_reg_table ivb_blt_reg_tables[] = { + { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs), false }, + { ivb_master_regs, ARRAY_SIZE(ivb_master_regs), true }, +}; + +static const struct drm_i915_reg_table hsw_render_reg_tables[] = { + { gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false }, + { hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true }, +}; + +static const struct drm_i915_reg_table hsw_blt_reg_tables[] = { + { gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs), false }, + { hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true }, +}; + static u32 gen7_render_get_cmd_length_mask(u32 cmd_header) { u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT; @@ -614,9 +640,16 @@ static bool check_sorted(int ring_id, static bool validate_regs_sorted(struct intel_engine_cs *engine) { - return check_sorted(engine->id, engine->reg_table, engine->reg_count) && - check_sorted(engine->id, engine->master_reg_table, - engine->master_reg_count); + int i; + const struct drm_i915_reg_table *table; + + for (i = 0; i < engine->reg_table_count; i++) { + table = &engine->reg_tables[i]; + if (!check_sorted(engine->id, table->regs, table->num_regs)) + return false; + } + + return true; } struct cmd_node { @@ -711,15 +744,12 @@ int i915_cmd_parser_init_ring(struct intel_engine_cs *engine) cmd_table_count = ARRAY_SIZE(gen7_render_cmds); } - engine->reg_table = gen7_render_regs; - engine->reg_count = ARRAY_SIZE(gen7_render_regs); - if (IS_HASWELL(engine->dev)) { - engine->master_reg_table = hsw_master_regs; - engine->master_reg_count = ARRAY_SIZE(hsw_master_regs); + engine->reg_tables = hsw_render_reg_tables; + engine->reg_table_count = ARRAY_SIZE(hsw_render_reg_tables); } else { - engine->master_reg_table = ivb_master_regs; - engine->master_reg_count = ARRAY_SIZE(ivb_master_regs); + engine->reg_tables = ivb_render_reg_tables; + engine->reg_table_count = ARRAY_SIZE(ivb_render_reg_tables); } engine->get_cmd_length_mask = gen7_render_get_cmd_length_mask; @@ -738,15 +768,12 @@ int i915_cmd_parser_init_ring(struct intel_engine_cs *engine) cmd_table_count = ARRAY_SIZE(gen7_blt_cmds); } - engine->reg_table = gen7_blt_regs; - engine->reg_count = ARRAY_SIZE(gen7_blt_regs); - if (IS_HASWELL(engine->dev)) { - engine->master_reg_table = hsw_master_regs; - engine->master_reg_count = ARRAY_SIZE(hsw_master_regs); + engine->reg_tables = hsw_blt_reg_tables; + engine->reg_table_count = ARRAY_SIZE(hsw_blt_reg_tables); } else { - engine->master_reg_table = ivb_master_regs; - engine->master_reg_count = ARRAY_SIZE(ivb_master_regs); + engine->reg_tables = ivb_blt_reg_tables; + engine->reg_table_count = ARRAY_SIZE(ivb_blt_reg_tables); } engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask; @@ -849,12 +876,31 @@ static const struct drm_i915_reg_descriptor * find_reg(const struct drm_i915_reg_descriptor *table, int count, u32 addr) { - if (table) { - int i; + int i; + + for (i = 0; i < count; i++) { + if (i915_mmio_reg_offset(table[i].addr) == addr) + return &table[i]; + } - for (i = 0; i < count; i++) { - if (i915_mmio_reg_offset(table[i].addr) == addr) - return &table[i]; + return NULL; +} + +static const struct drm_i915_reg_descriptor * +find_reg_in_tables(const struct drm_i915_reg_table *tables, + int count, bool is_master, u32 addr) +{ + int i; + const struct drm_i915_reg_table *table; + const struct drm_i915_reg_descriptor *reg; + + for (i = 0; i < count; i++) { + table = &tables[i]; + if (!table->master || is_master) { + reg = find_reg(table->regs, table->num_regs, + addr); + if (reg != NULL) + return reg; } } @@ -1005,13 +1051,10 @@ static bool check_cmd(const struct intel_engine_cs *engine, offset += step) { const u32 reg_addr = cmd[offset] & desc->reg.mask; const struct drm_i915_reg_descriptor *reg = - find_reg(engine->reg_table, engine->reg_count, - reg_addr); - - if (!reg && is_master) - reg = find_reg(engine->master_reg_table, - engine->master_reg_count, - reg_addr); + find_reg_in_tables(engine->reg_tables, + engine->reg_table_count, + is_master, + reg_addr); if (!reg) { DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n", diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 3e40f7b..221a946 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -123,7 +123,7 @@ struct intel_ringbuffer { }; struct intel_context; -struct drm_i915_reg_descriptor; +struct drm_i915_reg_table; /* * we use a single page to load ctx workarounds so all of these @@ -331,15 +331,8 @@ struct intel_engine_cs { /* * Table of registers allowed in commands that read/write registers. */ - const struct drm_i915_reg_descriptor *reg_table; - int reg_count; - - /* - * Table of registers allowed in commands that read/write registers, but - * only from the DRM master. - */ - const struct drm_i915_reg_descriptor *master_reg_table; - int master_reg_count; + const struct drm_i915_reg_table *reg_tables; + int reg_table_count; /* * Returns the bitmask for the length field of the specified command. -- cgit v0.10.2 From 99c5aeca94a506a2b279022fae5de3f8606730bd Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Sun, 6 Mar 2016 23:30:28 -0800 Subject: drm/i915: Move Haswell registers to separate whitelist table Now that we can whitelist registers only on Haswell, move HSW_SCRATCH1 and HSW_ROW_CHICKEN3 into a separate Haswell only table. Signed-off-by: Jordan Justen Cc: Francisco Jerez Reviewed-by: Francisco Jerez Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1457335830-30923-4-git-send-email-jordan.l.justen@intel.com diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index ce753d3..6c81c70 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -472,6 +472,9 @@ static const struct drm_i915_reg_descriptor gen7_render_regs[] = { REG32(GEN7_L3SQCREG1), REG32(GEN7_L3CNTLREG2), REG32(GEN7_L3CNTLREG3), +}; + +static const struct drm_i915_reg_descriptor hsw_render_regs[] = { REG32(HSW_SCRATCH1, .mask = ~HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE, .value = 0), @@ -519,6 +522,7 @@ static const struct drm_i915_reg_table ivb_blt_reg_tables[] = { static const struct drm_i915_reg_table hsw_render_reg_tables[] = { { gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false }, + { hsw_render_regs, ARRAY_SIZE(hsw_render_regs), false }, { hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true }, }; -- cgit v0.10.2 From 1b85066bb1332e4298e533b7f15e04d82990ceaf Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Sun, 6 Mar 2016 23:30:29 -0800 Subject: drm/i915: Add Haswell CS GPR registers to whitelist This is needed for the Mesa Vulkan driver on Haswell. Signed-off-by: Jordan Justen Reviewed-by: Francisco Jerez Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1457335830-30923-5-git-send-email-jordan.l.justen@intel.com diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 6c81c70..546dfcc 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -475,6 +475,22 @@ static const struct drm_i915_reg_descriptor gen7_render_regs[] = { }; static const struct drm_i915_reg_descriptor hsw_render_regs[] = { + REG64_IDX(HSW_CS_GPR, 0), + REG64_IDX(HSW_CS_GPR, 1), + REG64_IDX(HSW_CS_GPR, 2), + REG64_IDX(HSW_CS_GPR, 3), + REG64_IDX(HSW_CS_GPR, 4), + REG64_IDX(HSW_CS_GPR, 5), + REG64_IDX(HSW_CS_GPR, 6), + REG64_IDX(HSW_CS_GPR, 7), + REG64_IDX(HSW_CS_GPR, 8), + REG64_IDX(HSW_CS_GPR, 9), + REG64_IDX(HSW_CS_GPR, 10), + REG64_IDX(HSW_CS_GPR, 11), + REG64_IDX(HSW_CS_GPR, 12), + REG64_IDX(HSW_CS_GPR, 13), + REG64_IDX(HSW_CS_GPR, 14), + REG64_IDX(HSW_CS_GPR, 15), REG32(HSW_SCRATCH1, .mask = ~HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE, .value = 0), diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 264885f..06fb589 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -588,6 +588,10 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define GEN7_GPGPU_DISPATCHDIMY _MMIO(0x2504) #define GEN7_GPGPU_DISPATCHDIMZ _MMIO(0x2508) +/* There are the 16 64-bit CS General Purpose Registers */ +#define HSW_CS_GPR(n) _MMIO(0x2600 + (n) * 8) +#define HSW_CS_GPR_UDW(n) _MMIO(0x2600 + (n) * 8 + 4) + #define OACONTROL _MMIO(0x2360) #define _GEN7_PIPEA_DE_LOAD_SL 0x70068 -- cgit v0.10.2 From 6cf0716c0321344fdc72205d590e968e53492088 Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Sun, 6 Mar 2016 23:30:30 -0800 Subject: drm/i915: Bump command parser version for new whitelisted registers Signed-off-by: Jordan Justen Reviewed-by: Francisco Jerez Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1457335830-30923-6-git-send-email-jordan.l.justen@intel.com diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 546dfcc..a337f33 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1287,6 +1287,7 @@ int i915_cmd_parser_get_version(void) * 3. Allow access to the GPGPU_THREADS_DISPATCHED register. * 4. L3 atomic chicken bits of HSW_SCRATCH1 and HSW_ROW_CHICKEN3. * 5. GPGPU dispatch compute indirect registers. + * 6. TIMESTAMP register and Haswell CS GPR registers */ - return 5; + return 6; } -- cgit v0.10.2 From 1844a66b98800b3cfd92aea4e801641304ac07d7 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 16 Mar 2016 13:31:30 -0700 Subject: drm/i915: add another virtual PCH bridge for passthrough support Some configs use the P2X type but some use a P3X type PCH, so add that to the detect_pch function so things work correctly. Signed-off-by: Jesse Barnes Reviewed-by: Allen Kay Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1458160290-16710-1-git-send-email-jbarnes@virtuousgeek.org diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3648b73..2a076b0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -504,6 +504,7 @@ void intel_detect_pch(struct drm_device *dev) WARN_ON(!IS_SKYLAKE(dev) && !IS_KABYLAKE(dev)); } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) || + (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) || ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) && pch->subsystem_vendor == 0x1af4 && pch->subsystem_device == 0x1100)) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f330a53..8727746 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2665,6 +2665,7 @@ struct drm_i915_cmd_table { #define INTEL_PCH_SPT_DEVICE_ID_TYPE 0xA100 #define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE 0x9D00 #define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100 +#define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000 #define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */ #define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type) -- cgit v0.10.2 From bc58be6058d65f05c5bce8c562ec196e70760a9a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 18 Mar 2016 17:05:39 +0200 Subject: drm/i915: split get/set pipe timings to timings and src size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prep work for DSI transcoders. No functional changes. v2: call split functions at a higher level (Ville) Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/8d67a05eb869a7b0c4ee17c2d3b0b029de34851c.1458313400.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 74b0165..a356a0a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -96,6 +96,7 @@ static int intel_framebuffer_init(struct drm_device *dev, struct drm_i915_gem_object *obj); static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc); static void intel_set_pipe_timings(struct intel_crtc *intel_crtc); +static void intel_set_pipe_src_size(struct intel_crtc *intel_crtc); static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, struct intel_link_m_n *m_n, struct intel_link_m_n *m2_n2); @@ -4827,6 +4828,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) intel_dp_set_m_n(intel_crtc, M1_N1); intel_set_pipe_timings(intel_crtc); + intel_set_pipe_src_size(intel_crtc); if (intel_crtc->config->has_pch_encoder) { intel_cpu_transcoder_set_m_n(intel_crtc, @@ -4913,6 +4915,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) intel_dp_set_m_n(intel_crtc, M1_N1); intel_set_pipe_timings(intel_crtc); + intel_set_pipe_src_size(intel_crtc); if (intel_crtc->config->cpu_transcoder != TRANSCODER_EDP) { I915_WRITE(PIPE_MULT(intel_crtc->config->cpu_transcoder), @@ -6120,6 +6123,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) intel_dp_set_m_n(intel_crtc, M1_N1); intel_set_pipe_timings(intel_crtc); + intel_set_pipe_src_size(intel_crtc); if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -6192,6 +6196,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) intel_dp_set_m_n(intel_crtc, M1_N1); intel_set_pipe_timings(intel_crtc); + intel_set_pipe_src_size(intel_crtc); i9xx_set_pipeconf(intel_crtc); @@ -7719,6 +7724,14 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) (pipe == PIPE_B || pipe == PIPE_C)) I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder))); +} + +static void intel_set_pipe_src_size(struct intel_crtc *intel_crtc) +{ + struct drm_device *dev = intel_crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_crtc->pipe; + /* pipesrc controls the size that is scaled from, which should * always be the user's requested size. */ @@ -7760,6 +7773,14 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc, pipe_config->base.adjusted_mode.crtc_vtotal += 1; pipe_config->base.adjusted_mode.crtc_vblank_end += 1; } +} + +static void intel_get_pipe_src_size(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 tmp; tmp = I915_READ(PIPESRC(crtc->pipe)); pipe_config->pipe_src_h = (tmp & 0xffff) + 1; @@ -8125,6 +8146,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE; intel_get_pipe_timings(crtc, pipe_config); + intel_get_pipe_src_size(crtc, pipe_config); i9xx_get_pfit_config(crtc, pipe_config); @@ -9364,6 +9386,7 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, } intel_get_pipe_timings(crtc, pipe_config); + intel_get_pipe_src_size(crtc, pipe_config); ironlake_get_pfit_config(crtc, pipe_config); @@ -9972,6 +9995,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, haswell_get_ddi_port_state(crtc, pipe_config); intel_get_pipe_timings(crtc, pipe_config); + intel_get_pipe_src_size(crtc, pipe_config); if (INTEL_INFO(dev)->gen >= 9) { skl_init_scalers(dev, crtc, pipe_config); -- cgit v0.10.2 From 391bf04862feab95beffcb3634e8aba8961f4d35 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 18 Mar 2016 17:05:40 +0200 Subject: drm/i915: split set pipeconf to pipeconf, pipemisc, pipe_gamma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prep work for DSI transcoders. No functional changes. v2: call split functions at a higher level (Ville) Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/981252d5d5f82d009d73e1b2ae93d9ab7bee8de8.1458313400.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a356a0a..eece50e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -102,6 +102,8 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, struct intel_link_m_n *m2_n2); static void ironlake_set_pipeconf(struct drm_crtc *crtc); static void haswell_set_pipeconf(struct drm_crtc *crtc); +static void haswell_set_pipe_gamma(struct drm_crtc *crtc); +static void haswell_set_pipemisc(struct drm_crtc *crtc); static void intel_set_pipe_csc(struct drm_crtc *crtc); static void vlv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); @@ -4928,6 +4930,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) } haswell_set_pipeconf(crtc); + haswell_set_pipe_gamma(crtc); + haswell_set_pipemisc(crtc); intel_set_pipe_csc(crtc); @@ -8764,16 +8768,12 @@ static void intel_set_pipe_csc(struct drm_crtc *crtc) static void haswell_set_pipeconf(struct drm_crtc *crtc) { - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = crtc->dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; - uint32_t val; + u32 val = 0; - val = 0; - - if (IS_HASWELL(dev) && intel_crtc->config->dither) + if (IS_HASWELL(dev_priv) && intel_crtc->config->dither) val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP); if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) @@ -8783,12 +8783,24 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc) I915_WRITE(PIPECONF(cpu_transcoder), val); POSTING_READ(PIPECONF(cpu_transcoder)); +} + +static void haswell_set_pipe_gamma(struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT); POSTING_READ(GAMMA_MODE(intel_crtc->pipe)); +} + +static void haswell_set_pipemisc(struct drm_crtc *crtc) +{ + struct drm_i915_private *dev_priv = crtc->dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - if (IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) { - val = 0; + if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) { + u32 val = 0; switch (intel_crtc->config->pipe_bpp) { case 18: @@ -8811,7 +8823,7 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc) if (intel_crtc->config->dither) val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP; - I915_WRITE(PIPEMISC(pipe), val); + I915_WRITE(PIPEMISC(intel_crtc->pipe), val); } } -- cgit v0.10.2 From cf30429e9420556399aab92995ff23e15c22de6b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 18 Mar 2016 17:05:41 +0200 Subject: drm/i915: abstract get config for cpu transcoder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes it neater to add the same for DSI transcoder. No functional changes. v2: rename to hsw_get_transcoder_state and add a comment about grabbing power reference (Ville) Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/c473a73d69dcd61584419d85ff7908a8717b0594.1458313400.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index eece50e..98d8b56 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9910,6 +9910,53 @@ static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv, pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id); } +static bool hsw_get_transcoder_state(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config, + unsigned long *power_domain_mask) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum intel_display_power_domain power_domain; + u32 tmp; + + pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; + + /* + * XXX: Do intel_display_power_get_if_enabled before reading this (for + * consistency and less surprising code; it's in always on power). + */ + tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); + if (tmp & TRANS_DDI_FUNC_ENABLE) { + enum pipe trans_edp_pipe; + switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { + default: + WARN(1, "unknown pipe linked to edp transcoder\n"); + case TRANS_DDI_EDP_INPUT_A_ONOFF: + case TRANS_DDI_EDP_INPUT_A_ON: + trans_edp_pipe = PIPE_A; + break; + case TRANS_DDI_EDP_INPUT_B_ONOFF: + trans_edp_pipe = PIPE_B; + break; + case TRANS_DDI_EDP_INPUT_C_ONOFF: + trans_edp_pipe = PIPE_C; + break; + } + + if (trans_edp_pipe == crtc->pipe) + pipe_config->cpu_transcoder = TRANSCODER_EDP; + } + + power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + return false; + *power_domain_mask |= BIT(power_domain); + + tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder)); + + return tmp & PIPECONF_ENABLE; +} + static void haswell_get_ddi_port_state(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { @@ -9960,48 +10007,18 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, struct drm_i915_private *dev_priv = dev->dev_private; enum intel_display_power_domain power_domain; unsigned long power_domain_mask; - uint32_t tmp; - bool ret; + bool active; power_domain = POWER_DOMAIN_PIPE(crtc->pipe); if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; power_domain_mask = BIT(power_domain); - ret = false; - - pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe; pipe_config->shared_dpll = NULL; - tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)); - if (tmp & TRANS_DDI_FUNC_ENABLE) { - enum pipe trans_edp_pipe; - switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { - default: - WARN(1, "unknown pipe linked to edp transcoder\n"); - case TRANS_DDI_EDP_INPUT_A_ONOFF: - case TRANS_DDI_EDP_INPUT_A_ON: - trans_edp_pipe = PIPE_A; - break; - case TRANS_DDI_EDP_INPUT_B_ONOFF: - trans_edp_pipe = PIPE_B; - break; - case TRANS_DDI_EDP_INPUT_C_ONOFF: - trans_edp_pipe = PIPE_C; - break; - } - - if (trans_edp_pipe == crtc->pipe) - pipe_config->cpu_transcoder = TRANSCODER_EDP; - } + active = hsw_get_transcoder_state(crtc, pipe_config, &power_domain_mask); - power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder); - if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) - goto out; - power_domain_mask |= BIT(power_domain); - - tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder)); - if (!(tmp & PIPECONF_ENABLE)) + if (!active) goto out; haswell_get_ddi_port_state(crtc, pipe_config); @@ -10038,13 +10055,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, pipe_config->pixel_multiplier = 1; } - ret = true; - out: for_each_power_domain(power_domain, power_domain_mask) intel_display_power_put(dev_priv, power_domain); - return ret; + return active; } static void i845_update_cursor(struct drm_crtc *crtc, u32 base, -- cgit v0.10.2 From 4d1de97568321828b9e63522c60ee77d23925471 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 18 Mar 2016 17:05:42 +0200 Subject: drm/i915/bxt: add dsi transcoders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The BXT display connections have DSI transcoders A and C that can be muxed to any pipe, not unlike the eDP transcoder. Add the notion of DSI transcoders. The "normal" transcoders A, B and C are not used with BXT DSI, so care must be taken to avoid accessing those registers with DSI transcoders in the hardware state readout, modeset, and generally everywhere. v2: addressing comments by Ville: - rename the dsi get config function to hsw_get_dsi_transcoder_state - rebase onto the higher level split of pipe/transcoder functions - use more has_dsi_encoder as we can now because of the above, with no need to look at the transcoder so much - rename IS_DSI_TRANSCODER to transcoder_is_dsi - use the above a bit more instead of comparing to < TRANSCODER_EDP Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/299740536b7941e31b2744f3ce34f7afe936a771.1458313400.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8727746..efca534 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -127,6 +127,8 @@ enum transcoder { TRANSCODER_B, TRANSCODER_C, TRANSCODER_EDP, + TRANSCODER_DSI_A, + TRANSCODER_DSI_C, I915_MAX_TRANSCODERS }; @@ -141,11 +143,20 @@ static inline const char *transcoder_name(enum transcoder transcoder) return "C"; case TRANSCODER_EDP: return "EDP"; + case TRANSCODER_DSI_A: + return "DSI A"; + case TRANSCODER_DSI_C: + return "DSI C"; default: return ""; } } +static inline bool transcoder_is_dsi(enum transcoder transcoder) +{ + return transcoder == TRANSCODER_DSI_A || transcoder == TRANSCODER_DSI_C; +} + /* * I915_MAX_PLANES in the enum below is the maximum (across all platforms) * number of planes per CRTC. Not all platforms really have this many planes, @@ -196,6 +207,8 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_B, POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_EDP, + POWER_DOMAIN_TRANSCODER_DSI_A, + POWER_DOMAIN_TRANSCODER_DSI_C, POWER_DOMAIN_PORT_DDI_A_LANES, POWER_DOMAIN_PORT_DDI_B_LANES, POWER_DOMAIN_PORT_DDI_C_LANES, diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 91654ff..e6c3a80 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1061,6 +1061,8 @@ void intel_ddi_set_pipe_settings(struct drm_crtc *crtc) uint32_t temp; if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP_MST) { + WARN_ON(transcoder_is_dsi(cpu_transcoder)); + temp = TRANS_MSA_SYNC_CLK; switch (intel_crtc->config->pipe_bpp) { case 18: @@ -1942,6 +1944,10 @@ void intel_ddi_get_config(struct intel_encoder *encoder, struct intel_hdmi *intel_hdmi; u32 temp, flags = 0; + /* XXX: DSI transcoder paranoia */ + if (WARN_ON(transcoder_is_dsi(cpu_transcoder))) + return; + temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); if (temp & TRANS_DDI_PHSYNC) flags |= DRM_MODE_FLAG_PHSYNC; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 98d8b56..28ead66 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4900,6 +4900,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe, hsw_workaround_pipe; + enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc->state); @@ -4916,11 +4917,14 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) if (intel_crtc->config->has_dp_encoder) intel_dp_set_m_n(intel_crtc, M1_N1); - intel_set_pipe_timings(intel_crtc); + if (!intel_crtc->config->has_dsi_encoder) + intel_set_pipe_timings(intel_crtc); + intel_set_pipe_src_size(intel_crtc); - if (intel_crtc->config->cpu_transcoder != TRANSCODER_EDP) { - I915_WRITE(PIPE_MULT(intel_crtc->config->cpu_transcoder), + if (cpu_transcoder != TRANSCODER_EDP && + !transcoder_is_dsi(cpu_transcoder)) { + I915_WRITE(PIPE_MULT(cpu_transcoder), intel_crtc->config->pixel_multiplier - 1); } @@ -4929,7 +4933,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) &intel_crtc->config->fdi_m_n, NULL); } - haswell_set_pipeconf(crtc); + if (!intel_crtc->config->has_dsi_encoder) + haswell_set_pipeconf(crtc); + haswell_set_pipe_gamma(crtc); haswell_set_pipemisc(crtc); @@ -4972,7 +4978,10 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) dev_priv->display.initial_watermarks(pipe_config); else intel_update_watermarks(crtc); - intel_enable_pipe(intel_crtc); + + /* XXX: Do the pipe assertions at the right place for BXT DSI. */ + if (!intel_crtc->config->has_dsi_encoder) + intel_enable_pipe(intel_crtc); if (intel_crtc->config->has_pch_encoder) lpt_pch_enable(crtc); @@ -5105,7 +5114,9 @@ static void haswell_crtc_disable(struct drm_crtc *crtc) drm_crtc_vblank_off(crtc); assert_vblank_disabled(crtc); - intel_disable_pipe(intel_crtc); + /* XXX: Do the pipe assertions at the right place for BXT DSI. */ + if (!intel_crtc->config->has_dsi_encoder) + intel_disable_pipe(intel_crtc); if (intel_crtc->config->dp_encoder_is_mst) intel_ddi_set_vc_payload_alloc(crtc, false); @@ -9957,6 +9968,47 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, return tmp & PIPECONF_ENABLE; } +static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config, + unsigned long *power_domain_mask) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum intel_display_power_domain power_domain; + enum port port; + enum transcoder cpu_transcoder; + u32 tmp; + + pipe_config->has_dsi_encoder = false; + + for_each_port_masked(port, BIT(PORT_A) | BIT(PORT_C)) { + if (port == PORT_A) + cpu_transcoder = TRANSCODER_DSI_A; + else + cpu_transcoder = TRANSCODER_DSI_C; + + power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); + if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) + continue; + *power_domain_mask |= BIT(power_domain); + + /* XXX: this works for video mode only */ + tmp = I915_READ(BXT_MIPI_PORT_CTRL(port)); + if (!(tmp & DPI_ENABLE)) + continue; + + tmp = I915_READ(MIPI_CTRL(port)); + if ((tmp & BXT_PIPE_SELECT_MASK) != BXT_PIPE_SELECT(crtc->pipe)) + continue; + + pipe_config->cpu_transcoder = cpu_transcoder; + pipe_config->has_dsi_encoder = true; + break; + } + + return pipe_config->has_dsi_encoder; +} + static void haswell_get_ddi_port_state(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { @@ -10018,12 +10070,22 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, active = hsw_get_transcoder_state(crtc, pipe_config, &power_domain_mask); + if (IS_BROXTON(dev_priv)) { + bxt_get_dsi_transcoder_state(crtc, pipe_config, + &power_domain_mask); + WARN_ON(active && pipe_config->has_dsi_encoder); + if (pipe_config->has_dsi_encoder) + active = true; + } + if (!active) goto out; - haswell_get_ddi_port_state(crtc, pipe_config); + if (!pipe_config->has_dsi_encoder) { + haswell_get_ddi_port_state(crtc, pipe_config); + intel_get_pipe_timings(crtc, pipe_config); + } - intel_get_pipe_timings(crtc, pipe_config); intel_get_pipe_src_size(crtc, pipe_config); if (INTEL_INFO(dev)->gen >= 9) { @@ -10048,7 +10110,8 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) && (I915_READ(IPS_CTL) & IPS_ENABLE); - if (pipe_config->cpu_transcoder != TRANSCODER_EDP) { + if (pipe_config->cpu_transcoder != TRANSCODER_EDP && + !transcoder_is_dsi(pipe_config->cpu_transcoder)) { pipe_config->pixel_multiplier = I915_READ(PIPE_MULT(pipe_config->cpu_transcoder)) + 1; } else { @@ -15520,10 +15583,15 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - i915_reg_t reg = PIPECONF(crtc->config->cpu_transcoder); + enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; /* Clear any frame start delays used for debugging left by the BIOS */ - I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); + if (!transcoder_is_dsi(cpu_transcoder)) { + i915_reg_t reg = PIPECONF(cpu_transcoder); + + I915_WRITE(reg, + I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); + } /* restore vblank interrupts to correct state */ drm_crtc_vblank_reset(&crtc->base); @@ -16194,6 +16262,7 @@ intel_display_capture_error_state(struct drm_device *dev) error->pipe[i].stat = I915_READ(PIPESTAT(i)); } + /* Note: this does not include DSI transcoders. */ error->num_transcoders = INTEL_INFO(dev)->num_pipes; if (HAS_DDI(dev_priv->dev)) error->num_transcoders++; /* Account for eDP. */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5136eef..ba45245 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -437,7 +437,8 @@ struct intel_crtc_state { bool has_infoframe; /* CPU Transcoder for the pipe. Currently this can only differ from the - * pipe on Haswell (where we have a special eDP transcoder). */ + * pipe on Haswell and later (where we have a special eDP transcoder) + * and Broxton (where we have special DSI transcoders). */ enum transcoder cpu_transcoder; /* diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 3562bf3..1981212 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -268,6 +268,7 @@ static inline bool is_cmd_mode(struct intel_dsi *intel_dsi) static bool intel_dsi_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { + struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi, base); struct intel_connector *intel_connector = intel_dsi->attached_connector; @@ -284,6 +285,14 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder, /* DSI uses short packets for sync events, so clear mode flags for DSI */ adjusted_mode->flags = 0; + if (IS_BROXTON(dev_priv)) { + /* Dual link goes to DSI transcoder A. */ + if (intel_dsi->ports == BIT(PORT_C)) + pipe_config->cpu_transcoder = TRANSCODER_DSI_C; + else + pipe_config->cpu_transcoder = TRANSCODER_DSI_A; + } + return true; } diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 2e88a5e..d189a00 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -89,6 +89,10 @@ intel_display_power_domain_str(enum intel_display_power_domain domain) return "TRANSCODER_C"; case POWER_DOMAIN_TRANSCODER_EDP: return "TRANSCODER_EDP"; + case POWER_DOMAIN_TRANSCODER_DSI_A: + return "TRANSCODER_DSI_A"; + case POWER_DOMAIN_TRANSCODER_DSI_C: + return "TRANSCODER_DSI_C"; case POWER_DOMAIN_PORT_DDI_A_LANES: return "PORT_DDI_A_LANES"; case POWER_DOMAIN_PORT_DDI_B_LANES: @@ -419,6 +423,8 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv, BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS | \ BIT(POWER_DOMAIN_PIPE_A) | \ BIT(POWER_DOMAIN_TRANSCODER_EDP) | \ + BIT(POWER_DOMAIN_TRANSCODER_DSI_A) | \ + BIT(POWER_DOMAIN_TRANSCODER_DSI_C) | \ BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) | \ BIT(POWER_DOMAIN_PORT_DDI_A_LANES) | \ BIT(POWER_DOMAIN_PORT_DSI) | \ -- cgit v0.10.2 From 701d25b40c2e69a0b8e472a8b40a13a0b051bb43 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 18 Mar 2016 17:05:43 +0200 Subject: drm/i915/dsi: use the BIT macro for clarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/9115c0a80ad57075700e006db965dd31cc4358fc.1458313400.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 1981212..dd6f7bc 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -412,7 +412,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder) temp &= ~LANE_CONFIGURATION_MASK; temp &= ~DUAL_LINK_MODE_MASK; - if (intel_dsi->ports == ((1 << PORT_A) | (1 << PORT_C))) { + if (intel_dsi->ports == (BIT(PORT_A) | BIT(PORT_C))) { temp |= (intel_dsi->dual_link - 1) << DUAL_LINK_MODE_SHIFT; temp |= intel_crtc->pipe ? @@ -1200,14 +1200,14 @@ void intel_dsi_init(struct drm_device *dev) /* Pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI port C */ if (port == PORT_A) - intel_encoder->crtc_mask = 1 << PIPE_A; + intel_encoder->crtc_mask = BIT(PIPE_A); else - intel_encoder->crtc_mask = 1 << PIPE_B; + intel_encoder->crtc_mask = BIT(PIPE_B); if (dev_priv->vbt.dsi.config->dual_link) - intel_dsi->ports = (1 << PORT_A) | (1 << PORT_C); + intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C); else - intel_dsi->ports = 1 << port; + intel_dsi->ports = BIT(port); /* Create a DSI host (and a device) for each port. */ for_each_dsi_port(port, intel_dsi->ports) { -- cgit v0.10.2 From 2e85ab4fed5762f86ae12c0347e64b89412191ca Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 18 Mar 2016 17:05:44 +0200 Subject: drm/i915/bxt: allow dsi on any pipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BXT isn't as limited as BYT and CHT regarding DSI pipes and ports. Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/0375f1e237092d0ae3f39ecfc5702024918acbfd.1458313400.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index dd6f7bc..456676c 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -1198,8 +1198,13 @@ void intel_dsi_init(struct drm_device *dev) intel_connector->get_hw_state = intel_connector_get_hw_state; intel_connector->unregister = intel_connector_unregister; - /* Pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI port C */ - if (port == PORT_A) + /* + * On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI + * port C. BXT isn't limited like this. + */ + if (IS_BROXTON(dev_priv)) + intel_encoder->crtc_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C); + else if (port == PORT_A) intel_encoder->crtc_mask = BIT(PIPE_A); else intel_encoder->crtc_mask = BIT(PIPE_B); -- cgit v0.10.2 From 8563b1e8ef88c8bdb824ab1c00ebb7d66308fef0 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Wed, 16 Mar 2016 10:57:14 +0000 Subject: drm/i915: Extract out gamma table and CSC to their own file The moves a couple of functions programming the gamma LUT and CSC units into their own file. On generations prior to Haswell there is only a gamma LUT. From haswell on there is also a new enhanced color correction unit that isn't used yet. This is why we need to set the GAMMA_MODE register, either we're using the legacy 8bits LUT or enhanced LUTs (of 10 or 12bits). The CSC unit is only available from Haswell on. We also need to make a special case for CherryView which is recognized as a gen 8 but doesn't have the same enhanced color correction unit from Haswell on. v2: Fix access to GAMMA_MODE register on older generations than Haswell (from Matt Roper's comments) Signed-off-by: Lionel Landwerlin Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/1458125837-2576-2-git-send-email-lionel.g.landwerlin@intel.com diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 5558a03..7ffb51b 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -55,6 +55,7 @@ i915-y += intel_audio.o \ intel_atomic.o \ intel_atomic_plane.o \ intel_bios.o \ + intel_color.o \ intel_display.o \ intel_dpll_mgr.o \ intel_fbc.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index efca534..8e5527b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -629,6 +629,8 @@ struct drm_i915_display_funcs { /* render clock increase/decrease */ /* display clock increase/decrease */ /* pll clock increase/decrease */ + + void (*load_luts)(struct drm_crtc *crtc); }; enum forcewake_domain_id { diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c new file mode 100644 index 0000000..35b7f62 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_color.c @@ -0,0 +1,191 @@ +/* + * Copyright © 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "intel_drv.h" + +/* + * Set up the pipe CSC unit. + * + * Currently only full range RGB to limited range RGB conversion + * is supported, but eventually this should handle various + * RGB<->YCbCr scenarios as well. + */ +static void i9xx_load_csc_matrix(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + uint16_t coeff = 0x7800; /* 1.0 */ + + /* + * TODO: Check what kind of values actually come out of the pipe + * with these coeff/postoff values and adjust to get the best + * accuracy. Perhaps we even need to take the bpc value into + * consideration. + */ + + if (intel_crtc->config->limited_color_range) + coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */ + + I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16); + I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0); + + I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff); + I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0); + + I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0); + I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16); + + I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0); + I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0); + I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0); + + if (INTEL_INFO(dev)->gen > 6) { + uint16_t postoff = 0; + + if (intel_crtc->config->limited_color_range) + postoff = (16 * (1 << 12) / 255) & 0x1fff; + + I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff); + I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff); + I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff); + + I915_WRITE(PIPE_CSC_MODE(pipe), 0); + } else { + uint32_t mode = CSC_MODE_YUV_TO_RGB; + + if (intel_crtc->config->limited_color_range) + mode |= CSC_BLACK_SCREEN_OFFSET; + + I915_WRITE(PIPE_CSC_MODE(pipe), mode); + } +} + +void intel_color_set_csc(struct drm_crtc *crtc) +{ + i9xx_load_csc_matrix(crtc); +} + +/* Loads the palette/gamma unit for the CRTC with the prepared values. */ +static void i9xx_load_luts(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + enum pipe pipe = intel_crtc->pipe; + int i; + + if (HAS_GMCH_DISPLAY(dev)) { + if (intel_crtc->config->has_dsi_encoder) + assert_dsi_pll_enabled(dev_priv); + else + assert_pll_enabled(dev_priv, pipe); + } + + for (i = 0; i < 256; i++) { + uint32_t word = (intel_crtc->lut_r[i] << 16) | + (intel_crtc->lut_g[i] << 8) | + intel_crtc->lut_b[i]; + if (HAS_GMCH_DISPLAY(dev)) + I915_WRITE(PALETTE(pipe, i), word); + else + I915_WRITE(LGC_PALETTE(pipe, i), word); + } +} + +/* Loads the legacy palette/gamma unit for the CRTC on Haswell+. */ +static void haswell_load_luts(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + bool reenable_ips = false; + + /* + * Workaround : Do not read or write the pipe palette/gamma data while + * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. + */ + if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled && + ((I915_READ(GAMMA_MODE(intel_crtc->pipe)) & GAMMA_MODE_MODE_MASK) == + GAMMA_MODE_MODE_SPLIT)) { + hsw_disable_ips(intel_crtc); + reenable_ips = true; + } + I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT); + + i9xx_load_luts(crtc); + + if (reenable_ips) + hsw_enable_ips(intel_crtc); +} + +void intel_color_load_luts(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + /* The clocks have to be on to load the palette. */ + if (!crtc->state->active) + return; + + dev_priv->display.load_luts(crtc); +} + +void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, uint32_t start, uint32_t size) +{ + int end = (start + size > 256) ? 256 : start + size, i; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + for (i = start; i < end; i++) { + intel_crtc->lut_r[i] = red[i] >> 8; + intel_crtc->lut_g[i] = green[i] >> 8; + intel_crtc->lut_b[i] = blue[i] >> 8; + } + + intel_color_load_luts(crtc); +} + +void intel_color_init(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int i; + + drm_mode_crtc_set_gamma_size(crtc, 256); + for (i = 0; i < 256; i++) { + intel_crtc->lut_r[i] = i; + intel_crtc->lut_g[i] = i; + intel_crtc->lut_b[i] = i; + } + + if (IS_HASWELL(dev) || + (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev))) { + dev_priv->display.load_luts = haswell_load_luts; + } else { + dev_priv->display.load_luts = i9xx_load_luts; + } +} diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 28ead66..4e0695d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -102,9 +102,7 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, struct intel_link_m_n *m2_n2); static void ironlake_set_pipeconf(struct drm_crtc *crtc); static void haswell_set_pipeconf(struct drm_crtc *crtc); -static void haswell_set_pipe_gamma(struct drm_crtc *crtc); static void haswell_set_pipemisc(struct drm_crtc *crtc); -static void intel_set_pipe_csc(struct drm_crtc *crtc); static void vlv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); static void chv_prepare_pll(struct intel_crtc *crtc, @@ -1183,7 +1181,7 @@ void assert_pll(struct drm_i915_private *dev_priv, } /* XXX: the dsi pll is shared between MIPI DSI ports */ -static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state) +void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state) { u32 val; bool cur_state; @@ -1197,8 +1195,6 @@ static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state) "DSI PLL state assertion failure (expected %s, current %s)\n", onoff(state), onoff(cur_state)); } -#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true) -#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false) static void assert_fdi_tx(struct drm_i915_private *dev_priv, enum pipe pipe, bool state) @@ -3270,7 +3266,7 @@ static void intel_update_pipe_config(struct intel_crtc *crtc, pipe_config->pipe_src_w, pipe_config->pipe_src_h); if (HAS_DDI(dev)) - intel_set_pipe_csc(&crtc->base); + intel_color_set_csc(&crtc->base); /* * Update pipe size and adjust fitter if needed: the reason for this is @@ -4510,55 +4506,6 @@ void hsw_disable_ips(struct intel_crtc *crtc) intel_wait_for_vblank(dev, crtc->pipe); } -/** Loads the palette/gamma unit for the CRTC with the prepared values */ -static void intel_crtc_load_lut(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum pipe pipe = intel_crtc->pipe; - int i; - bool reenable_ips = false; - - /* The clocks have to be on to load the palette. */ - if (!crtc->state->active) - return; - - if (HAS_GMCH_DISPLAY(dev_priv->dev)) { - if (intel_crtc->config->has_dsi_encoder) - assert_dsi_pll_enabled(dev_priv); - else - assert_pll_enabled(dev_priv, pipe); - } - - /* Workaround : Do not read or write the pipe palette/gamma data while - * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. - */ - if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled && - ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) == - GAMMA_MODE_MODE_SPLIT)) { - hsw_disable_ips(intel_crtc); - reenable_ips = true; - } - - for (i = 0; i < 256; i++) { - i915_reg_t palreg; - - if (HAS_GMCH_DISPLAY(dev)) - palreg = PALETTE(pipe, i); - else - palreg = LGC_PALETTE(pipe, i); - - I915_WRITE(palreg, - (intel_crtc->lut_r[i] << 16) | - (intel_crtc->lut_g[i] << 8) | - intel_crtc->lut_b[i]); - } - - if (reenable_ips) - hsw_enable_ips(intel_crtc); -} - static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc) { if (intel_crtc->overlay) { @@ -4863,7 +4810,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) * On ILK+ LUT must be loaded before the pipe is running but with * clocks enabled */ - intel_crtc_load_lut(crtc); + intel_color_load_luts(crtc); if (dev_priv->display.initial_watermarks != NULL) dev_priv->display.initial_watermarks(intel_crtc->config); @@ -4936,10 +4883,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) if (!intel_crtc->config->has_dsi_encoder) haswell_set_pipeconf(crtc); - haswell_set_pipe_gamma(crtc); haswell_set_pipemisc(crtc); - intel_set_pipe_csc(crtc); + intel_color_set_csc(crtc); intel_crtc->active = true; @@ -4968,7 +4914,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) * On ILK+ LUT must be loaded before the pipe is running but with * clocks enabled */ - intel_crtc_load_lut(crtc); + intel_color_load_luts(crtc); intel_ddi_set_pipe_settings(crtc); if (!intel_crtc->config->has_dsi_encoder) @@ -6173,7 +6119,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) i9xx_pfit_enable(intel_crtc); - intel_crtc_load_lut(crtc); + intel_color_load_luts(crtc); intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); @@ -6228,7 +6174,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) i9xx_pfit_enable(intel_crtc); - intel_crtc_load_lut(crtc); + intel_color_load_luts(crtc); intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); @@ -8713,70 +8659,6 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc) POSTING_READ(PIPECONF(pipe)); } -/* - * Set up the pipe CSC unit. - * - * Currently only full range RGB to limited range RGB conversion - * is supported, but eventually this should handle various - * RGB<->YCbCr scenarios as well. - */ -static void intel_set_pipe_csc(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - uint16_t coeff = 0x7800; /* 1.0 */ - - /* - * TODO: Check what kind of values actually come out of the pipe - * with these coeff/postoff values and adjust to get the best - * accuracy. Perhaps we even need to take the bpc value into - * consideration. - */ - - if (intel_crtc->config->limited_color_range) - coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */ - - /* - * GY/GU and RY/RU should be the other way around according - * to BSpec, but reality doesn't agree. Just set them up in - * a way that results in the correct picture. - */ - I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16); - I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0); - - I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff); - I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0); - - I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0); - I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16); - - I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0); - I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0); - I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0); - - if (INTEL_INFO(dev)->gen > 6) { - uint16_t postoff = 0; - - if (intel_crtc->config->limited_color_range) - postoff = (16 * (1 << 12) / 255) & 0x1fff; - - I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff); - I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff); - I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff); - - I915_WRITE(PIPE_CSC_MODE(pipe), 0); - } else { - uint32_t mode = CSC_MODE_YUV_TO_RGB; - - if (intel_crtc->config->limited_color_range) - mode |= CSC_BLACK_SCREEN_OFFSET; - - I915_WRITE(PIPE_CSC_MODE(pipe), mode); - } -} - static void haswell_set_pipeconf(struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->dev->dev_private; @@ -8796,15 +8678,6 @@ static void haswell_set_pipeconf(struct drm_crtc *crtc) POSTING_READ(PIPECONF(cpu_transcoder)); } -static void haswell_set_pipe_gamma(struct drm_crtc *crtc) -{ - struct drm_i915_private *dev_priv = crtc->dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT); - POSTING_READ(GAMMA_MODE(intel_crtc->pipe)); -} - static void haswell_set_pipemisc(struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->dev->dev_private; @@ -10315,21 +10188,6 @@ static bool cursor_size_ok(struct drm_device *dev, return true; } -static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, uint32_t start, uint32_t size) -{ - int end = (start + size > 256) ? 256 : start + size, i; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - for (i = start; i < end; i++) { - intel_crtc->lut_r[i] = red[i] >> 8; - intel_crtc->lut_g[i] = green[i] >> 8; - intel_crtc->lut_b[i] = blue[i] >> 8; - } - - intel_crtc_load_lut(crtc); -} - /* VESA 640x480x72Hz mode to set on the pipe */ static struct drm_display_mode load_detect_mode = { DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664, @@ -12092,7 +11950,7 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs intel_helper_funcs = { .mode_set_base_atomic = intel_pipe_set_base_atomic, - .load_lut = intel_crtc_load_lut, + .load_lut = intel_color_load_luts, .atomic_begin = intel_begin_crtc_commit, .atomic_flush = intel_finish_crtc_commit, .atomic_check = intel_crtc_atomic_check, @@ -13825,7 +13683,7 @@ out: #undef for_each_intel_crtc_masked static const struct drm_crtc_funcs intel_crtc_funcs = { - .gamma_set = intel_crtc_gamma_set, + .gamma_set = intel_color_legacy_gamma_set, .set_config = drm_atomic_helper_set_config, .destroy = intel_crtc_destroy, .page_flip = intel_crtc_page_flip, @@ -14329,7 +14187,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) struct intel_crtc_state *crtc_state = NULL; struct drm_plane *primary = NULL; struct drm_plane *cursor = NULL; - int i, ret; + int ret; intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); if (intel_crtc == NULL) @@ -14365,13 +14223,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) if (ret) goto fail; - drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256); - for (i = 0; i < 256; i++) { - intel_crtc->lut_r[i] = i; - intel_crtc->lut_g[i] = i; - intel_crtc->lut_b[i] = i; - } - /* * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port * is hooked to pipe B. Hence we want plane A feeding pipe B. @@ -14396,6 +14247,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); + intel_color_init(&intel_crtc->base); + WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe); return; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ba45245..5d0da22 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1199,6 +1199,9 @@ void assert_pll(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); #define assert_pll_enabled(d, p) assert_pll(d, p, true) #define assert_pll_disabled(d, p) assert_pll(d, p, false) +void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state); +#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true) +#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false) void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); #define assert_fdi_rx_pll_enabled(d, p) assert_fdi_rx_pll(d, p, true) @@ -1660,4 +1663,11 @@ void intel_plane_destroy_state(struct drm_plane *plane, struct drm_plane_state *state); extern const struct drm_plane_helper_funcs intel_plane_helper_funcs; +/* intel_color.c */ +void intel_color_init(struct drm_crtc *crtc); +void intel_color_set_csc(struct drm_crtc *crtc); +void intel_color_load_luts(struct drm_crtc *crtc); +void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, uint32_t start, uint32_t size); + #endif /* __INTEL_DRV_H__ */ -- cgit v0.10.2 From 05dc698c2e5c9d4453f62fd1cd5acbc68bc97b0f Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Wed, 16 Mar 2016 10:57:15 +0000 Subject: drm/i915: Do not read GAMMA_MODE register Implement Daniel Stone's recommendation to not read registers to infer the hardware's state. v2: Read GAMMA_MODE register value at init (Matt Roper's comment) v3: Read GAMMA_MODE register in intel_modeset_readout_hw_state along with other registers (Matt Roper's comment). v4: Mask GAMMA_MODE register with interesting bits when reading Signed-off-by: Lionel Landwerlin Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1458125837-2576-3-git-send-email-lionel.g.landwerlin@intel.com diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index 35b7f62..16657eb 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -121,6 +121,8 @@ static void haswell_load_luts(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_crtc_state *intel_crtc_state = + to_intel_crtc_state(crtc->state); bool reenable_ips = false; /* @@ -128,11 +130,12 @@ static void haswell_load_luts(struct drm_crtc *crtc) * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. */ if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled && - ((I915_READ(GAMMA_MODE(intel_crtc->pipe)) & GAMMA_MODE_MODE_MASK) == - GAMMA_MODE_MODE_SPLIT)) { + (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) { hsw_disable_ips(intel_crtc); reenable_ips = true; } + + intel_crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT; I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT); i9xx_load_luts(crtc); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4e0695d..a06c656 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9961,6 +9961,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, intel_get_pipe_src_size(crtc, pipe_config); + pipe_config->gamma_mode = + I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK; + if (INTEL_INFO(dev)->gen >= 9) { skl_init_scalers(dev, crtc, pipe_config); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5d0da22..d4945bb 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -578,6 +578,9 @@ struct intel_crtc_state { */ bool need_postvbl_update; } wm; + + /* Gamma mode programmed on the pipe */ + uint32_t gamma_mode; }; struct vlv_wm_state { -- cgit v0.10.2 From 82cf435b3134a5f892971b721b34e4c5d249363d Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Wed, 16 Mar 2016 10:57:16 +0000 Subject: drm/i915: Implement color management on bdw/skl/bxt/kbl Patch based on a previous series by Shashank Sharma. v2: Do not read GAMMA_MODE register to figure what mode we're in v3: Program PREC_PAL_GC_MAX to clamp pixel values > 1.0 Add documentation on how the Broadcast RGB property is affected by CTM v4: Update contributors v5: Refactor degamma/gamma LUTs load into a single function v6: Fix missing intel_crtc variable (bisect issue) v7: Fix & simplify limited range matrix multiplication (Matt Roper's comment) Signed-off-by: Shashank Sharma Signed-off-by: Kumar, Kiran S Signed-off-by: Kausal Malladi Signed-off-by: Lionel Landwerlin Acknowledged-by: Matt Roper Signed-off-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1458125837-2576-4-git-send-email-lionel.g.landwerlin@intel.com diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index ab7ffeb..1464fb2 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -2153,7 +2153,11 @@ void intel_crt_init(struct drm_device *dev) ENUM { "Automatic", "Full", "Limited 16:235" } Connector - TBD + When this property is set to Limited 16:235 + and CTM is set, the hardware will be programmed with the + result of the multiplication of CTM by the limited range + matrix to ensure the pixels normaly in the range 0..1.0 are + remapped to the range 16/255..235/255. “audio” diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2a076b0..f118a93 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -66,6 +66,9 @@ static struct drm_driver driver; #define IVB_CURSOR_OFFSETS \ .cursor_offsets = { CURSOR_A_OFFSET, IVB_CURSOR_B_OFFSET, IVB_CURSOR_C_OFFSET } +#define BDW_COLORS \ + .color = { .degamma_lut_size = 512, .gamma_lut_size = 512 } + static const struct intel_device_info intel_i830_info = { .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, .has_overlay = 1, .overlay_needs_physical = 1, @@ -288,24 +291,28 @@ static const struct intel_device_info intel_haswell_m_info = { .is_mobile = 1, }; +#define BDW_FEATURES \ + HSW_FEATURES, \ + BDW_COLORS + static const struct intel_device_info intel_broadwell_d_info = { - HSW_FEATURES, + BDW_FEATURES, .gen = 8, }; static const struct intel_device_info intel_broadwell_m_info = { - HSW_FEATURES, + BDW_FEATURES, .gen = 8, .is_mobile = 1, }; static const struct intel_device_info intel_broadwell_gt3d_info = { - HSW_FEATURES, + BDW_FEATURES, .gen = 8, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; static const struct intel_device_info intel_broadwell_gt3m_info = { - HSW_FEATURES, + BDW_FEATURES, .gen = 8, .is_mobile = 1, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; @@ -321,13 +328,13 @@ static const struct intel_device_info intel_cherryview_info = { }; static const struct intel_device_info intel_skylake_info = { - HSW_FEATURES, + BDW_FEATURES, .is_skylake = 1, .gen = 9, }; static const struct intel_device_info intel_skylake_gt3_info = { - HSW_FEATURES, + BDW_FEATURES, .is_skylake = 1, .gen = 9, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, @@ -345,17 +352,18 @@ static const struct intel_device_info intel_broxton_info = { .has_fbc = 1, GEN_DEFAULT_PIPEOFFSETS, IVB_CURSOR_OFFSETS, + BDW_COLORS, }; static const struct intel_device_info intel_kabylake_info = { - HSW_FEATURES, + BDW_FEATURES, .is_preliminary = 1, .is_kabylake = 1, .gen = 9, }; static const struct intel_device_info intel_kabylake_gt3_info = { - HSW_FEATURES, + BDW_FEATURES, .is_preliminary = 1, .is_kabylake = 1, .gen = 9, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8e5527b..050d860 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -630,6 +630,7 @@ struct drm_i915_display_funcs { /* display clock increase/decrease */ /* pll clock increase/decrease */ + void (*load_csc_matrix)(struct drm_crtc *crtc); void (*load_luts)(struct drm_crtc *crtc); }; @@ -781,6 +782,11 @@ struct intel_device_info { u8 has_slice_pg:1; u8 has_subslice_pg:1; u8 has_eu_pg:1; + + struct color_luts { + u16 degamma_lut_size; + u16 gamma_lut_size; + } color; }; #undef DEFINE_FLAG diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 06fb589..77efafd 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7663,6 +7663,28 @@ enum skl_disp_power_wells { #define PIPE_CSC_POSTOFF_ME(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME) #define PIPE_CSC_POSTOFF_LO(pipe) _MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO) +/* pipe degamma/gamma LUTs on IVB+ */ +#define _PAL_PREC_INDEX_A 0x4A400 +#define _PAL_PREC_INDEX_B 0x4AC00 +#define _PAL_PREC_INDEX_C 0x4B400 +#define PAL_PREC_10_12_BIT (0 << 31) +#define PAL_PREC_SPLIT_MODE (1 << 31) +#define PAL_PREC_AUTO_INCREMENT (1 << 15) +#define _PAL_PREC_DATA_A 0x4A404 +#define _PAL_PREC_DATA_B 0x4AC04 +#define _PAL_PREC_DATA_C 0x4B404 +#define _PAL_PREC_GC_MAX_A 0x4A410 +#define _PAL_PREC_GC_MAX_B 0x4AC10 +#define _PAL_PREC_GC_MAX_C 0x4B410 +#define _PAL_PREC_EXT_GC_MAX_A 0x4A420 +#define _PAL_PREC_EXT_GC_MAX_B 0x4AC20 +#define _PAL_PREC_EXT_GC_MAX_C 0x4B420 + +#define PREC_PAL_INDEX(pipe) _MMIO_PIPE(pipe, _PAL_PREC_INDEX_A, _PAL_PREC_INDEX_B) +#define PREC_PAL_DATA(pipe) _MMIO_PIPE(pipe, _PAL_PREC_DATA_A, _PAL_PREC_DATA_B) +#define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4) +#define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4) + /* MIPI DSI registers */ #define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */ diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index 16657eb..c6340d8 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -24,39 +24,155 @@ #include "intel_drv.h" +#define CTM_COEFF_SIGN (1ULL << 63) + +#define CTM_COEFF_1_0 (1ULL << 32) +#define CTM_COEFF_2_0 (CTM_COEFF_1_0 << 1) +#define CTM_COEFF_4_0 (CTM_COEFF_2_0 << 1) +#define CTM_COEFF_0_5 (CTM_COEFF_1_0 >> 1) +#define CTM_COEFF_0_25 (CTM_COEFF_0_5 >> 1) +#define CTM_COEFF_0_125 (CTM_COEFF_0_25 >> 1) + +#define CTM_COEFF_LIMITED_RANGE ((235ULL - 16ULL) * CTM_COEFF_1_0 / 255) + +#define CTM_COEFF_NEGATIVE(coeff) (((coeff) & CTM_COEFF_SIGN) != 0) +#define CTM_COEFF_ABS(coeff) ((coeff) & (CTM_COEFF_SIGN - 1)) + +#define LEGACY_LUT_LENGTH (sizeof(struct drm_color_lut) * 256) + /* - * Set up the pipe CSC unit. + * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point + * format). This macro takes the coefficient we want transformed and the + * number of fractional bits. * - * Currently only full range RGB to limited range RGB conversion - * is supported, but eventually this should handle various - * RGB<->YCbCr scenarios as well. + * We only have a 9 bits precision window which slides depending on the value + * of the CTM coefficient and we write the value from bit 3. We also round the + * value. */ +#define I9XX_CSC_COEFF_FP(coeff, fbits) \ + (clamp_val(((coeff) >> (32 - (fbits) - 3)) + 4, 0, 0xfff) & 0xff8) + +#define I9XX_CSC_COEFF_LIMITED_RANGE \ + I9XX_CSC_COEFF_FP(CTM_COEFF_LIMITED_RANGE, 9) +#define I9XX_CSC_COEFF_1_0 \ + ((7 << 12) | I9XX_CSC_COEFF_FP(CTM_COEFF_1_0, 8)) + +static bool crtc_state_is_legacy(struct drm_crtc_state *state) +{ + return !state->degamma_lut && + !state->ctm && + state->gamma_lut && + state->gamma_lut->length == LEGACY_LUT_LENGTH; +} + +/* + * When using limited range, multiply the matrix given by userspace by + * the matrix that we would use for the limited range. We do the + * multiplication in U2.30 format. + */ +static void ctm_mult_by_limited(uint64_t *result, int64_t *input) +{ + int i; + + for (i = 0; i < 9; i++) + result[i] = 0; + + for (i = 0; i < 3; i++) { + int64_t user_coeff = input[i * 3 + i]; + uint64_t limited_coeff = CTM_COEFF_LIMITED_RANGE >> 2; + uint64_t abs_coeff = clamp_val(CTM_COEFF_ABS(user_coeff), + 0, + CTM_COEFF_4_0 - 1) >> 2; + + result[i * 3 + i] = (limited_coeff * abs_coeff) >> 27; + if (CTM_COEFF_NEGATIVE(user_coeff)) + result[i * 3 + i] |= CTM_COEFF_SIGN; + } +} + +/* Set up the pipe CSC unit. */ static void i9xx_load_csc_matrix(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; + struct drm_crtc_state *crtc_state = crtc->state; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int pipe = intel_crtc->pipe; - uint16_t coeff = 0x7800; /* 1.0 */ - - /* - * TODO: Check what kind of values actually come out of the pipe - * with these coeff/postoff values and adjust to get the best - * accuracy. Perhaps we even need to take the bpc value into - * consideration. - */ - - if (intel_crtc->config->limited_color_range) - coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */ + int i, pipe = intel_crtc->pipe; + uint16_t coeffs[9] = { 0, }; + + if (crtc_state->ctm) { + struct drm_color_ctm *ctm = + (struct drm_color_ctm *)crtc_state->ctm->data; + uint64_t input[9] = { 0, }; + + if (intel_crtc->config->limited_color_range) { + ctm_mult_by_limited(input, ctm->matrix); + } else { + for (i = 0; i < ARRAY_SIZE(input); i++) + input[i] = ctm->matrix[i]; + } + + /* + * Convert fixed point S31.32 input to format supported by the + * hardware. + */ + for (i = 0; i < ARRAY_SIZE(coeffs); i++) { + uint64_t abs_coeff = ((1ULL << 63) - 1) & input[i]; + + /* + * Clamp input value to min/max supported by + * hardware. + */ + abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1); + + /* sign bit */ + if (CTM_COEFF_NEGATIVE(input[i])) + coeffs[i] |= 1 << 15; + + if (abs_coeff < CTM_COEFF_0_125) + coeffs[i] |= (3 << 12) | + I9XX_CSC_COEFF_FP(abs_coeff, 12); + else if (abs_coeff < CTM_COEFF_0_25) + coeffs[i] |= (2 << 12) | + I9XX_CSC_COEFF_FP(abs_coeff, 11); + else if (abs_coeff < CTM_COEFF_0_5) + coeffs[i] |= (1 << 12) | + I9XX_CSC_COEFF_FP(abs_coeff, 10); + else if (abs_coeff < CTM_COEFF_1_0) + coeffs[i] |= I9XX_CSC_COEFF_FP(abs_coeff, 9); + else if (abs_coeff < CTM_COEFF_2_0) + coeffs[i] |= (7 << 12) | + I9XX_CSC_COEFF_FP(abs_coeff, 8); + else + coeffs[i] |= (6 << 12) | + I9XX_CSC_COEFF_FP(abs_coeff, 7); + } + } else { + /* + * Load an identity matrix if no coefficients are provided. + * + * TODO: Check what kind of values actually come out of the + * pipe with these coeff/postoff values and adjust to get the + * best accuracy. Perhaps we even need to take the bpc value + * into consideration. + */ + for (i = 0; i < 3; i++) { + if (intel_crtc->config->limited_color_range) + coeffs[i * 3 + i] = + I9XX_CSC_COEFF_LIMITED_RANGE; + else + coeffs[i * 3 + i] = I9XX_CSC_COEFF_1_0; + } + } - I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16); - I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0); + I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeffs[0] << 16 | coeffs[1]); + I915_WRITE(PIPE_CSC_COEFF_BY(pipe), coeffs[2] << 16); - I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff); - I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0); + I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeffs[3] << 16 | coeffs[4]); + I915_WRITE(PIPE_CSC_COEFF_BU(pipe), coeffs[5] << 16); - I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0); - I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16); + I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), coeffs[6] << 16 | coeffs[7]); + I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeffs[8] << 16); I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0); I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0); @@ -85,13 +201,18 @@ static void i9xx_load_csc_matrix(struct drm_crtc *crtc) void intel_color_set_csc(struct drm_crtc *crtc) { - i9xx_load_csc_matrix(crtc); + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->display.load_csc_matrix) + dev_priv->display.load_csc_matrix(crtc); } -/* Loads the palette/gamma unit for the CRTC with the prepared values. */ +/* Loads the legacy palette/gamma unit for the CRTC. */ static void i9xx_load_luts(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; + struct drm_crtc_state *state = crtc->state; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; @@ -104,18 +225,33 @@ static void i9xx_load_luts(struct drm_crtc *crtc) assert_pll_enabled(dev_priv, pipe); } - for (i = 0; i < 256; i++) { - uint32_t word = (intel_crtc->lut_r[i] << 16) | - (intel_crtc->lut_g[i] << 8) | - intel_crtc->lut_b[i]; - if (HAS_GMCH_DISPLAY(dev)) - I915_WRITE(PALETTE(pipe, i), word); - else - I915_WRITE(LGC_PALETTE(pipe, i), word); + if (state->gamma_lut) { + struct drm_color_lut *lut = + (struct drm_color_lut *) state->gamma_lut->data; + for (i = 0; i < 256; i++) { + uint32_t word = + (drm_color_lut_extract(lut[i].red, 8) << 16) | + (drm_color_lut_extract(lut[i].green, 8) << 8) | + drm_color_lut_extract(lut[i].blue, 8); + + if (HAS_GMCH_DISPLAY(dev)) + I915_WRITE(PALETTE(pipe, i), word); + else + I915_WRITE(LGC_PALETTE(pipe, i), word); + } + } else { + for (i = 0; i < 256; i++) { + uint32_t word = (i << 16) | (i << 8) | i; + + if (HAS_GMCH_DISPLAY(dev)) + I915_WRITE(PALETTE(pipe, i), word); + else + I915_WRITE(LGC_PALETTE(pipe, i), word); + } } } -/* Loads the legacy palette/gamma unit for the CRTC on Haswell+. */ +/* Loads the legacy palette/gamma unit for the CRTC on Haswell. */ static void haswell_load_luts(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -144,6 +280,89 @@ static void haswell_load_luts(struct drm_crtc *crtc) hsw_enable_ips(intel_crtc); } +/* Loads the palette/gamma unit for the CRTC on Broadwell+. */ +static void broadwell_load_luts(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_crtc_state *state = crtc->state; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc_state *intel_state = to_intel_crtc_state(state); + enum pipe pipe = to_intel_crtc(crtc)->pipe; + uint32_t i, lut_size = INTEL_INFO(dev)->color.degamma_lut_size; + + if (crtc_state_is_legacy(state)) { + haswell_load_luts(crtc); + return; + } + + I915_WRITE(PREC_PAL_INDEX(pipe), + PAL_PREC_SPLIT_MODE | PAL_PREC_AUTO_INCREMENT); + + if (state->degamma_lut) { + struct drm_color_lut *lut = + (struct drm_color_lut *) state->degamma_lut->data; + + for (i = 0; i < lut_size; i++) { + uint32_t word = + drm_color_lut_extract(lut[i].red, 10) << 20 | + drm_color_lut_extract(lut[i].green, 10) << 10 | + drm_color_lut_extract(lut[i].blue, 10); + + I915_WRITE(PREC_PAL_DATA(pipe), word); + } + } else { + for (i = 0; i < lut_size; i++) { + uint32_t v = (i * ((1 << 10) - 1)) / (lut_size - 1); + + I915_WRITE(PREC_PAL_DATA(pipe), + (v << 20) | (v << 10) | v); + } + } + + if (state->gamma_lut) { + struct drm_color_lut *lut = + (struct drm_color_lut *) state->gamma_lut->data; + + for (i = 0; i < lut_size; i++) { + uint32_t word = + (drm_color_lut_extract(lut[i].red, 10) << 20) | + (drm_color_lut_extract(lut[i].green, 10) << 10) | + drm_color_lut_extract(lut[i].blue, 10); + + I915_WRITE(PREC_PAL_DATA(pipe), word); + } + + /* Program the max register to clamp values > 1.0. */ + I915_WRITE(PREC_PAL_GC_MAX(pipe, 0), + drm_color_lut_extract(lut[i].red, 16)); + I915_WRITE(PREC_PAL_GC_MAX(pipe, 1), + drm_color_lut_extract(lut[i].green, 16)); + I915_WRITE(PREC_PAL_GC_MAX(pipe, 2), + drm_color_lut_extract(lut[i].blue, 16)); + } else { + for (i = 0; i < lut_size; i++) { + uint32_t v = (i * ((1 << 10) - 1)) / (lut_size - 1); + + I915_WRITE(PREC_PAL_DATA(pipe), + (v << 20) | (v << 10) | v); + } + + I915_WRITE(PREC_PAL_GC_MAX(pipe, 0), (1 << 16) - 1); + I915_WRITE(PREC_PAL_GC_MAX(pipe, 1), (1 << 16) - 1); + I915_WRITE(PREC_PAL_GC_MAX(pipe, 2), (1 << 16) - 1); + } + + intel_state->gamma_mode = GAMMA_MODE_MODE_SPLIT; + I915_WRITE(GAMMA_MODE(pipe), GAMMA_MODE_MODE_SPLIT); + POSTING_READ(GAMMA_MODE(pipe)); + + /* + * Reset the index, otherwise it prevents the legacy palette to be + * written properly. + */ + I915_WRITE(PREC_PAL_INDEX(pipe), 0); +} + void intel_color_load_luts(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -156,39 +375,61 @@ void intel_color_load_luts(struct drm_crtc *crtc) dev_priv->display.load_luts(crtc); } -void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, uint32_t start, uint32_t size) +int intel_color_check(struct drm_crtc *crtc, + struct drm_crtc_state *crtc_state) { - int end = (start + size > 256) ? 256 : start + size, i; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_device *dev = crtc->dev; + size_t gamma_length, degamma_length; - for (i = start; i < end; i++) { - intel_crtc->lut_r[i] = red[i] >> 8; - intel_crtc->lut_g[i] = green[i] >> 8; - intel_crtc->lut_b[i] = blue[i] >> 8; - } + degamma_length = INTEL_INFO(dev)->color.degamma_lut_size * + sizeof(struct drm_color_lut); + gamma_length = INTEL_INFO(dev)->color.gamma_lut_size * + sizeof(struct drm_color_lut); - intel_color_load_luts(crtc); + /* + * We allow both degamma & gamma luts at the right size or + * NULL. + */ + if ((!crtc_state->degamma_lut || + crtc_state->degamma_lut->length == degamma_length) && + (!crtc_state->gamma_lut || + crtc_state->gamma_lut->length == gamma_length)) + return 0; + + /* + * We also allow no degamma lut and a gamma lut at the legacy + * size (256 entries). + */ + if (!crtc_state->degamma_lut && + crtc_state->gamma_lut && + crtc_state->gamma_lut->length == LEGACY_LUT_LENGTH) + return 0; + + return -EINVAL; } void intel_color_init(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - int i; drm_mode_crtc_set_gamma_size(crtc, 256); - for (i = 0; i < 256; i++) { - intel_crtc->lut_r[i] = i; - intel_crtc->lut_g[i] = i; - intel_crtc->lut_b[i] = i; - } - if (IS_HASWELL(dev) || - (INTEL_INFO(dev)->gen >= 8 && !IS_CHERRYVIEW(dev))) { + if (IS_HASWELL(dev)) { + dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; dev_priv->display.load_luts = haswell_load_luts; + } else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev) || + IS_BROXTON(dev) || IS_KABYLAKE(dev)) { + dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; + dev_priv->display.load_luts = broadwell_load_luts; } else { dev_priv->display.load_luts = i9xx_load_luts; } + + /* Enable color management support when we have degamma & gamma LUTs. */ + if (INTEL_INFO(dev)->color.degamma_lut_size != 0 && + INTEL_INFO(dev)->color.gamma_lut_size != 0) + drm_helper_crtc_enable_color_mgmt(crtc, + INTEL_INFO(dev)->color.degamma_lut_size, + INTEL_INFO(dev)->color.gamma_lut_size); } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a06c656..602d23c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11911,6 +11911,12 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, return ret; } + if (crtc_state->color_mgmt_changed) { + ret = intel_color_check(crtc, crtc_state); + if (ret) + return ret; + } + ret = 0; if (dev_priv->display.compute_pipe_wm) { ret = dev_priv->display.compute_pipe_wm(pipe_config); @@ -11953,7 +11959,6 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs intel_helper_funcs = { .mode_set_base_atomic = intel_pipe_set_base_atomic, - .load_lut = intel_color_load_luts, .atomic_begin = intel_begin_crtc_commit, .atomic_flush = intel_finish_crtc_commit, .atomic_check = intel_crtc_atomic_check, @@ -13576,6 +13581,18 @@ static int intel_atomic_commit(struct drm_device *dev, dev_priv->display.crtc_enable(crtc); } + if (!modeset && + crtc->state->active && + crtc->state->color_mgmt_changed) { + /* + * Only update color management when not doing + * a modeset as this will be done by + * crtc_enable already. + */ + intel_color_set_csc(crtc); + intel_color_load_luts(crtc); + } + if (!modeset) intel_pre_plane_update(to_intel_crtc_state(old_crtc_state)); @@ -13686,8 +13703,9 @@ out: #undef for_each_intel_crtc_masked static const struct drm_crtc_funcs intel_crtc_funcs = { - .gamma_set = intel_color_legacy_gamma_set, + .gamma_set = drm_atomic_helper_legacy_gamma_set, .set_config = drm_atomic_helper_set_config, + .set_property = drm_atomic_helper_crtc_set_property, .destroy = intel_crtc_destroy, .page_flip = intel_crtc_page_flip, .atomic_duplicate_state = intel_crtc_duplicate_state, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d4945bb..c87b450 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1668,9 +1668,8 @@ extern const struct drm_plane_helper_funcs intel_plane_helper_funcs; /* intel_color.c */ void intel_color_init(struct drm_crtc *crtc); +int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state); void intel_color_set_csc(struct drm_crtc *crtc); void intel_color_load_luts(struct drm_crtc *crtc); -void intel_color_legacy_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, uint32_t start, uint32_t size); #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index ea4188a..5e0dcb3 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -379,6 +379,7 @@ retry: struct drm_connector *connector; struct drm_encoder *encoder; struct drm_fb_helper_crtc *new_crtc; + struct intel_crtc *intel_crtc; fb_conn = fb_helper->connector_info[i]; connector = fb_conn->connector; @@ -420,6 +421,13 @@ retry: num_connectors_enabled++; + intel_crtc = to_intel_crtc(connector->state->crtc); + for (j = 0; j < 256; j++) { + intel_crtc->lut_r[j] = j; + intel_crtc->lut_g[j] = j; + intel_crtc->lut_b[j] = j; + } + new_crtc = intel_fb_helper_crtc(fb_helper, connector->state->crtc); /* -- cgit v0.10.2 From 29dc3739e50da3576ddf89d9ea2704640676135d Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Wed, 16 Mar 2016 10:57:17 +0000 Subject: drm/i915: Implement color management on chv Patch based on a previous series by Shashank Sharma. v2: Update contributors v3: Refactor degamma/gamma LUTs load into a single function v4: Remove unused variable Signed-off-by: Shashank Sharma Signed-off-by: Kumar, Kiran S Signed-off-by: Kausal Malladi Signed-off-by: Lionel Landwerlin Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: http://patchwork.freedesktop.org/patch/msgid/1458125837-2576-5-git-send-email-lionel.g.landwerlin@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f118a93..20f8dbe 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -68,6 +68,8 @@ static struct drm_driver driver; #define BDW_COLORS \ .color = { .degamma_lut_size = 512, .gamma_lut_size = 512 } +#define CHV_COLORS \ + .color = { .degamma_lut_size = 65, .gamma_lut_size = 257 } static const struct intel_device_info intel_i830_info = { .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, @@ -325,6 +327,7 @@ static const struct intel_device_info intel_cherryview_info = { .display_mmio_offset = VLV_DISPLAY_BASE, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, + CHV_COLORS, }; static const struct intel_device_info intel_skylake_info = { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 77efafd..23ca6c0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7685,6 +7685,37 @@ enum skl_disp_power_wells { #define PREC_PAL_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4) #define PREC_PAL_EXT_GC_MAX(pipe, i) _MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4) +/* pipe CSC & degamma/gamma LUTs on CHV */ +#define _CGM_PIPE_A_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x67900) +#define _CGM_PIPE_A_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x67904) +#define _CGM_PIPE_A_CSC_COEFF45 (VLV_DISPLAY_BASE + 0x67908) +#define _CGM_PIPE_A_CSC_COEFF67 (VLV_DISPLAY_BASE + 0x6790C) +#define _CGM_PIPE_A_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x67910) +#define _CGM_PIPE_A_DEGAMMA (VLV_DISPLAY_BASE + 0x66000) +#define _CGM_PIPE_A_GAMMA (VLV_DISPLAY_BASE + 0x67000) +#define _CGM_PIPE_A_MODE (VLV_DISPLAY_BASE + 0x67A00) +#define CGM_PIPE_MODE_GAMMA (1 << 2) +#define CGM_PIPE_MODE_CSC (1 << 1) +#define CGM_PIPE_MODE_DEGAMMA (1 << 0) + +#define _CGM_PIPE_B_CSC_COEFF01 (VLV_DISPLAY_BASE + 0x69900) +#define _CGM_PIPE_B_CSC_COEFF23 (VLV_DISPLAY_BASE + 0x69904) +#define _CGM_PIPE_B_CSC_COEFF45 (VLV_DISPLAY_BASE + 0x69908) +#define _CGM_PIPE_B_CSC_COEFF67 (VLV_DISPLAY_BASE + 0x6990C) +#define _CGM_PIPE_B_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x69910) +#define _CGM_PIPE_B_DEGAMMA (VLV_DISPLAY_BASE + 0x68000) +#define _CGM_PIPE_B_GAMMA (VLV_DISPLAY_BASE + 0x69000) +#define _CGM_PIPE_B_MODE (VLV_DISPLAY_BASE + 0x69A00) + +#define CGM_PIPE_CSC_COEFF01(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF01, _CGM_PIPE_B_CSC_COEFF01) +#define CGM_PIPE_CSC_COEFF23(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF23, _CGM_PIPE_B_CSC_COEFF23) +#define CGM_PIPE_CSC_COEFF45(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF45, _CGM_PIPE_B_CSC_COEFF45) +#define CGM_PIPE_CSC_COEFF67(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF67, _CGM_PIPE_B_CSC_COEFF67) +#define CGM_PIPE_CSC_COEFF8(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF8, _CGM_PIPE_B_CSC_COEFF8) +#define CGM_PIPE_DEGAMMA(pipe, i, w) _MMIO(_PIPE(pipe, _CGM_PIPE_A_DEGAMMA, _CGM_PIPE_B_DEGAMMA) + (i) * 8 + (w) * 4) +#define CGM_PIPE_GAMMA(pipe, i, w) _MMIO(_PIPE(pipe, _CGM_PIPE_A_GAMMA, _CGM_PIPE_B_GAMMA) + (i) * 8 + (w) * 4) +#define CGM_PIPE_MODE(pipe) _MMIO_PIPE(pipe, _CGM_PIPE_A_MODE, _CGM_PIPE_B_MODE) + /* MIPI DSI registers */ #define _MIPI_PORT(port, a, c) _PORT3(port, a, 0, c) /* ports A and C only */ diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index c6340d8..aa0b20d 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -29,6 +29,7 @@ #define CTM_COEFF_1_0 (1ULL << 32) #define CTM_COEFF_2_0 (CTM_COEFF_1_0 << 1) #define CTM_COEFF_4_0 (CTM_COEFF_2_0 << 1) +#define CTM_COEFF_8_0 (CTM_COEFF_4_0 << 1) #define CTM_COEFF_0_5 (CTM_COEFF_1_0 >> 1) #define CTM_COEFF_0_25 (CTM_COEFF_0_5 >> 1) #define CTM_COEFF_0_125 (CTM_COEFF_0_25 >> 1) @@ -199,6 +200,58 @@ static void i9xx_load_csc_matrix(struct drm_crtc *crtc) } } +/* + * Set up the pipe CSC unit on CherryView. + */ +static void cherryview_load_csc_matrix(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_crtc_state *state = crtc->state; + struct drm_i915_private *dev_priv = dev->dev_private; + int pipe = to_intel_crtc(crtc)->pipe; + uint32_t mode; + + if (state->ctm) { + struct drm_color_ctm *ctm = + (struct drm_color_ctm *) state->ctm->data; + uint16_t coeffs[9] = { 0, }; + int i; + + for (i = 0; i < ARRAY_SIZE(coeffs); i++) { + uint64_t abs_coeff = + ((1ULL << 63) - 1) & ctm->matrix[i]; + + /* Round coefficient. */ + abs_coeff += 1 << (32 - 13); + /* Clamp to hardware limits. */ + abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1); + + /* Write coefficients in S3.12 format. */ + if (ctm->matrix[i] & (1ULL << 63)) + coeffs[i] = 1 << 15; + coeffs[i] |= ((abs_coeff >> 32) & 7) << 12; + coeffs[i] |= (abs_coeff >> 20) & 0xfff; + } + + I915_WRITE(CGM_PIPE_CSC_COEFF01(pipe), + coeffs[1] << 16 | coeffs[0]); + I915_WRITE(CGM_PIPE_CSC_COEFF23(pipe), + coeffs[3] << 16 | coeffs[2]); + I915_WRITE(CGM_PIPE_CSC_COEFF45(pipe), + coeffs[5] << 16 | coeffs[4]); + I915_WRITE(CGM_PIPE_CSC_COEFF67(pipe), + coeffs[7] << 16 | coeffs[6]); + I915_WRITE(CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]); + } + + mode = (state->ctm ? CGM_PIPE_MODE_CSC : 0); + if (!crtc_state_is_legacy(state)) { + mode |= (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) | + (state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0); + } + I915_WRITE(CGM_PIPE_MODE(pipe), mode); +} + void intel_color_set_csc(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -209,10 +262,10 @@ void intel_color_set_csc(struct drm_crtc *crtc) } /* Loads the legacy palette/gamma unit for the CRTC. */ -static void i9xx_load_luts(struct drm_crtc *crtc) +static void i9xx_load_luts_internal(struct drm_crtc *crtc, + struct drm_property_blob *blob) { struct drm_device *dev = crtc->dev; - struct drm_crtc_state *state = crtc->state; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; @@ -225,9 +278,8 @@ static void i9xx_load_luts(struct drm_crtc *crtc) assert_pll_enabled(dev_priv, pipe); } - if (state->gamma_lut) { - struct drm_color_lut *lut = - (struct drm_color_lut *) state->gamma_lut->data; + if (blob) { + struct drm_color_lut *lut = (struct drm_color_lut *) blob->data; for (i = 0; i < 256; i++) { uint32_t word = (drm_color_lut_extract(lut[i].red, 8) << 16) | @@ -251,6 +303,11 @@ static void i9xx_load_luts(struct drm_crtc *crtc) } } +static void i9xx_load_luts(struct drm_crtc *crtc) +{ + i9xx_load_luts_internal(crtc, crtc->state->gamma_lut); +} + /* Loads the legacy palette/gamma unit for the CRTC on Haswell. */ static void haswell_load_luts(struct drm_crtc *crtc) { @@ -363,6 +420,67 @@ static void broadwell_load_luts(struct drm_crtc *crtc) I915_WRITE(PREC_PAL_INDEX(pipe), 0); } +/* Loads the palette/gamma unit for the CRTC on CherryView. */ +static void cherryview_load_luts(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_crtc_state *state = crtc->state; + enum pipe pipe = to_intel_crtc(crtc)->pipe; + struct drm_color_lut *lut; + uint32_t i, lut_size; + uint32_t word0, word1; + + if (crtc_state_is_legacy(state)) { + /* Turn off degamma/gamma on CGM block. */ + I915_WRITE(CGM_PIPE_MODE(pipe), + (state->ctm ? CGM_PIPE_MODE_CSC : 0)); + i9xx_load_luts_internal(crtc, state->gamma_lut); + return; + } + + if (state->degamma_lut) { + lut = (struct drm_color_lut *) state->degamma_lut->data; + lut_size = INTEL_INFO(dev)->color.degamma_lut_size; + for (i = 0; i < lut_size; i++) { + /* Write LUT in U0.14 format. */ + word0 = + (drm_color_lut_extract(lut[i].green, 14) << 16) | + drm_color_lut_extract(lut[i].blue, 14); + word1 = drm_color_lut_extract(lut[i].red, 14); + + I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 0), word0); + I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 1), word1); + } + } + + if (state->gamma_lut) { + lut = (struct drm_color_lut *) state->gamma_lut->data; + lut_size = INTEL_INFO(dev)->color.gamma_lut_size; + for (i = 0; i < lut_size; i++) { + /* Write LUT in U0.10 format. */ + word0 = + (drm_color_lut_extract(lut[i].green, 10) << 16) | + drm_color_lut_extract(lut[i].blue, 10); + word1 = drm_color_lut_extract(lut[i].red, 10); + + I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 0), word0); + I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 1), word1); + } + } + + I915_WRITE(CGM_PIPE_MODE(pipe), + (state->ctm ? CGM_PIPE_MODE_CSC : 0) | + (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) | + (state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0)); + + /* + * Also program a linear LUT in the legacy block (behind the + * CGM block). + */ + i9xx_load_luts_internal(crtc, NULL); +} + void intel_color_load_luts(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -415,7 +533,10 @@ void intel_color_init(struct drm_crtc *crtc) drm_mode_crtc_set_gamma_size(crtc, 256); - if (IS_HASWELL(dev)) { + if (IS_CHERRYVIEW(dev)) { + dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix; + dev_priv->display.load_luts = cherryview_load_luts; + } else if (IS_HASWELL(dev)) { dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; dev_priv->display.load_luts = haswell_load_luts; } else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev) || -- cgit v0.10.2 From fc0768ceac126ea6ec2ff8bd56bbe4abe11695bc Mon Sep 17 00:00:00 2001 From: Tomas Elf Date: Mon, 21 Mar 2016 16:26:59 +0000 Subject: drm/i915/tdr: Initialize hangcheck struct for each engine Initialize hangcheck struct during driver load. Since we do the same after recovering from a reset, this is extracted into a helper function. v2: remove redundant hangcheck init during load as this is done when engines are initialized (Chris) Cc: Mika Kuoppala Signed-off-by: Tomas Elf Signed-off-by: Arun Siluvery Reviewed-by: Chris Wilson Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1458577619-12006-1-git-send-email-arun.siluvery@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 050d860..56eb5f0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2740,6 +2740,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, extern int intel_gpu_reset(struct drm_device *dev, u32 engine_mask); extern bool intel_has_gpu_reset(struct drm_device *dev); extern int i915_reset(struct drm_device *dev); +extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine); extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 3a23b95..40ef4ea 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1606,7 +1606,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) engine->next_context_status_buffer = next_context_status_buffer_hw; DRM_DEBUG_DRIVER("Execlists enabled for %s\n", engine->name); - memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); + intel_engine_init_hangcheck(engine); return 0; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index df0ef5b..ce59850 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -555,6 +555,11 @@ static bool stop_ring(struct intel_engine_cs *engine) return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0; } +void intel_engine_init_hangcheck(struct intel_engine_cs *engine) +{ + memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); +} + static int init_ring_common(struct intel_engine_cs *engine) { struct drm_device *dev = engine->dev; @@ -634,7 +639,7 @@ static int init_ring_common(struct intel_engine_cs *engine) ringbuf->tail = I915_READ_TAIL(engine) & TAIL_ADDR; intel_ring_update_space(ringbuf); - memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); + intel_engine_init_hangcheck(engine); out: intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); -- cgit v0.10.2 From 14b730fcb8d9b9c6fed540829548040ef8d2ca2c Mon Sep 17 00:00:00 2001 From: "arun.siluvery@linux.intel.com" Date: Fri, 18 Mar 2016 20:07:55 +0000 Subject: drm/i915/tdr: Prepare error handler to accept mask of hung engines In preparation for engine reset, the wedged argument of i915_handle_error() is extended to reflect as a mask of engines that are hung. This is further passed down to error state capture functions which are also updated. Engine reset recovery mechanism uses this mask and schedules recovery work for those particular engines. Cc: Chris Wilson Cc: Mika Kuoppala Signed-off-by: Tomas Elf Signed-off-by: Arun Siluvery Reviewed-by: Mika Kuoppala Signed-off-by: Mika Kuoppala Link: http://patchwork.freedesktop.org/patch/msgid/1458331676-567-3-git-send-email-arun.siluvery@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 56eb5f0..9d29ab0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2757,7 +2757,7 @@ bool intel_hpd_pin_to_port(enum hpd_pin pin, enum port *port); /* i915_irq.c */ void i915_queue_hangcheck(struct drm_device *dev); __printf(3, 4) -void i915_handle_error(struct drm_device *dev, bool wedged, +void i915_handle_error(struct drm_device *dev, u32 engine_mask, const char *fmt, ...); extern void intel_irq_init(struct drm_i915_private *dev_priv); @@ -3343,7 +3343,7 @@ static inline void i915_error_state_buf_release( { kfree(eb->buf); } -void i915_capture_error_state(struct drm_device *dev, bool wedge, +void i915_capture_error_state(struct drm_device *dev, u32 engine_mask, const char *error_msg); void i915_error_state_get(struct drm_device *dev, struct i915_error_state_file_priv *error_priv); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index db8600a..1f8ff06 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1301,7 +1301,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, static void i915_error_capture_msg(struct drm_device *dev, struct drm_i915_error_state *error, - bool wedged, + u32 engine_mask, const char *error_msg) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1324,7 +1324,7 @@ static void i915_error_capture_msg(struct drm_device *dev, scnprintf(error->error_msg + len, sizeof(error->error_msg) - len, ", reason: %s, action: %s", error_msg, - wedged ? "reset" : "continue"); + engine_mask ? "reset" : "continue"); } static void i915_capture_gen_state(struct drm_i915_private *dev_priv, @@ -1347,7 +1347,7 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv, * out a structure which becomes available in debugfs for user level tools * to pick up. */ -void i915_capture_error_state(struct drm_device *dev, bool wedged, +void i915_capture_error_state(struct drm_device *dev, u32 engine_mask, const char *error_msg) { static bool warned; @@ -1375,7 +1375,7 @@ void i915_capture_error_state(struct drm_device *dev, bool wedged, error->overlay = intel_overlay_capture_error_state(dev); error->display = intel_display_capture_error_state(dev); - i915_error_capture_msg(dev, error, wedged, error_msg); + i915_error_capture_msg(dev, error, engine_mask, error_msg); DRM_INFO("%s\n", error->error_msg); spin_lock_irqsave(&dev_priv->gpu_error.lock, flags); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8f3e330..a55a7cc 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2653,14 +2653,14 @@ static void i915_report_and_clear_eir(struct drm_device *dev) /** * i915_handle_error - handle a gpu error * @dev: drm device - * + * @engine_mask: mask representing engines that are hung * Do some basic checking of register state at error time and * dump it to the syslog. Also call i915_capture_error_state() to make * sure we get a record and make it available in debugfs. Fire a uevent * so userspace knows something bad happened (should trigger collection * of a ring dump etc.). */ -void i915_handle_error(struct drm_device *dev, bool wedged, +void i915_handle_error(struct drm_device *dev, u32 engine_mask, const char *fmt, ...) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -2671,10 +2671,10 @@ void i915_handle_error(struct drm_device *dev, bool wedged, vscnprintf(error_msg, sizeof(error_msg), fmt, args); va_end(args); - i915_capture_error_state(dev, wedged, error_msg); + i915_capture_error_state(dev, engine_mask, error_msg); i915_report_and_clear_eir(dev); - if (wedged) { + if (engine_mask) { atomic_or(I915_RESET_IN_PROGRESS_FLAG, &dev_priv->gpu_error.reset_counter); @@ -3033,7 +3033,7 @@ ring_stuck(struct intel_engine_cs *engine, u64 acthd) */ tmp = I915_READ_CTL(engine); if (tmp & RING_WAIT) { - i915_handle_error(dev, false, + i915_handle_error(dev, 0, "Kicking stuck wait on %s", engine->name); I915_WRITE_CTL(engine, tmp); @@ -3045,7 +3045,7 @@ ring_stuck(struct intel_engine_cs *engine, u64 acthd) default: return HANGCHECK_HUNG; case 1: - i915_handle_error(dev, false, + i915_handle_error(dev, 0, "Kicking stuck semaphore on %s", engine->name); I915_WRITE_CTL(engine, tmp); @@ -3189,12 +3189,12 @@ static void i915_hangcheck_elapsed(struct work_struct *work) DRM_INFO("%s on %s\n", stuck[i] ? "stuck" : "no progress", engine->name); - rings_hung++; + rings_hung |= intel_engine_flag(engine); } } if (rings_hung) { - i915_handle_error(dev, true, "Ring hung"); + i915_handle_error(dev, rings_hung, "Engine(s) hung"); goto out; } -- cgit v0.10.2 From 177246a84d133888b5428e44201282d94635f473 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 4 Mar 2016 15:59:39 -0800 Subject: drm/i915: Wait until after wm optimization to drop runtime PM reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the end of an atomic commit, we currently wait for vblanks to complete, call put() on the various runtime PM references, and then try to optimize our watermarks (on platforms that need two-step watermark programming). This can lead to watermark registers being programmed while the power well is powered down. We need to wait until after watermark optimization is complete before dropping our runtime power references. Note that in the future the watermark optimization is probably going to move to an asynchronous workqueue task that happens at some arbitrary point after vblank. When we make that change, we'll no longer necessarily be operating under the power reference held here, so we'll need to wrap the watermark register programmin in a call to intel_runtime_pm_get_if_in_use() or similar. Cc: arun.siluvery@linux.intel.com Cc: ville.syrjala@linux.intel.com Cc: maarten.lankhorst@linux.intel.com Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94349 Fixes: ed4a6a7ca853 ("drm/i915: Add two-stage ILK-style watermark programming (v11)") Signed-off-by: Matt Roper Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1457135979-23727-1-git-send-email-matthew.d.roper@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 602d23c..47332a1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13613,16 +13613,6 @@ static int intel_atomic_commit(struct drm_device *dev, if (!state->legacy_cursor_update) intel_atomic_wait_for_vblanks(dev, dev_priv, crtc_vblank_mask); - for_each_crtc_in_state(state, crtc, old_crtc_state, i) { - intel_post_plane_update(to_intel_crtc_state(old_crtc_state)); - - if (put_domains[i]) - modeset_put_power_domains(dev_priv, put_domains[i]); - } - - if (intel_state->modeset) - intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET); - /* * Now that the vblank has passed, we can go ahead and program the * optimal watermarks on platforms that need two-step watermark @@ -13637,6 +13627,16 @@ static int intel_atomic_commit(struct drm_device *dev, dev_priv->display.optimize_watermarks(intel_cstate); } + for_each_crtc_in_state(state, crtc, old_crtc_state, i) { + intel_post_plane_update(to_intel_crtc_state(old_crtc_state)); + + if (put_domains[i]) + modeset_put_power_domains(dev_priv, put_domains[i]); + } + + if (intel_state->modeset) + intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET); + mutex_lock(&dev->struct_mutex); drm_atomic_helper_cleanup_planes(dev, state); mutex_unlock(&dev->struct_mutex); -- cgit v0.10.2 From ad45d83968caf8e757cf895f4fd53903a092fad8 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 21 Mar 2016 17:08:57 +0200 Subject: drm/i915: Make __i915_printk debug output behave the same as DRM_DEBUG_DRIVER Joonas and Daniel remarked that our debugging output should stay compatible with the core DRM's debug facility. The recently added __i915_printk() would output debug messages even if debugging is completely disabled via the drm.debug option. To fix this make __i915_printk behave the same as DRM_DEBUG_DRIVER in this case. CC: Joonas Lahtinen CC: Daniel Vetter CC: Chris Wilson Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458572937-21712-1-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 3f439a0..a3458fc 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -77,9 +77,13 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level, static bool shown_bug_once; struct device *dev = dev_priv->dev->dev; bool is_error = level[1] <= KERN_ERR[1]; + bool is_debug = level[1] == KERN_DEBUG[1]; struct va_format vaf; va_list args; + if (is_debug && !(drm_debug & DRM_UT_DRIVER)) + return; + va_start(args, fmt); vaf.fmt = fmt; -- cgit v0.10.2 From c6c794a2fc5e3bc8976fa318fbc7a003ecd712a1 Mon Sep 17 00:00:00 2001 From: Shashank Sharma Date: Tue, 22 Mar 2016 12:01:50 +0200 Subject: drm/i915/bxt: Initialize MIPI DSI for BXT This patch contains following changes: 1. Add BXT MIPI display address base. 2. Call dsi_init from display_setup function. v2: Rebased on latest nightly branch v3 by Jani: init dsi after ddi Signed-off-by: Shashank Sharma Signed-off-by: Uma Shankar Acked-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458640910-5338-1-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 23ca6c0..f3ba43c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1802,6 +1802,7 @@ enum skl_disp_power_wells { #define VLV_DISPLAY_BASE 0x180000 #define VLV_MIPI_BASE VLV_DISPLAY_BASE +#define BXT_MIPI_BASE 0x60000 #define VLV_GU_CTL0 _MMIO(VLV_DISPLAY_BASE + 0x2030) #define VLV_GU_CTL1 _MMIO(VLV_DISPLAY_BASE + 0x2034) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 47332a1..51f913f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14394,6 +14394,8 @@ static void intel_setup_outputs(struct drm_device *dev) intel_ddi_init(dev, PORT_A); intel_ddi_init(dev, PORT_B); intel_ddi_init(dev, PORT_C); + + intel_dsi_init(dev); } else if (HAS_DDI(dev)) { int found; diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 456676c..96ea3f7 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -1163,6 +1163,8 @@ void intel_dsi_init(struct drm_device *dev) if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { dev_priv->mipi_mmio_base = VLV_MIPI_BASE; + } else if (IS_BROXTON(dev)) { + dev_priv->mipi_mmio_base = BXT_MIPI_BASE; } else { DRM_ERROR("Unsupported Mipi device to reg base"); return; -- cgit v0.10.2 From 2dc10cd8bc2662d0311224d92fb82f34be0424bc Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Wed, 23 Mar 2016 10:31:46 +0200 Subject: drm/i915: Fix use after free when printing load failure Commit d15d7538c6d2 ("drm/i915: Tune down init error message due to failure injection") added i915_load_error message to failure path on device initialization. The message is printed after the device is freed. And as the message printing helper uses the device structure, this leads to use after free. Spotted by Kasan. Cc: Imre Deak Cc: Chris Wilson Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1458721906-10625-1-git-send-email-mika.kuoppala@intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a3458fc..fc8ac98 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1398,10 +1398,10 @@ out_runtime_pm_put: intel_runtime_pm_put(dev_priv); i915_driver_cleanup_early(dev_priv); out_free_priv: - kfree(dev_priv); - i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret); + kfree(dev_priv); + return ret; } -- cgit v0.10.2 From 90e83e5390a04d31eb2846293cd3db506c2315e7 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 22 Mar 2016 10:11:24 +0200 Subject: drm/i915: Wait for vblank in i9xx_disable_crtc() for gen 2 only The wait for other gens was added in commit 564ed191f5d8 ("drm/i915: gmch: fix stuck primary plane due to memory self-refresh mode") since that's necessary when disabling cxsr. However, cxsr disabling was later moved to intel_pre_disable_primary() in commit 87d4300a7dbc ("drm/i915: Move intel_(pre_disable/post_enable)_primary to intel_display.c, and use it there.") and that function got its own vblank wait for cxsr in commit 262cd2e154c2 ("drm/i915: CHV DDR DVFS support and another watermark rewrite"). So remove the extra vblank wait from i9xx_crtc_distable(). Cc: Kalyan Kondapally Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1458634284-6080-1-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 51f913f..d007f04 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6212,10 +6212,9 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) /* * On gen2 planes are double buffered but the pipe isn't, so we must * wait for planes to fully turn off before disabling the pipe. - * We also need to wait on all gmch platforms because of the - * self-refresh mode constraint explained above. */ - intel_wait_for_vblank(dev, pipe); + if (IS_GEN2(dev)) + intel_wait_for_vblank(dev, pipe); for_each_encoder_on_crtc(dev, crtc, encoder) encoder->disable(encoder); -- cgit v0.10.2 From ceb41007b42bbc9e4be1cf17575b01de6c3b3b18 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:02 +0200 Subject: drm/i915: Remove checks for cloned config with LVDS in dpll code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LVDS is not cloneable, so the check is unnecessary. Removing it makes the code neater. v2: Remove checks from GMCH code too, not only ILK+. (Ville) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-2-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d007f04..d147d2f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -111,8 +111,7 @@ static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *); static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *); static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state); -static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state, - int num_connectors); +static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state); 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); @@ -1074,7 +1073,7 @@ chv_find_best_dpll(const intel_limit_t *limit, bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock, intel_clock_t *best_clock) { - int refclk = i9xx_get_refclk(crtc_state, 0); + int refclk = i9xx_get_refclk(crtc_state); return chv_find_best_dpll(intel_limit(crtc_state, refclk), crtc_state, target_clock, refclk, NULL, best_clock); @@ -7058,8 +7057,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); } -static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state, - int num_connectors) +static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state) { struct drm_device *dev = crtc_state->base.crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7070,7 +7068,7 @@ static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state, if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) { refclk = 100000; } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_panel_use_ssc(dev_priv) && num_connectors < 2) { + intel_panel_use_ssc(dev_priv)) { refclk = dev_priv->vbt.lvds_ssc_freq; DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); } else if (!IS_GEN2(dev)) { @@ -7511,8 +7509,7 @@ void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe) static void i9xx_compute_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, - intel_clock_t *reduced_clock, - int num_connectors) + intel_clock_t *reduced_clock) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7571,7 +7568,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc, if (crtc_state->sdvo_tv_clock) dpll |= PLL_REF_INPUT_TVCLKINBC; else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_panel_use_ssc(dev_priv) && num_connectors < 2) + intel_panel_use_ssc(dev_priv)) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; else dpll |= PLL_REF_INPUT_DREFCLK; @@ -7588,8 +7585,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc, static void i8xx_compute_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, - intel_clock_t *reduced_clock, - int num_connectors) + intel_clock_t *reduced_clock) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -7615,7 +7611,7 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc, dpll |= DPLL_DVO_2X_MODE; if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_panel_use_ssc(dev_priv) && num_connectors < 2) + intel_panel_use_ssc(dev_priv)) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; else dpll |= PLL_REF_INPUT_DREFCLK; @@ -7843,14 +7839,10 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - int refclk, num_connectors = 0; + int refclk; intel_clock_t clock; bool ok; const intel_limit_t *limit; - struct drm_atomic_state *state = crtc_state->base.state; - struct drm_connector *connector; - struct drm_connector_state *connector_state; - int i; memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); @@ -7858,13 +7850,8 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, if (crtc_state->has_dsi_encoder) return 0; - for_each_connector_in_state(state, connector, connector_state, i) { - if (connector_state->crtc == &crtc->base) - num_connectors++; - } - if (!crtc_state->clock_set) { - refclk = i9xx_get_refclk(crtc_state, num_connectors); + refclk = i9xx_get_refclk(crtc_state); /* * Returns a set of divisors for the desired target clock with @@ -7890,15 +7877,13 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, } if (IS_GEN2(dev)) { - i8xx_compute_dpll(crtc, crtc_state, NULL, - num_connectors); + i8xx_compute_dpll(crtc, crtc_state, NULL); } else if (IS_CHERRYVIEW(dev)) { chv_compute_dpll(crtc, crtc_state); } else if (IS_VALLEYVIEW(dev)) { vlv_compute_dpll(crtc, crtc_state); } else { - i9xx_compute_dpll(crtc, crtc_state, NULL, - num_connectors); + i9xx_compute_dpll(crtc, crtc_state, NULL); } return 0; @@ -8584,30 +8569,9 @@ static int ironlake_get_refclk(struct intel_crtc_state *crtc_state) { struct drm_device *dev = crtc_state->base.crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_atomic_state *state = crtc_state->base.state; - struct drm_connector *connector; - struct drm_connector_state *connector_state; - struct intel_encoder *encoder; - int num_connectors = 0, i; - bool is_lvds = false; - - for_each_connector_in_state(state, connector, connector_state, i) { - if (connector_state->crtc != crtc_state->base.crtc) - continue; - - encoder = to_intel_encoder(connector_state->best_encoder); - - switch (encoder->type) { - case INTEL_OUTPUT_LVDS: - is_lvds = true; - break; - default: - break; - } - num_connectors++; - } - if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && + intel_panel_use_ssc(dev_priv)) { DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", dev_priv->vbt.lvds_ssc_freq); return dev_priv->vbt.lvds_ssc_freq; @@ -8768,7 +8732,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, struct drm_connector_state *connector_state; struct intel_encoder *encoder; uint32_t dpll; - int factor, num_connectors = 0, i; + int factor, i; bool is_lvds = false, is_sdvo = false; for_each_connector_in_state(state, connector, connector_state, i) { @@ -8788,8 +8752,6 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, default: break; } - - num_connectors++; } /* Enable autotuning of the PLL clock (if permissible) */ @@ -8843,7 +8805,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, break; } - if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) + if (is_lvds && intel_panel_use_ssc(dev_priv)) dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; else dpll |= PLL_REF_INPUT_DREFCLK; -- cgit v0.10.2 From 26ce6d5980fa399e7ca4cb83414ece931ce316ba Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:03 +0200 Subject: drm/i915: Merge ironlake_get_refclk() into its only caller A previous patch made ironlake_get_refclk() very simple, so merge it into its only caller. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-3-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d147d2f..78fb86c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8565,21 +8565,6 @@ void intel_init_pch_refclk(struct drm_device *dev) lpt_init_pch_refclk(dev); } -static int ironlake_get_refclk(struct intel_crtc_state *crtc_state) -{ - struct drm_device *dev = crtc_state->base.crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - - if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_panel_use_ssc(dev_priv)) { - DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", - dev_priv->vbt.lvds_ssc_freq); - return dev_priv->vbt.lvds_ssc_freq; - } - - return 120000; -} - static void ironlake_set_pipeconf(struct drm_crtc *crtc) { struct drm_i915_private *dev_priv = crtc->dev->dev_private; @@ -8686,7 +8671,14 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, const intel_limit_t *limit; bool ret; - refclk = ironlake_get_refclk(crtc_state); + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && + intel_panel_use_ssc(dev_priv)) { + DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", + dev_priv->vbt.lvds_ssc_freq); + refclk = dev_priv->vbt.lvds_ssc_freq; + } else { + refclk = 120000; + } /* * Returns a set of divisors for the desired target clock with the given -- cgit v0.10.2 From 8f0d5b9b5891d7e29513bba44fe6c5c3d84df1d8 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:04 +0200 Subject: drm/i915: Fold intel_ironlake_limit() into clock computation function The function intel_ironlake_limit() is only called by the crtc compute clock path. By merging it into ironlake_compute_clocks(), the code gets clearer, since there's no more if-ladders to follow. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-4-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 78fb86c..8c90426 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -566,30 +566,6 @@ static bool intel_pipe_will_have_type(const struct intel_crtc_state *crtc_state, } static const intel_limit_t * -intel_ironlake_limit(struct intel_crtc_state *crtc_state, int refclk) -{ - struct drm_device *dev = crtc_state->base.crtc->dev; - const intel_limit_t *limit; - - if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) { - if (intel_is_dual_link_lvds(dev)) { - if (refclk == 100000) - limit = &intel_limits_ironlake_dual_lvds_100m; - else - limit = &intel_limits_ironlake_dual_lvds; - } else { - if (refclk == 100000) - limit = &intel_limits_ironlake_single_lvds_100m; - else - limit = &intel_limits_ironlake_single_lvds; - } - } else - limit = &intel_limits_ironlake_dac; - - return limit; -} - -static const intel_limit_t * intel_g4x_limit(struct intel_crtc_state *crtc_state) { struct drm_device *dev = crtc_state->base.crtc->dev; @@ -619,8 +595,8 @@ intel_limit(struct intel_crtc_state *crtc_state, int refclk) if (IS_BROXTON(dev)) limit = &intel_limits_bxt; - else if (HAS_PCH_SPLIT(dev)) - limit = intel_ironlake_limit(crtc_state, refclk); + else if (WARN_ON(HAS_PCH_SPLIT(dev))) + limit = NULL; else if (IS_G4X(dev)) { limit = intel_g4x_limit(crtc_state); } else if (IS_PINEVIEW(dev)) { @@ -8671,13 +8647,28 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, const intel_limit_t *limit; bool ret; - if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_panel_use_ssc(dev_priv)) { - DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", - dev_priv->vbt.lvds_ssc_freq); - refclk = dev_priv->vbt.lvds_ssc_freq; + refclk = 120000; + + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) { + if (intel_panel_use_ssc(dev_priv)) { + DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", + dev_priv->vbt.lvds_ssc_freq); + refclk = dev_priv->vbt.lvds_ssc_freq; + } + + if (intel_is_dual_link_lvds(dev)) { + if (refclk == 100000) + limit = &intel_limits_ironlake_dual_lvds_100m; + else + limit = &intel_limits_ironlake_dual_lvds; + } else { + if (refclk == 100000) + limit = &intel_limits_ironlake_single_lvds_100m; + else + limit = &intel_limits_ironlake_single_lvds; + } } else { - refclk = 120000; + limit = &intel_limits_ironlake_dac; } /* @@ -8685,7 +8676,6 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, * refclk, or FALSE. The returned values represent the clock equation: * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. */ - limit = intel_limit(crtc_state, refclk); ret = dev_priv->display.find_dpll(limit, crtc_state, crtc_state->port_clock, refclk, NULL, clock); -- cgit v0.10.2 From 2d7feacc817e8882ab87f29e468918f6dbabf611 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:05 +0200 Subject: drm/i915: Call g4x_find_best_dpll() directly from ILK+ code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The call to dev_priv->display.find_dpll() is already in platform specific code, so avoid the extra detour. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Ville Syrjälä Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-5-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8c90426..14f6e30 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8676,9 +8676,8 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, * refclk, or FALSE. The returned values represent the clock equation: * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. */ - ret = dev_priv->display.find_dpll(limit, crtc_state, - crtc_state->port_clock, - refclk, NULL, clock); + ret = g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock, + refclk, NULL, clock); if (!ret) return false; -- cgit v0.10.2 From bfa044457c8a0ea20f4aee33337232a3bcfa1dcf Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:06 +0200 Subject: drm/i915: Simplify ironlake reduced clock logic a bit Check has_reduced_clock only once when setting dpll_hw_state, making the code slightly more readable. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-6-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 14f6e30..25d7639 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8832,6 +8832,8 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, fp = i9xx_dpll_compute_fp(&crtc_state->dpll); if (has_reduced_clock) fp2 = i9xx_dpll_compute_fp(&reduced_clock); + else + fp2 = fp; dpll = ironlake_compute_dpll(crtc, crtc_state, &fp, &reduced_clock, @@ -8839,10 +8841,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, crtc_state->dpll_hw_state.dpll = dpll; crtc_state->dpll_hw_state.fp0 = fp; - if (has_reduced_clock) - crtc_state->dpll_hw_state.fp1 = fp2; - else - crtc_state->dpll_hw_state.fp1 = fp; + crtc_state->dpll_hw_state.fp1 = fp2; pll = intel_get_shared_dpll(crtc, crtc_state, NULL); if (pll == NULL) { -- cgit v0.10.2 From 7ed9f894e55e5a623c640d2e5be5db2b0bf14374 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:07 +0200 Subject: drm/i915: Don't calculate a new clock in ILK+ code if it is already set Remove the clock calculation from ironlake_crtc_compute_clock() when the encoder compute_config() already set one. The value was just thrown away in that case. Note that the previously set clock is not validated against the limits anymore. That is ok since the fixed clocks from DP and SDVO are within the supported range, so the call to ironlake_compute_clocks() would never fail in that case. v2: Add note about not checking fixed clocks agains limits. (Maarten) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-7-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 25d7639..2df5dbf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8800,7 +8800,7 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; intel_clock_t clock, reduced_clock; u32 dpll = 0, fp = 0, fp2 = 0; - bool ok, has_reduced_clock = false; + bool has_reduced_clock = false; bool is_lvds = false; struct intel_shared_dpll *pll; @@ -8812,14 +8812,15 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)), "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev)); - ok = ironlake_compute_clocks(&crtc->base, crtc_state, &clock, - &has_reduced_clock, &reduced_clock); - if (!ok && !crtc_state->clock_set) { - DRM_ERROR("Couldn't find PLL settings for mode!\n"); - return -EINVAL; - } - /* Compat-code for transition, will disappear. */ if (!crtc_state->clock_set) { + if (!ironlake_compute_clocks(&crtc->base, crtc_state, &clock, + &has_reduced_clock, + &reduced_clock)) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; + } + + /* Compat-code for transition, will disappear. */ crtc_state->dpll.n = clock.n; crtc_state->dpll.m1 = clock.m1; crtc_state->dpll.m2 = clock.m2; -- cgit v0.10.2 From fade85ae2122cd6f136cbbfe2c1a392910354cdf Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:08 +0200 Subject: drm/i915: Remove PCH type checks from ironlake_crtc_compute_clock() The checks were added in commit 5dc5298bb3e5 ("drm/i915: add proper CPU/PCH checks to crtc_mode_set functions") in a time when there was doubts on what PCHs would be supported by HSW. There are similar checks for PCH type in intel_detect_pch() and the function pointers are initialized based on platform/pch information, so the removed WARN can't ever be reached. v2: Rebase without patch that drops lvds downclock code. (Ville) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-8-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2df5dbf..c6920fc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8797,7 +8797,6 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { - struct drm_device *dev = crtc->base.dev; intel_clock_t clock, reduced_clock; u32 dpll = 0, fp = 0, fp2 = 0; bool has_reduced_clock = false; @@ -8809,9 +8808,6 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, is_lvds = intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS); - WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)), - "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev)); - if (!crtc_state->clock_set) { if (!ironlake_compute_clocks(&crtc->base, crtc_state, &clock, &has_reduced_clock, -- cgit v0.10.2 From ded220e2513dee45807ba586a566f64b2887c2c4 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:09 +0200 Subject: drm/i915: Simplify ironlake_crtc_compute_clock() CPU eDP case None of the code in ironlake_crtc_compute_clock() is relevant for CPU eDP. The CPU eDP PLL is turned on and off in ironlake_edp_pll_{on,off} from the DP code and that doesn't depend on the crtc_state->dpll values, so just return early in that case. v2: Rebase without patch that drops lvds downclock code. (Ville) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-9-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c6920fc..0a5e855 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8800,13 +8800,16 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, intel_clock_t clock, reduced_clock; u32 dpll = 0, fp = 0, fp2 = 0; bool has_reduced_clock = false; - bool is_lvds = false; struct intel_shared_dpll *pll; memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); - is_lvds = intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS); + crtc->lowfreq_avail = false; + + /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */ + if (!crtc_state->has_pch_encoder) + return 0; if (!crtc_state->clock_set) { if (!ironlake_compute_clocks(&crtc->base, crtc_state, &clock, @@ -8824,34 +8827,30 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, crtc_state->dpll.p2 = clock.p2; } - /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */ - if (crtc_state->has_pch_encoder) { - fp = i9xx_dpll_compute_fp(&crtc_state->dpll); - if (has_reduced_clock) - fp2 = i9xx_dpll_compute_fp(&reduced_clock); - else - fp2 = fp; + fp = i9xx_dpll_compute_fp(&crtc_state->dpll); + if (has_reduced_clock) + fp2 = i9xx_dpll_compute_fp(&reduced_clock); + else + fp2 = fp; - dpll = ironlake_compute_dpll(crtc, crtc_state, - &fp, &reduced_clock, - has_reduced_clock ? &fp2 : NULL); + dpll = ironlake_compute_dpll(crtc, crtc_state, + &fp, &reduced_clock, + has_reduced_clock ? &fp2 : NULL); - crtc_state->dpll_hw_state.dpll = dpll; - crtc_state->dpll_hw_state.fp0 = fp; - crtc_state->dpll_hw_state.fp1 = fp2; + crtc_state->dpll_hw_state.dpll = dpll; + crtc_state->dpll_hw_state.fp0 = fp; + crtc_state->dpll_hw_state.fp1 = fp2; - pll = intel_get_shared_dpll(crtc, crtc_state, NULL); - if (pll == NULL) { - DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", - pipe_name(crtc->pipe)); - return -EINVAL; - } + pll = intel_get_shared_dpll(crtc, crtc_state, NULL); + if (pll == NULL) { + DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", + pipe_name(crtc->pipe)); + return -EINVAL; } - if (is_lvds && has_reduced_clock) + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && + has_reduced_clock) crtc->lowfreq_avail = true; - else - crtc->lowfreq_avail = false; return 0; } -- cgit v0.10.2 From 364ee29d12062458286f560bbca10e523088204e Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:10 +0200 Subject: drm/i915: Pass crtc_state->dpll directly to ->find_dpll() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When calculating clocks, just pass a pointer to crtc_state->dpll directly to the find_dpll() hook. Back when this was introduced in commit f47709a9502f3 ("drm/i915: create pipe_config->dpll for clock state") there was no staged crtc config or atomic crtc state, so it was possible to overwrite the current configuration on error. That hasn't been the case for a while now, so finally make it "disappear". Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-10-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0a5e855..c803006 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7816,7 +7816,6 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; int refclk; - intel_clock_t clock; bool ok; const intel_limit_t *limit; @@ -7838,18 +7837,12 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, limit = intel_limit(crtc_state, refclk); ok = dev_priv->display.find_dpll(limit, crtc_state, crtc_state->port_clock, - refclk, NULL, &clock); + refclk, NULL, + &crtc_state->dpll); if (!ok) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); return -EINVAL; } - - /* Compat-code for transition, will disappear. */ - crtc_state->dpll.n = clock.n; - crtc_state->dpll.m1 = clock.m1; - crtc_state->dpll.m2 = clock.m2; - crtc_state->dpll.p1 = clock.p1; - crtc_state->dpll.p2 = clock.p2; } if (IS_GEN2(dev)) { @@ -8797,7 +8790,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { - intel_clock_t clock, reduced_clock; + intel_clock_t reduced_clock; u32 dpll = 0, fp = 0, fp2 = 0; bool has_reduced_clock = false; struct intel_shared_dpll *pll; @@ -8811,20 +8804,13 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, if (!crtc_state->has_pch_encoder) return 0; - if (!crtc_state->clock_set) { - if (!ironlake_compute_clocks(&crtc->base, crtc_state, &clock, - &has_reduced_clock, - &reduced_clock)) { - DRM_ERROR("Couldn't find PLL settings for mode!\n"); - return -EINVAL; - } - - /* Compat-code for transition, will disappear. */ - crtc_state->dpll.n = clock.n; - crtc_state->dpll.m1 = clock.m1; - crtc_state->dpll.m2 = clock.m2; - crtc_state->dpll.p1 = clock.p1; - crtc_state->dpll.p2 = clock.p2; + if (!crtc_state->clock_set && + !ironlake_compute_clocks(&crtc->base, crtc_state, + &crtc_state->dpll, + &has_reduced_clock, + &reduced_clock)) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; } fp = i9xx_dpll_compute_fp(&crtc_state->dpll); -- cgit v0.10.2 From b75ca6f62e57923e9c2870bf8d795c410ebb9534 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:11 +0200 Subject: drm/i915: Move fp divisor calculation into ironlake_compute_dpll() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow what is done in i8xx_compute_dpll() and i9xx_compute_dpll() and move the lower level details of setting crtc_state->dpll_hw_state into the _compute_dpll() function. Reviewed-by: Ville Syrjälä Signed-off-by: Ander Conselvan de Oliveira Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-11-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c803006..9741ee7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8693,10 +8693,9 @@ static bool ironlake_needs_fb_cb_tune(struct dpll *dpll, int factor) return i9xx_dpll_compute_m(dpll) < factor * dpll->n; } -static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, - struct intel_crtc_state *crtc_state, - u32 *fp, - intel_clock_t *reduced_clock, u32 *fp2) +static void ironlake_compute_dpll(struct intel_crtc *intel_crtc, + struct intel_crtc_state *crtc_state, + intel_clock_t *reduced_clock) { struct drm_crtc *crtc = &intel_crtc->base; struct drm_device *dev = crtc->dev; @@ -8705,7 +8704,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, struct drm_connector *connector; struct drm_connector_state *connector_state; struct intel_encoder *encoder; - uint32_t dpll; + u32 dpll, fp, fp2; int factor, i; bool is_lvds = false, is_sdvo = false; @@ -8738,11 +8737,19 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, } else if (crtc_state->sdvo_tv_clock) factor = 20; + fp = i9xx_dpll_compute_fp(&crtc_state->dpll); + if (ironlake_needs_fb_cb_tune(&crtc_state->dpll, factor)) - *fp |= FP_CB_TUNE; + fp |= FP_CB_TUNE; + + if (reduced_clock) { + fp2 = i9xx_dpll_compute_fp(reduced_clock); - if (fp2 && (reduced_clock->m < factor * reduced_clock->n)) - *fp2 |= FP_CB_TUNE; + if (reduced_clock->m < factor * reduced_clock->n) + fp2 |= FP_CB_TUNE; + } else { + fp2 = fp; + } dpll = 0; @@ -8784,14 +8791,17 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc, else dpll |= PLL_REF_INPUT_DREFCLK; - return dpll | DPLL_VCO_ENABLE; + dpll |= DPLL_VCO_ENABLE; + + crtc_state->dpll_hw_state.dpll = dpll; + crtc_state->dpll_hw_state.fp0 = fp; + crtc_state->dpll_hw_state.fp1 = fp2; } static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { intel_clock_t reduced_clock; - u32 dpll = 0, fp = 0, fp2 = 0; bool has_reduced_clock = false; struct intel_shared_dpll *pll; @@ -8813,19 +8823,8 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, return -EINVAL; } - fp = i9xx_dpll_compute_fp(&crtc_state->dpll); - if (has_reduced_clock) - fp2 = i9xx_dpll_compute_fp(&reduced_clock); - else - fp2 = fp; - - dpll = ironlake_compute_dpll(crtc, crtc_state, - &fp, &reduced_clock, - has_reduced_clock ? &fp2 : NULL); - - crtc_state->dpll_hw_state.dpll = dpll; - crtc_state->dpll_hw_state.fp0 = fp; - crtc_state->dpll_hw_state.fp1 = fp2; + ironlake_compute_dpll(crtc, crtc_state, + has_reduced_clock ? &reduced_clock : NULL); pll = intel_get_shared_dpll(crtc, crtc_state, NULL); if (pll == NULL) { -- cgit v0.10.2 From 997c030cfdd0f87ca5ac8b77ef0821c5597263f8 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:12 +0200 Subject: drm/i915: Merge ironlake_compute_clocks() and ironlake_crtc_compute_clock() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge ironlake_compute_clocks() into ironlake_crtc_compute_clock() so the clock computation logic is all in one place. The resulting function is still quite simple. Follow up patches will make the similar code for GMCH platforms look similar. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-12-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9741ee7..894091f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -846,6 +846,11 @@ pnv_find_best_dpll(const intel_limit_t *limit, return (err != target); } +/* + * Returns a set of divisors for the desired target clock with the given + * refclk, or FALSE. The returned values represent the clock equation: + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + */ static bool g4x_find_best_dpll(const intel_limit_t *limit, struct intel_crtc_state *crtc_state, @@ -8628,55 +8633,6 @@ static void haswell_set_pipemisc(struct drm_crtc *crtc) } } -static bool ironlake_compute_clocks(struct drm_crtc *crtc, - struct intel_crtc_state *crtc_state, - intel_clock_t *clock, - bool *has_reduced_clock, - intel_clock_t *reduced_clock) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int refclk; - const intel_limit_t *limit; - bool ret; - - refclk = 120000; - - if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) { - if (intel_panel_use_ssc(dev_priv)) { - DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", - dev_priv->vbt.lvds_ssc_freq); - refclk = dev_priv->vbt.lvds_ssc_freq; - } - - if (intel_is_dual_link_lvds(dev)) { - if (refclk == 100000) - limit = &intel_limits_ironlake_dual_lvds_100m; - else - limit = &intel_limits_ironlake_dual_lvds; - } else { - if (refclk == 100000) - limit = &intel_limits_ironlake_single_lvds_100m; - else - limit = &intel_limits_ironlake_single_lvds; - } - } else { - limit = &intel_limits_ironlake_dac; - } - - /* - * Returns a set of divisors for the desired target clock with the given - * refclk, or FALSE. The returned values represent the clock equation: - * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. - */ - ret = g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock, - refclk, NULL, clock); - if (!ret) - return false; - - return true; -} - int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp) { /* @@ -8801,9 +8757,13 @@ static void ironlake_compute_dpll(struct intel_crtc *intel_crtc, static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; intel_clock_t reduced_clock; bool has_reduced_clock = false; struct intel_shared_dpll *pll; + const intel_limit_t *limit; + int refclk = 120000; memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); @@ -8814,11 +8774,31 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, if (!crtc_state->has_pch_encoder) return 0; + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) { + if (intel_panel_use_ssc(dev_priv)) { + DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", + dev_priv->vbt.lvds_ssc_freq); + refclk = dev_priv->vbt.lvds_ssc_freq; + } + + if (intel_is_dual_link_lvds(dev)) { + if (refclk == 100000) + limit = &intel_limits_ironlake_dual_lvds_100m; + else + limit = &intel_limits_ironlake_dual_lvds; + } else { + if (refclk == 100000) + limit = &intel_limits_ironlake_single_lvds_100m; + else + limit = &intel_limits_ironlake_single_lvds; + } + } else { + limit = &intel_limits_ironlake_dac; + } + if (!crtc_state->clock_set && - !ironlake_compute_clocks(&crtc->base, crtc_state, - &crtc_state->dpll, - &has_reduced_clock, - &reduced_clock)) { + !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock, + refclk, NULL, &crtc_state->dpll)) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); return -EINVAL; } -- cgit v0.10.2 From 65b3d6a976490bc731ad56e287965223030abe89 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:13 +0200 Subject: drm/i915: Split CHV and VLV specific crtc_compute_clock() hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order for VLV and CHV to use i9xx_crtc_compute_clocks(), a number of if ladders is necessary: one for setting the find_dpll() hook, one for choosing the limits struct, one for choosing the right compute dpll function and one for initializing the crtc_compute_clock() hook. By extracting a platform specific implementation for each platform, the number of if-ladders is reduced to one. While at it also clean up bxt_find_best_dpll() which depends on some of the CHV code. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-13-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 894091f..688fdb8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -111,7 +111,6 @@ static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *); static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *); static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state); -static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state); 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); @@ -593,21 +592,17 @@ intel_limit(struct intel_crtc_state *crtc_state, int refclk) struct drm_device *dev = crtc_state->base.crtc->dev; const intel_limit_t *limit; - if (IS_BROXTON(dev)) - limit = &intel_limits_bxt; - else if (WARN_ON(HAS_PCH_SPLIT(dev))) + if (IS_BROXTON(dev) || IS_CHERRYVIEW(dev) || IS_VALLEYVIEW(dev) || + HAS_PCH_SPLIT(dev)) limit = NULL; - else if (IS_G4X(dev)) { + + if (IS_G4X(dev)) { limit = intel_g4x_limit(crtc_state); } else if (IS_PINEVIEW(dev)) { if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) limit = &intel_limits_pineview_lvds; else limit = &intel_limits_pineview_sdvo; - } else if (IS_CHERRYVIEW(dev)) { - limit = &intel_limits_chv; - } else if (IS_VALLEYVIEW(dev)) { - limit = &intel_limits_vlv; } else if (!IS_GEN2(dev)) { if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) limit = &intel_limits_i9xx_lvds; @@ -621,6 +616,9 @@ intel_limit(struct intel_crtc_state *crtc_state, int refclk) else limit = &intel_limits_i8xx_dac; } + + WARN_ON(limit == NULL); + return limit; } @@ -939,6 +937,11 @@ static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq, return *error_ppm + 10 < best_error_ppm; } +/* + * Returns a set of divisors for the desired target clock with the given + * refclk, or FALSE. The returned values represent the clock equation: + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + */ static bool vlv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc_state *crtc_state, @@ -993,6 +996,11 @@ vlv_find_best_dpll(const intel_limit_t *limit, return found; } +/* + * Returns a set of divisors for the desired target clock with the given + * refclk, or FALSE. The returned values represent the clock equation: + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + */ static bool chv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc_state *crtc_state, @@ -1054,9 +1062,10 @@ chv_find_best_dpll(const intel_limit_t *limit, bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock, intel_clock_t *best_clock) { - int refclk = i9xx_get_refclk(crtc_state); + int refclk = 100000; + const intel_limit_t *limit = &intel_limits_bxt; - return chv_find_best_dpll(intel_limit(crtc_state, refclk), crtc_state, + return chv_find_best_dpll(limit, crtc_state, target_clock, refclk, NULL, best_clock); } @@ -7046,9 +7055,7 @@ static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state) WARN_ON(!crtc_state->base.state); - if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) { - refclk = 100000; - } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && intel_panel_use_ssc(dev_priv)) { refclk = dev_priv->vbt.lvds_ssc_freq; DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); @@ -7852,10 +7859,6 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, if (IS_GEN2(dev)) { i8xx_compute_dpll(crtc, crtc_state, NULL); - } else if (IS_CHERRYVIEW(dev)) { - chv_compute_dpll(crtc, crtc_state); - } else if (IS_VALLEYVIEW(dev)) { - vlv_compute_dpll(crtc, crtc_state); } else { i9xx_compute_dpll(crtc, crtc_state, NULL); } @@ -7863,6 +7866,54 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, return 0; } +static int chv_crtc_compute_clock(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + int refclk = 100000; + const intel_limit_t *limit = &intel_limits_chv; + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + + if (crtc_state->has_dsi_encoder) + return 0; + + if (!crtc_state->clock_set && + !chv_find_best_dpll(limit, crtc_state, crtc_state->port_clock, + refclk, NULL, &crtc_state->dpll)) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; + } + + chv_compute_dpll(crtc, crtc_state); + + return 0; +} + +static int vlv_crtc_compute_clock(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + int refclk = 100000; + const intel_limit_t *limit = &intel_limits_vlv; + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + + if (crtc_state->has_dsi_encoder) + return 0; + + if (!crtc_state->clock_set && + !vlv_find_best_dpll(limit, crtc_state, crtc_state->port_clock, + refclk, NULL, &crtc_state->dpll)) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; + } + + vlv_compute_dpll(crtc, crtc_state); + + return 0; +} + static void i9xx_get_pfit_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { @@ -14724,10 +14775,6 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) { if (HAS_PCH_SPLIT(dev_priv) || IS_G4X(dev_priv)) dev_priv->display.find_dpll = g4x_find_best_dpll; - else if (IS_CHERRYVIEW(dev_priv)) - dev_priv->display.find_dpll = chv_find_best_dpll; - else if (IS_VALLEYVIEW(dev_priv)) - dev_priv->display.find_dpll = vlv_find_best_dpll; else if (IS_PINEVIEW(dev_priv)) dev_priv->display.find_dpll = pnv_find_best_dpll; else @@ -14757,11 +14804,18 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) ironlake_crtc_compute_clock; dev_priv->display.crtc_enable = ironlake_crtc_enable; dev_priv->display.crtc_disable = ironlake_crtc_disable; - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + } else if (IS_CHERRYVIEW(dev_priv)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.get_initial_plane_config = i9xx_get_initial_plane_config; - dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock; + dev_priv->display.crtc_compute_clock = chv_crtc_compute_clock; + dev_priv->display.crtc_enable = valleyview_crtc_enable; + dev_priv->display.crtc_disable = i9xx_crtc_disable; + } else if (IS_VALLEYVIEW(dev_priv)) { + dev_priv->display.get_pipe_config = i9xx_get_pipe_config; + dev_priv->display.get_initial_plane_config = + i9xx_get_initial_plane_config; + dev_priv->display.crtc_compute_clock = vlv_crtc_compute_clock; dev_priv->display.crtc_enable = valleyview_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; } else { -- cgit v0.10.2 From 81c97f522e41c022f96cd009feacb9acb994f115 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 22 Mar 2016 15:35:23 +0200 Subject: drm/i915: Split i8xx_crtc_compute_clock() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split a GEN2 specific version from i9xx_crtc_compute_clock(). With this there is no need for i9xx_get_refclk() anymore, and the differences between platforms become more obvious. v2: Use i8xx as prefix instead of gen2. (Ville and Daniel) Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458653723-17951-1-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 688fdb8..611757a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -593,7 +593,7 @@ intel_limit(struct intel_crtc_state *crtc_state, int refclk) const intel_limit_t *limit; if (IS_BROXTON(dev) || IS_CHERRYVIEW(dev) || IS_VALLEYVIEW(dev) || - HAS_PCH_SPLIT(dev)) + HAS_PCH_SPLIT(dev) || IS_GEN2(dev)) limit = NULL; if (IS_G4X(dev)) { @@ -608,13 +608,6 @@ intel_limit(struct intel_crtc_state *crtc_state, int refclk) limit = &intel_limits_i9xx_lvds; else limit = &intel_limits_i9xx_sdvo; - } else { - if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) - limit = &intel_limits_i8xx_lvds; - else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_DVO)) - limit = &intel_limits_i8xx_dvo; - else - limit = &intel_limits_i8xx_dac; } WARN_ON(limit == NULL); @@ -7047,27 +7040,6 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); } -static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state) -{ - struct drm_device *dev = crtc_state->base.crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - int refclk; - - WARN_ON(!crtc_state->base.state); - - if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_panel_use_ssc(dev_priv)) { - refclk = dev_priv->vbt.lvds_ssc_freq; - DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); - } else if (!IS_GEN2(dev)) { - refclk = 96000; - } else { - refclk = 48000; - } - - return refclk; -} - static uint32_t pnv_dpll_compute_fp(struct dpll *dpll) { return (1 << dpll->n) << 16 | dpll->m2; @@ -7822,14 +7794,50 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) POSTING_READ(PIPECONF(intel_crtc->pipe)); } +static int i8xx_crtc_compute_clock(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + const intel_limit_t *limit; + int refclk = 48000; + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) { + if (intel_panel_use_ssc(dev_priv)) { + refclk = dev_priv->vbt.lvds_ssc_freq; + DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); + } + + limit = &intel_limits_i8xx_lvds; + } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_DVO)) { + limit = &intel_limits_i8xx_dvo; + } else { + limit = &intel_limits_i8xx_dac; + } + + if (!crtc_state->clock_set && + !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock, + refclk, NULL, &crtc_state->dpll)) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; + } + + i8xx_compute_dpll(crtc, crtc_state, NULL); + + return 0; +} + static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - int refclk; bool ok; const intel_limit_t *limit; + int refclk = 96000; memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); @@ -7837,9 +7845,13 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, if (crtc_state->has_dsi_encoder) return 0; - if (!crtc_state->clock_set) { - refclk = i9xx_get_refclk(crtc_state); + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && + intel_panel_use_ssc(dev_priv)) { + refclk = dev_priv->vbt.lvds_ssc_freq; + DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); + } + if (!crtc_state->clock_set) { /* * Returns a set of divisors for the desired target clock with * the given refclk, or FALSE. The returned values represent @@ -7857,11 +7869,7 @@ static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, } } - if (IS_GEN2(dev)) { - i8xx_compute_dpll(crtc, crtc_state, NULL); - } else { - i9xx_compute_dpll(crtc, crtc_state, NULL); - } + i9xx_compute_dpll(crtc, crtc_state, NULL); return 0; } @@ -14818,13 +14826,20 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) dev_priv->display.crtc_compute_clock = vlv_crtc_compute_clock; dev_priv->display.crtc_enable = valleyview_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; - } else { + } else if (!IS_GEN2(dev_priv)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.get_initial_plane_config = i9xx_get_initial_plane_config; dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock; dev_priv->display.crtc_enable = i9xx_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; + } else { + dev_priv->display.get_pipe_config = i9xx_get_pipe_config; + dev_priv->display.get_initial_plane_config = + i9xx_get_initial_plane_config; + dev_priv->display.crtc_compute_clock = i8xx_crtc_compute_clock; + dev_priv->display.crtc_enable = i9xx_crtc_enable; + dev_priv->display.crtc_disable = i9xx_crtc_disable; } /* Returns the core display clock speed */ -- cgit v0.10.2 From 19ec6693098c80d3fd693d9defbc7e46e60e1c1b Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:15 +0200 Subject: drm/i915: Split g4x_crtc_compute_clock() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split a G4X specific version from i9xx_crtc_compute_clock(). With this the differences between platforms become more obvious. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-15-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 611757a..2764ade 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -565,40 +565,16 @@ static bool intel_pipe_will_have_type(const struct intel_crtc_state *crtc_state, } static const intel_limit_t * -intel_g4x_limit(struct intel_crtc_state *crtc_state) -{ - struct drm_device *dev = crtc_state->base.crtc->dev; - const intel_limit_t *limit; - - if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) { - if (intel_is_dual_link_lvds(dev)) - limit = &intel_limits_g4x_dual_channel_lvds; - else - limit = &intel_limits_g4x_single_channel_lvds; - } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_HDMI) || - intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_ANALOG)) { - limit = &intel_limits_g4x_hdmi; - } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_SDVO)) { - limit = &intel_limits_g4x_sdvo; - } else /* The option is for other outputs */ - limit = &intel_limits_i9xx_sdvo; - - return limit; -} - -static const intel_limit_t * intel_limit(struct intel_crtc_state *crtc_state, int refclk) { struct drm_device *dev = crtc_state->base.crtc->dev; const intel_limit_t *limit; if (IS_BROXTON(dev) || IS_CHERRYVIEW(dev) || IS_VALLEYVIEW(dev) || - HAS_PCH_SPLIT(dev) || IS_GEN2(dev)) + HAS_PCH_SPLIT(dev) || IS_G4X(dev) || IS_GEN2(dev)) limit = NULL; - if (IS_G4X(dev)) { - limit = intel_g4x_limit(crtc_state); - } else if (IS_PINEVIEW(dev)) { + if (IS_PINEVIEW(dev)) { if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) limit = &intel_limits_pineview_lvds; else @@ -7830,6 +7806,49 @@ static int i8xx_crtc_compute_clock(struct intel_crtc *crtc, return 0; } +static int g4x_crtc_compute_clock(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + const intel_limit_t *limit; + int refclk = 96000; + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) { + if (intel_panel_use_ssc(dev_priv)) { + refclk = dev_priv->vbt.lvds_ssc_freq; + DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); + } + + if (intel_is_dual_link_lvds(dev)) + limit = &intel_limits_g4x_dual_channel_lvds; + else + limit = &intel_limits_g4x_single_channel_lvds; + } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_HDMI) || + intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_ANALOG)) { + limit = &intel_limits_g4x_hdmi; + } else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_SDVO)) { + limit = &intel_limits_g4x_sdvo; + } else { + /* The option is for other outputs */ + limit = &intel_limits_i9xx_sdvo; + } + + if (!crtc_state->clock_set && + !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock, + refclk, NULL, &crtc_state->dpll)) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; + } + + i9xx_compute_dpll(crtc, crtc_state, NULL); + + return 0; +} + static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { @@ -14781,9 +14800,7 @@ static const struct drm_mode_config_funcs intel_mode_funcs = { */ void intel_init_display_hooks(struct drm_i915_private *dev_priv) { - if (HAS_PCH_SPLIT(dev_priv) || IS_G4X(dev_priv)) - dev_priv->display.find_dpll = g4x_find_best_dpll; - else if (IS_PINEVIEW(dev_priv)) + if (IS_PINEVIEW(dev_priv)) dev_priv->display.find_dpll = pnv_find_best_dpll; else dev_priv->display.find_dpll = i9xx_find_best_dpll; @@ -14826,6 +14843,13 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) dev_priv->display.crtc_compute_clock = vlv_crtc_compute_clock; dev_priv->display.crtc_enable = valleyview_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; + } else if (IS_G4X(dev_priv)) { + dev_priv->display.get_pipe_config = i9xx_get_pipe_config; + dev_priv->display.get_initial_plane_config = + i9xx_get_initial_plane_config; + dev_priv->display.crtc_compute_clock = g4x_crtc_compute_clock; + dev_priv->display.crtc_enable = i9xx_crtc_enable; + dev_priv->display.crtc_disable = i9xx_crtc_disable; } else if (!IS_GEN2(dev_priv)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.get_initial_plane_config = -- cgit v0.10.2 From 70e8aa215623b5c4d3d3457fd6e6090ad6bfe9a3 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 21 Mar 2016 18:00:16 +0200 Subject: drm/i915: Split PNV version of crtc_compute_clock() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split a pnv_crtc_compute_clock(), so the differences between platforms become more obvious. With this, there are no more users of intel_limit() or the ->find_dpll() hook, so get rid of them. Signed-off-by: Ander Conselvan de Oliveira Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458576016-30348-16-git-send-email-ander.conselvan.de.oliveira@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9d29ab0..08b88c0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -575,24 +575,6 @@ struct dpll; struct drm_i915_display_funcs { int (*get_display_clock_speed)(struct drm_device *dev); int (*get_fifo_size)(struct drm_device *dev, int plane); - /** - * find_dpll() - Find the best values for the PLL - * @limit: limits for the PLL - * @crtc: current CRTC - * @target: target frequency in kHz - * @refclk: reference clock frequency in kHz - * @match_clock: if provided, @best_clock P divider must - * match the P divider from @match_clock - * used for LVDS downclocking - * @best_clock: best PLL values found - * - * Returns true on success, false on failure. - */ - bool (*find_dpll)(const struct intel_limit *limit, - struct intel_crtc_state *crtc_state, - int target, int refclk, - struct dpll *match_clock, - struct dpll *best_clock); int (*compute_pipe_wm)(struct intel_crtc_state *cstate); int (*compute_intermediate_wm)(struct drm_device *dev, struct intel_crtc *intel_crtc, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2764ade..009b03b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -564,33 +564,6 @@ static bool intel_pipe_will_have_type(const struct intel_crtc_state *crtc_state, return false; } -static const intel_limit_t * -intel_limit(struct intel_crtc_state *crtc_state, int refclk) -{ - struct drm_device *dev = crtc_state->base.crtc->dev; - const intel_limit_t *limit; - - if (IS_BROXTON(dev) || IS_CHERRYVIEW(dev) || IS_VALLEYVIEW(dev) || - HAS_PCH_SPLIT(dev) || IS_G4X(dev) || IS_GEN2(dev)) - limit = NULL; - - if (IS_PINEVIEW(dev)) { - if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) - limit = &intel_limits_pineview_lvds; - else - limit = &intel_limits_pineview_sdvo; - } else if (!IS_GEN2(dev)) { - if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) - limit = &intel_limits_i9xx_lvds; - else - limit = &intel_limits_i9xx_sdvo; - } - - WARN_ON(limit == NULL); - - return limit; -} - /* * Platform specific helpers to calculate the port PLL loopback- (clock.m), * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast @@ -721,6 +694,16 @@ i9xx_select_p2_div(const intel_limit_t *limit, } } +/* + * Returns a set of divisors for the desired target clock with the given + * refclk, or FALSE. The returned values represent the clock equation: + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + * + * Target and reference clocks are specified in kHz. + * + * If match_clock is provided, then best_clock P divider must match the P + * divider from @match_clock used for LVDS downclocking. + */ static bool i9xx_find_best_dpll(const intel_limit_t *limit, struct intel_crtc_state *crtc_state, @@ -768,6 +751,16 @@ i9xx_find_best_dpll(const intel_limit_t *limit, return (err != target); } +/* + * Returns a set of divisors for the desired target clock with the given + * refclk, or FALSE. The returned values represent the clock equation: + * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + * + * Target and reference clocks are specified in kHz. + * + * If match_clock is provided, then best_clock P divider must match the P + * divider from @match_clock used for LVDS downclocking. + */ static bool pnv_find_best_dpll(const intel_limit_t *limit, struct intel_crtc_state *crtc_state, @@ -817,6 +810,11 @@ pnv_find_best_dpll(const intel_limit_t *limit, * Returns a set of divisors for the desired target clock with the given * refclk, or FALSE. The returned values represent the clock equation: * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + * + * Target and reference clocks are specified in kHz. + * + * If match_clock is provided, then best_clock P divider must match the P + * divider from @match_clock used for LVDS downclocking. */ static bool g4x_find_best_dpll(const intel_limit_t *limit, @@ -7849,43 +7847,67 @@ static int g4x_crtc_compute_clock(struct intel_crtc *crtc, return 0; } +static int pnv_crtc_compute_clock(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + const intel_limit_t *limit; + int refclk = 96000; + + memset(&crtc_state->dpll_hw_state, 0, + sizeof(crtc_state->dpll_hw_state)); + + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) { + if (intel_panel_use_ssc(dev_priv)) { + refclk = dev_priv->vbt.lvds_ssc_freq; + DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); + } + + limit = &intel_limits_pineview_lvds; + } else { + limit = &intel_limits_pineview_sdvo; + } + + if (!crtc_state->clock_set && + !pnv_find_best_dpll(limit, crtc_state, crtc_state->port_clock, + refclk, NULL, &crtc_state->dpll)) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; + } + + i9xx_compute_dpll(crtc, crtc_state, NULL); + + return 0; +} + static int i9xx_crtc_compute_clock(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - bool ok; const intel_limit_t *limit; int refclk = 96000; memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); - if (crtc_state->has_dsi_encoder) - return 0; + if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) { + if (intel_panel_use_ssc(dev_priv)) { + refclk = dev_priv->vbt.lvds_ssc_freq; + DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); + } - if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_panel_use_ssc(dev_priv)) { - refclk = dev_priv->vbt.lvds_ssc_freq; - DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk); + limit = &intel_limits_i9xx_lvds; + } else { + limit = &intel_limits_i9xx_sdvo; } - if (!crtc_state->clock_set) { - /* - * Returns a set of divisors for the desired target clock with - * the given refclk, or FALSE. The returned values represent - * the clock equation: reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + - * 2) / p1 / p2. - */ - limit = intel_limit(crtc_state, refclk); - ok = dev_priv->display.find_dpll(limit, crtc_state, - crtc_state->port_clock, - refclk, NULL, - &crtc_state->dpll); - if (!ok) { - DRM_ERROR("Couldn't find PLL settings for mode!\n"); - return -EINVAL; - } + if (!crtc_state->clock_set && + !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock, + refclk, NULL, &crtc_state->dpll)) { + DRM_ERROR("Couldn't find PLL settings for mode!\n"); + return -EINVAL; } i9xx_compute_dpll(crtc, crtc_state, NULL); @@ -14800,11 +14822,6 @@ static const struct drm_mode_config_funcs intel_mode_funcs = { */ void intel_init_display_hooks(struct drm_i915_private *dev_priv) { - if (IS_PINEVIEW(dev_priv)) - dev_priv->display.find_dpll = pnv_find_best_dpll; - else - dev_priv->display.find_dpll = i9xx_find_best_dpll; - if (INTEL_INFO(dev_priv)->gen >= 9) { dev_priv->display.get_pipe_config = haswell_get_pipe_config; dev_priv->display.get_initial_plane_config = @@ -14850,6 +14867,13 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) dev_priv->display.crtc_compute_clock = g4x_crtc_compute_clock; dev_priv->display.crtc_enable = i9xx_crtc_enable; dev_priv->display.crtc_disable = i9xx_crtc_disable; + } else if (IS_PINEVIEW(dev_priv)) { + dev_priv->display.get_pipe_config = i9xx_get_pipe_config; + dev_priv->display.get_initial_plane_config = + i9xx_get_initial_plane_config; + dev_priv->display.crtc_compute_clock = pnv_crtc_compute_clock; + dev_priv->display.crtc_enable = i9xx_crtc_enable; + dev_priv->display.crtc_disable = i9xx_crtc_disable; } else if (!IS_GEN2(dev_priv)) { dev_priv->display.get_pipe_config = i9xx_get_pipe_config; dev_priv->display.get_initial_plane_config = -- cgit v0.10.2 From 321d178edb17d4619dbfa6216ac185c30c18d31a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 20 Nov 2015 10:27:18 +0000 Subject: drm/i915: Tidy aliasing_gtt_bind_vma() In commit 0a878716265e9af9f697264dc2e858fcc060d833 Author: Daniel Vetter Date: Thu Oct 15 14:23:01 2015 +0200 drm/i915: restore ggtt double-bind avoidance we wrote the ggtt_bind_vma() observing a number of cleanups we could do over the template of aliasing_gtt_bind_vma(). Now let's apply the cleanups we made there back to the original. The essence is to avoid redundant variables and assignements, and by doing so make the code easier to read. Signed-off-by: Chris Wilson Cc: Daniel Vetter Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1448015238-24639-1-git-send-email-chris@chris-wilson.co.uk diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 0715bb7..cbbd666 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2613,32 +2613,31 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) { - struct drm_device *dev = vma->vm->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj = vma->obj; - struct sg_table *pages = obj->pages; - u32 pte_flags = 0; + u32 pte_flags; int ret; ret = i915_get_ggtt_vma_pages(vma); if (ret) return ret; - pages = vma->ggtt_view.pages; /* Currently applicable only to VLV */ - if (obj->gt_ro) + pte_flags = 0; + if (vma->obj->gt_ro) pte_flags |= PTE_READ_ONLY; if (flags & GLOBAL_BIND) { - vma->vm->insert_entries(vma->vm, pages, + vma->vm->insert_entries(vma->vm, + vma->ggtt_view.pages, vma->node.start, cache_level, pte_flags); } if (flags & LOCAL_BIND) { - struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt; - appgtt->base.insert_entries(&appgtt->base, pages, + struct i915_hw_ppgtt *appgtt = + to_i915(vma->vm->dev)->mm.aliasing_ppgtt; + appgtt->base.insert_entries(&appgtt->base, + vma->ggtt_view.pages, vma->node.start, cache_level, pte_flags); } -- cgit v0.10.2 From 307e44988018943586f27d554a1773f685b3342e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 23 Mar 2016 14:33:28 +0100 Subject: drm/i915: Remove vblank wait from hsw_enable_ips, v2. intel_post_plane_update did an extra vblank wait that's no longer needed when enabling ips. Changes since v1: - Add comment explaining why vblank wait is performed. (Paulo) Signed-off-by: Maarten Lankhorst Reviewed-by: Paulo Zanoni Link: http://patchwork.freedesktop.org/patch/msgid/56F29B28.5070804@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 009b03b..7c4ffca 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4412,8 +4412,11 @@ void hsw_enable_ips(struct intel_crtc *crtc) if (!crtc->config->ips_enabled) return; - /* We can only enable IPS after we enable a plane and wait for a vblank */ - intel_wait_for_vblank(dev, crtc->pipe); + /* + * We can only enable IPS after we enable a plane and wait for a vblank + * This function is called from post_plane_update, which is run after + * a vblank wait. + */ assert_plane_enabled(dev_priv, crtc->plane); if (IS_BROADWELL(dev)) { -- cgit v0.10.2 From db18b6a64ca3fb260858279b218b84d5c179330f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 24 Mar 2016 12:41:40 +0200 Subject: drm/i915/bxt: Fix DSI HW state readout Currently the machine hangs during booting while accessing the BXT_MIPI_PORT_CTRL register during pipe HW state readout. After some experimentation I found that the hang is caused by the DSI PLL being disabled, or it being enabled but with an incorrect divider configuration. Enabling the PLL got rid of the boot problem, so fix this by checking the PLL enabled state/configuration before attempting to read out the HW state. The DSI_PLL_ENABLE register is in the always-on power well, while the BXT_DSI_PLL_CTL is in power well 0. This isn't exactly matched by the transcoder power domain, but what we really need is just a runtime PM reference, which is provided by any power domain. Ville also found this dependency specified in BSpec, so I added a reference to that too. v2: - Make sure we hold a power reference while accessing the PLL registers. v3: (Jani) - Simplify check in bxt_get_dsi_transcoder_state() - Add comment explaining why we check for valid dividers in bxt_dsi_pll_is_enabled() CC: Shashank Sharma CC: Uma Shankar CC: Jani Nikula Fixes: c6c794a2fc5e ("drm/i915/bxt: Initialize MIPI DSI for BXT") Signed-off-by: Imre Deak Reviewed-by: Jani Nikula Reviewed-by: Shashank Sharma Link: http://patchwork.freedesktop.org/patch/msgid/1458816100-31269-1-git-send-email-imre.deak@intel.com diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f3ba43c..c839ce9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7811,9 +7811,11 @@ enum skl_disp_power_wells { #define BXT_DSIC_16X_BY2 (1 << 10) #define BXT_DSIC_16X_BY3 (2 << 10) #define BXT_DSIC_16X_BY4 (3 << 10) +#define BXT_DSIC_16X_MASK (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_DSIA_16X_MASK (3 << 8) #define BXT_DSI_FREQ_SEL_SHIFT 8 #define BXT_DSI_FREQ_SEL_MASK (0xF << BXT_DSI_FREQ_SEL_SHIFT) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7c4ffca..29aa64b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -36,6 +36,7 @@ #include "intel_drv.h" #include #include "i915_drv.h" +#include "intel_dsi.h" #include "i915_trace.h" #include #include @@ -9870,6 +9871,16 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc, continue; *power_domain_mask |= BIT(power_domain); + /* + * The PLL needs to be enabled with a valid divider + * configuration, otherwise accessing DSI registers will hang + * the machine. See BSpec North Display Engine + * registers/MIPI[BXT]. We can break out here early, since we + * need the same DSI PLL to be enabled for both DSI ports. + */ + if (!intel_dsi_pll_is_enabled(dev_priv)) + break; + /* XXX: this works for video mode only */ tmp = I915_READ(BXT_MIPI_PORT_CTRL(port)); if (!(tmp & DPI_ENABLE)) diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 96ea3f7..0de74e1 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -684,6 +684,14 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) return false; + /* + * On Broxton the PLL needs to be enabled with a valid divider + * configuration, otherwise accessing DSI registers will hang the + * machine. See BSpec North Display Engine registers/MIPI[BXT]. + */ + if (IS_BROXTON(dev_priv) && !intel_dsi_pll_is_enabled(dev_priv)) + goto out_put_power; + /* XXX: this only works for one DSI output */ for_each_dsi_port(port, intel_dsi->ports) { i915_reg_t ctrl_reg = IS_BROXTON(dev) ? @@ -726,6 +734,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, break; } +out_put_power: intel_display_power_put(dev_priv, power_domain); return active; diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index e582ef8..ec58ead 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -126,6 +126,7 @@ static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder) return container_of(encoder, struct intel_dsi, base.base); } +bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv); extern void intel_enable_dsi_pll(struct intel_encoder *encoder); extern void intel_disable_dsi_pll(struct intel_encoder *encoder); extern u32 intel_dsi_get_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 e3e343c..4e53fcf 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c @@ -192,6 +192,36 @@ static void vlv_disable_dsi_pll(struct intel_encoder *encoder) mutex_unlock(&dev_priv->sb_lock); } +static bool bxt_dsi_pll_is_enabled(struct drm_i915_private *dev_priv) +{ + bool enabled; + u32 val; + u32 mask; + + mask = BXT_DSI_PLL_DO_ENABLE | BXT_DSI_PLL_LOCKED; + val = I915_READ(BXT_DSI_PLL_ENABLE); + enabled = (val & mask) == mask; + + if (!enabled) + return false; + + /* + * Both dividers must be programmed with valid values even if only one + * of the PLL is used, see BSpec/Broxton Clocks. Check this here for + * paranoia, since BIOS is known to misconfigure PLLs in this way at + * times, and since accessing DSI registers with invalid dividers + * causes a system hang. + */ + val = I915_READ(BXT_DSI_PLL_CTL); + if (!(val & BXT_DSIA_16X_MASK) || !(val & BXT_DSIC_16X_MASK)) { + DRM_DEBUG_DRIVER("PLL is enabled with invalid divider settings (%08x)\n", + val); + enabled = false; + } + + return enabled; +} + static void bxt_disable_dsi_pll(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; @@ -486,6 +516,16 @@ static void bxt_enable_dsi_pll(struct intel_encoder *encoder) DRM_DEBUG_KMS("DSI PLL locked\n"); } +bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv) +{ + if (IS_BROXTON(dev_priv)) + return bxt_dsi_pll_is_enabled(dev_priv); + + MISSING_CASE(INTEL_DEVID(dev_priv)); + + return false; +} + void intel_enable_dsi_pll(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; -- cgit v0.10.2 From c3232b1883e033e291aa3146f431b7ec87c80ec5 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Wed, 23 Mar 2016 18:19:53 +0000 Subject: drm/i915: introduce for_each_engine_id() Equivalent to the existing for_each_engine() macro, this will replace the latter wherever the third argument *is* actually wanted (in most places, it is not used). The third argument is renamed to emphasise that it is an engine id (type enum intel_engine_id). All the callers of the macro that actually need the third argument are updated to use this version, and the argument (generally 'i') is also updated to be 'id'. Other callers (where the third argument is unused) are untouched for now; they will be updated in the next patch. Signed-off-by: Dave Gordon Signed-off-by: Tvrtko Ursulin Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e0ba3e3..77dce52 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -132,7 +132,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) struct intel_engine_cs *engine; struct i915_vma *vma; int pin_count = 0; - int i; + enum intel_engine_id id; seq_printf(m, "%pK: %s%s%s%s %8zdKiB %02x %02x [ ", &obj->base, @@ -143,9 +143,9 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) obj->base.size / 1024, obj->base.read_domains, obj->base.write_domain); - for_each_engine(engine, dev_priv, i) + for_each_engine_id(engine, dev_priv, id) seq_printf(m, "%x ", - i915_gem_request_get_seqno(obj->last_read_req[i])); + i915_gem_request_get_seqno(obj->last_read_req[id])); seq_printf(m, "] %x %x%s%s%s", i915_gem_request_get_seqno(obj->last_write_req), i915_gem_request_get_seqno(obj->last_fenced_req), @@ -1334,7 +1334,8 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) u64 acthd[I915_NUM_ENGINES]; u32 seqno[I915_NUM_ENGINES]; u32 instdone[I915_NUM_INSTDONE_REG]; - int i, j; + enum intel_engine_id id; + int j; if (!i915.enable_hangcheck) { seq_printf(m, "Hangcheck disabled\n"); @@ -1343,9 +1344,9 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); - for_each_engine(engine, dev_priv, i) { - seqno[i] = engine->get_seqno(engine, false); - acthd[i] = intel_ring_get_active_head(engine); + for_each_engine_id(engine, dev_priv, id) { + seqno[id] = engine->get_seqno(engine, false); + acthd[id] = intel_ring_get_active_head(engine); } i915_get_extra_instdone(dev, instdone); @@ -1359,13 +1360,13 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) } else seq_printf(m, "Hangcheck inactive\n"); - for_each_engine(engine, dev_priv, i) { + for_each_engine_id(engine, dev_priv, id) { seq_printf(m, "%s:\n", engine->name); seq_printf(m, "\tseqno = %x [current %x]\n", - engine->hangcheck.seqno, seqno[i]); + engine->hangcheck.seqno, seqno[id]); seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n", (long long)engine->hangcheck.acthd, - (long long)acthd[i]); + (long long)acthd[id]); seq_printf(m, "\tscore = %d\n", engine->hangcheck.score); seq_printf(m, "\taction = %d\n", engine->hangcheck.action); @@ -1947,7 +1948,8 @@ static int i915_context_status(struct seq_file *m, void *unused) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; struct intel_context *ctx; - int ret, i; + enum intel_engine_id id; + int ret; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) @@ -1965,11 +1967,11 @@ static int i915_context_status(struct seq_file *m, void *unused) if (i915.enable_execlists) { seq_putc(m, '\n'); - for_each_engine(engine, dev_priv, i) { + for_each_engine_id(engine, dev_priv, id) { struct drm_i915_gem_object *ctx_obj = - ctx->engine[i].state; + ctx->engine[id].state; struct intel_ringbuffer *ringbuf = - ctx->engine[i].ringbuf; + ctx->engine[id].ringbuf; seq_printf(m, "%s: ", engine->name); if (ctx_obj) @@ -3134,7 +3136,8 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; int num_rings = hweight32(INTEL_INFO(dev)->ring_mask); - int i, j, ret; + enum intel_engine_id id; + int j, ret; if (!i915_semaphore_is_enabled(dev)) { seq_puts(m, "Semaphores are disabled\n"); @@ -3153,14 +3156,14 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) page = i915_gem_object_get_page(dev_priv->semaphore_obj, 0); seqno = (uint64_t *)kmap_atomic(page); - for_each_engine(engine, dev_priv, i) { + for_each_engine_id(engine, dev_priv, id) { uint64_t offset; seq_printf(m, "%s\n", engine->name); seq_puts(m, " Last signal:"); for (j = 0; j < num_rings; j++) { - offset = i * I915_NUM_ENGINES + j; + offset = id * I915_NUM_ENGINES + j; seq_printf(m, "0x%08llx (0x%02llx) ", seqno[offset], offset * 8); } @@ -3168,7 +3171,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) seq_puts(m, " Last wait: "); for (j = 0; j < num_rings; j++) { - offset = i + (j * I915_NUM_ENGINES); + offset = id + (j * I915_NUM_ENGINES); seq_printf(m, "0x%08llx (0x%02llx) ", seqno[offset], offset * 8); } @@ -3178,7 +3181,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) kunmap_atomic(seqno); } else { seq_puts(m, " Last signal:"); - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv, id) for (j = 0; j < num_rings; j++) seq_printf(m, "0x%08x\n", I915_READ(engine->semaphore.mbox.signal[j])); @@ -3186,7 +3189,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) } seq_puts(m, "\nSync seqno:\n"); - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv, id) { for (j = 0; j < num_rings; j++) { seq_printf(m, " 0x%08x ", engine->semaphore.sync_seqno[j]); @@ -3236,6 +3239,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct i915_workarounds *workarounds = &dev_priv->workarounds; + enum intel_engine_id id; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) @@ -3244,9 +3248,9 @@ static int i915_wa_registers(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); seq_printf(m, "Workarounds applied: %d\n", workarounds->count); - for_each_engine(engine, dev_priv, i) + for_each_engine_id(engine, dev_priv, id) seq_printf(m, "HW whitelist count for %s: %d\n", - engine->name, workarounds->hw_whitelist_count[i]); + engine->name, workarounds->hw_whitelist_count[id]); for (i = 0; i < workarounds->count; ++i) { i915_reg_t addr; u32 mask, value, read; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 08b88c0..8fe0592 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1995,6 +1995,15 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) for ((i__) = 0; (i__) < I915_NUM_ENGINES; (i__)++) \ for_each_if ((((ring__) = &(dev_priv__)->engine[(i__)]), intel_engine_initialized((ring__)))) +/* Iterator with engine_id */ +#define for_each_engine_id(engine__, dev_priv__, id__) \ + for ((engine__) = &(dev_priv__)->engine[0], (id__) = 0; \ + (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \ + (engine__)++) \ + for_each_if (((id__) = (engine__)->id, \ + intel_engine_initialized(engine__))) + +/* Iterator over subset of engines selected by mask */ #define for_each_engine_masked(engine__, dev_priv__, mask__) \ for ((engine__) = &dev_priv->engine[0]; (engine__) < &dev_priv->engine[I915_NUM_ENGINES]; (engine__)++) \ for_each_if (intel_engine_flag((engine__)) & (mask__) && intel_engine_initialized((engine__))) diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 1f8ff06..54c2086 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -846,7 +846,7 @@ static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv, struct drm_i915_error_ring *ering) { struct intel_engine_cs *to; - int i; + enum intel_engine_id id; if (!i915_semaphore_is_enabled(dev_priv->dev)) return; @@ -856,7 +856,7 @@ static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv, i915_error_ggtt_object_create(dev_priv, dev_priv->semaphore_obj); - for_each_engine(to, dev_priv, i) { + for_each_engine_id(to, dev_priv, id) { int idx; u16 signal_offset; u32 *tmp; @@ -864,7 +864,7 @@ static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv, if (engine == to) continue; - signal_offset = (GEN8_SIGNAL_OFFSET(engine, i) & (PAGE_SIZE - 1)) + signal_offset = (GEN8_SIGNAL_OFFSET(engine, id) & (PAGE_SIZE - 1)) / 4; tmp = error->semaphore_obj->pages[0]; idx = intel_ring_sync_index(engine, to); diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index ae1f58d..0611bdc 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -381,7 +381,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc, struct intel_context *ctx = client->owner; struct guc_context_desc desc; struct sg_table *sg; - int i; + enum intel_engine_id id; memset(&desc, 0, sizeof(desc)); @@ -390,7 +390,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc, desc.priority = client->priority; desc.db_id = client->doorbell_id; - for_each_engine(engine, dev_priv, i) { + for_each_engine_id(engine, dev_priv, id) { struct guc_execlist_context *lrc = &desc.lrc[engine->guc_id]; struct drm_i915_gem_object *obj; uint64_t ctx_desc; @@ -402,7 +402,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc, * for now who owns a GuC client. But for future owner of GuC * client, need to make sure lrc is pinned prior to enter here. */ - obj = ctx->engine[i].state; + obj = ctx->engine[id].state; if (!obj) break; /* XXX: continue? */ @@ -415,7 +415,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc, lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) | (engine->guc_id << GUC_ELC_ENGINE_OFFSET); - obj = ctx->engine[i].ringbuf->obj; + obj = ctx->engine[id].ringbuf->obj; lrc->ring_begin = i915_gem_obj_ggtt_offset(obj); lrc->ring_end = lrc->ring_begin + obj->base.size - 1; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a55a7cc..14a23b3 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3073,7 +3073,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) gpu_error.hangcheck_work.work); struct drm_device *dev = dev_priv->dev; struct intel_engine_cs *engine; - int i; + enum intel_engine_id id; int busy_count = 0, rings_hung = 0; bool stuck[I915_NUM_ENGINES] = { 0 }; #define BUSY 1 @@ -3097,7 +3097,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) */ intel_uncore_arm_unclaimed_mmio_detection(dev_priv); - for_each_engine(engine, dev_priv, i) { + for_each_engine_id(engine, dev_priv, id) { u64 acthd; u32 seqno; bool busy = true; @@ -3157,7 +3157,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) break; case HANGCHECK_HUNG: engine->hangcheck.score += HUNG; - stuck[i] = true; + stuck[id] = true; break; } } @@ -3184,10 +3184,10 @@ static void i915_hangcheck_elapsed(struct work_struct *work) busy_count += busy; } - for_each_engine(engine, dev_priv, i) { + for_each_engine_id(engine, dev_priv, id) { if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) { DRM_INFO("%s on %s\n", - stuck[i] ? "stuck" : "no progress", + stuck[id] ? "stuck" : "no progress", engine->name); rings_hung |= intel_engine_flag(engine); } diff --git a/drivers/gpu/drm/i915/intel_mocs.c b/drivers/gpu/drm/i915/intel_mocs.c index 3c725dd..7c7ac0a 100644 --- a/drivers/gpu/drm/i915/intel_mocs.c +++ b/drivers/gpu/drm/i915/intel_mocs.c @@ -325,11 +325,11 @@ int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req) if (get_mocs_settings(req->engine->dev, &t)) { struct drm_i915_private *dev_priv = req->i915; struct intel_engine_cs *engine; - enum intel_engine_id ring_id; + enum intel_engine_id id; /* Program the control registers */ - for_each_engine(engine, dev_priv, ring_id) { - ret = emit_mocs_control_table(req, &t, ring_id); + for_each_engine_id(engine, dev_priv, id) { + ret = emit_mocs_control_table(req, &t, id); if (ret) return ret; } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index ce59850..a492bca 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1280,7 +1280,8 @@ static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, struct drm_device *dev = signaller->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *waiter; - int i, ret, num_rings; + enum intel_engine_id id; + int ret, num_rings; num_rings = hweight32(INTEL_INFO(dev)->ring_mask); num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; @@ -1290,9 +1291,9 @@ static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req, if (ret) return ret; - for_each_engine(waiter, dev_priv, i) { + for_each_engine_id(waiter, dev_priv, id) { u32 seqno; - u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; + u64 gtt_offset = signaller->semaphore.signal_ggtt[id]; if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) continue; @@ -1321,7 +1322,8 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, struct drm_device *dev = signaller->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *waiter; - int i, ret, num_rings; + enum intel_engine_id id; + int ret, num_rings; num_rings = hweight32(INTEL_INFO(dev)->ring_mask); num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS; @@ -1331,9 +1333,9 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *signaller_req, if (ret) return ret; - for_each_engine(waiter, dev_priv, i) { + for_each_engine_id(waiter, dev_priv, id) { u32 seqno; - u64 gtt_offset = signaller->semaphore.signal_ggtt[i]; + u64 gtt_offset = signaller->semaphore.signal_ggtt[id]; if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) continue; @@ -1359,7 +1361,8 @@ static int gen6_signal(struct drm_i915_gem_request *signaller_req, struct drm_device *dev = signaller->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *useless; - int i, ret, num_rings; + enum intel_engine_id id; + int ret, num_rings; #define MBOX_UPDATE_DWORDS 3 num_rings = hweight32(INTEL_INFO(dev)->ring_mask); @@ -1370,8 +1373,8 @@ static int gen6_signal(struct drm_i915_gem_request *signaller_req, if (ret) return ret; - for_each_engine(useless, dev_priv, i) { - i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[i]; + for_each_engine_id(useless, dev_priv, id) { + i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[id]; if (i915_mmio_reg_valid(mbox_reg)) { u32 seqno = i915_gem_request_get_seqno(signaller_req); -- cgit v0.10.2 From b4ac5afc6b8398b15d061e909bbad153aae41f15 Mon Sep 17 00:00:00 2001 From: Dave Gordon Date: Thu, 24 Mar 2016 11:20:38 +0000 Subject: drm/i915: replace for_each_engine() Having provided for_each_engine_id() for cases where the third (id) argument is useful, we can now replace all the remaining instances with a simpler version that takes only two parameters. In many cases, this also allows the elimination of the local variable used in the iterator (usually 'i'). v2: s/dev_priv/(dev_priv__)/ in body of for_each_engine_masked() [Chris Wilson] Signed-off-by: Dave Gordon Reviewed-by: Chris Wilson Signed-off-by: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/1458757194-17783-2-git-send-email-david.s.gordon@intel.com diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 77dce52..d02f8ce 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -398,11 +398,11 @@ static void print_batch_pool_stats(struct seq_file *m, struct drm_i915_gem_object *obj; struct file_stats stats; struct intel_engine_cs *engine; - int i, j; + int j; memset(&stats, 0, sizeof(stats)); - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { list_for_each_entry(obj, &engine->batch_pool.cache_list[j], @@ -638,13 +638,13 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) struct drm_i915_gem_object *obj; struct intel_engine_cs *engine; int total = 0; - int ret, i, j; + int ret, j; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { int count; @@ -682,14 +682,14 @@ static int i915_gem_request_info(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; struct drm_i915_gem_request *req; - int ret, any, i; + int ret, any; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; any = 0; - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { int count; count = 0; @@ -739,14 +739,14 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int ret, i; + int ret; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; intel_runtime_pm_get(dev_priv); - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) i915_ring_seqno_info(m, engine); intel_runtime_pm_put(dev_priv); @@ -933,7 +933,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) seq_printf(m, "Graphics Interrupt mask: %08x\n", I915_READ(GTIMR)); } - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { if (INTEL_INFO(dev)->gen >= 6) { seq_printf(m, "Graphics Interrupt mask (%s): %08x\n", @@ -2044,7 +2044,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; struct intel_context *ctx; - int ret, i; + int ret; if (!i915.enable_execlists) { seq_printf(m, "Logical Ring Contexts are disabled\n"); @@ -2057,7 +2057,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) list_for_each_entry(ctx, &dev_priv->context_list, link) if (ctx != dev_priv->kernel_context) - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) i915_dump_lrc_obj(m, ctx, engine); mutex_unlock(&dev->struct_mutex); @@ -2077,8 +2077,7 @@ static int i915_execlists(struct seq_file *m, void *data) u32 status; u32 ctx_id; struct list_head *cursor; - int ring_id, i; - int ret; + int i, ret; if (!i915.enable_execlists) { seq_puts(m, "Logical Ring Contexts are disabled\n"); @@ -2091,7 +2090,7 @@ static int i915_execlists(struct seq_file *m, void *data) intel_runtime_pm_get(dev_priv); - for_each_engine(engine, dev_priv, ring_id) { + for_each_engine(engine, dev_priv) { struct drm_i915_gem_request *head_req = NULL; int count = 0; unsigned long flags; @@ -2250,12 +2249,12 @@ static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; - int unused, i; + int i; if (!ppgtt) return; - for_each_engine(engine, dev_priv, unused) { + for_each_engine(engine, dev_priv) { seq_printf(m, "%s\n", engine->name); for (i = 0; i < 4; i++) { u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i)); @@ -2270,12 +2269,11 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int i; if (INTEL_INFO(dev)->gen == 6) seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE)); - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { seq_printf(m, "%s\n", engine->name); if (INTEL_INFO(dev)->gen == 7) seq_printf(m, "GFX_MODE: 0x%08x\n", @@ -2342,9 +2340,8 @@ static int count_irq_waiters(struct drm_i915_private *i915) { struct intel_engine_cs *engine; int count = 0; - int i; - for_each_engine(engine, i915, i) + for_each_engine(engine, i915) count += engine->irq_refcount; return count; @@ -2455,7 +2452,6 @@ static void i915_guc_client_info(struct seq_file *m, { struct intel_engine_cs *engine; uint64_t tot = 0; - uint32_t i; seq_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n", client->priority, client->ctx_index, client->proc_desc_offset); @@ -2468,7 +2464,7 @@ static void i915_guc_client_info(struct seq_file *m, seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail); seq_printf(m, "\tLast submission result: %d\n", client->retcode); - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { seq_printf(m, "\tSubmissions: %llu %s\n", client->submissions[engine->guc_id], engine->name); @@ -2485,7 +2481,6 @@ static int i915_guc_info(struct seq_file *m, void *data) struct intel_guc guc; struct i915_guc_client client = {}; struct intel_engine_cs *engine; - enum intel_engine_id i; u64 total = 0; if (!HAS_GUC_SCHED(dev_priv->dev)) @@ -2508,7 +2503,7 @@ static int i915_guc_info(struct seq_file *m, void *data) seq_printf(m, "GuC last action error code: %d\n", guc.action_err); seq_printf(m, "\nGuC submissions:\n"); - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n", engine->name, guc.submissions[engine->guc_id], guc.last_seqno[engine->guc_id]); @@ -3181,7 +3176,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) kunmap_atomic(seqno); } else { seq_puts(m, " Last signal:"); - for_each_engine(engine, dev_priv, id) + for_each_engine(engine, dev_priv) for (j = 0; j < num_rings; j++) seq_printf(m, "0x%08x\n", I915_READ(engine->semaphore.mbox.signal[j])); @@ -3189,11 +3184,10 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) } seq_puts(m, "\nSync seqno:\n"); - for_each_engine(engine, dev_priv, id) { - for (j = 0; j < num_rings; j++) { + for_each_engine(engine, dev_priv) { + for (j = 0; j < num_rings; j++) seq_printf(m, " 0x%08x ", engine->semaphore.sync_seqno[j]); - } seq_putc(m, '\n'); } seq_putc(m, '\n'); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8fe0592..b93ef70 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1990,10 +1990,12 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) return container_of(guc, struct drm_i915_private, guc); } -/* Iterate over initialised rings */ -#define for_each_engine(ring__, dev_priv__, i__) \ - for ((i__) = 0; (i__) < I915_NUM_ENGINES; (i__)++) \ - for_each_if ((((ring__) = &(dev_priv__)->engine[(i__)]), intel_engine_initialized((ring__)))) +/* Simple iterator over all initialised engines */ +#define for_each_engine(engine__, dev_priv__) \ + for ((engine__) = &(dev_priv__)->engine[0]; \ + (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \ + (engine__)++) \ + for_each_if (intel_engine_initialized(engine__)) /* Iterator with engine_id */ #define for_each_engine_id(engine__, dev_priv__, id__) \ @@ -2005,8 +2007,11 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) /* Iterator over subset of engines selected by mask */ #define for_each_engine_masked(engine__, dev_priv__, mask__) \ - for ((engine__) = &dev_priv->engine[0]; (engine__) < &dev_priv->engine[I915_NUM_ENGINES]; (engine__)++) \ - for_each_if (intel_engine_flag((engine__)) & (mask__) && intel_engine_initialized((engine__))) + for ((engine__) = &(dev_priv__)->engine[0]; \ + (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \ + (engine__)++) \ + for_each_if (((mask__) & intel_engine_flag(engine__)) && \ + intel_engine_initialized(engine__)) enum hdmi_force_audio { HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8588c83..c7a997a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2466,10 +2466,10 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int ret, i, j; + int ret, j; /* Carefully retire all requests without writing to the rings */ - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { ret = intel_engine_idle(engine); if (ret) return ret; @@ -2477,7 +2477,7 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno) i915_gem_retire_requests(dev); /* Finally reset hw state */ - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { intel_ring_init_seqno(engine, seqno); for (j = 0; j < ARRAY_SIZE(engine->semaphore.sync_seqno); j++) @@ -2884,17 +2884,16 @@ void i915_gem_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int i; /* * Before we free the objects from the requests, we need to inspect * them for finding the guilty party. As the requests only borrow * their reference to the objects, the inspection must be done first. */ - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) i915_gem_reset_engine_status(dev_priv, engine); - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) i915_gem_reset_engine_cleanup(dev_priv, engine); i915_gem_context_reset(dev); @@ -2962,9 +2961,8 @@ i915_gem_retire_requests(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; bool idle = true; - int i; - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { i915_gem_retire_requests_ring(engine); idle &= list_empty(&engine->request_list); if (i915.enable_execlists) { @@ -3009,24 +3007,20 @@ i915_gem_idle_work_handler(struct work_struct *work) struct drm_i915_private *dev_priv = container_of(work, typeof(*dev_priv), mm.idle_work.work); struct drm_device *dev = dev_priv->dev; - struct intel_engine_cs *ring; - int i; + struct intel_engine_cs *engine; - for_each_engine(ring, dev_priv, i) - if (!list_empty(&ring->request_list)) + for_each_engine(engine, dev_priv) + if (!list_empty(&engine->request_list)) return; /* we probably should sync with hangcheck here, using cancel_work_sync. - * Also locking seems to be fubar here, ring->request_list is protected + * Also locking seems to be fubar here, engine->request_list is protected * by dev->struct_mutex. */ intel_mark_idle(dev); if (mutex_trylock(&dev->struct_mutex)) { - struct intel_engine_cs *engine; - int i; - - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) i915_gem_batch_pool_fini(&engine->batch_pool); mutex_unlock(&dev->struct_mutex); @@ -3390,10 +3384,10 @@ int i915_gpu_idle(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int ret, i; + int ret; /* Flush everything onto the inactive list. */ - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { if (!i915.enable_execlists) { struct drm_i915_gem_request *req; @@ -4655,9 +4649,8 @@ i915_gem_stop_engines(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int i; - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) dev_priv->gt.stop_engine(engine); } @@ -4828,7 +4821,7 @@ i915_gem_init_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int ret, i, j; + int ret, j; if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt()) return -EIO; @@ -4874,7 +4867,7 @@ i915_gem_init_hw(struct drm_device *dev) } /* Need to do basic initialisation of all rings first: */ - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { ret = engine->init_hw(engine); if (ret) goto out; @@ -4899,7 +4892,7 @@ i915_gem_init_hw(struct drm_device *dev) goto out; /* Now it is safe to go back round and do everything else: */ - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { struct drm_i915_gem_request *req; req = i915_gem_request_alloc(engine, NULL); @@ -4916,7 +4909,8 @@ i915_gem_init_hw(struct drm_device *dev) ret = i915_ppgtt_init_ring(req); if (ret && ret != -EIO) { - DRM_ERROR("PPGTT enable ring #%d failed %d\n", i, ret); + DRM_ERROR("PPGTT enable %s failed %d\n", + engine->name, ret); i915_gem_request_cancel(req); i915_gem_cleanup_engines(dev); goto out; @@ -4924,7 +4918,8 @@ i915_gem_init_hw(struct drm_device *dev) ret = i915_gem_context_enable(req); if (ret && ret != -EIO) { - DRM_ERROR("Context enable ring #%d failed %d\n", i, ret); + DRM_ERROR("Context enable %s failed %d\n", + engine->name, ret); i915_gem_request_cancel(req); i915_gem_cleanup_engines(dev); goto out; @@ -5005,9 +5000,8 @@ i915_gem_cleanup_engines(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int i; - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) dev_priv->gt.cleanup_engine(engine); if (i915.enable_execlists) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 394e525..fe580cb 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -517,7 +517,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) i915_semaphore_is_enabled(engine->dev) ? hweight32(INTEL_INFO(engine->dev)->ring_mask) - 1 : 0; - int len, i, ret; + int len, ret; /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value @@ -553,7 +553,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(num_rings)); - for_each_engine(signaller, to_i915(engine->dev), i) { + for_each_engine(signaller, to_i915(engine->dev)) { if (signaller == engine) continue; @@ -582,7 +582,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(num_rings)); - for_each_engine(signaller, to_i915(engine->dev), i) { + for_each_engine(signaller, to_i915(engine->dev)) { if (signaller == engine) continue; diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index ef9cd70..a565164 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c @@ -38,12 +38,11 @@ i915_verify_lists(struct drm_device *dev) struct drm_i915_gem_object *obj; struct intel_engine_cs *engine; int err = 0; - int i; if (warned) return 0; - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { list_for_each_entry(obj, &engine->active_list, engine_list[engine->id]) { if (obj->base.dev != dev || diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index cbbd666..7cfafdc 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1737,9 +1737,8 @@ static void gen8_ppgtt_enable(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int j; - for_each_engine(engine, dev_priv, j) { + for_each_engine(engine, dev_priv) { u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0; I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level)); @@ -1751,7 +1750,6 @@ static void gen7_ppgtt_enable(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; uint32_t ecochk, ecobits; - int i; ecobits = I915_READ(GAC_ECO_BITS); I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); @@ -1765,7 +1763,7 @@ static void gen7_ppgtt_enable(struct drm_device *dev) } I915_WRITE(GAM_ECOCHK, ecochk); - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { /* GFX_MODE is per-ring on gen7+ */ I915_WRITE(RING_MODE_GEN7(engine), _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); @@ -2287,12 +2285,11 @@ void i915_check_and_clear_faults(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int i; if (INTEL_INFO(dev)->gen < 6) return; - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { u32 fault_reg; fault_reg = I915_READ(RING_FAULT_REG(engine)); if (fault_reg & RING_FAULT_VALID) { diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 0611bdc..da86bdb 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -842,7 +842,7 @@ static void guc_create_ads(struct intel_guc *guc) struct guc_mmio_reg_state *reg_state; struct intel_engine_cs *engine; struct page *page; - u32 size, i; + u32 size; /* The ads obj includes the struct itself and buffers passed to GuC */ size = sizeof(struct guc_ads) + sizeof(struct guc_policies) + @@ -871,7 +871,7 @@ static void guc_create_ads(struct intel_guc *guc) engine = &dev_priv->engine[RCS]; ads->golden_context_lrca = engine->status_page.gfx_addr; - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) ads->eng_state_size[engine->guc_id] = intel_lr_context_size(engine); /* GuC scheduling policies */ @@ -884,7 +884,7 @@ static void guc_create_ads(struct intel_guc *guc) /* MMIO reg state */ reg_state = (void *)policies + sizeof(struct guc_policies); - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { reg_state->mmio_white_list[engine->guc_id].mmio_start = engine->mmio_base + GUC_MMIO_WHITE_LIST_START; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 14a23b3..5aa4239 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1080,9 +1080,8 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) static bool any_waiters(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; - int i; - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) if (engine->irq_refcount) return true; @@ -2450,7 +2449,6 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv, bool reset_completed) { struct intel_engine_cs *engine; - int i; /* * Notify all waiters for GPU completion events that reset state has @@ -2460,7 +2458,7 @@ static void i915_error_wake_up(struct drm_i915_private *dev_priv, */ /* Wake up __wait_seqno, potentially holding dev->struct_mutex. */ - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) wake_up_all(&engine->irq_queue); /* Wake up intel_crtc_wait_for_pending_flips, holding crtc->mutex. */ @@ -2829,10 +2827,9 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, { struct drm_i915_private *dev_priv = engine->dev->dev_private; struct intel_engine_cs *signaller; - int i; if (INTEL_INFO(dev_priv->dev)->gen >= 8) { - for_each_engine(signaller, dev_priv, i) { + for_each_engine(signaller, dev_priv) { if (engine == signaller) continue; @@ -2842,7 +2839,7 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, } else { u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK; - for_each_engine(signaller, dev_priv, i) { + for_each_engine(signaller, dev_priv) { if(engine == signaller) continue; @@ -2958,9 +2955,8 @@ static int semaphore_passed(struct intel_engine_cs *engine) static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; - int i; - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) engine->hangcheck.deadlock = 0; } diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index e1aff62..b4976f9 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c @@ -82,12 +82,12 @@ const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status) static void direct_interrupts_to_host(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; - int i, irqs; + int irqs; /* tell all command streamers NOT to forward interrupts and vblank to GuC */ irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER); irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING); - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) I915_WRITE(RING_MODE_GEN7(engine), irqs); /* route all GT interrupts to the host */ @@ -99,12 +99,12 @@ static void direct_interrupts_to_host(struct drm_i915_private *dev_priv) static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; - int i, irqs; + int irqs; /* tell all command streamers to forward interrupts and vblank to GuC */ irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_ALWAYS); irqs |= _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) I915_WRITE(RING_MODE_GEN7(engine), irqs); /* route USER_INTERRUPT to Host, all others are sent to GuC. */ diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 40ef4ea..5d4ca3b 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2673,9 +2673,8 @@ void intel_lr_context_reset(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; - int i; - for_each_engine(engine, dev_priv, i) { + for_each_engine(engine, dev_priv) { struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state; struct intel_ringbuffer *ringbuf = diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 521cf45..6a04761 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4817,7 +4817,6 @@ static void gen9_enable_rc6(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; uint32_t rc6_mask = 0; - int unused; /* 1a: Software RC state - RC0 */ I915_WRITE(GEN6_RC_STATE, 0); @@ -4838,7 +4837,7 @@ static void gen9_enable_rc6(struct drm_device *dev) 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_engine(engine, dev_priv, unused) + for_each_engine(engine, dev_priv) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); if (HAS_GUC_UCODE(dev)) @@ -4887,7 +4886,6 @@ static void gen8_enable_rps(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; uint32_t rc6_mask = 0; - int unused; /* 1a: Software RC state - RC0 */ I915_WRITE(GEN6_RC_STATE, 0); @@ -4906,7 +4904,7 @@ static void gen8_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16); I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ - for_each_engine(engine, dev_priv, unused) + for_each_engine(engine, dev_priv) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); if (IS_BROADWELL(dev)) @@ -4971,7 +4969,7 @@ static void gen6_enable_rps(struct drm_device *dev) u32 rc6vids, pcu_mbox = 0, rc6_mask = 0; u32 gtfifodbg; int rc6_mode; - int i, ret; + int ret; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); @@ -5003,7 +5001,7 @@ static void gen6_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); @@ -5497,7 +5495,6 @@ static void cherryview_enable_rps(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; u32 gtfifodbg, val, rc6_mode = 0, pcbr; - int i; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); @@ -5522,7 +5519,7 @@ static void cherryview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); @@ -5595,7 +5592,6 @@ static void valleyview_enable_rps(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_engine_cs *engine; u32 gtfifodbg, val, rc6_mode = 0; - int i; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); @@ -5633,7 +5629,7 @@ static void valleyview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); @@ -6012,14 +6008,13 @@ bool i915_gpu_busy(void) struct drm_i915_private *dev_priv; struct intel_engine_cs *engine; bool ret = false; - int i; spin_lock_irq(&mchdev_lock); if (!i915_mch_dev) goto out_unlock; dev_priv = i915_mch_dev; - for_each_engine(engine, dev_priv, i) + for_each_engine(engine, dev_priv) ret |= !list_empty(&engine->request_list); out_unlock: -- cgit v0.10.2 From 11622d4c638ad3dd229e39064d0e5726c4f3b454 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 26 Feb 2016 11:51:06 +0200 Subject: drm: bridge: Make (pre/post) enable/disable callbacks optional Instead of forcing bridges to implement empty callbacks make them all optional. Signed-off-by: Laurent Pinchart Link: http://patchwork.freedesktop.org/patch/msgid/1456480266-7904-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com Acked-by: Archit Taneja Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index bd93453..b365440 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -186,7 +186,8 @@ void drm_bridge_disable(struct drm_bridge *bridge) drm_bridge_disable(bridge->next); - bridge->funcs->disable(bridge); + if (bridge->funcs->disable) + bridge->funcs->disable(bridge); } EXPORT_SYMBOL(drm_bridge_disable); @@ -206,7 +207,8 @@ void drm_bridge_post_disable(struct drm_bridge *bridge) if (!bridge) return; - bridge->funcs->post_disable(bridge); + if (bridge->funcs->post_disable) + bridge->funcs->post_disable(bridge); drm_bridge_post_disable(bridge->next); } @@ -256,7 +258,8 @@ void drm_bridge_pre_enable(struct drm_bridge *bridge) drm_bridge_pre_enable(bridge->next); - bridge->funcs->pre_enable(bridge); + if (bridge->funcs->pre_enable) + bridge->funcs->pre_enable(bridge); } EXPORT_SYMBOL(drm_bridge_pre_enable); @@ -276,7 +279,8 @@ void drm_bridge_enable(struct drm_bridge *bridge) if (!bridge) return; - bridge->funcs->enable(bridge); + if (bridge->funcs->enable) + bridge->funcs->enable(bridge); drm_bridge_enable(bridge->next); } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index b10eba23a..f048a7b 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1596,6 +1596,8 @@ struct drm_bridge_funcs { * * The bridge can assume that the display pipe (i.e. clocks and timing * signals) feeding it is still running when this callback is called. + * + * The disable callback is optional. */ void (*disable)(struct drm_bridge *bridge); @@ -1612,6 +1614,8 @@ struct drm_bridge_funcs { * The bridge must assume that the display pipe (i.e. clocks and timing * singals) feeding it is no longer running when this callback is * called. + * + * The post_disable callback is optional. */ void (*post_disable)(struct drm_bridge *bridge); @@ -1640,6 +1644,8 @@ struct drm_bridge_funcs { * will not yet be running when this callback is called. The bridge must * not enable the display link feeding the next bridge in the chain (if * there is one) when this callback is called. + * + * The pre_enable callback is optional. */ void (*pre_enable)(struct drm_bridge *bridge); @@ -1657,6 +1663,8 @@ struct drm_bridge_funcs { * signals) feeding it is running when this callback is called. This * callback must enable the display link feeding the next bridge in the * chain if there is one. + * + * The enable callback is optional. */ void (*enable)(struct drm_bridge *bridge); }; -- cgit v0.10.2 From 6c87e5c3ec6db052f3744804a517b6fb003906e1 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Wed, 23 Mar 2016 11:42:54 +0300 Subject: drm: Rename drm_connector_unplug_all() to drm_connector_unregister_all() Current name is a bit misleading because what that helper function really does it calls drm_connector_unregister() for all connectors. This all has nothing to do with hotplugging so let's name things properly. And while at it remove potentially dangerous locking around drm_connector_unregister() in rcar_du_remove() as mentioned in kerneldoc for drm_connector_unregister_all(). Signed-off-by: Alexey Brodkin Cc: Daniel Vetter Cc: David Airlie Cc: Boris Brezillon Cc: linux-renesas-soc@vger.kernel.org Acked-by: Laurent Pinchart Acked-by: Boris Brezillon Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1458722577-20283-2-git-send-email-abrodkin@synopsys.com diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 49781a9..7675826 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1078,25 +1078,25 @@ void drm_connector_unregister(struct drm_connector *connector) } EXPORT_SYMBOL(drm_connector_unregister); - /** - * drm_connector_unplug_all - unregister connector userspace interfaces + * drm_connector_unregister_all - unregister connector userspace interfaces * @dev: drm device * - * This function unregisters all connector userspace interfaces in sysfs. Should - * be call when the device is disconnected, e.g. from an usb driver's - * ->disconnect callback. + * This functions unregisters all connectors from sysfs and other places so + * that userspace can no longer access them. Drivers should call this as the + * first step tearing down the device instace, or when the underlying + * physical device disappeared (e.g. USB unplug), right before calling + * drm_dev_unregister(). */ -void drm_connector_unplug_all(struct drm_device *dev) +void drm_connector_unregister_all(struct drm_device *dev) { struct drm_connector *connector; /* FIXME: taking the mode config mutex ends up in a clash with sysfs */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) + drm_for_each_connector(connector, dev) drm_connector_unregister(connector); - } -EXPORT_SYMBOL(drm_connector_unplug_all); +EXPORT_SYMBOL(drm_connector_unregister_all); /** * drm_encoder_init - Init a preallocated encoder diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index ed6006b..644db36 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -278,10 +278,7 @@ static int rcar_du_remove(struct platform_device *pdev) struct rcar_du_device *rcdu = platform_get_drvdata(pdev); struct drm_device *ddev = rcdu->ddev; - mutex_lock(&ddev->mode_config.mutex); - drm_connector_unplug_all(ddev); - mutex_unlock(&ddev->mode_config.mutex); - + drm_connector_unregister_all(ddev); drm_dev_unregister(ddev); if (rcdu->fbdev) diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 772ec9e..c204089 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -94,7 +94,7 @@ static void udl_usb_disconnect(struct usb_interface *interface) struct drm_device *dev = usb_get_intfdata(interface); drm_kms_helper_poll_disable(dev); - drm_connector_unplug_all(dev); + drm_connector_unregister_all(dev); udl_fbdev_unplug(dev); udl_drop_usb(dev); drm_unplug_dev(dev); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index f048a7b..12f2bd4 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -2253,8 +2253,8 @@ void drm_connector_unregister(struct drm_connector *connector); extern void drm_connector_cleanup(struct drm_connector *connector); extern unsigned int drm_connector_index(struct drm_connector *connector); -/* helper to unplug all connectors from sysfs for device */ -extern void drm_connector_unplug_all(struct drm_device *dev); +/* helper to unregister all connectors from sysfs for device */ +extern void drm_connector_unregister_all(struct drm_device *dev); extern int drm_bridge_add(struct drm_bridge *bridge); extern void drm_bridge_remove(struct drm_bridge *bridge); -- cgit v0.10.2 From 6aa23e658d910342e8fedb23780638ddaed744d7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 24 Mar 2016 17:50:20 +0200 Subject: drm/i915: use a substruct in vbt data for edp Housekeeping, similar to psr, backlight, and dsi. No functional changes. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458834623-8734-2-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b93ef70..fe8021e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1446,15 +1446,16 @@ struct intel_vbt_data { enum drrs_support_type drrs_type; - /* eDP */ - int edp_rate; - int edp_lanes; - int edp_preemphasis; - int edp_vswing; - bool edp_initialized; - bool edp_support; - int edp_bpp; - struct edp_power_seq edp_pps; + struct { + int rate; + int lanes; + int preemphasis; + int vswing; + bool initialized; + bool support; + int bpp; + struct edp_power_seq pps; + } edp; struct { bool full_link; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 083003b..61eb7a6 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -527,7 +527,7 @@ parse_driver_features(struct drm_i915_private *dev_priv, return; if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP) - dev_priv->vbt.edp_support = 1; + dev_priv->vbt.edp.support = 1; if (driver->dual_frequency) dev_priv->render_reclock_avail = true; @@ -552,20 +552,20 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) edp = find_section(bdb, BDB_EDP); if (!edp) { - if (dev_priv->vbt.edp_support) + if (dev_priv->vbt.edp.support) DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); return; } switch ((edp->color_depth >> (panel_type * 2)) & 3) { case EDP_18BPP: - dev_priv->vbt.edp_bpp = 18; + dev_priv->vbt.edp.bpp = 18; break; case EDP_24BPP: - dev_priv->vbt.edp_bpp = 24; + dev_priv->vbt.edp.bpp = 24; break; case EDP_30BPP: - dev_priv->vbt.edp_bpp = 30; + dev_priv->vbt.edp.bpp = 30; break; } @@ -573,14 +573,14 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) edp_pps = &edp->power_seqs[panel_type]; edp_link_params = &edp->link_params[panel_type]; - dev_priv->vbt.edp_pps = *edp_pps; + dev_priv->vbt.edp.pps = *edp_pps; switch (edp_link_params->rate) { case EDP_RATE_1_62: - dev_priv->vbt.edp_rate = DP_LINK_BW_1_62; + dev_priv->vbt.edp.rate = DP_LINK_BW_1_62; break; case EDP_RATE_2_7: - dev_priv->vbt.edp_rate = DP_LINK_BW_2_7; + dev_priv->vbt.edp.rate = DP_LINK_BW_2_7; break; default: DRM_DEBUG_KMS("VBT has unknown eDP link rate value %u\n", @@ -590,13 +590,13 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) switch (edp_link_params->lanes) { case EDP_LANE_1: - dev_priv->vbt.edp_lanes = 1; + dev_priv->vbt.edp.lanes = 1; break; case EDP_LANE_2: - dev_priv->vbt.edp_lanes = 2; + dev_priv->vbt.edp.lanes = 2; break; case EDP_LANE_4: - dev_priv->vbt.edp_lanes = 4; + dev_priv->vbt.edp.lanes = 4; break; default: DRM_DEBUG_KMS("VBT has unknown eDP lane count value %u\n", @@ -606,16 +606,16 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) switch (edp_link_params->preemphasis) { case EDP_PREEMPHASIS_NONE: - dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0; + dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0; break; case EDP_PREEMPHASIS_3_5dB: - dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1; + dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1; break; case EDP_PREEMPHASIS_6dB: - dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2; + dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2; break; case EDP_PREEMPHASIS_9_5dB: - dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3; + dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3; break; default: DRM_DEBUG_KMS("VBT has unknown eDP pre-emphasis value %u\n", @@ -625,16 +625,16 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) switch (edp_link_params->vswing) { case EDP_VSWING_0_4V: - dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0; + dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0; break; case EDP_VSWING_0_6V: - dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1; + dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1; break; case EDP_VSWING_0_8V: - dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2; + dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2; break; case EDP_VSWING_1_2V: - dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3; + dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3; break; default: DRM_DEBUG_KMS("VBT has unknown eDP voltage swing value %u\n", diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index e6c3a80..50e4978 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2002,8 +2002,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder, pipe_config->has_audio = intel_ddi_is_audio_enabled(dev_priv, intel_crtc); - if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp && - pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { + if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.bpp && + pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) { /* * This is a big fat ugly hack. * @@ -2018,8 +2018,8 @@ void intel_ddi_get_config(struct intel_encoder *encoder, * load. */ DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", - pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp); - dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; + pipe_config->pipe_bpp, dev_priv->vbt.edp.bpp); + dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp; } intel_ddi_clock_get(encoder, pipe_config); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3ff8f1d..55faad1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1500,10 +1500,10 @@ intel_dp_compute_config(struct intel_encoder *encoder, /* Get bpp from vbt only for panels that dont have bpp in edid */ if (intel_connector->base.display_info.bpc == 0 && - (dev_priv->vbt.edp_bpp && dev_priv->vbt.edp_bpp < bpp)) { + (dev_priv->vbt.edp.bpp && dev_priv->vbt.edp.bpp < bpp)) { DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n", - dev_priv->vbt.edp_bpp); - bpp = dev_priv->vbt.edp_bpp; + dev_priv->vbt.edp.bpp); + bpp = dev_priv->vbt.edp.bpp; } /* @@ -2386,8 +2386,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder, intel_dotclock_calculate(pipe_config->port_clock, &pipe_config->dp_m_n); - if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp && - pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { + if (is_edp(intel_dp) && dev_priv->vbt.edp.bpp && + pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) { /* * This is a big fat ugly hack. * @@ -2402,8 +2402,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder, * load. */ DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", - pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp); - dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; + pipe_config->pipe_bpp, dev_priv->vbt.edp.bpp); + dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp; } } @@ -5111,7 +5111,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12); - vbt = dev_priv->vbt.edp_pps; + vbt = dev_priv->vbt.edp.pps; /* Upper limits from eDP 1.3 spec. Note that we use the clunky units of * our hw here, which are all in 100usec. */ diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 766ba56..5d2b257 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -924,7 +924,7 @@ void intel_lvds_init(struct drm_device *dev) if (HAS_PCH_SPLIT(dev)) { if ((lvds & LVDS_DETECTED) == 0) return; - if (dev_priv->vbt.edp_support) { + if (dev_priv->vbt.edp.support) { DRM_DEBUG_KMS("disable LVDS for eDP support\n"); return; } -- cgit v0.10.2 From 06411f08b3f3a55f621d73356d0326f471978f18 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 24 Mar 2016 17:50:21 +0200 Subject: drm/i915: move edp low vswing config to vbt data Move all data initialized from VBT under dev_priv->vbt. No functional changes. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458834623-8734-3-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fe8021e..ad6f69e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1451,6 +1451,7 @@ struct intel_vbt_data { int lanes; int preemphasis; int vswing; + bool low_vswing; bool initialized; bool support; int bpp; @@ -1963,8 +1964,6 @@ struct drm_i915_private { struct intel_context *kernel_context; - bool edp_low_vswing; - /* perform PHY state sanity checks? */ bool chv_phy_assert[2]; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 61eb7a6..3af8a4a 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -647,10 +647,10 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) /* Don't read from VBT if module parameter has valid value*/ if (i915.edp_vswing) { - dev_priv->edp_low_vswing = i915.edp_vswing == 1; + dev_priv->vbt.edp.low_vswing = i915.edp_vswing == 1; } else { vswing = (edp->edp_vswing_preemph >> (panel_type * 4)) & 0xF; - dev_priv->edp_low_vswing = vswing == 0; + dev_priv->vbt.edp.low_vswing = vswing == 0; } } } diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 50e4978..1e08385 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -360,7 +360,7 @@ skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) static const struct ddi_buf_trans * skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) { - if (dev_priv->edp_low_vswing) { + if (dev_priv->vbt.edp.low_vswing) { if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) { *n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp); return skl_y_ddi_translations_edp; @@ -1431,7 +1431,7 @@ static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv, u32 n_entries, i; uint32_t val; - if (type == INTEL_OUTPUT_EDP && dev_priv->edp_low_vswing) { + if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) { n_entries = ARRAY_SIZE(bxt_ddi_translations_edp); ddi_translations = bxt_ddi_translations_edp; } else if (type == INTEL_OUTPUT_DISPLAYPORT diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 55faad1..3bdd8ba 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3157,7 +3157,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) if (IS_BROXTON(dev)) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; else if (INTEL_INFO(dev)->gen >= 9) { - if (dev_priv->edp_low_vswing && port == PORT_A) + if (dev_priv->vbt.edp.low_vswing && port == PORT_A) return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) -- cgit v0.10.2 From 9d6c875db4ada9f91e1643b5a72d74bea043d67e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 24 Mar 2016 17:50:22 +0200 Subject: drm/i915: move sdvo mappings to vbt data Move all data initialized from VBT under dev_priv->vbt. No functional changes. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458834623-8734-4-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ad6f69e..bf867e2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1491,6 +1491,7 @@ struct intel_vbt_data { union child_device_config *child_dev; struct ddi_vbt_port_info ddi_port_info[I915_MAX_PORTS]; + struct sdvo_device_mapping sdvo_mappings[2]; }; enum intel_ddb_partitioning { @@ -1823,8 +1824,6 @@ struct drm_i915_private { /* Kernel Modesetting */ - struct sdvo_device_mapping sdvo_mappings[2]; - struct drm_crtc *plane_to_crtc_mapping[I915_MAX_PIPES]; struct drm_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES]; wait_queue_head_t pending_flip_queue; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 3af8a4a..407fb7a 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -482,7 +482,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, child->slave_addr, (child->dvo_port == DEVICE_PORT_DVOB) ? "SDVOB" : "SDVOC"); - p_mapping = &(dev_priv->sdvo_mappings[child->dvo_port - 1]); + p_mapping = &dev_priv->vbt.sdvo_mappings[child->dvo_port - 1]; if (!p_mapping->initialized) { p_mapping->dvo_port = child->dvo_port; p_mapping->slave_addr = child->slave_addr; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index fae64bc..2128fae 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2260,9 +2260,9 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, struct sdvo_device_mapping *mapping; if (sdvo->port == PORT_B) - mapping = &(dev_priv->sdvo_mappings[0]); + mapping = &dev_priv->vbt.sdvo_mappings[0]; else - mapping = &(dev_priv->sdvo_mappings[1]); + mapping = &dev_priv->vbt.sdvo_mappings[1]; if (mapping->initialized) sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4); @@ -2278,9 +2278,9 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv, u8 pin; if (sdvo->port == PORT_B) - mapping = &dev_priv->sdvo_mappings[0]; + mapping = &dev_priv->vbt.sdvo_mappings[0]; else - mapping = &dev_priv->sdvo_mappings[1]; + mapping = &dev_priv->vbt.sdvo_mappings[1]; if (mapping->initialized && intel_gmbus_is_valid_pin(dev_priv, mapping->i2c_pin)) @@ -2316,11 +2316,11 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo) struct sdvo_device_mapping *my_mapping, *other_mapping; if (sdvo->port == PORT_B) { - my_mapping = &dev_priv->sdvo_mappings[0]; - other_mapping = &dev_priv->sdvo_mappings[1]; + my_mapping = &dev_priv->vbt.sdvo_mappings[0]; + other_mapping = &dev_priv->vbt.sdvo_mappings[1]; } else { - my_mapping = &dev_priv->sdvo_mappings[1]; - other_mapping = &dev_priv->sdvo_mappings[0]; + my_mapping = &dev_priv->vbt.sdvo_mappings[1]; + other_mapping = &dev_priv->vbt.sdvo_mappings[0]; } /* If the BIOS described our SDVO device, take advantage of it. */ -- cgit v0.10.2 From 583349896482ed1d6af3cd75b2a15bb334df2777 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 24 Mar 2016 17:50:23 +0200 Subject: drm/i915: remove unused dev_priv->render_reclock_avail Set from VBT, but never used. Good riddance. Reviewed-by: Daniel Vetter Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/1458834623-8734-5-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bf867e2..0906dfd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1844,9 +1844,6 @@ struct drm_i915_private { struct i915_workarounds workarounds; - /* Reclocking support */ - bool render_reclock_avail; - struct i915_frontbuffer_tracking fb_tracking; u16 orig_clock; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 407fb7a..9c406b0 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -529,9 +529,6 @@ parse_driver_features(struct drm_i915_private *dev_priv, if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP) dev_priv->vbt.edp.support = 1; - if (driver->dual_frequency) - dev_priv->render_reclock_avail = true; - DRM_DEBUG_KMS("DRRS State Enabled:%d\n", driver->drrs_enabled); /* * If DRRS is not supported, drrs_type has to be set to 0. -- cgit v0.10.2 From 222b90943446e36d44395917b1be28732cbdab08 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 29 Mar 2016 14:14:25 +0200 Subject: drm/atmel: Fixup drm_connector_/unplug/unregister/_all Accidentally fell through the cracks in commit 6c87e5c3ec6db052f3744804a517b6fb003906e1 Author: Alexey Brodkin Date: Wed Mar 23 11:42:54 2016 +0300 drm: Rename drm_connector_unplug_all() to drm_connector_unregister_all() despite that Boris acked that patch. Cc: Boris Brezillon Cc: Alexey Brodkin Acked-by: Boris Brezillon Reported-by: kbuild test robot Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 3d8d164..8ab4318 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -615,7 +615,7 @@ err: static void atmel_hlcdc_dc_connector_unplug_all(struct drm_device *dev) { mutex_lock(&dev->mode_config.mutex); - drm_connector_unplug_all(dev); + drm_connector_unregister_all(dev); mutex_unlock(&dev->mode_config.mutex); } -- cgit v0.10.2 From a7442b93cf32c1e1ddb721a26cd1f92302e2a222 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Wed, 9 Mar 2016 12:52:53 +0100 Subject: drm/i915: Fix races on fbdev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ->lastclose callback invokes intel_fbdev_restore_mode() and has been witnessed to run before intel_fbdev_initial_config_async() has finished. We might likewise receive hotplug events before we've had a chance to fully set up the fbdev. Fix by waiting for the asynchronous thread to finish. v2: An async_synchronize_full() was also added to intel_fbdev_set_suspend() in v1 which turned out to be entirely gratuitous. It caused a deadlock on suspend (discovered by CI, thanks to Damien Lespiau and Tomi Sarvela for CI support) and was unnecessary since a device is never suspended until its ->probe callback (and all asynchronous tasks it scheduled) have finished. See dpm_prepare(), which calls wait_for_device_probe(), which calls async_synchronize_full(). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93580 Reported-by: Gustav Fägerlind Reported-by: "Li, Weinan Z" Cc: Chris Wilson Cc: stable@vger.kernel.org Signed-off-by: Lukas Wunner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20160309115147.67B2B6E0D3@gabe.freedesktop.org diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index fc8ac98..1ac1ea9 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -493,11 +493,9 @@ static int i915_load_modeset_init(struct drm_device *dev) * Some ports require correctly set-up hpd registers for detection to * work properly (leading to ghost connected connector status), e.g. VGA * on gm45. Hence we can only set up the initial fbdev config after hpd - * irqs are fully enabled. Now we should scan for the initial config - * only once hotplug handling is enabled, but due to screwed-up locking - * around kms/fbdev init we can't protect the fdbev initial config - * scanning against hotplug events. Hence do this first and ignore the - * tiny window where we will loose hotplug notifactions. + * irqs are fully enabled. We protect the fbdev initial config scanning + * against hotplug events by waiting in intel_fbdev_output_poll_changed + * until the asynchronous thread has finished. */ intel_fbdev_initial_config_async(dev); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 5e0dcb3..153ea7a3 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -808,6 +808,8 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous void intel_fbdev_output_poll_changed(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + + async_synchronize_full(); if (dev_priv->fbdev) drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); } @@ -819,6 +821,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev) struct intel_fbdev *ifbdev = dev_priv->fbdev; struct drm_fb_helper *fb_helper; + async_synchronize_full(); if (!ifbdev) return; -- cgit v0.10.2 From a16b7658f4e0d4aec9bc3e75a5f0cc3f7a3a0422 Mon Sep 17 00:00:00 2001 From: Lyude Date: Fri, 11 Mar 2016 10:57:01 -0500 Subject: drm/i915: Call intel_dp_mst_resume() before resuming displays Since we need MST devices ready before we try to resume displays, calling this after intel_display_resume() can result in some issues with various laptop docks where the monitor won't turn back on after suspending the system. This order was originally changed in commit e7d6f7d70829 ("drm/i915: resume MST after reading back hw state") In order to fix some unclaimed register errors, however the actual cause of those has since been fixed. CC: stable@vger.kernel.org Signed-off-by: Lyude [danvet: Resolve conflicts with locking changes.] Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 20f8dbe..f73b4f7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -770,10 +770,10 @@ static int i915_drm_resume(struct drm_device *dev) dev_priv->display.hpd_irq_setup(dev); spin_unlock_irq(&dev_priv->irq_lock); - intel_display_resume(dev); - intel_dp_mst_resume(dev); + intel_display_resume(dev); + /* * ... but also need to make sure that hotplug processing * doesn't cause havoc. Like in the driver load code we don't -- cgit v0.10.2 From a91d7b9142b91c9567bc0304cb7d718ac411e85e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 29 Mar 2016 13:12:22 +0200 Subject: Revert "drm: Don't pass negative delta to ktime_sub_ns()" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e91abf80a0998f326107874c88d549f94839f13c. Since commit 24e4a8c3e8868874835b0f1ad6dd417341e99822 Author: John Stultz Date: Wed Jul 16 21:03:53 2014 +0000 ktime: Kill non-scalar ktime_t implementation for 2038 there is no longer a 32bit version that's unsigned, and we don't have to jump through ridiculous hoops to make the calculations correct. I didn't look whether there's more of this pattern in the kernel. Cc: John Stultz Cc: Thomas Gleixner Cc: Michel Dänzer Cc: Imre Deak Cc: Dave Airlie Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459249942-21589-1-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 96d03ac..bfc4b37 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -805,10 +805,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, /* Subtract time delta from raw timestamp to get final * vblank_time timestamp for end of vblank. */ - if (delta_ns < 0) - etime = ktime_add_ns(etime, -delta_ns); - else - etime = ktime_sub_ns(etime, delta_ns); + etime = ktime_sub_ns(etime, delta_ns); *vblank_time = ktime_to_timeval(etime); DRM_DEBUG_VBL("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", -- cgit v0.10.2 From 68d4aee9d1f271fe06e904cb99a10cf8479d3d2e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 09:33:11 +0200 Subject: drm/i915: Update DRIVER_DATE to 20160330 Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0906dfd..f6d7159 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -60,7 +60,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20160314" +#define DRIVER_DATE "20160330" #undef WARN_ON /* Many gcc seem to no see through this and fall over :( */ -- cgit v0.10.2 From 67535531b1b2bfcc707c8c37f35196cf4ede4252 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Wed, 30 Mar 2016 14:53:24 +0530 Subject: drm: bridge/dw-hdmi: Remove pre_enable/post_disable dummy funcs We don't need to keep empty callbacks for the (pre/post) enable/disable drm_bridge ops anymore. Remove the nop callback used here for pre_enable and post_disable ops. Signed-off-by: Archit Taneja Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459329804-10488-1-git-send-email-architt@codeaurora.org diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index 9795b72..c9d9412 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -1413,11 +1413,6 @@ static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) mutex_unlock(&hdmi->mutex); } -static void dw_hdmi_bridge_nop(struct drm_bridge *bridge) -{ - /* do nothing */ -} - static enum drm_connector_status dw_hdmi_connector_detect(struct drm_connector *connector, bool force) { @@ -1536,8 +1531,6 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = { .enable = dw_hdmi_bridge_enable, .disable = dw_hdmi_bridge_disable, - .pre_enable = dw_hdmi_bridge_nop, - .post_disable = dw_hdmi_bridge_nop, .mode_set = dw_hdmi_bridge_mode_set, }; -- cgit v0.10.2 From 9f54d4bd5808b5c892a44c539c126b71d299f341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 30 Mar 2016 11:08:33 +0200 Subject: drm/i915: fix deadlock on lid open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e2c8b8701e2d moved modeset locking inside resume/suspend functions, but missed a code path only executed on lid close/open on older hardware. The result was a deadlock when closing and opening the lid without suspending on such hardware: ============================================= [ INFO: possible recursive locking detected ] 4.6.0-rc1 #385 Not tainted --------------------------------------------- kworker/0:3/88 is trying to acquire lock: (&dev->mode_config.mutex){+.+.+.}, at: [] intel_display_resume+0x4a/0x12f [i915] but task is already holding lock: (&dev->mode_config.mutex){+.+.+.}, at: [] drm_modeset_lock_all+0x3e/0xa6 [drm] other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&dev->mode_config.mutex); lock(&dev->mode_config.mutex); *** DEADLOCK *** May be due to missing lock nesting notation 7 locks held by kworker/0:3/88: #0: ("kacpi_notify"){++++.+}, at: [] process_one_work+0x14a/0x50b #1: ((&dpc->work)#2){+.+.+.}, at: [] process_one_work+0x14a/0x50b #2: ((acpi_lid_notifier).rwsem){++++.+}, at: [] __blocking_notifier_call_chain+0x34/0x65 #3: (&dev_priv->modeset_restore_lock){+.+.+.}, at: [] intel_lid_notify+0x3c/0xd9 [i915] #4: (&dev->mode_config.mutex){+.+.+.}, at: [] drm_modeset_lock_all+0x3e/0xa6 [drm] #5: (crtc_ww_class_acquire){+.+.+.}, at: [] drm_modeset_lock_all+0x48/0xa6 [drm] #6: (crtc_ww_class_mutex){+.+.+.}, at: [] modeset_lock+0x13c/0x1cd [drm] stack backtrace: CPU: 0 PID: 88 Comm: kworker/0:3 Not tainted 4.6.0-rc1 #385 Hardware name: LENOVO 2776LEG/2776LEG, BIOS 6EET55WW (3.15 ) 12/19/2011 Workqueue: kacpi_notify acpi_os_execute_deferred 0000000000000000 ffff88022fd5f990 ffffffff8124af06 ffffffff825b39c0 ffffffff825b39c0 ffff88022fd5fa60 ffffffff8108f547 ffff88022fd5fa70 000000008108e817 ffff880230236cc0 0000000000000000 ffffffff825b39c0 Call Trace: [] dump_stack+0x67/0x90 [] __lock_acquire+0xdb5/0xf71 [] ? look_up_lock_class+0xbe/0x10a [] lock_acquire+0x137/0x1cb [] ? lock_acquire+0x137/0x1cb [] ? intel_display_resume+0x4a/0x12f [i915] [] mutex_lock_nested+0x7e/0x3a4 [] ? intel_display_resume+0x4a/0x12f [i915] [] ? intel_display_resume+0x4a/0x12f [i915] [] ? modeset_lock+0x13c/0x1cd [drm] [] intel_display_resume+0x4a/0x12f [i915] [] ? intel_display_resume+0x4a/0x12f [i915] [] ? modeset_lock+0x13c/0x1cd [drm] [] ? modeset_lock+0x13c/0x1cd [drm] [] ? drm_modeset_lock+0x17/0x24 [drm] [] ? drm_modeset_lock_all_ctx+0x87/0xa1 [drm] [] intel_lid_notify+0xb0/0xd9 [i915] [] notifier_call_chain+0x4a/0x6c [] __blocking_notifier_call_chain+0x4d/0x65 [] blocking_notifier_call_chain+0x14/0x16 [] acpi_lid_send_state+0x83/0xad [button] [] acpi_button_notify+0x41/0x132 [button] [] acpi_device_notify+0x19/0x1b [] acpi_ev_notify_dispatch+0x49/0x64 [] acpi_os_execute_deferred+0x14/0x20 [] process_one_work+0x265/0x50b [] worker_thread+0x1fc/0x2dd [] ? rescuer_thread+0x309/0x309 [] ? rescuer_thread+0x309/0x309 [] kthread+0xe0/0xe8 [] ? local_clock+0x19/0x22 [] ret_from_fork+0x22/0x40 [] ? kthread_create_on_node+0x1b5/0x1b5 Fixes: e2c8b8701e2d ("drm/i915: Use atomic helpers for suspend, v2.") Cc: Maarten Lankhorst Signed-off-by: Bjørn Mork Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/1459328913-13719-1-git-send-email-bjorn@mork.no diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 5d2b257..66e832b 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -472,11 +472,8 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, * and as part of the cleanup in the hw state restore we also redisable * the vga plane. */ - if (!HAS_PCH_SPLIT(dev)) { - drm_modeset_lock_all(dev); + if (!HAS_PCH_SPLIT(dev)) intel_display_resume(dev); - drm_modeset_unlock_all(dev); - } dev_priv->modeset_restore = MODESET_DONE; -- cgit v0.10.2 From ade7daa164709e5851836195c6cd7502cea1eb5e Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Thu, 24 Mar 2016 15:54:20 +0000 Subject: drm/i915: BUG_ON when ggtt_view is NULL Lets BUG_ON and don't bother with a WARN and returning an error, so we can remove the need to pollute the code with error handling, after all it is a programmer error to provide NULL view. Also while we're here remove redundant NULL ggtt_view check. Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Signed-off-by: Matthew Auld Acked-by: Daniel Vetter Reviewed-by: Joonas Lahtinen Signed-off-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1458834860-7898-1-git-send-email-matthew.auld@intel.com diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c7a997a..cbf616a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4235,9 +4235,6 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj, vma = ggtt_view ? i915_gem_obj_to_ggtt_view(obj, ggtt_view) : i915_gem_obj_to_vma(obj, vm); - if (IS_ERR(vma)) - return PTR_ERR(vma); - if (vma) { if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) return -EBUSY; @@ -4300,8 +4297,7 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, uint32_t alignment, uint64_t flags) { - if (WARN_ONCE(!view, "no view specified")) - return -EINVAL; + BUG_ON(!view); return i915_gem_object_do_pin(obj, i915_obj_to_ggtt(obj), view, alignment, flags | PIN_GLOBAL); @@ -4618,8 +4614,7 @@ struct i915_vma *i915_gem_obj_to_ggtt_view(struct drm_i915_gem_object *obj, struct i915_address_space *ggtt = i915_obj_to_ggtt(obj); struct i915_vma *vma; - if (WARN_ONCE(!view, "no view specified")) - return ERR_PTR(-EINVAL); + BUG_ON(!view); list_for_each_entry(vma, &obj->vma_list, obj_link) if (vma->vm == ggtt && diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 7cfafdc..073c6bb 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3341,15 +3341,7 @@ i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj, const struct i915_ggtt_view *view) { struct i915_address_space *ggtt = i915_obj_to_ggtt(obj); - struct i915_vma *vma; - - if (WARN_ON(!view)) - return ERR_PTR(-EINVAL); - - vma = i915_gem_obj_to_ggtt_view(obj, view); - - if (IS_ERR(vma)) - return vma; + struct i915_vma *vma = i915_gem_obj_to_ggtt_view(obj, view); if (!vma) vma = __i915_gem_vma_create(obj, ggtt, view); -- cgit v0.10.2 From d85489d314f2d273ffb4217b77bc659900b8a3f6 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Thu, 24 Mar 2016 16:47:46 +0200 Subject: drm/i915: Rename GGTT init functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename and document the GGTT init functions to give a better idea of the context where they are called from. i915_gem_gtt_init => i915_ggtt_init_hw i915_gem_init_global_gtt => i915_gem_init_ggtt i915_global_gtt_cleanup => i915_ggtt_cleanup_hw Cc: Tvrtko Ursulin Cc: Mika Kuoppala Cc: Ville Syrjälä Cc: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1458830866-12578-1-git-send-email-joonas.lahtinen@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 1ac1ea9..d301173 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1178,7 +1178,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) intel_device_info_runtime_init(dev); - ret = i915_gem_gtt_init(dev); + ret = i915_ggtt_init_hw(dev); if (ret) return ret; @@ -1187,13 +1187,13 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) ret = i915_kick_out_firmware_fb(dev_priv); if (ret) { DRM_ERROR("failed to remove conflicting framebuffer drivers\n"); - goto out_gtt; + goto out_ggtt; } ret = i915_kick_out_vgacon(dev_priv); if (ret) { DRM_ERROR("failed to remove conflicting VGA console\n"); - goto out_gtt; + goto out_ggtt; } pci_set_master(dev->pdev); @@ -1220,7 +1220,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) aperture_size); if (dev_priv->ggtt.mappable == NULL) { ret = -EIO; - goto out_gtt; + goto out_ggtt; } dev_priv->ggtt.mtrr = arch_phys_wc_add(dev_priv->ggtt.mappable_base, @@ -1253,8 +1253,8 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) return 0; -out_gtt: - i915_global_gtt_cleanup(dev); +out_ggtt: + i915_ggtt_cleanup_hw(dev); return ret; } @@ -1273,7 +1273,7 @@ static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv) pm_qos_remove_request(&dev_priv->pm_qos); arch_phys_wc_del(dev_priv->ggtt.mtrr); io_mapping_free(dev_priv->ggtt.mappable); - i915_global_gtt_cleanup(dev); + i915_ggtt_cleanup_hw(dev); } /** diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cbf616a..11a6ccd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4962,7 +4962,7 @@ int i915_gem_init(struct drm_device *dev) if (ret) goto out_unlock; - i915_gem_init_global_gtt(dev); + i915_gem_init_ggtt(dev); ret = i915_gem_context_init(dev); if (ret) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 073c6bb..f8f09d1 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2804,7 +2804,11 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, return 0; } -void i915_gem_init_global_gtt(struct drm_device *dev) +/** + * i915_gem_init_ggtt - Initialize GEM for Global GTT + * @dev: DRM device + */ +void i915_gem_init_ggtt(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u64 gtt_size, mappable_size; @@ -2815,7 +2819,11 @@ void i915_gem_init_global_gtt(struct drm_device *dev) i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size); } -void i915_global_gtt_cleanup(struct drm_device *dev) +/** + * i915_ggtt_cleanup_hw - Clean up GGTT hardware initialization + * @dev: DRM device + */ +void i915_ggtt_cleanup_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_address_space *vm = &dev_priv->ggtt.base; @@ -3153,7 +3161,11 @@ static void i915_gmch_remove(struct i915_address_space *vm) intel_gmch_remove(); } -int i915_gem_gtt_init(struct drm_device *dev) +/** + * i915_ggtt_init_hw - Initialize GGTT hardware + * @dev: DRM device + */ +int i915_ggtt_init_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_ggtt *ggtt = &dev_priv->ggtt; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index d804be0..242a13b 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -513,10 +513,9 @@ i915_page_dir_dma_addr(const struct i915_hw_ppgtt *ppgtt, const unsigned n) px_dma(ppgtt->base.scratch_pd); } -int i915_gem_gtt_init(struct drm_device *dev); -void i915_gem_init_global_gtt(struct drm_device *dev); -void i915_global_gtt_cleanup(struct drm_device *dev); - +int i915_ggtt_init_hw(struct drm_device *dev); +void i915_gem_init_ggtt(struct drm_device *dev); +void i915_ggtt_cleanup_hw(struct drm_device *dev); int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt); int i915_ppgtt_init_hw(struct drm_device *dev); -- cgit v0.10.2 From b208ba8e49cd2b70a5e8f8f778627e5a2f050fed Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 24 Mar 2016 14:31:47 +0000 Subject: drm/i915: Rename __force_wake_get to __force_wake_auto __force_wake_get() only acquires a temporary wakeref on forcewake that is automatically released when a timer expires. When reading the code again, I confused __intel_uncore_forcewake_get() for __force_wake_get() and to my shame thought I found a bug in unbalanced wake_count handling. I claim that if the function had been called __force_wake_auto() instead I would not have embarrassed myself. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Tvrtko Ursulin Link: http://patchwork.freedesktop.org/patch/msgid/1458829907-26596-1-git-send-email-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 512b7fa..ac1c545 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -716,8 +716,8 @@ __gen2_read(64) trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ return val -static inline void __force_wake_get(struct drm_i915_private *dev_priv, - enum forcewake_domains fw_domains) +static inline void __force_wake_auto(struct drm_i915_private *dev_priv, + enum forcewake_domains fw_domains) { struct intel_uncore_forcewake_domain *domain; enum forcewake_domain_id id; @@ -745,7 +745,7 @@ static u##x \ gen6_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ GEN6_READ_HEADER(x); \ if (NEEDS_FORCE_WAKE(offset)) \ - __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ + __force_wake_auto(dev_priv, FORCEWAKE_RENDER); \ val = __raw_i915_read##x(dev_priv, reg); \ GEN6_READ_FOOTER; \ } @@ -762,7 +762,7 @@ vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(offset)) \ fw_engine = FORCEWAKE_MEDIA; \ if (fw_engine) \ - __force_wake_get(dev_priv, fw_engine); \ + __force_wake_auto(dev_priv, fw_engine); \ val = __raw_i915_read##x(dev_priv, reg); \ GEN6_READ_FOOTER; \ } @@ -781,7 +781,7 @@ chv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \ fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ if (fw_engine) \ - __force_wake_get(dev_priv, fw_engine); \ + __force_wake_auto(dev_priv, fw_engine); \ val = __raw_i915_read##x(dev_priv, reg); \ GEN6_READ_FOOTER; \ } @@ -805,7 +805,7 @@ gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ else \ fw_engine = FORCEWAKE_BLITTER; \ if (fw_engine) \ - __force_wake_get(dev_priv, fw_engine); \ + __force_wake_auto(dev_priv, fw_engine); \ val = __raw_i915_read##x(dev_priv, reg); \ GEN6_READ_FOOTER; \ } @@ -969,7 +969,7 @@ static void \ gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ GEN6_WRITE_HEADER; \ if (NEEDS_FORCE_WAKE(offset) && !is_gen8_shadowed(dev_priv, reg)) \ - __force_wake_get(dev_priv, FORCEWAKE_RENDER); \ + __force_wake_auto(dev_priv, FORCEWAKE_RENDER); \ __raw_i915_write##x(dev_priv, reg, val); \ GEN6_WRITE_FOOTER; \ } @@ -989,7 +989,7 @@ chv_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool t else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \ fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ if (fw_engine) \ - __force_wake_get(dev_priv, fw_engine); \ + __force_wake_auto(dev_priv, fw_engine); \ __raw_i915_write##x(dev_priv, reg, val); \ GEN6_WRITE_FOOTER; \ } @@ -1036,7 +1036,7 @@ gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \ else \ fw_engine = FORCEWAKE_BLITTER; \ if (fw_engine) \ - __force_wake_get(dev_priv, fw_engine); \ + __force_wake_auto(dev_priv, fw_engine); \ __raw_i915_write##x(dev_priv, reg, val); \ GEN6_WRITE_FOOTER; \ } -- cgit v0.10.2 From 579de73b048a0a4c66c25a033ac76a2836e0cf73 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 14 Mar 2016 09:01:57 +0000 Subject: drm/i915: Exit cherryview_irq_handler() after one pass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This effectively reverts commit 8e5fd599eb219f1054e39b40d18b217af669eea9 Author: Ville Syrjälä Date: Wed Apr 9 13:28:50 2014 +0300 drm/i915/chv: Make CHV irq handler loop until all interrupts are consumed as under continuous execlists load we can saturate the IRQ handler, destablising the tsc clock and triggering the NMI watchdog to declare a hung CPU. [ 552.756051] clocksource: timekeeping watchdog on CPU0: Marking clocksource 'tsc' as unstable because the skew is too large: [ 552.756080] clocksource: 'refined-jiffies' wd_now: 10003b480 wd_last: 10003b28c mask: ffffffff [ 552.756091] clocksource: 'tsc' cs_now: d55d31aa50 cs_last: d17446166c mask: ffffffffffffffff [ 552.756210] clocksource: Switched to clocksource refined-jiffies [ 575.217870] NMI watchdog: Watchdog detected hard LOCKUP on cpu 1 [ 575.217893] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.5.0-rc7+ #18 [ 575.217905] Hardware name: /NUC5CPYB, BIOS PYBSWCEL.86A.0027.2015.0507.1758 05/07/2015 [ 575.217915] 0000000000000000 ffff88027fd05bc0 ffffffff81288c6d 0000000000000000 [ 575.217935] 0000000000000001 ffff88027fd05be0 ffffffff810e72d1 0000000000000000 [ 575.217951] ffff88027fd05c80 ffff88027fd05c20 ffffffff81114b60 0000000181015f1e [ 575.217967] Call Trace: [ 575.217973] [] dump_stack+0x4f/0x72 [ 575.217994] [] watchdog_overflow_callback+0x151/0x160 [ 575.218003] [] __perf_event_overflow+0xa0/0x1e0 [ 575.218016] [] perf_event_overflow+0x14/0x20 [ 575.218028] [] intel_pmu_handle_irq+0x1da/0x460 [ 575.218042] [] ? poll_idle+0x3e/0x70 [ 575.218052] [] ? poll_idle+0x3e/0x70 [ 575.218064] [] perf_event_nmi_handler+0x28/0x50 [ 575.218075] [] nmi_handle+0x60/0x130 [ 575.218086] [] ? poll_idle+0x3e/0x70 [ 575.218096] [] do_nmi+0x140/0x470 [ 575.218108] [] end_repeat_nmi+0x1a/0x1e [ 575.218119] [] ? poll_idle+0x3e/0x70 [ 575.218129] [] ? poll_idle+0x3e/0x70 [ 575.218139] [] ? poll_idle+0x3e/0x70 [ 575.218148] <> [] cpuidle_enter_state+0xf3/0x2f0 [ 575.218164] [] cpuidle_enter+0x17/0x20 [ 575.218175] [] call_cpuidle+0x2a/0x40 [ 575.218185] [] cpu_startup_entry+0x273/0x330 [ 575.218196] [] start_secondary+0x10e/0x130 However, not servicing all available IIR within the handler does hurt the throughput of pathological nop execbuf by about 20%, with a similar effect upon the dispatch latency of a series of execbuf. v2: use do {} while(0) for a smaller patch, and easier to revert again I have reasonable confidence that we do not miss GT interrupts (as execlists provides a stress case with a failure mechanism easily detected by igt), however I have less confidence about all the other sources of interrupts and worry that may lose a display hotplug interrupt, for example. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93467 Testcase: igt/gem_exec_nop/basic # requires NMI watchdog Signed-off-by: Chris Wilson Cc: Ville Syrjälä Cc: Antti Koskipää Cc: Tvrtko Ursulin Cc: stable@vger.kernel.org Reviewed-by: Tvrtko Ursulin Reviewed-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1457946117-6714-1-git-send-email-chris@chris-wilson.co.uk diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5aa4239..a9c1813 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1828,7 +1828,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ disable_rpm_wakeref_asserts(dev_priv); - for (;;) { + do { master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL; iir = I915_READ(VLV_IIR); @@ -1856,7 +1856,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL); POSTING_READ(GEN8_MASTER_IRQ); - } + } while (0); enable_rpm_wakeref_asserts(dev_priv); -- cgit v0.10.2 From e6bf6e5799f72f04bac61056804d6dd8dac98062 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 13:24:06 +0200 Subject: drm/ttm: Remove TTM_HAS_AGP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It tries to do fancy things with excluding agp support if ttm is built-in, but agp isn't. Instead just express this depency like drm does and use CONFIG_AGP everywhere. Also use the neat Makefile magic to make the entire ttm_agp_backend file optional. v2: Use IS_ENABLED(CONFIG_AGP) as suggested by Ville v3: Review from Emil. v4: Actually get it right as spotted by 0-day. Cc: Emil Velikov Cc: Ville Syrjälä Reviewed-by: Emil Velikov Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459337046-25882-1-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/ttm/Makefile b/drivers/gpu/drm/ttm/Makefile index b433b9f..f923258 100644 --- a/drivers/gpu/drm/ttm/Makefile +++ b/drivers/gpu/drm/ttm/Makefile @@ -2,9 +2,10 @@ # Makefile for the drm device driver. This driver provides support for the ccflags-y := -Iinclude/drm -ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \ +ttm-y := ttm_memory.o ttm_tt.o ttm_bo.o \ ttm_bo_util.o ttm_bo_vm.o ttm_module.o \ ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o \ ttm_bo_manager.o ttm_page_alloc_dma.o +ttm-$(CONFIG_AGP) += ttm_agp_backend.o obj-$(CONFIG_DRM_TTM) += ttm.o diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index 764be36..028ab60 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -34,7 +34,6 @@ #include #include #include -#ifdef TTM_HAS_AGP #include #include #include @@ -148,5 +147,3 @@ void ttm_agp_tt_unpopulate(struct ttm_tt *ttm) ttm_pool_unpopulate(ttm); } EXPORT_SYMBOL(ttm_agp_tt_unpopulate); - -#endif diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index 025c429..a37de5d 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -48,7 +48,7 @@ #include #include -#ifdef TTM_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) #include #endif @@ -219,7 +219,7 @@ static struct ttm_pool_manager *_manager; #ifndef CONFIG_X86 static int set_pages_array_wb(struct page **pages, int addrinarray) { -#ifdef TTM_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) int i; for (i = 0; i < addrinarray; i++) @@ -230,7 +230,7 @@ static int set_pages_array_wb(struct page **pages, int addrinarray) static int set_pages_array_wc(struct page **pages, int addrinarray) { -#ifdef TTM_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) int i; for (i = 0; i < addrinarray; i++) @@ -241,7 +241,7 @@ static int set_pages_array_wc(struct page **pages, int addrinarray) static int set_pages_array_uc(struct page **pages, int addrinarray) { -#ifdef TTM_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) int i; for (i = 0; i < addrinarray; i++) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index 624d941..bef9f6f 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -50,7 +50,7 @@ #include #include #include -#ifdef TTM_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) #include #endif @@ -271,7 +271,7 @@ static struct kobj_type ttm_pool_kobj_type = { #ifndef CONFIG_X86 static int set_pages_array_wb(struct page **pages, int addrinarray) { -#ifdef TTM_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) int i; for (i = 0; i < addrinarray; i++) @@ -282,7 +282,7 @@ static int set_pages_array_wb(struct page **pages, int addrinarray) static int set_pages_array_wc(struct page **pages, int addrinarray) { -#ifdef TTM_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) int i; for (i = 0; i < addrinarray; i++) @@ -293,7 +293,7 @@ static int set_pages_array_wc(struct page **pages, int addrinarray) static int set_pages_array_uc(struct page **pages, int addrinarray) { -#ifdef TTM_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) int i; for (i = 0; i < addrinarray; i++) diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 3d4bf08..cb91f80 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -1030,8 +1030,7 @@ extern pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp); extern const struct ttm_mem_type_manager_func ttm_bo_manager_func; -#if (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE))) -#define TTM_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) #include /** -- cgit v0.10.2 From aa2e2996b1518b3e4b72dab5c2cb6cd082e3002e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 11:45:14 +0200 Subject: drm/sysfs: Nuke TV/DVI property files This goes all the way back to the original KMS commit aeons ago commit f453ba0460742ad027ae0c4c7d61e62817b3e7ef Author: Dave Airlie Date: Fri Nov 7 14:05:41 2008 -0800 DRM: add mode setting support But it seems to be completely unused. Only i915 and nouveau even register these properties, and the corresponding DDX don't even look at them. Also the sysfs files are read-only, so not useful to configure anything. I suspect that this was added with the goal to have read-only access to all properties in sysfs, but we never followed through on that. Also, that should be done in a more generic fashion. Since it would be real work to fix up the locking (with atomic we're now chasing pointers when reading properties) and it seems unused lets just nuke this all. It's easier. Of course we'll keep the properties themselves, those are still exposed through the KMS ioctls. Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459331120-27864-5-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index d503f8e..d7d8cec 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -287,102 +287,6 @@ static ssize_t modes_show(struct device *device, return written; } -static ssize_t tv_subconnector_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct drm_connector *connector = to_drm_connector(device); - struct drm_device *dev = connector->dev; - struct drm_property *prop; - uint64_t subconnector; - int ret; - - prop = dev->mode_config.tv_subconnector_property; - if (!prop) { - DRM_ERROR("Unable to find subconnector property\n"); - return 0; - } - - ret = drm_object_property_get_value(&connector->base, prop, &subconnector); - if (ret) - return 0; - - return snprintf(buf, PAGE_SIZE, "%s", - drm_get_tv_subconnector_name((int)subconnector)); -} - -static ssize_t tv_select_subconnector_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct drm_connector *connector = to_drm_connector(device); - struct drm_device *dev = connector->dev; - struct drm_property *prop; - uint64_t subconnector; - int ret; - - prop = dev->mode_config.tv_select_subconnector_property; - if (!prop) { - DRM_ERROR("Unable to find select subconnector property\n"); - return 0; - } - - ret = drm_object_property_get_value(&connector->base, prop, &subconnector); - if (ret) - return 0; - - return snprintf(buf, PAGE_SIZE, "%s", - drm_get_tv_select_name((int)subconnector)); -} - -static ssize_t dvii_subconnector_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct drm_connector *connector = to_drm_connector(device); - struct drm_device *dev = connector->dev; - struct drm_property *prop; - uint64_t subconnector; - int ret; - - prop = dev->mode_config.dvi_i_subconnector_property; - if (!prop) { - DRM_ERROR("Unable to find subconnector property\n"); - return 0; - } - - ret = drm_object_property_get_value(&connector->base, prop, &subconnector); - if (ret) - return 0; - - return snprintf(buf, PAGE_SIZE, "%s", - drm_get_dvi_i_subconnector_name((int)subconnector)); -} - -static ssize_t dvii_select_subconnector_show(struct device *device, - struct device_attribute *attr, - char *buf) -{ - struct drm_connector *connector = to_drm_connector(device); - struct drm_device *dev = connector->dev; - struct drm_property *prop; - uint64_t subconnector; - int ret; - - prop = dev->mode_config.dvi_i_select_subconnector_property; - if (!prop) { - DRM_ERROR("Unable to find select subconnector property\n"); - return 0; - } - - ret = drm_object_property_get_value(&connector->base, prop, &subconnector); - if (ret) - return 0; - - return snprintf(buf, PAGE_SIZE, "%s", - drm_get_dvi_i_select_name((int)subconnector)); -} - static DEVICE_ATTR_RW(status); static DEVICE_ATTR_RO(enabled); static DEVICE_ATTR_RO(dpms); @@ -396,54 +300,6 @@ static struct attribute *connector_dev_attrs[] = { NULL }; -static DEVICE_ATTR_RO(tv_subconnector); -static DEVICE_ATTR_RO(tv_select_subconnector); - -static struct attribute *connector_tv_dev_attrs[] = { - &dev_attr_tv_subconnector.attr, - &dev_attr_tv_select_subconnector.attr, - NULL -}; - -static DEVICE_ATTR_RO(dvii_subconnector); -static DEVICE_ATTR_RO(dvii_select_subconnector); - -static struct attribute *connector_dvii_dev_attrs[] = { - &dev_attr_dvii_subconnector.attr, - &dev_attr_dvii_select_subconnector.attr, - NULL -}; - -/* Connector type related helpers */ -static int kobj_connector_type(struct kobject *kobj) -{ - struct device *dev = kobj_to_dev(kobj); - struct drm_connector *connector = to_drm_connector(dev); - - return connector->connector_type; -} - -static umode_t connector_is_dvii(struct kobject *kobj, - struct attribute *attr, int idx) -{ - return kobj_connector_type(kobj) == DRM_MODE_CONNECTOR_DVII ? - attr->mode : 0; -} - -static umode_t connector_is_tv(struct kobject *kobj, - struct attribute *attr, int idx) -{ - switch (kobj_connector_type(kobj)) { - case DRM_MODE_CONNECTOR_Composite: - case DRM_MODE_CONNECTOR_SVIDEO: - case DRM_MODE_CONNECTOR_Component: - case DRM_MODE_CONNECTOR_TV: - return attr->mode; - } - - return 0; -} - static struct bin_attribute edid_attr = { .attr.name = "edid", .attr.mode = 0444, @@ -461,20 +317,8 @@ static const struct attribute_group connector_dev_group = { .bin_attrs = connector_bin_attrs, }; -static const struct attribute_group connector_tv_dev_group = { - .attrs = connector_tv_dev_attrs, - .is_visible = connector_is_tv, -}; - -static const struct attribute_group connector_dvii_dev_group = { - .attrs = connector_dvii_dev_attrs, - .is_visible = connector_is_dvii, -}; - static const struct attribute_group *connector_dev_groups[] = { &connector_dev_group, - &connector_tv_dev_group, - &connector_dvii_dev_group, NULL }; -- cgit v0.10.2 From 44debe7a123cc760fc90ccbe253210798c917fa7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 11:26:35 +0200 Subject: vgacon: dummy implementation for vgacon_text_force MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to ditch a ton of ugly #ifdefs from a bunch of drm modeset drivers. v2: Make the dummy function actually return a sane value, spotted by Ville. v3: Because the patch is still in limbo there's no more drivers to convert, noticed by Emil. v4: Rebase once more, because hooray. I'll just go ahead an apply this one later on to drm-misc. Cc: Emil Velikov Cc: Ville Syrjälä Cc: Andrew Morton Cc: Greg Kroah-Hartman Reviewed-by: Emil Velikov Reviewed-by: Alex Deucher Signed-off-by: Daniel Vetter diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index ce79a8b..fba20bd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -539,12 +539,10 @@ static struct pci_driver amdgpu_kms_pci_driver = { static int __init amdgpu_init(void) { -#ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force()) { DRM_ERROR("VGACON disables amdgpu kernel modesetting.\n"); return -EINVAL; } -#endif DRM_INFO("amdgpu kernel modesetting enabled.\n"); driver = &kms_driver; pdriver = &amdgpu_kms_pci_driver; diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 9a32d9d..fcd9c07 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -218,10 +218,8 @@ static struct drm_driver driver = { static int __init ast_init(void) { -#ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force() && ast_modeset == -1) return -EINVAL; -#endif if (ast_modeset == 0) return -EINVAL; diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index b1619e2..b394e6d 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -162,10 +162,8 @@ static struct pci_driver cirrus_pci_driver = { static int __init cirrus_init(void) { -#ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force() && cirrus_modeset == -1) return -EINVAL; -#endif if (cirrus_modeset == 0) return -EINVAL; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 44912ec..8a62690 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1750,10 +1750,8 @@ static int __init i915_init(void) if (i915.modeset == 0) driver.driver_features &= ~DRIVER_MODESET; -#ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force() && i915.modeset == -1) driver.driver_features &= ~DRIVER_MODESET; -#endif if (!(driver.driver_features & DRIVER_MODESET)) { /* Silently fail loading to not upset userspace. */ diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index b0af774..ebb470f 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -116,10 +116,8 @@ static struct pci_driver mgag200_pci_driver = { static int __init mgag200_init(void) { -#ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force() && mgag200_modeset == -1) return -EINVAL; -#endif if (mgag200_modeset == 0) return -EINVAL; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index bb8498c..731c5c2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -1082,10 +1082,8 @@ nouveau_drm_init(void) nouveau_display_options(); if (nouveau_modeset == -1) { -#ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force()) nouveau_modeset = 0; -#endif } if (!nouveau_modeset) diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index 7307b07..dc9df5f 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -272,10 +272,8 @@ static struct drm_driver qxl_driver = { static int __init qxl_init(void) { -#ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force() && qxl_modeset == -1) return -EINVAL; -#endif if (qxl_modeset == 0) return -EINVAL; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index cad2555..ad136fc 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -558,12 +558,10 @@ static struct pci_driver radeon_kms_pci_driver = { static int __init radeon_init(void) { -#ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force() && radeon_modeset == -1) { DRM_INFO("VGACON disable radeon kernel modesetting.\n"); radeon_modeset = 0; } -#endif /* set to modesetting by default if not nomodeset */ if (radeon_modeset == -1) radeon_modeset = 1; diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index 7f898cf..3cc7afa 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -42,10 +42,8 @@ module_param_named(modeset, virtio_gpu_modeset, int, 0400); static int virtio_gpu_probe(struct virtio_device *vdev) { -#ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force() && virtio_gpu_modeset == -1) return -EINVAL; -#endif if (virtio_gpu_modeset == 0) return -EINVAL; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 0ee76e5..fa10395 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1529,10 +1529,8 @@ static int __init vmwgfx_init(void) { int ret; -#ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force()) return -EINVAL; -#endif ret = drm_pci_init(&driver, &vmw_pci_driver); if (ret) diff --git a/include/linux/console.h b/include/linux/console.h index ea731af..e49cc1e 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -191,6 +191,8 @@ void vcs_remove_sysfs(int index); #ifdef CONFIG_VGA_CONSOLE extern bool vgacon_text_force(void); +#else +static inline bool vgacon_text_force(void) { return false; } #endif #endif /* _LINUX_CONSOLE_H */ -- cgit v0.10.2 From 9c7417022ded5700a4b1a11da59951ebf080e4e0 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Wed, 30 Mar 2016 07:58:01 -0700 Subject: drm/i915/kbl: Remove preliminary_hw_support protection from KBL. We now have KBL machines running in our CI systems and with no blocking issues that could cause a full hangs or blank screens. Signed-off-by: Rodrigo Vivi Link: http://patchwork.freedesktop.org/patch/msgid/1459349881-951-1-git-send-email-rodrigo.vivi@intel.com Acked-by: Daniel Vetter diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f73b4f7..79b63cb 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -360,14 +360,12 @@ static const struct intel_device_info intel_broxton_info = { static const struct intel_device_info intel_kabylake_info = { BDW_FEATURES, - .is_preliminary = 1, .is_kabylake = 1, .gen = 9, }; static const struct intel_device_info intel_kabylake_gt3_info = { BDW_FEATURES, - .is_preliminary = 1, .is_kabylake = 1, .gen = 9, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, -- cgit v0.10.2 From 55c561a708eec328822721233b1148119e80f5c3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 11:34:36 +0200 Subject: drm/i915: Remove PIPE_CONF_CHECK_I_ALT And move the comment to the right macro. This was mixed up in commit cfb23ed622d040619abb91e625fcba74d356b8a8 Author: Maarten Lankhorst Date: Tue Jul 14 12:17:40 2015 +0200 drm/i915: Allow fuzzy matching in pipe_config_compare, v2 v2: Rebase. Cc: Maarten Lankhorst Cc: Daniel Stone Acked-by: Maarten Lankhorst Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459330476-32453-1-git-send-email-daniel.vetter@ffwll.ch diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 29aa64b..fec6392 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -12569,6 +12569,11 @@ intel_pipe_config_compare(struct drm_device *dev, ret = false; \ } +/* This is required for BDW+ where there is only one set of registers for + * switching between high and low RR. + * This macro can be used whenever a comparison has to be made between one + * hw state and multiple sw state variables. + */ #define PIPE_CONF_CHECK_M_N_ALT(name, alt_name) \ if (!intel_compare_link_m_n(¤t_config->name, \ &pipe_config->name, adjust) && \ @@ -12596,22 +12601,6 @@ intel_pipe_config_compare(struct drm_device *dev, ret = false; \ } -/* This is required for BDW+ where there is only one set of registers for - * switching between high and low RR. - * This macro can be used whenever a comparison has to be made between one - * hw state and multiple sw state variables. - */ -#define PIPE_CONF_CHECK_I_ALT(name, alt_name) \ - if ((current_config->name != pipe_config->name) && \ - (current_config->alt_name != pipe_config->name)) { \ - INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \ - "(expected %i or %i, found %i)\n", \ - current_config->name, \ - current_config->alt_name, \ - pipe_config->name); \ - ret = false; \ - } - #define PIPE_CONF_CHECK_FLAGS(name, mask) \ if ((current_config->name ^ pipe_config->name) & (mask)) { \ INTEL_ERR_OR_DBG_KMS("mismatch in " #name "(" #mask ") " \ @@ -12736,7 +12725,6 @@ intel_pipe_config_compare(struct drm_device *dev, #undef PIPE_CONF_CHECK_X #undef PIPE_CONF_CHECK_I #undef PIPE_CONF_CHECK_P -#undef PIPE_CONF_CHECK_I_ALT #undef PIPE_CONF_CHECK_FLAGS #undef PIPE_CONF_CHECK_CLOCK_FUZZY #undef PIPE_CONF_QUIRK -- cgit v0.10.2 From 4c4925fa0c2b5943655ef28b2d6a379961db551f Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 17:12:33 +0200 Subject: drm: Make drm.h uapi header safe for C++ virtual is a protected keyword in C++ and can't be used at all. Ugh. This aligns the kernel versions of the drm headers with the ones in libdrm. v2: Also annote with __user, as request by Emil&Ilia. Cc: Ilia Mirkin Cc: Emil Velikov Reviewed-by: Emil Velikov Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459350753-18320-1-git-send-email-daniel.vetter@ffwll.ch diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index a0ebfe7..7d42d10 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -373,7 +373,11 @@ struct drm_buf_pub { */ struct drm_buf_map { int count; /**< Length of the buffer list */ +#ifdef __cplusplus + void __user *virt; +#else void __user *virtual; /**< Mmap'd area in user-virtual */ +#endif struct drm_buf_pub __user *list; /**< Buffer information */ }; -- cgit v0.10.2 From 0b1ccd49ba3252c5cbb0ac98ee2a8682b9a529cb Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 17:54:52 +0200 Subject: drm: align #include directives with libdrm in uapi headers We can't use because that upsets the serach paths in libdrm. Also, drop the circular inclusion in drm_mode.h. v2: Actually change the right headers. v3: Drop the #include removal per Emil's request. Cc: Emil Velikov Reviewed-by: Emil Velikov Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459353292-9063-1-git-send-email-daniel.vetter@ffwll.ch diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 7d42d10..85ada49 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -685,7 +685,7 @@ struct drm_prime_handle { __s32 fd; }; -#include +#include "drm_mode.h" #define DRM_IOCTL_BASE 'd' #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) -- cgit v0.10.2 From 8812f3814120873ac625d0085e64e4b83ff5aff3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 16:19:44 +0200 Subject: drm: Move DRM_MODE_OBJECT_* to uapi headers These type defines are officially part of the uapi, but ended up in the wrong headers somehow when we split them all. Cc: Emil Velikov Reviewed-by: Emil Velikov Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459347584-30566-3-git-send-email-daniel.vetter@ffwll.ch diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 12f2bd4..dc5cbf2 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -45,16 +45,6 @@ struct drm_clip_rect; struct device_node; struct fence; -#define DRM_MODE_OBJECT_CRTC 0xcccccccc -#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 -#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 -#define DRM_MODE_OBJECT_MODE 0xdededede -#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 -#define DRM_MODE_OBJECT_FB 0xfbfbfbfb -#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb -#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee -#define DRM_MODE_OBJECT_ANY 0 - struct drm_mode_object { uint32_t id; uint32_t type; diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index c021743..7a7856e 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -320,6 +320,16 @@ struct drm_mode_connector_set_property { __u32 connector_id; }; +#define DRM_MODE_OBJECT_CRTC 0xcccccccc +#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 +#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0 +#define DRM_MODE_OBJECT_MODE 0xdededede +#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 +#define DRM_MODE_OBJECT_FB 0xfbfbfbfb +#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb +#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee +#define DRM_MODE_OBJECT_ANY 0 + struct drm_mode_obj_get_properties { __u64 props_ptr; __u64 prop_values_ptr; -- cgit v0.10.2 From 00c9672606f781f2db7e904127dcbdc2831701ca Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 16:42:22 +0200 Subject: drm: Untangle __KERNEL__ guards make headers_install can't handle fancy conditions, so let's simplify things for it a bit. Cc: Emil Velikov Reviewed-by: Emil Velikov Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459348943-12803-1-git-send-email-daniel.vetter@ffwll.ch diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 85ada49..fbc0818 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -36,7 +36,13 @@ #ifndef _DRM_H_ #define _DRM_H_ -#if defined(__KERNEL__) || defined(__linux__) +#if defined(__KERNEL__) + +#include +#include +typedef unsigned int drm_handle_t; + +#elif defined(__linux__) #include #include -- cgit v0.10.2 From 4c5b7f3ae53b02136d38dee46b412ac8a7f6f4ff Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 18 Mar 2016 19:14:55 -0400 Subject: drm/atomic: export drm_atomic_helper_wait_for_fences() Signed-off-by: Rob Clark Reviewed-by: Gustavo Padovan Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1458342904-23326-3-git-send-email-robdclark@gmail.com diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 9135111..00afa9f 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -984,7 +984,17 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables); -static void wait_for_fences(struct drm_device *dev, +/** + * drm_atomic_helper_wait_for_fences - wait for fences stashed in plane state + * @dev: DRM device + * @state: atomic state object with old state structures + * + * For implicit sync, driver should fish the exclusive fence out from the + * incoming fb's and stash it in the drm_plane_state. This is called after + * drm_atomic_helper_swap_state() so it uses the current plane state (and + * just uses the atomic state to find the changed planes) + */ +void drm_atomic_helper_wait_for_fences(struct drm_device *dev, struct drm_atomic_state *state) { struct drm_plane *plane; @@ -1002,6 +1012,7 @@ static void wait_for_fences(struct drm_device *dev, plane->state->fence = NULL; } } +EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences); /** * drm_atomic_helper_framebuffer_changed - check if framebuffer has changed @@ -1163,7 +1174,7 @@ int drm_atomic_helper_commit(struct drm_device *dev, * current layout. */ - wait_for_fences(dev, state); + drm_atomic_helper_wait_for_fences(dev, state); drm_atomic_helper_commit_modeset_disables(dev, state); diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h index 9054598c..fe9d89c 100644 --- a/include/drm/drm_atomic_helper.h +++ b/include/drm/drm_atomic_helper.h @@ -42,6 +42,8 @@ int drm_atomic_helper_commit(struct drm_device *dev, struct drm_atomic_state *state, bool async); +void drm_atomic_helper_wait_for_fences(struct drm_device *dev, + struct drm_atomic_state *state); bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev, struct drm_atomic_state *old_state, struct drm_crtc *crtc); -- cgit v0.10.2 From 00fdf360d05111d4dfc4cb03727ff26f8ab2fd46 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 16:42:23 +0200 Subject: drm: Make uapi headers C89 pendantic compliant This ports the below libdrm commit to the kernel commit 0f4452bb51306024fbf4cbf77d8baab20cefba67 Author: Daniel Kurtz Date: Mon Aug 26 23:39:16 2013 +0800 libdrm: Make some drm headers compatible with gcc -std=c89 -pedantic The following minor changes were needed to these headers: * Convert // comments to /* */ * No , after final member of enum With these changes, these header files can be included by a program that is built with gcc options: -std=c89 -Werror -pedantic Signed-off-by: Daniel Kurtz Signed-off-by: Eric Anholt Reviewed-by: Eric Anholt Reviewed-by: Emil Velikov Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459348943-12803-2-git-send-email-daniel.vetter@ffwll.ch diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index fbc0818..3683250 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -187,7 +187,7 @@ enum drm_map_type { _DRM_SHM = 2, /**< shared, cached */ _DRM_AGP = 3, /**< AGP/GART */ _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ - _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */ + _DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */ }; /** @@ -441,7 +441,7 @@ struct drm_draw { * DRM_IOCTL_UPDATE_DRAW ioctl argument type. */ typedef enum { - DRM_DRAWABLE_CLIPRECTS, + DRM_DRAWABLE_CLIPRECTS } drm_drawable_info_type_t; struct drm_update_draw { -- cgit v0.10.2 From 249c4f538b1aae55d41699f8bafc6cb762a7f48f Mon Sep 17 00:00:00 2001 From: Deepak M Date: Wed, 30 Mar 2016 17:03:39 +0300 Subject: drm: Add new DCS commands in the enum list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding new DCS commands which are specified in the DCS 1.3 spec related to CABC. v2: Sorted the Macro`s by value (Andrzej) v3 by Jani: sort all of enum, refer to MIPI DCS 1.3 Cc: Andrzej Hajda Cc: Thierry Reding Cc: David Airlie Cc: Ville Syrjälä Cc: Daniel Vetter Cc: Suggested-by: Jani Nikula Signed-off-by: Deepak M Signed-off-by: Jani Nikula Reviewed-by: Andrzej Hajda Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459346623-30752-1-git-send-email-jani.nikula@intel.com diff --git a/include/video/mipi_display.h b/include/video/mipi_display.h index ddcc8ca..19aa65a 100644 --- a/include/video/mipi_display.h +++ b/include/video/mipi_display.h @@ -115,6 +115,14 @@ enum { MIPI_DCS_READ_MEMORY_CONTINUE = 0x3E, MIPI_DCS_SET_TEAR_SCANLINE = 0x44, MIPI_DCS_GET_SCANLINE = 0x45, + MIPI_DCS_SET_DISPLAY_BRIGHTNESS = 0x51, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_DISPLAY_BRIGHTNESS = 0x52, /* MIPI DCS 1.3 */ + MIPI_DCS_WRITE_CONTROL_DISPLAY = 0x53, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_CONTROL_DISPLAY = 0x54, /* MIPI DCS 1.3 */ + MIPI_DCS_WRITE_POWER_SAVE = 0x55, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_POWER_SAVE = 0x56, /* MIPI DCS 1.3 */ + MIPI_DCS_SET_CABC_MIN_BRIGHTNESS = 0x5E, /* MIPI DCS 1.3 */ + MIPI_DCS_GET_CABC_MIN_BRIGHTNESS = 0x5F, /* MIPI DCS 1.3 */ MIPI_DCS_READ_DDB_START = 0xA1, MIPI_DCS_READ_DDB_CONTINUE = 0xA8, }; -- cgit v0.10.2 From fbf6d8798fceb1f64eb0e5fd7cd541becfc376cd Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 23 Mar 2016 14:51:12 +0100 Subject: drm/i915: Add locking to pll updates, v3. With async modesets this is no longer protected with connection_mutex, so ensure that each pll has its own lock. The pll configuration state is still protected; it's only the pll updates that need locking against concurrency. Changes since v1: - Rebased. - Fix locking to protect all accesses. (Durgadoss) Changes since v2: - Make the dpll_lock global to protect concurrent updates to the same register, for example DPLL_CTRL1 on skl. (Ander) Signed-off-by: Maarten Lankhorst Link: http://patchwork.freedesktop.org/patch/msgid/56F29F50.1090708@linux.intel.com Reviewed-by: Ander Conselvan de Oliveira diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f6d7159..86fafd8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1837,6 +1837,13 @@ struct drm_i915_private { struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; const struct intel_dpll_mgr *dpll_mgr; + /* + * dpll_lock serializes intel_{prepare,enable,disable}_shared_dpll. + * Must be global rather than per dpll, because on some platforms + * plls share registers. + */ + struct mutex dpll_lock; + unsigned int active_crtcs; unsigned int min_pixclk[I915_MAX_PIPES]; diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index 19bfe67..1175eeb 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -89,14 +89,16 @@ void intel_prepare_shared_dpll(struct intel_crtc *crtc) if (WARN_ON(pll == NULL)) return; + mutex_lock(&dev_priv->dpll_lock); WARN_ON(!pll->config.crtc_mask); - if (pll->active_mask == 0) { + if (!pll->active_mask) { DRM_DEBUG_DRIVER("setting up %s\n", pll->name); WARN_ON(pll->on); assert_shared_dpll_disabled(dev_priv, pll); pll->funcs.mode_set(dev_priv, pll); } + mutex_unlock(&dev_priv->dpll_lock); } /** @@ -113,14 +115,17 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_shared_dpll *pll = crtc->config->shared_dpll; unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base); - unsigned old_mask = pll->active_mask; + unsigned old_mask; if (WARN_ON(pll == NULL)) return; + mutex_lock(&dev_priv->dpll_lock); + old_mask = pll->active_mask; + if (WARN_ON(!(pll->config.crtc_mask & crtc_mask)) || WARN_ON(pll->active_mask & crtc_mask)) - return; + goto out; pll->active_mask |= crtc_mask; @@ -131,13 +136,16 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc) if (old_mask) { WARN_ON(!pll->on); assert_shared_dpll_enabled(dev_priv, pll); - return; + goto out; } WARN_ON(pll->on); DRM_DEBUG_KMS("enabling %s\n", pll->name); pll->funcs.enable(dev_priv, pll); pll->on = true; + +out: + mutex_unlock(&dev_priv->dpll_lock); } void intel_disable_shared_dpll(struct intel_crtc *crtc) @@ -154,8 +162,9 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) if (pll == NULL) return; + mutex_lock(&dev_priv->dpll_lock); if (WARN_ON(!(pll->active_mask & crtc_mask))) - return; + goto out; DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n", pll->name, pll->active_mask, pll->on, @@ -166,11 +175,14 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc) pll->active_mask &= ~crtc_mask; if (pll->active_mask) - return; + goto out; DRM_DEBUG_KMS("disabling %s\n", pll->name); pll->funcs.disable(dev_priv, pll); pll->on = false; + +out: + mutex_unlock(&dev_priv->dpll_lock); } static struct intel_shared_dpll * @@ -1750,6 +1762,7 @@ void intel_shared_dpll_init(struct drm_device *dev) dev_priv->dpll_mgr = dpll_mgr; dev_priv->num_shared_dpll = i; + mutex_init(&dev_priv->dpll_lock); BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); -- cgit v0.10.2 From 3a9b33c6048a9f41c596954e9c3de7c3ab3c4717 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 30 Mar 2016 11:51:25 +0200 Subject: drm/tegra: Don't set a gamma table size Tegra doesn't have any functions to set gamma tables, so this is completely defunct. Not nice to lie to userspace, so let's stop! Cc: Thierry Reding Signed-off-by: Daniel Vetter Signed-off-by: Thierry Reding diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index fb2b4b0..3b85a31 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1722,7 +1722,6 @@ static int tegra_dc_init(struct host1x_client *client) if (err < 0) goto cleanup; - drm_mode_crtc_set_gamma_size(&dc->base, 256); drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); /* -- cgit v0.10.2 From b95c532148dd839d0cd362e469c9a37172427480 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 30 Mar 2016 17:16:34 +0200 Subject: drm/i915: Pass crtc_state to color management functions. Signed-off-by: Maarten Lankhorst Reviewed-by: Lionel Landwerlin Link: http://patchwork.freedesktop.org/patch/msgid/1459350996-4957-2-git-send-email-maarten.lankhorst@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 86fafd8..820c91f5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -612,8 +612,8 @@ struct drm_i915_display_funcs { /* display clock increase/decrease */ /* pll clock increase/decrease */ - void (*load_csc_matrix)(struct drm_crtc *crtc); - void (*load_luts)(struct drm_crtc *crtc); + void (*load_csc_matrix)(struct drm_crtc_state *crtc_state); + void (*load_luts)(struct drm_crtc_state *crtc_state); }; enum forcewake_domain_id { diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index aa0b20d..9cffa63 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -92,10 +92,10 @@ static void ctm_mult_by_limited(uint64_t *result, int64_t *input) } /* Set up the pipe CSC unit. */ -static void i9xx_load_csc_matrix(struct drm_crtc *crtc) +static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state) { + struct drm_crtc *crtc = crtc_state->crtc; struct drm_device *dev = crtc->dev; - struct drm_crtc_state *crtc_state = crtc->state; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int i, pipe = intel_crtc->pipe; @@ -203,10 +203,10 @@ static void i9xx_load_csc_matrix(struct drm_crtc *crtc) /* * Set up the pipe CSC unit on CherryView. */ -static void cherryview_load_csc_matrix(struct drm_crtc *crtc) +static void cherryview_load_csc_matrix(struct drm_crtc_state *state) { + struct drm_crtc *crtc = state->crtc; struct drm_device *dev = crtc->dev; - struct drm_crtc_state *state = crtc->state; struct drm_i915_private *dev_priv = dev->dev_private; int pipe = to_intel_crtc(crtc)->pipe; uint32_t mode; @@ -252,13 +252,13 @@ static void cherryview_load_csc_matrix(struct drm_crtc *crtc) I915_WRITE(CGM_PIPE_MODE(pipe), mode); } -void intel_color_set_csc(struct drm_crtc *crtc) +void intel_color_set_csc(struct drm_crtc_state *crtc_state) { - struct drm_device *dev = crtc->dev; + struct drm_device *dev = crtc_state->crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; if (dev_priv->display.load_csc_matrix) - dev_priv->display.load_csc_matrix(crtc); + dev_priv->display.load_csc_matrix(crtc_state); } /* Loads the legacy palette/gamma unit for the CRTC. */ @@ -303,19 +303,20 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc, } } -static void i9xx_load_luts(struct drm_crtc *crtc) +static void i9xx_load_luts(struct drm_crtc_state *crtc_state) { - i9xx_load_luts_internal(crtc, crtc->state->gamma_lut); + i9xx_load_luts_internal(crtc_state->crtc, crtc_state->gamma_lut); } /* Loads the legacy palette/gamma unit for the CRTC on Haswell. */ -static void haswell_load_luts(struct drm_crtc *crtc) +static void haswell_load_luts(struct drm_crtc_state *crtc_state) { + struct drm_crtc *crtc = crtc_state->crtc; struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc_state *intel_crtc_state = - to_intel_crtc_state(crtc->state); + to_intel_crtc_state(crtc_state); bool reenable_ips = false; /* @@ -331,24 +332,24 @@ static void haswell_load_luts(struct drm_crtc *crtc) intel_crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT; I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT); - i9xx_load_luts(crtc); + i9xx_load_luts(crtc_state); if (reenable_ips) hsw_enable_ips(intel_crtc); } /* Loads the palette/gamma unit for the CRTC on Broadwell+. */ -static void broadwell_load_luts(struct drm_crtc *crtc) +static void broadwell_load_luts(struct drm_crtc_state *state) { + struct drm_crtc *crtc = state->crtc; struct drm_device *dev = crtc->dev; - struct drm_crtc_state *state = crtc->state; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc_state *intel_state = to_intel_crtc_state(state); enum pipe pipe = to_intel_crtc(crtc)->pipe; uint32_t i, lut_size = INTEL_INFO(dev)->color.degamma_lut_size; if (crtc_state_is_legacy(state)) { - haswell_load_luts(crtc); + haswell_load_luts(state); return; } @@ -421,11 +422,11 @@ static void broadwell_load_luts(struct drm_crtc *crtc) } /* Loads the palette/gamma unit for the CRTC on CherryView. */ -static void cherryview_load_luts(struct drm_crtc *crtc) +static void cherryview_load_luts(struct drm_crtc_state *state) { + struct drm_crtc *crtc = state->crtc; struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc_state *state = crtc->state; enum pipe pipe = to_intel_crtc(crtc)->pipe; struct drm_color_lut *lut; uint32_t i, lut_size; @@ -481,16 +482,16 @@ static void cherryview_load_luts(struct drm_crtc *crtc) i9xx_load_luts_internal(crtc, NULL); } -void intel_color_load_luts(struct drm_crtc *crtc) +void intel_color_load_luts(struct drm_crtc_state *crtc_state) { - struct drm_device *dev = crtc->dev; + struct drm_device *dev = crtc_state->crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; /* The clocks have to be on to load the palette. */ - if (!crtc->state->active) + if (!crtc_state->active) return; - dev_priv->display.load_luts(crtc); + dev_priv->display.load_luts(crtc_state); } int intel_color_check(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fec6392..c33f2ac 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3223,7 +3223,7 @@ static void intel_update_pipe_config(struct intel_crtc *crtc, pipe_config->pipe_src_w, pipe_config->pipe_src_h); if (HAS_DDI(dev)) - intel_color_set_csc(&crtc->base); + intel_color_set_csc(&pipe_config->base); /* * Update pipe size and adjust fitter if needed: the reason for this is @@ -4723,6 +4723,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; int pipe = intel_crtc->pipe; + struct intel_crtc_state *pipe_config = + to_intel_crtc_state(crtc->state); if (WARN_ON(intel_crtc->active)) return; @@ -4770,7 +4772,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) * On ILK+ LUT must be loaded before the pipe is running but with * clocks enabled */ - intel_color_load_luts(crtc); + intel_color_load_luts(&pipe_config->base); if (dev_priv->display.initial_watermarks != NULL) dev_priv->display.initial_watermarks(intel_crtc->config); @@ -4845,7 +4847,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) haswell_set_pipemisc(crtc); - intel_color_set_csc(crtc); + intel_color_set_csc(&pipe_config->base); intel_crtc->active = true; @@ -4874,7 +4876,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc) * On ILK+ LUT must be loaded before the pipe is running but with * clocks enabled */ - intel_color_load_luts(crtc); + intel_color_load_luts(&pipe_config->base); intel_ddi_set_pipe_settings(crtc); if (!intel_crtc->config->has_dsi_encoder) @@ -6035,6 +6037,8 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; + struct intel_crtc_state *pipe_config = + to_intel_crtc_state(crtc->state); int pipe = intel_crtc->pipe; if (WARN_ON(intel_crtc->active)) @@ -6079,7 +6083,7 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc) i9xx_pfit_enable(intel_crtc); - intel_color_load_luts(crtc); + intel_color_load_luts(&pipe_config->base); intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); @@ -6106,6 +6110,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_encoder *encoder; + struct intel_crtc_state *pipe_config = + to_intel_crtc_state(crtc->state); int pipe = intel_crtc->pipe; if (WARN_ON(intel_crtc->active)) @@ -6134,7 +6140,7 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) i9xx_pfit_enable(intel_crtc); - intel_color_load_luts(crtc); + intel_color_load_luts(&pipe_config->base); intel_update_watermarks(crtc); intel_enable_pipe(intel_crtc); @@ -13593,8 +13599,8 @@ static int intel_atomic_commit(struct drm_device *dev, * a modeset as this will be done by * crtc_enable already. */ - intel_color_set_csc(crtc); - intel_color_load_luts(crtc); + intel_color_set_csc(crtc->state); + intel_color_load_luts(crtc->state); } if (!modeset) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c87b450..6ac46d9 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1669,7 +1669,7 @@ extern const struct drm_plane_helper_funcs intel_plane_helper_funcs; /* intel_color.c */ void intel_color_init(struct drm_crtc *crtc); int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state); -void intel_color_set_csc(struct drm_crtc *crtc); -void intel_color_load_luts(struct drm_crtc *crtc); +void intel_color_set_csc(struct drm_crtc_state *crtc_state); +void intel_color_load_luts(struct drm_crtc_state *crtc_state); #endif /* __INTEL_DRV_H__ */ -- cgit v0.10.2 From e872ef6941ac302ec3e30974e84c9070eeec99ef Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 30 Mar 2016 17:16:35 +0200 Subject: drm/i915: Do not check crtc_state->active in intel_color_load_luts. This is already tested by its callers. Signed-off-by: Maarten Lankhorst Reviewed-by: Lionel Landwerlin Link: http://patchwork.freedesktop.org/patch/msgid/1459350996-4957-3-git-send-email-maarten.lankhorst@linux.intel.com diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index 9cffa63..1b3f974 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -487,10 +487,6 @@ void intel_color_load_luts(struct drm_crtc_state *crtc_state) struct drm_device *dev = crtc_state->crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - /* The clocks have to be on to load the palette. */ - if (!crtc_state->active) - return; - dev_priv->display.load_luts(crtc_state); } -- cgit v0.10.2 From 20a34e78f0d71cab058a943b2e9601b97b761227 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 30 Mar 2016 17:16:36 +0200 Subject: drm/i915: Update color management during vblank evasion. Without this a vblank may occur between updating color management and planes, which should be prevented. intel_color_set_csc was called in update pipe config because the handover from hardware may not have any csc set, which resulted in a black screen. Because of this also update color management during fastset. Signed-off-by: Maarten Lankhorst Tested-by: Lionel Landwerlin Reviewed-by: Lionel Landwerlin Link: http://patchwork.freedesktop.org/patch/msgid/1459350996-4957-4-git-send-email-maarten.lankhorst@linux.intel.com [mlankhorst: Remove comment in response to review feedback.] diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c33f2ac..60bb486 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3222,9 +3222,6 @@ static void intel_update_pipe_config(struct intel_crtc *crtc, 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_color_set_csc(&pipe_config->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 @@ -13591,18 +13588,6 @@ static int intel_atomic_commit(struct drm_device *dev, dev_priv->display.crtc_enable(crtc); } - if (!modeset && - crtc->state->active && - crtc->state->color_mgmt_changed) { - /* - * Only update color management when not doing - * a modeset as this will be done by - * crtc_enable already. - */ - intel_color_set_csc(crtc->state); - intel_color_load_luts(crtc->state); - } - if (!modeset) intel_pre_plane_update(to_intel_crtc_state(old_crtc_state)); @@ -13921,6 +13906,11 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, if (modeset) return; + if (crtc->state->color_mgmt_changed || to_intel_crtc_state(crtc->state)->update_pipe) { + intel_color_set_csc(crtc->state); + intel_color_load_luts(crtc->state); + } + 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) -- cgit v0.10.2 From 72e96d6450c067f58b65224bb5e73914e2cc43ab Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Wed, 30 Mar 2016 16:57:10 +0300 Subject: drm/i915: Refer to GGTT {,VM} consistently Refer to the GGTT VM consistently as "ggtt->base" instead of just "ggtt", "vm" or indirectly through other variables like "dev_priv->ggtt.base" to avoid confusion with the i915_ggtt object itself and PPGTT VMs. Refer to the GGTT as "ggtt" instead of indirectly through chaining. As a bonus gets rid of the long-standing i915_obj_to_ggtt vs. i915_gem_obj_to_ggtt conflict, due to removal of i915_obj_to_ggtt! v2: - Added some more after grepping sources with Chris v3: - Refer to GGTT VM through ggtt->base consistently instead of ggtt_vm (Chris) v4: - Convert all dev_priv->ggtt->foo accesses to ggtt->foo. v5: - Make patch checker happy Cc: Tvrtko Ursulin Cc: Mika Kuoppala Cc: Chris Wilson Signed-off-by: Joonas Lahtinen Reviewed-by: Chris Wilson diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d02f8ce..74f2274 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -202,8 +202,8 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) uintptr_t list = (uintptr_t) node->info_ent->data; struct list_head *head; struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_address_space *vm = &dev_priv->ggtt.base; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_vma *vma; u64 total_obj_size, total_gtt_size; int count, ret; @@ -216,11 +216,11 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) switch (list) { case ACTIVE_LIST: seq_puts(m, "Active:\n"); - head = &vm->active_list; + head = &ggtt->base.active_list; break; case INACTIVE_LIST: seq_puts(m, "Inactive:\n"); - head = &vm->inactive_list; + head = &ggtt->base.inactive_list; break; default: mutex_unlock(&dev->struct_mutex); @@ -429,11 +429,11 @@ static int i915_gem_object_info(struct seq_file *m, void* data) { struct drm_info_node *node = m->private; struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; u32 count, mappable_count, purgeable_count; u64 size, mappable_size, purgeable_size; struct drm_i915_gem_object *obj; - struct i915_address_space *vm = &dev_priv->ggtt.base; struct drm_file *file; struct i915_vma *vma; int ret; @@ -452,12 +452,12 @@ static int i915_gem_object_info(struct seq_file *m, void* data) count, mappable_count, size, mappable_size); size = count = mappable_size = mappable_count = 0; - count_vmas(&vm->active_list, vm_link); + count_vmas(&ggtt->base.active_list, vm_link); seq_printf(m, " %u [%u] active objects, %llu [%llu] bytes\n", count, mappable_count, size, mappable_size); size = count = mappable_size = mappable_count = 0; - count_vmas(&vm->inactive_list, vm_link); + count_vmas(&ggtt->base.inactive_list, vm_link); seq_printf(m, " %u [%u] inactive objects, %llu [%llu] bytes\n", count, mappable_count, size, mappable_size); @@ -492,8 +492,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) count, size); seq_printf(m, "%llu [%llu] gtt total\n", - dev_priv->ggtt.base.total, - (u64)dev_priv->ggtt.mappable_end - dev_priv->ggtt.base.start); + ggtt->base.total, ggtt->mappable_end - ggtt->base.start); seq_putc(m, '\n'); print_batch_pool_stats(m, dev_priv); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d301173..a66ce49 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -527,6 +527,7 @@ static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) { struct apertures_struct *ap; struct pci_dev *pdev = dev_priv->dev->pdev; + struct i915_ggtt *ggtt = &dev_priv->ggtt; bool primary; int ret; @@ -534,8 +535,8 @@ static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv) if (!ap) return -ENOMEM; - ap->ranges[0].base = dev_priv->ggtt.mappable_base; - ap->ranges[0].size = dev_priv->ggtt.mappable_end; + ap->ranges[0].base = ggtt->mappable_base; + ap->ranges[0].size = ggtt->mappable_end; primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; @@ -1170,6 +1171,7 @@ static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv) static int i915_driver_init_hw(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; + struct i915_ggtt *ggtt = &dev_priv->ggtt; uint32_t aperture_size; int ret; @@ -1213,17 +1215,17 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32)); - aperture_size = dev_priv->ggtt.mappable_end; + aperture_size = ggtt->mappable_end; - dev_priv->ggtt.mappable = - io_mapping_create_wc(dev_priv->ggtt.mappable_base, + ggtt->mappable = + io_mapping_create_wc(ggtt->mappable_base, aperture_size); - if (dev_priv->ggtt.mappable == NULL) { + if (!ggtt->mappable) { ret = -EIO; goto out_ggtt; } - dev_priv->ggtt.mtrr = arch_phys_wc_add(dev_priv->ggtt.mappable_base, + ggtt->mtrr = arch_phys_wc_add(ggtt->mappable_base, aperture_size); pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, @@ -1266,13 +1268,14 @@ out_ggtt: static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv) { struct drm_device *dev = dev_priv->dev; + struct i915_ggtt *ggtt = &dev_priv->ggtt; if (dev->pdev->msi_enabled) pci_disable_msi(dev->pdev); pm_qos_remove_request(&dev_priv->pm_qos); - arch_phys_wc_del(dev_priv->ggtt.mtrr); - io_mapping_free(dev_priv->ggtt.mappable); + arch_phys_wc_del(ggtt->mtrr); + io_mapping_free(ggtt->mappable); i915_ggtt_cleanup_hw(dev); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 820c91f5..d3ebb2f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3154,9 +3154,6 @@ i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj) bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj); /* Some GGTT VM helpers */ -#define i915_obj_to_ggtt(obj) \ - (&((struct drm_i915_private *)(obj)->base.dev->dev_private)->ggtt.base) - static inline struct i915_hw_ppgtt * i915_vm_to_ppgtt(struct i915_address_space *vm) { @@ -3173,7 +3170,10 @@ static inline bool i915_gem_obj_ggtt_bound(struct drm_i915_gem_object *obj) static inline unsigned long i915_gem_obj_ggtt_size(struct drm_i915_gem_object *obj) { - return i915_gem_obj_size(obj, i915_obj_to_ggtt(obj)); + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; + + return i915_gem_obj_size(obj, &ggtt->base); } static inline int __must_check @@ -3181,7 +3181,10 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj, uint32_t alignment, unsigned flags) { - return i915_gem_object_pin(obj, i915_obj_to_ggtt(obj), + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; + + return i915_gem_object_pin(obj, &ggtt->base, alignment, flags | PIN_GLOBAL); } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 11a6ccd..ca96fc1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -130,9 +130,9 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_get_aperture *args = data; + struct drm_i915_private *dev_priv = to_i915(dev); struct i915_ggtt *ggtt = &dev_priv->ggtt; + struct drm_i915_gem_get_aperture *args = data; struct i915_vma *vma; size_t pinned; @@ -146,7 +146,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, pinned += vma->node.size; mutex_unlock(&dev->struct_mutex); - args->aper_size = dev_priv->ggtt.base.total; + args->aper_size = ggtt->base.total; args->aper_available_size = args->aper_size - pinned; return 0; @@ -765,7 +765,8 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_i915_gem_pwrite *args, struct drm_file *file) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; ssize_t remain; loff_t offset, page_base; char __user *user_data; @@ -807,7 +808,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, * source page isn't available. Return the error and we'll * retry in the slow path. */ - if (fast_user_write(dev_priv->ggtt.mappable, page_base, + if (fast_user_write(ggtt->mappable, page_base, page_offset, user_data, page_length)) { ret = -EFAULT; goto out_flush; @@ -1790,7 +1791,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct drm_i915_gem_object *obj = to_intel_bo(vma->vm_private_data); struct drm_device *dev = obj->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_ggtt_view view = i915_ggtt_view_normal; pgoff_t page_offset; unsigned long pfn; @@ -1825,7 +1827,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } /* Use a partial view if the object is bigger than the aperture. */ - if (obj->base.size >= dev_priv->ggtt.mappable_end && + if (obj->base.size >= ggtt->mappable_end && obj->tiling_mode == I915_TILING_NONE) { static const unsigned int chunk_size = 256; // 1 MiB @@ -1853,7 +1855,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) goto unpin; /* Finally, remap it using the new GTT offset */ - pfn = dev_priv->ggtt.mappable_base + + pfn = ggtt->mappable_base + i915_gem_obj_ggtt_offset_view(obj, &view); pfn >>= PAGE_SHIFT; @@ -3458,7 +3460,8 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, uint64_t flags) { struct drm_device *dev = obj->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; u32 fence_alignment, unfenced_alignment; u32 search_flag, alloc_flag; u64 start, end; @@ -3505,7 +3508,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0; end = vm->total; if (flags & PIN_MAPPABLE) - end = min_t(u64, end, dev_priv->ggtt.mappable_end); + end = min_t(u64, end, ggtt->mappable_end); if (flags & PIN_ZONE_4G) end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE); @@ -3712,6 +3715,9 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj) int i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) { + struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; uint32_t old_write_domain, old_read_domains; struct i915_vma *vma; int ret; @@ -3766,7 +3772,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) vma = i915_gem_obj_to_ggtt(obj); if (vma && drm_mm_node_allocated(&vma->node) && !obj->active) list_move_tail(&vma->vm_link, - &to_i915(obj->base.dev)->ggtt.base.inactive_list); + &ggtt->base.inactive_list); return 0; } @@ -4297,9 +4303,13 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, uint32_t alignment, uint64_t flags) { + struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; + BUG_ON(!view); - return i915_gem_object_do_pin(obj, i915_obj_to_ggtt(obj), view, + return i915_gem_object_do_pin(obj, &ggtt->base, view, alignment, flags | PIN_GLOBAL); } @@ -4611,13 +4621,15 @@ struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj, struct i915_vma *i915_gem_obj_to_ggtt_view(struct drm_i915_gem_object *obj, const struct i915_ggtt_view *view) { - struct i915_address_space *ggtt = i915_obj_to_ggtt(obj); + struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_vma *vma; BUG_ON(!view); list_for_each_entry(vma, &obj->vma_list, obj_link) - if (vma->vm == ggtt && + if (vma->vm == &ggtt->base && i915_ggtt_view_equal(&vma->ggtt_view, view)) return vma; return NULL; @@ -5210,11 +5222,12 @@ u64 i915_gem_obj_offset(struct drm_i915_gem_object *o, u64 i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o, const struct i915_ggtt_view *view) { - struct i915_address_space *ggtt = i915_obj_to_ggtt(o); + struct drm_i915_private *dev_priv = to_i915(o->base.dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_vma *vma; list_for_each_entry(vma, &o->vma_list, obj_link) - if (vma->vm == ggtt && + if (vma->vm == &ggtt->base && i915_ggtt_view_equal(&vma->ggtt_view, view)) return vma->node.start; @@ -5241,11 +5254,12 @@ bool i915_gem_obj_bound(struct drm_i915_gem_object *o, bool i915_gem_obj_ggtt_bound_view(struct drm_i915_gem_object *o, const struct i915_ggtt_view *view) { - struct i915_address_space *ggtt = i915_obj_to_ggtt(o); + struct drm_i915_private *dev_priv = to_i915(o->base.dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_vma *vma; list_for_each_entry(vma, &o->vma_list, obj_link) - if (vma->vm == ggtt && + if (vma->vm == &ggtt->base && i915_ggtt_view_equal(&vma->ggtt_view, view) && drm_mm_node_allocated(&vma->node)) return true; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 374a0cb..0ee61fd 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -313,7 +313,8 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, uint64_t target_offset) { struct drm_device *dev = obj->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; uint64_t delta = relocation_target(reloc, target_offset); uint64_t offset; void __iomem *reloc_page; @@ -330,7 +331,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, /* Map the page containing the relocation we're going to perform. */ offset = i915_gem_obj_ggtt_offset(obj); offset += reloc->offset; - reloc_page = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable, + reloc_page = io_mapping_map_atomic_wc(ggtt->mappable, offset & PAGE_MASK); iowrite32(lower_32_bits(delta), reloc_page + offset_in_page(offset)); @@ -340,7 +341,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj, if (offset_in_page(offset) == 0) { io_mapping_unmap_atomic(reloc_page); reloc_page = - io_mapping_map_atomic_wc(dev_priv->ggtt.mappable, + io_mapping_map_atomic_wc(ggtt->mappable, offset); } @@ -1431,7 +1432,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, struct drm_i915_gem_execbuffer2 *args, struct drm_i915_gem_exec_object2 *exec) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct drm_i915_gem_request *req = NULL; struct eb_vmas *eb; struct drm_i915_gem_object *batch_obj; @@ -1504,7 +1506,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (ctx->ppgtt) vm = &ctx->ppgtt->base; else - vm = &dev_priv->ggtt.base; + vm = &ggtt->base; memset(¶ms_master, 0x00, sizeof(params_master)); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index f8f09d1..ae9cb27 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1629,6 +1629,7 @@ static void gen6_write_page_range(struct drm_i915_private *dev_priv, struct i915_page_directory *pd, uint32_t start, uint32_t length) { + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_page_table *pt; uint32_t pde, temp; @@ -1637,7 +1638,7 @@ static void gen6_write_page_range(struct drm_i915_private *dev_priv, /* Make sure write is complete before other code can use this page * table. Also require for WC mapped PTEs */ - readl(dev_priv->ggtt.gsm); + readl(ggtt->gsm); } static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt) @@ -1862,7 +1863,8 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, { DECLARE_BITMAP(new_page_tables, I915_PDES); struct drm_device *dev = vm->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); struct i915_page_table *pt; @@ -1930,7 +1932,7 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, /* Make sure write is complete before other code can use this page * table. Also require for WC mapped PTEs */ - readl(dev_priv->ggtt.gsm); + readl(ggtt->gsm); mark_tlbs_dirty(ppgtt); return 0; @@ -1995,7 +1997,8 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt) { struct i915_address_space *vm = &ppgtt->base; struct drm_device *dev = ppgtt->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; bool retried = false; int ret; @@ -2003,23 +2006,23 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt) * allocator works in address space sizes, so it's multiplied by page * size. We allocate at the top of the GTT to avoid fragmentation. */ - BUG_ON(!drm_mm_initialized(&dev_priv->ggtt.base.mm)); + BUG_ON(!drm_mm_initialized(&ggtt->base.mm)); ret = gen6_init_scratch(vm); if (ret) return ret; alloc: - ret = drm_mm_insert_node_in_range_generic(&dev_priv->ggtt.base.mm, + ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm, &ppgtt->node, GEN6_PD_SIZE, GEN6_PD_ALIGN, 0, - 0, dev_priv->ggtt.base.total, + 0, ggtt->base.total, DRM_MM_TOPDOWN); if (ret == -ENOSPC && !retried) { - ret = i915_gem_evict_something(dev, &dev_priv->ggtt.base, + ret = i915_gem_evict_something(dev, &ggtt->base, GEN6_PD_SIZE, GEN6_PD_ALIGN, I915_CACHE_NONE, - 0, dev_priv->ggtt.base.total, + 0, ggtt->base.total, 0); if (ret) goto err_out; @@ -2032,7 +2035,7 @@ alloc: goto err_out; - if (ppgtt->node.start < dev_priv->ggtt.mappable_end) + if (ppgtt->node.start < ggtt->mappable_end) DRM_DEBUG("Forced to use aperture for PDEs\n"); return 0; @@ -2060,10 +2063,11 @@ static void gen6_scratch_va_range(struct i915_hw_ppgtt *ppgtt, static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) { struct drm_device *dev = ppgtt->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; int ret; - ppgtt->base.pte_encode = dev_priv->ggtt.base.pte_encode; + ppgtt->base.pte_encode = ggtt->base.pte_encode; if (IS_GEN6(dev)) { ppgtt->switch_mm = gen6_mm_switch; } else if (IS_HASWELL(dev)) { @@ -2093,7 +2097,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->pd.base.ggtt_offset = ppgtt->node.start / PAGE_SIZE * sizeof(gen6_pte_t); - ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->ggtt.gsm + + ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm + ppgtt->pd.base.ggtt_offset / sizeof(gen6_pte_t); gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total); @@ -2261,9 +2265,10 @@ static bool needs_idle_maps(struct drm_device *dev) static bool do_idling(struct drm_i915_private *dev_priv) { + struct i915_ggtt *ggtt = &dev_priv->ggtt; bool ret = dev_priv->mm.interruptible; - if (unlikely(dev_priv->ggtt.do_idle_maps)) { + if (unlikely(ggtt->do_idle_maps)) { dev_priv->mm.interruptible = false; if (i915_gpu_idle(dev_priv->dev)) { DRM_ERROR("Couldn't idle GPU\n"); @@ -2277,7 +2282,9 @@ static bool do_idling(struct drm_i915_private *dev_priv) static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) { - if (unlikely(dev_priv->ggtt.do_idle_maps)) + struct i915_ggtt *ggtt = &dev_priv->ggtt; + + if (unlikely(ggtt->do_idle_maps)) dev_priv->mm.interruptible = interruptible; } @@ -2321,7 +2328,8 @@ static void i915_ggtt_flush(struct drm_i915_private *dev_priv) void i915_gem_suspend_gtt_mappings(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; /* Don't bother messing with faults pre GEN6 as we have little * documentation supporting that it's a good idea. @@ -2331,10 +2339,8 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) i915_check_and_clear_faults(dev); - dev_priv->ggtt.base.clear_range(&dev_priv->ggtt.base, - dev_priv->ggtt.base.start, - dev_priv->ggtt.base.total, - true); + ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total, + true); i915_ggtt_flush(dev_priv); } @@ -2364,10 +2370,11 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, uint64_t start, enum i915_cache_level level, u32 unused) { - struct drm_i915_private *dev_priv = vm->dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(vm->dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; unsigned first_entry = start >> PAGE_SHIFT; gen8_pte_t __iomem *gtt_entries = - (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + first_entry; + (gen8_pte_t __iomem *)ggtt->gsm + first_entry; int i = 0; struct sg_page_iter sg_iter; dma_addr_t addr = 0; /* shut up gcc */ @@ -2441,10 +2448,11 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, uint64_t start, enum i915_cache_level level, u32 flags) { - struct drm_i915_private *dev_priv = vm->dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(vm->dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; unsigned first_entry = start >> PAGE_SHIFT; gen6_pte_t __iomem *gtt_entries = - (gen6_pte_t __iomem *)dev_priv->ggtt.gsm + first_entry; + (gen6_pte_t __iomem *)ggtt->gsm + first_entry; int i = 0; struct sg_page_iter sg_iter; dma_addr_t addr = 0; @@ -2484,12 +2492,13 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, uint64_t length, bool use_scratch) { - struct drm_i915_private *dev_priv = vm->dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(vm->dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; unsigned first_entry = start >> PAGE_SHIFT; unsigned num_entries = length >> PAGE_SHIFT; gen8_pte_t scratch_pte, __iomem *gtt_base = - (gen8_pte_t __iomem *) dev_priv->ggtt.gsm + first_entry; - const int max_entries = gtt_total_entries(dev_priv->ggtt) - first_entry; + (gen8_pte_t __iomem *)ggtt->gsm + first_entry; + const int max_entries = ggtt_total_entries(ggtt) - first_entry; int i; int rpm_atomic_seq; @@ -2515,12 +2524,13 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, uint64_t length, bool use_scratch) { - struct drm_i915_private *dev_priv = vm->dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(vm->dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; unsigned first_entry = start >> PAGE_SHIFT; unsigned num_entries = length >> PAGE_SHIFT; gen6_pte_t scratch_pte, __iomem *gtt_base = - (gen6_pte_t __iomem *) dev_priv->ggtt.gsm + first_entry; - const int max_entries = gtt_total_entries(dev_priv->ggtt) - first_entry; + (gen6_pte_t __iomem *)ggtt->gsm + first_entry; + const int max_entries = ggtt_total_entries(ggtt) - first_entry; int i; int rpm_atomic_seq; @@ -2713,8 +2723,8 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, * aperture. One page should be enough to keep any prefetching inside * of the aperture. */ - struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_address_space *ggtt_vm = &dev_priv->ggtt.base; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct drm_mm_node *entry; struct drm_i915_gem_object *obj; unsigned long hole_start, hole_end; @@ -2722,13 +2732,13 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, BUG_ON(mappable_end > end); - ggtt_vm->start = start; + ggtt->base.start = 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; + ggtt->base.total = end - start - PAGE_SIZE; + i915_address_space_init(&ggtt->base, dev_priv); + ggtt->base.total += PAGE_SIZE; if (intel_vgpu_active(dev)) { ret = intel_vgt_balloon(dev); @@ -2737,36 +2747,36 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, } if (!HAS_LLC(dev)) - ggtt_vm->mm.color_adjust = i915_gtt_color_adjust; + ggtt->base.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) { - struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm); + struct i915_vma *vma = i915_gem_obj_to_vma(obj, &ggtt->base); DRM_DEBUG_KMS("reserving preallocated space: %llx + %zx\n", i915_gem_obj_ggtt_offset(obj), obj->base.size); WARN_ON(i915_gem_obj_ggtt_bound(obj)); - ret = drm_mm_reserve_node(&ggtt_vm->mm, &vma->node); + ret = drm_mm_reserve_node(&ggtt->base.mm, &vma->node); if (ret) { DRM_DEBUG_KMS("Reservation failed: %i\n", ret); return ret; } vma->bound |= GLOBAL_BIND; __i915_vma_set_map_and_fenceable(vma); - list_add_tail(&vma->vm_link, &ggtt_vm->inactive_list); + list_add_tail(&vma->vm_link, &ggtt->base.inactive_list); } /* Clear any non-preallocated blocks */ - drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) { + drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) { DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", hole_start, hole_end); - ggtt_vm->clear_range(ggtt_vm, hole_start, + ggtt->base.clear_range(&ggtt->base, hole_start, hole_end - hole_start, true); } /* And finally clear the reserved guard page */ - ggtt_vm->clear_range(ggtt_vm, end - PAGE_SIZE, PAGE_SIZE, true); + ggtt->base.clear_range(&ggtt->base, end - PAGE_SIZE, PAGE_SIZE, true); if (USES_PPGTT(dev) && !USES_FULL_PPGTT(dev)) { struct i915_hw_ppgtt *ppgtt; @@ -2797,8 +2807,8 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, true); dev_priv->mm.aliasing_ppgtt = ppgtt; - WARN_ON(dev_priv->ggtt.base.bind_vma != ggtt_bind_vma); - dev_priv->ggtt.base.bind_vma = aliasing_gtt_bind_vma; + WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma); + ggtt->base.bind_vma = aliasing_gtt_bind_vma; } return 0; @@ -2810,13 +2820,10 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev, */ void i915_gem_init_ggtt(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; - u64 gtt_size, mappable_size; - - gtt_size = dev_priv->ggtt.base.total; - mappable_size = dev_priv->ggtt.mappable_end; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; - i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size); + i915_gem_setup_global_gtt(dev, 0, ggtt->mappable_end, ggtt->base.total); } /** @@ -2825,8 +2832,8 @@ void i915_gem_init_ggtt(struct drm_device *dev) */ void i915_ggtt_cleanup_hw(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_address_space *vm = &dev_priv->ggtt.base; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; if (dev_priv->mm.aliasing_ppgtt) { struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; @@ -2836,15 +2843,15 @@ void i915_ggtt_cleanup_hw(struct drm_device *dev) i915_gem_cleanup_stolen(dev); - if (drm_mm_initialized(&vm->mm)) { + if (drm_mm_initialized(&ggtt->base.mm)) { if (intel_vgpu_active(dev)) intel_vgt_deballoon(); - drm_mm_takedown(&vm->mm); - list_del(&vm->global_link); + drm_mm_takedown(&ggtt->base.mm); + list_del(&ggtt->base.global_link); } - vm->cleanup(vm); + ggtt->base.cleanup(&ggtt->base); } static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) @@ -2928,13 +2935,14 @@ static size_t gen9_get_stolen_size(u16 gen9_gmch_ctl) static int ggtt_probe_common(struct drm_device *dev, size_t gtt_size) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_page_scratch *scratch_page; - phys_addr_t gtt_phys_addr; + phys_addr_t ggtt_phys_addr; /* For Modern GENs the PTEs and register space are split in the BAR */ - gtt_phys_addr = pci_resource_start(dev->pdev, 0) + - (pci_resource_len(dev->pdev, 0) / 2); + ggtt_phys_addr = pci_resource_start(dev->pdev, 0) + + (pci_resource_len(dev->pdev, 0) / 2); /* * On BXT writes larger than 64 bit to the GTT pagetable range will be @@ -2944,10 +2952,10 @@ static int ggtt_probe_common(struct drm_device *dev, * readback check when writing GTT PTE entries. */ if (IS_BROXTON(dev)) - dev_priv->ggtt.gsm = ioremap_nocache(gtt_phys_addr, gtt_size); + ggtt->gsm = ioremap_nocache(ggtt_phys_addr, gtt_size); else - dev_priv->ggtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size); - if (!dev_priv->ggtt.gsm) { + ggtt->gsm = ioremap_wc(ggtt_phys_addr, gtt_size); + if (!ggtt->gsm) { DRM_ERROR("Failed to map the gtt page table\n"); return -ENOMEM; } @@ -2956,11 +2964,11 @@ static int ggtt_probe_common(struct drm_device *dev, if (IS_ERR(scratch_page)) { DRM_ERROR("Scratch setup failed\n"); /* iounmap will also get called at remove, but meh */ - iounmap(dev_priv->ggtt.gsm); + iounmap(ggtt->gsm); return PTR_ERR(scratch_page); } - dev_priv->ggtt.base.scratch_page = scratch_page; + ggtt->base.scratch_page = scratch_page; return 0; } @@ -3041,7 +3049,7 @@ static void chv_setup_private_ppat(struct drm_i915_private *dev_priv) static int gen8_gmch_probe(struct i915_ggtt *ggtt) { struct drm_device *dev = ggtt->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); u16 snb_gmch_ctl; int ret; @@ -3082,7 +3090,6 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) ggtt->base.bind_vma = ggtt_bind_vma; ggtt->base.unbind_vma = ggtt_unbind_vma; - return ret; } @@ -3132,7 +3139,7 @@ static void gen6_gmch_remove(struct i915_address_space *vm) static int i915_gmch_probe(struct i915_ggtt *ggtt) { struct drm_device *dev = ggtt->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); int ret; ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->dev->pdev, NULL); @@ -3167,7 +3174,7 @@ static void i915_gmch_remove(struct i915_address_space *vm) */ int i915_ggtt_init_hw(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); struct i915_ggtt *ggtt = &dev_priv->ggtt; int ret; @@ -3236,33 +3243,30 @@ int i915_ggtt_init_hw(struct drm_device *dev) return 0; out_gtt_cleanup: - ggtt->base.cleanup(&dev_priv->ggtt.base); + ggtt->base.cleanup(&ggtt->base); return ret; } void i915_gem_restore_gtt_mappings(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct drm_i915_gem_object *obj; - struct i915_address_space *vm; struct i915_vma *vma; bool flush; i915_check_and_clear_faults(dev); /* First fill our portion of the GTT with scratch pages */ - dev_priv->ggtt.base.clear_range(&dev_priv->ggtt.base, - dev_priv->ggtt.base.start, - dev_priv->ggtt.base.total, - true); + ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total, + true); /* Cache flush objects bound into GGTT and rebind them. */ - vm = &dev_priv->ggtt.base; list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { flush = false; list_for_each_entry(vma, &obj->vma_list, obj_link) { - if (vma->vm != vm) + if (vma->vm != &ggtt->base) continue; WARN_ON(i915_vma_bind(vma, obj->cache_level, @@ -3285,6 +3289,8 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) } if (USES_PPGTT(dev)) { + struct i915_address_space *vm; + list_for_each_entry(vm, &dev_priv->vm_list, global_link) { /* TODO: Perhaps it shouldn't be gen6 specific */ @@ -3352,11 +3358,13 @@ struct i915_vma * i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj, const struct i915_ggtt_view *view) { - struct i915_address_space *ggtt = i915_obj_to_ggtt(obj); + struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct i915_vma *vma = i915_gem_obj_to_ggtt_view(obj, view); if (!vma) - vma = __i915_gem_vma_create(obj, ggtt, view); + vma = __i915_gem_vma_create(obj, &ggtt->base, view); return vma; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 242a13b..d7dd3d8 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -42,7 +42,7 @@ typedef uint64_t gen8_pde_t; typedef uint64_t gen8_ppgtt_pdpe_t; typedef uint64_t gen8_ppgtt_pml4e_t; -#define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT) +#define ggtt_total_entries(ggtt) ((ggtt)->base.total >> PAGE_SHIFT) /* gen6-hsw has bit 11-4 for physical addr bit 39-32 */ #define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0)) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index de891c9..ea06da0 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -72,9 +72,11 @@ int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, struct drm_mm_node *node, u64 size, unsigned alignment) { + struct i915_ggtt *ggtt = &dev_priv->ggtt; + return i915_gem_stolen_insert_node_in_range(dev_priv, node, size, - alignment, 0, - dev_priv->ggtt.stolen_usable_size); + alignment, 0, + ggtt->stolen_usable_size); } void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, @@ -87,7 +89,8 @@ void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, static unsigned long i915_stolen_to_physical(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct resource *r; u32 base; @@ -134,7 +137,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) I85X_DRB3, &tmp); tom = tmp * MB(32); - base = tom - tseg_size - dev_priv->ggtt.stolen_size; + base = tom - tseg_size - ggtt->stolen_size; } else if (IS_845G(dev)) { u32 tseg_size = 0; u32 tom; @@ -158,7 +161,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) I830_DRB3, &tmp); tom = tmp * MB(32); - base = tom - tseg_size - dev_priv->ggtt.stolen_size; + base = tom - tseg_size - ggtt->stolen_size; } else if (IS_I830(dev)) { u32 tseg_size = 0; u32 tom; @@ -178,7 +181,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) I830_DRB3, &tmp); tom = tmp * MB(32); - base = tom - tseg_size - dev_priv->ggtt.stolen_size; + base = tom - tseg_size - ggtt->stolen_size; } if (base == 0) @@ -189,41 +192,41 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) struct { u32 start, end; } stolen[2] = { - { .start = base, .end = base + dev_priv->ggtt.stolen_size, }, - { .start = base, .end = base + dev_priv->ggtt.stolen_size, }, + { .start = base, .end = base + ggtt->stolen_size, }, + { .start = base, .end = base + ggtt->stolen_size, }, }; - u64 gtt_start, gtt_end; + u64 ggtt_start, ggtt_end; - gtt_start = I915_READ(PGTBL_CTL); + ggtt_start = I915_READ(PGTBL_CTL); if (IS_GEN4(dev)) - gtt_start = (gtt_start & PGTBL_ADDRESS_LO_MASK) | - (gtt_start & PGTBL_ADDRESS_HI_MASK) << 28; + ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) | + (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28; else - gtt_start &= PGTBL_ADDRESS_LO_MASK; - gtt_end = gtt_start + gtt_total_entries(dev_priv->ggtt) * 4; + ggtt_start &= PGTBL_ADDRESS_LO_MASK; + ggtt_end = ggtt_start + ggtt_total_entries(ggtt) * 4; - if (gtt_start >= stolen[0].start && gtt_start < stolen[0].end) - stolen[0].end = gtt_start; - if (gtt_end > stolen[1].start && gtt_end <= stolen[1].end) - stolen[1].start = gtt_end; + if (ggtt_start >= stolen[0].start && ggtt_start < stolen[0].end) + stolen[0].end = ggtt_start; + if (ggtt_end > stolen[1].start && ggtt_end <= stolen[1].end) + stolen[1].start = ggtt_end; /* pick the larger of the two chunks */ if (stolen[0].end - stolen[0].start > stolen[1].end - stolen[1].start) { base = stolen[0].start; - dev_priv->ggtt.stolen_size = stolen[0].end - stolen[0].start; + ggtt->stolen_size = stolen[0].end - stolen[0].start; } else { base = stolen[1].start; - dev_priv->ggtt.stolen_size = stolen[1].end - stolen[1].start; + ggtt->stolen_size = stolen[1].end - stolen[1].start; } if (stolen[0].start != stolen[1].start || stolen[0].end != stolen[1].end) { DRM_DEBUG_KMS("GTT within stolen memory at 0x%llx-0x%llx\n", - (unsigned long long) gtt_start, - (unsigned long long) gtt_end - 1); + (unsigned long long)ggtt_start, + (unsigned long long)ggtt_end - 1); DRM_DEBUG_KMS("Stolen memory adjusted to 0x%x-0x%x\n", - base, base + (u32) dev_priv->ggtt.stolen_size - 1); + base, base + (u32)ggtt->stolen_size - 1); } } @@ -233,7 +236,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) * kernel. So if the region is already marked as busy, something * is seriously wrong. */ - r = devm_request_mem_region(dev->dev, base, dev_priv->ggtt.stolen_size, + r = devm_request_mem_region(dev->dev, base, ggtt->stolen_size, "Graphics Stolen Memory"); if (r == NULL) { /* @@ -245,7 +248,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) * reservation starting from 1 instead of 0. */ r = devm_request_mem_region(dev->dev, base + 1, - dev_priv->ggtt.stolen_size - 1, + ggtt->stolen_size - 1, "Graphics Stolen Memory"); /* * GEN3 firmware likes to smash pci bridges into the stolen @@ -253,7 +256,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) */ if (r == NULL && !IS_GEN3(dev)) { DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n", - base, base + (uint32_t)dev_priv->ggtt.stolen_size); + base, base + (uint32_t)ggtt->stolen_size); base = 0; } } @@ -274,11 +277,12 @@ void i915_gem_cleanup_stolen(struct drm_device *dev) static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv, unsigned long *base, unsigned long *size) { + struct i915_ggtt *ggtt = &dev_priv->ggtt; 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->ggtt.stolen_size; + ggtt->stolen_size; *base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16; @@ -369,10 +373,11 @@ static void gen8_get_stolen_reserved(struct drm_i915_private *dev_priv, static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv, unsigned long *base, unsigned long *size) { + struct i915_ggtt *ggtt = &dev_priv->ggtt; uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED); unsigned long stolen_top; - stolen_top = dev_priv->mm.stolen_base + dev_priv->ggtt.stolen_size; + stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size; *base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK; @@ -388,7 +393,8 @@ 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; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; unsigned long reserved_total, reserved_base = 0, reserved_size; unsigned long stolen_top; @@ -401,14 +407,14 @@ int i915_gem_init_stolen(struct drm_device *dev) } #endif - if (dev_priv->ggtt.stolen_size == 0) + if (ggtt->stolen_size == 0) return 0; dev_priv->mm.stolen_base = i915_stolen_to_physical(dev); if (dev_priv->mm.stolen_base == 0) return 0; - stolen_top = dev_priv->mm.stolen_base + dev_priv->ggtt.stolen_size; + stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size; switch (INTEL_INFO(dev_priv)->gen) { case 2: @@ -458,19 +464,18 @@ int i915_gem_init_stolen(struct drm_device *dev) return 0; } - dev_priv->ggtt.stolen_reserved_base = reserved_base; - dev_priv->ggtt.stolen_reserved_size = reserved_size; + ggtt->stolen_reserved_base = reserved_base; + ggtt->stolen_reserved_size = reserved_size; /* It is possible for the reserved area to end before the end of stolen * memory, so just consider the start. */ reserved_total = stolen_top - reserved_base; DRM_DEBUG_KMS("Memory reserved for graphics device: %zuK, usable: %luK\n", - dev_priv->ggtt.stolen_size >> 10, - (dev_priv->ggtt.stolen_size - reserved_total) >> 10); + ggtt->stolen_size >> 10, + (ggtt->stolen_size - reserved_total) >> 10); - dev_priv->ggtt.stolen_usable_size = dev_priv->ggtt.stolen_size - - reserved_total; + ggtt->stolen_usable_size = ggtt->stolen_size - reserved_total; /* * Basic memrange allocator for stolen space. @@ -483,7 +488,7 @@ int i915_gem_init_stolen(struct drm_device *dev) * i915_gem_stolen_insert_node_in_range(). We may want to fix the fbcon * problem later. */ - drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->ggtt.stolen_usable_size); + drm_mm_init(&dev_priv->mm.stolen, 0, ggtt->stolen_usable_size); return 0; } @@ -492,12 +497,13 @@ static struct sg_table * i915_pages_create_for_stolen(struct drm_device *dev, u32 offset, u32 size) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct sg_table *st; struct scatterlist *sg; DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size); - BUG_ON(offset > dev_priv->ggtt.stolen_size - size); + BUG_ON(offset > ggtt->stolen_size - size); /* We hide that we have no struct page backing our stolen object * by wrapping the contiguous physical allocation with a fake @@ -628,8 +634,8 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, u32 gtt_offset, u32 size) { - struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_address_space *ggtt = &dev_priv->ggtt.base; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct drm_i915_gem_object *obj; struct drm_mm_node *stolen; struct i915_vma *vma; @@ -675,7 +681,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, if (gtt_offset == I915_GTT_OFFSET_NONE) return obj; - vma = i915_gem_obj_lookup_or_create_vma(obj, ggtt); + vma = i915_gem_obj_lookup_or_create_vma(obj, &ggtt->base); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto err; @@ -688,8 +694,8 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, */ vma->node.start = gtt_offset; vma->node.size = size; - if (drm_mm_initialized(&ggtt->mm)) { - ret = drm_mm_reserve_node(&ggtt->mm, &vma->node); + if (drm_mm_initialized(&ggtt->base.mm)) { + ret = drm_mm_reserve_node(&ggtt->base.mm, &vma->node); if (ret) { DRM_DEBUG_KMS("failed to allocate stolen GTT space\n"); goto err; @@ -697,7 +703,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev, vma->bound |= GLOBAL_BIND; __i915_vma_set_map_and_fenceable(vma); - list_add_tail(&vma->vm_link, &ggtt->inactive_list); + list_add_tail(&vma->vm_link, &ggtt->base.inactive_list); } list_add_tail(&obj->global_list, &dev_priv->mm.bound_list); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 54c2086..9b55409 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -627,6 +627,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv, struct drm_i915_gem_object *src, struct i915_address_space *vm) { + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct drm_i915_error_object *dst; struct i915_vma *vma = NULL; int num_pages; @@ -653,7 +654,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv, vma = i915_gem_obj_to_ggtt(src); use_ggtt = (src->cache_level == I915_CACHE_NONE && vma && (vma->bound & GLOBAL_BIND) && - reloc_offset + num_pages * PAGE_SIZE <= dev_priv->ggtt.mappable_end); + reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end); /* Cannot access stolen address directly, try to use the aperture */ if (src->stolen) { @@ -663,7 +664,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv, goto unwind; reloc_offset = i915_gem_obj_ggtt_offset(src); - if (reloc_offset + num_pages * PAGE_SIZE > dev_priv->ggtt.mappable_end) + if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end) goto unwind; } @@ -689,7 +690,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv, * captures what the GPU read. */ - s = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable, + s = io_mapping_map_atomic_wc(ggtt->mappable, reloc_offset); memcpy_fromio(d, s, PAGE_SIZE); io_mapping_unmap_atomic(s); @@ -1015,7 +1016,8 @@ static void i915_gem_record_active_context(struct intel_engine_cs *engine, static void i915_gem_record_rings(struct drm_device *dev, struct drm_i915_error_state *error) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct drm_i915_gem_request *request; int i, count; @@ -1038,7 +1040,7 @@ static void i915_gem_record_rings(struct drm_device *dev, vm = request->ctx && request->ctx->ppgtt ? &request->ctx->ppgtt->base : - &dev_priv->ggtt.base; + &ggtt->base; /* We need to copy these to an anonymous buffer * as the simplest method to avoid being overwritten diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c index 2891bcf..d02efb8 100644 --- a/drivers/gpu/drm/i915/i915_vgpu.c +++ b/drivers/gpu/drm/i915/i915_vgpu.c @@ -181,8 +181,8 @@ static int vgt_balloon_space(struct drm_mm *mm, int intel_vgt_balloon(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - struct i915_address_space *ggtt_vm = &dev_priv->ggtt.base; - unsigned long ggtt_vm_end = ggtt_vm->start + ggtt_vm->total; + struct i915_ggtt *ggtt = &dev_priv->ggtt; + unsigned long ggtt_end = ggtt->base.start + ggtt->base.total; unsigned long mappable_base, mappable_size, mappable_end; unsigned long unmappable_base, unmappable_size, unmappable_end; @@ -202,19 +202,19 @@ int intel_vgt_balloon(struct drm_device *dev) DRM_INFO("Unmappable graphic memory: base 0x%lx size %ldKiB\n", unmappable_base, unmappable_size / 1024); - if (mappable_base < ggtt_vm->start || - mappable_end > dev_priv->ggtt.mappable_end || - unmappable_base < dev_priv->ggtt.mappable_end || - unmappable_end > ggtt_vm_end) { + if (mappable_base < ggtt->base.start || + mappable_end > ggtt->mappable_end || + unmappable_base < ggtt->mappable_end || + unmappable_end > ggtt_end) { DRM_ERROR("Invalid ballooning configuration!\n"); return -EINVAL; } /* Unmappable graphic memory ballooning */ - if (unmappable_base > dev_priv->ggtt.mappable_end) { - ret = vgt_balloon_space(&ggtt_vm->mm, + if (unmappable_base > ggtt->mappable_end) { + ret = vgt_balloon_space(&ggtt->base.mm, &bl_info.space[2], - dev_priv->ggtt.mappable_end, + ggtt->mappable_end, unmappable_base); if (ret) @@ -225,30 +225,30 @@ int intel_vgt_balloon(struct drm_device *dev) * No need to partition out the last physical page, * because it is reserved to the guard page. */ - if (unmappable_end < ggtt_vm_end - PAGE_SIZE) { - ret = vgt_balloon_space(&ggtt_vm->mm, + if (unmappable_end < ggtt_end - PAGE_SIZE) { + ret = vgt_balloon_space(&ggtt->base.mm, &bl_info.space[3], unmappable_end, - ggtt_vm_end - PAGE_SIZE); + ggtt_end - PAGE_SIZE); if (ret) goto err; } /* Mappable graphic memory ballooning */ - if (mappable_base > ggtt_vm->start) { - ret = vgt_balloon_space(&ggtt_vm->mm, + if (mappable_base > ggtt->base.start) { + ret = vgt_balloon_space(&ggtt->base.mm, &bl_info.space[0], - ggtt_vm->start, mappable_base); + ggtt->base.start, mappable_base); if (ret) goto err; } - if (mappable_end < dev_priv->ggtt.mappable_end) { - ret = vgt_balloon_space(&ggtt_vm->mm, + if (mappable_end < ggtt->mappable_end) { + ret = vgt_balloon_space(&ggtt->base.mm, &bl_info.space[1], mappable_end, - dev_priv->ggtt.mappable_end); + ggtt->mappable_end); if (ret) goto err; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 60bb486..e6b5ee5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2444,6 +2444,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct drm_i915_gem_object *obj = NULL; struct drm_mode_fb_cmd2 mode_cmd = { 0 }; struct drm_framebuffer *fb = &plane_config->fb->base; @@ -2459,7 +2460,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, /* If the FB is too big, just don't use it since fbdev is not very * important and we should probably use that space with FBC or other * features. */ - if (size_aligned * 2 > dev_priv->ggtt.stolen_usable_size) + if (size_aligned * 2 > ggtt->stolen_usable_size) return false; mutex_lock(&dev->struct_mutex); @@ -15282,7 +15283,8 @@ fail: void intel_modeset_init(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; int sprite, ret; enum pipe pipe; struct intel_crtc *crtc; @@ -15346,7 +15348,7 @@ void intel_modeset_init(struct drm_device *dev) dev->mode_config.cursor_height = MAX_CURSOR_HEIGHT; } - dev->mode_config.fb_base = dev_priv->ggtt.mappable_base; + dev->mode_config.fb_base = ggtt->mappable_base; DRM_DEBUG_KMS("%d display pipe%s available.\n", INTEL_INFO(dev)->num_pipes, diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 2e571f5..d5a7cfe 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -506,6 +506,7 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, int size, int fb_cpp) { + struct i915_ggtt *ggtt = &dev_priv->ggtt; int compression_threshold = 1; int ret; u64 end; @@ -516,9 +517,9 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, * underruns, even if that range is not reserved by the BIOS. */ if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) - end = dev_priv->ggtt.stolen_size - 8 * 1024 * 1024; + end = ggtt->stolen_size - 8 * 1024 * 1024; else - end = dev_priv->ggtt.stolen_usable_size; + end = ggtt->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. diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 153ea7a3..4cf04ce 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -122,6 +122,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper, struct drm_framebuffer *fb; struct drm_device *dev = helper->dev; struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct drm_mode_fb_cmd2 mode_cmd = {}; struct drm_i915_gem_object *obj = NULL; int size, ret; @@ -146,7 +147,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper, /* If the FB is too big, just don't use it since fbdev is not very * important and we should probably use that space with FBC or other * features. */ - if (size * 2 < dev_priv->ggtt.stolen_usable_size) + if (size * 2 < ggtt->stolen_usable_size) obj = i915_gem_object_create_stolen(dev, size); if (obj == NULL) obj = i915_gem_alloc_object(dev, size); @@ -181,7 +182,8 @@ static int intelfb_create(struct drm_fb_helper *helper, container_of(helper, struct intel_fbdev, helper); struct intel_framebuffer *intel_fb = ifbdev->fb; struct drm_device *dev = helper->dev; - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct fb_info *info; struct drm_framebuffer *fb; struct drm_i915_gem_object *obj; @@ -244,13 +246,13 @@ static int intelfb_create(struct drm_fb_helper *helper, /* setup aperture base/size for vesafb takeover */ info->apertures->ranges[0].base = dev->mode_config.fb_base; - info->apertures->ranges[0].size = dev_priv->ggtt.mappable_end; + info->apertures->ranges[0].size = ggtt->mappable_end; info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj); info->fix.smem_len = size; info->screen_base = - ioremap_wc(dev_priv->ggtt.mappable_base + i915_gem_obj_ggtt_offset(obj), + ioremap_wc(ggtt->mappable_base + i915_gem_obj_ggtt_offset(obj), size); if (!info->screen_base) { DRM_ERROR("Failed to remap framebuffer into virtual memory\n"); diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index e1acb41..6694e92 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -190,13 +190,14 @@ struct intel_overlay { static struct overlay_registers __iomem * intel_overlay_map_regs(struct intel_overlay *overlay) { - struct drm_i915_private *dev_priv = overlay->dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(overlay->dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct overlay_registers __iomem *regs; if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr; else - regs = io_mapping_map_wc(dev_priv->ggtt.mappable, + regs = io_mapping_map_wc(ggtt->mappable, i915_gem_obj_ggtt_offset(overlay->reg_bo)); return regs; @@ -1481,7 +1482,8 @@ struct intel_overlay_error_state { static struct overlay_registers __iomem * intel_overlay_map_regs_atomic(struct intel_overlay *overlay) { - struct drm_i915_private *dev_priv = overlay->dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(overlay->dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct overlay_registers __iomem *regs; if (OVERLAY_NEEDS_PHYSICAL(overlay->dev)) @@ -1490,7 +1492,7 @@ intel_overlay_map_regs_atomic(struct intel_overlay *overlay) regs = (struct overlay_registers __iomem *) overlay->reg_bo->phys_handle->vaddr; else - regs = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable, + regs = io_mapping_map_atomic_wc(ggtt->mappable, i915_gem_obj_ggtt_offset(overlay->reg_bo)); return regs; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6a04761..9bc9c25 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4630,7 +4630,8 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode) static bool bxt_check_bios_rc6_setup(const struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; bool enable_rc6 = true; unsigned long rc6_ctx_base; @@ -4644,9 +4645,9 @@ static bool bxt_check_bios_rc6_setup(const struct drm_device *dev) * for this check. */ rc6_ctx_base = I915_READ(RC6_CTX_BASE) & RC6_CTX_BASE_MASK; - if (!((rc6_ctx_base >= dev_priv->ggtt.stolen_reserved_base) && - (rc6_ctx_base + PAGE_SIZE <= dev_priv->ggtt.stolen_reserved_base + - dev_priv->ggtt.stolen_reserved_size))) { + if (!((rc6_ctx_base >= ggtt->stolen_reserved_base) && + (rc6_ctx_base + PAGE_SIZE <= ggtt->stolen_reserved_base + + ggtt->stolen_reserved_size))) { DRM_DEBUG_KMS("RC6 Base address not as expected.\n"); enable_rc6 = false; } @@ -5287,9 +5288,9 @@ static void cherryview_check_pctx(struct drm_i915_private *dev_priv) static void cherryview_setup_pctx(struct drm_device *dev) { - struct drm_i915_private *dev_priv = dev->dev_private; - unsigned long pctx_paddr, paddr; + struct drm_i915_private *dev_priv = to_i915(dev); struct i915_ggtt *ggtt = &dev_priv->ggtt; + unsigned long pctx_paddr, paddr; u32 pcbr; int pctx_size = 32*1024; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index a492bca..2e864b7 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -2111,6 +2111,7 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, struct intel_ringbuffer *ringbuf) { struct drm_i915_private *dev_priv = to_i915(dev); + struct i915_ggtt *ggtt = &dev_priv->ggtt; struct drm_i915_gem_object *obj = ringbuf->obj; int ret; @@ -2144,7 +2145,7 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev, /* Access through the GTT requires the device to be awake. */ assert_rpm_wakelock_held(dev_priv); - ringbuf->virtual_start = ioremap_wc(dev_priv->ggtt.mappable_base + + ringbuf->virtual_start = ioremap_wc(ggtt->mappable_base + i915_gem_obj_ggtt_offset(obj), ringbuf->size); if (ringbuf->virtual_start == NULL) { i915_gem_object_ggtt_unpin(obj); -- cgit v0.10.2 From 0b27c02a7f1c697694f2ad6d6517e7dbf9ecfa39 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 18 Mar 2016 12:34:59 -0700 Subject: drm: Add an encoder and connector type enum for DPI. Right now exynos is exposing DPI as a TMDS encoder and VGA connector, which seems rather misleading. This isn't just an internal detail, since xrandr actually exposes "VGA" as the output name. Define some new enums so that vc4's DPI can have a more informative name. I considered other names for the connector as well. For VC4, the Adafruit DPI kippah takes the 28 GPIO pins and routes them to a standard-ish 40-pin FPC connector, but "40-pin FPC" doesn't uniquely identify an ordering of pins (apparently some other orderings exist), doesn't explain things as well for the user (who, if anything, knows their product is a DPI kippah/panel combo), and actually doesn't have to exist (one could connect the 28 GPIOs directly to something else). Simply "DPI" seems like a good compromise name to distinguish from the HDMI, DSI, and TV connectors . Signed-off-by: Eric Anholt Reviewed-by: Daniel Vetter diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e08f962..6bd8133 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -168,6 +168,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { { DRM_MODE_CONNECTOR_eDP, "eDP" }, { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, { DRM_MODE_CONNECTOR_DSI, "DSI" }, + { DRM_MODE_CONNECTOR_DPI, "DPI" }, }; static const struct drm_prop_enum_list drm_encoder_enum_list[] = { @@ -179,6 +180,7 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] = { { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, { DRM_MODE_ENCODER_DSI, "DSI" }, { DRM_MODE_ENCODER_DPMST, "DP MST" }, + { DRM_MODE_ENCODER_DPI, "DPI" }, }; static const struct drm_prop_enum_list drm_subpixel_enum_list[] = { diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index c021743..c10ab61 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -202,6 +202,7 @@ struct drm_mode_get_plane_res { #define DRM_MODE_ENCODER_VIRTUAL 5 #define DRM_MODE_ENCODER_DSI 6 #define DRM_MODE_ENCODER_DPMST 7 +#define DRM_MODE_ENCODER_DPI 8 struct drm_mode_get_encoder { __u32 encoder_id; @@ -241,6 +242,7 @@ struct drm_mode_get_encoder { #define DRM_MODE_CONNECTOR_eDP 14 #define DRM_MODE_CONNECTOR_VIRTUAL 15 #define DRM_MODE_CONNECTOR_DSI 16 +#define DRM_MODE_CONNECTOR_DPI 17 struct drm_mode_get_connector { -- cgit v0.10.2 From f21a21983ef13a031250c4c3f6018e29a549d0f1 Mon Sep 17 00:00:00 2001 From: Shubhangi Shrivastava Date: Wed, 30 Mar 2016 18:05:22 +0530 Subject: drm/i915: Splitting intel_dp_detect intel_dp_detect() is called for not just detection but during modes enumeration as well. Repeating the whole sequence during each of these calls is wasteful and time consuming. This patch moves probing for panel, DPCD read etc done in intel_dp_detect() to a new function intel_dp_long_pulse(). Note that the behavior of intel_dp_detect() is changed to report connected or disconnected depending on whether the EDID is available or not. This change will be required by further patches in the series to avoid performing duplicated DPCD operations on hotplug. v2: Moved a hunk to next patch of the series. Moved intel_dp_unset_edid to out. (Ander) v3: Rephrased commit message and intel_dp_unset_dp() is called within intel_dp_set_dp() to free the previous EDID. (Ander) v4: Added overriding of status to disconnected for MST. (Ander) Tested-by: Nathan D Ciobanu Signed-off-by: Sivakumar Thulasimani Signed-off-by: Shubhangi Shrivastava Reviewed-by: Ander Conselvan de Oliveira [anderco: fix parenthesis alignment] Signed-off-by: Ander Conselvan de Oliveira Link: http://patchwork.freedesktop.org/patch/msgid/1459341326-13142-1-git-send-email-shubhangi.shrivastava@intel.com diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3bdd8ba..81f10ab 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -129,6 +129,7 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync); static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp); static void vlv_steal_power_sequencer(struct drm_device *dev, enum pipe pipe); +static void intel_dp_unset_edid(struct intel_dp *intel_dp); static unsigned int intel_dp_unused_lane_mask(int lane_count) { @@ -4513,6 +4514,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp) struct intel_connector *intel_connector = intel_dp->attached_connector; struct edid *edid; + intel_dp_unset_edid(intel_dp); edid = intel_dp_get_edid(intel_dp); intel_connector->detect_edid = edid; @@ -4533,9 +4535,10 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) intel_dp->has_audio = false; } -static enum drm_connector_status -intel_dp_detect(struct drm_connector *connector, bool force) +static void +intel_dp_long_pulse(struct intel_connector *intel_connector) { + struct drm_connector *connector = &intel_connector->base; struct intel_dp *intel_dp = intel_attached_dp(connector); struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_encoder *intel_encoder = &intel_dig_port->base; @@ -4545,17 +4548,6 @@ intel_dp_detect(struct drm_connector *connector, bool force) bool ret; u8 sink_irq_vector; - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, connector->name); - intel_dp_unset_edid(intel_dp); - - if (intel_dp->is_mst) { - /* MST devices are disconnected from a monitor POV */ - if (intel_encoder->type != INTEL_OUTPUT_EDP) - intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; - return connector_status_disconnected; - } - power_domain = intel_display_port_aux_power_domain(intel_encoder); intel_display_power_get(to_i915(dev), power_domain); @@ -4576,14 +4568,18 @@ intel_dp_detect(struct drm_connector *connector, bool force) goto out; } + if (intel_encoder->type != INTEL_OUTPUT_EDP) + intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; + intel_dp_probe_oui(intel_dp); ret = intel_dp_probe_mst(intel_dp); if (ret) { - /* if we are in MST mode then this connector - won't appear connected or have anything with EDID on it */ - if (intel_encoder->type != INTEL_OUTPUT_EDP) - intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; + /* + * If we are in MST mode then this connector + * won't appear connected or have anything + * with EDID on it + */ status = connector_status_disconnected; goto out; } @@ -4598,8 +4594,6 @@ intel_dp_detect(struct drm_connector *connector, bool force) intel_dp_set_edid(intel_dp); - if (intel_encoder->type != INTEL_OUTPUT_EDP) - intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; status = connector_status_connected; /* Try to read the source of the interrupt */ @@ -4617,8 +4611,37 @@ intel_dp_detect(struct drm_connector *connector, bool force) } out: + if (status != connector_status_connected) + intel_dp_unset_edid(intel_dp); intel_display_power_put(to_i915(dev), power_domain); - return status; + return; +} + +static enum drm_connector_status +intel_dp_detect(struct drm_connector *connector, bool force) +{ + struct intel_dp *intel_dp = intel_attached_dp(connector); + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct intel_encoder *intel_encoder = &intel_dig_port->base; + struct intel_connector *intel_connector = to_intel_connector(connector); + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); + + if (intel_dp->is_mst) { + /* MST devices are disconnected from a monitor POV */ + intel_dp_unset_edid(intel_dp); + if (intel_encoder->type != INTEL_OUTPUT_EDP) + intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; + return connector_status_disconnected; + } + + intel_dp_long_pulse(intel_dp->attached_connector); + + if (intel_connector->detect_edid) + return connector_status_connected; + else + return connector_status_disconnected; } static void -- cgit v0.10.2 From 7d23e3c37bb3fc6952dc84007ee60cb533fd2d5c Mon Sep 17 00:00:00 2001 From: Shubhangi Shrivastava Date: Wed, 30 Mar 2016 18:05:23 +0530 Subject: drm/i915: Cleaning up intel_dp_hpd_pulse Current DP detection has DPCD operations split across intel_dp_hpd_pulse and intel_dp_detect which contains duplicates as well. Also intel_dp_detect is called during modes enumeration as well which will result in multiple dpcd operations. So this patch tries to solve both these by bringing all DPCD operations in one single function and make intel_dp_detect use existing values instead of repeating same steps. v2: Pulled in a hunk from last patch of the series to this patch. (Ander) v3: Added MST hotplug handling. (Ander) v4: Added a flag to check if detect is performed to prevent multiple detects on hotplug. (Ander) Tested-by: Nathan D Ciobanu Signed-off-by: Sivakumar Thulasimani Signed-off-by: Shubhangi Shrivastava Reviewed-by: Ander Conselvan de Oliveira [anderco: fix parenthesis aligment] Signed-off-by: Ander Conselvan de Oliveira Link: http://patchwork.freedesktop.org/patch/msgid/1459341326-13142-2-git-send-email-shubhangi.shrivastava@intel.com diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 81f10ab..01b9f18 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4582,6 +4582,16 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) */ status = connector_status_disconnected; goto out; + } else if (connector->status == connector_status_connected) { + /* + * If display was connected already and is still connected + * check links status, there has been known issues of + * link loss triggerring long pulse!!!! + */ + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + intel_dp_check_link_status(intel_dp); + drm_modeset_unlock(&dev->mode_config.connection_mutex); + goto out; } /* @@ -4595,6 +4605,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) intel_dp_set_edid(intel_dp); status = connector_status_connected; + intel_dp->detect_done = true; /* Try to read the source of the interrupt */ if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && @@ -4611,8 +4622,21 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) } out: - if (status != connector_status_connected) + if (status != connector_status_connected) { intel_dp_unset_edid(intel_dp); + /* + * If we were in MST mode, and device is not there, + * get out of MST mode + */ + if (intel_dp->is_mst) { + DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", + intel_dp->is_mst, intel_dp->mst_mgr.mst_state); + intel_dp->is_mst = false; + drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, + intel_dp->is_mst); + } + } + intel_display_power_put(to_i915(dev), power_domain); return; } @@ -4636,7 +4660,11 @@ intel_dp_detect(struct drm_connector *connector, bool force) return connector_status_disconnected; } - intel_dp_long_pulse(intel_dp->attached_connector); + /* If full detect is not performed yet, do a full detect */ + if (!intel_dp->detect_done) + intel_dp_long_pulse(intel_dp->attached_connector); + + intel_dp->detect_done = false; if (intel_connector->detect_edid) return connector_status_connected; @@ -4968,25 +4996,25 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) /* indicate that we need to restart link training */ intel_dp->train_set_valid = false; - if (!intel_digital_port_connected(dev_priv, intel_dig_port)) - goto mst_fail; - - if (!intel_dp_get_dpcd(intel_dp)) { - goto mst_fail; - } - - intel_dp_probe_oui(intel_dp); + intel_dp_long_pulse(intel_dp->attached_connector); + if (intel_dp->is_mst) + ret = IRQ_HANDLED; + goto put_power; - if (!intel_dp_probe_mst(intel_dp)) { - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); - intel_dp_check_link_status(intel_dp); - drm_modeset_unlock(&dev->mode_config.connection_mutex); - goto mst_fail; - } } else { if (intel_dp->is_mst) { - if (intel_dp_check_mst_status(intel_dp) == -EINVAL) - goto mst_fail; + if (intel_dp_check_mst_status(intel_dp) == -EINVAL) { + /* + * If we were in MST mode, and device is not + * there, get out of MST mode + */ + DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", + intel_dp->is_mst, intel_dp->mst_mgr.mst_state); + intel_dp->is_mst = false; + drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, + intel_dp->is_mst); + goto put_power; + } } if (!intel_dp->is_mst) { @@ -4998,14 +5026,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) ret = IRQ_HANDLED; - goto put_power; -mst_fail: - /* if we were in MST mode, and device is not there get out of MST mode */ - if (intel_dp->is_mst) { - DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", intel_dp->is_mst, intel_dp->mst_mgr.mst_state); - intel_dp->is_mst = false; - drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); - } put_power: intel_display_power_put(dev_priv, power_domain); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6ac46d9..ed65a71 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -797,6 +797,7 @@ struct intel_dp { int link_rate; uint8_t lane_count; bool has_audio; + bool detect_done; enum hdmi_force_audio force_audio; bool limited_color_range; bool color_range_auto; -- cgit v0.10.2 From 5c9114d0ced2f16d1bfeda650b4acf95159f4759 Mon Sep 17 00:00:00 2001 From: Shubhangi Shrivastava Date: Wed, 30 Mar 2016 18:05:24 +0530 Subject: drm/i915: Reorganizing intel_dp_check_link_status When created originally intel_dp_check_link_status() was supposed to handle only link training for short pulse but has grown into handler for short pulse itself. This patch cleans up this function by splitting it into two halves. First intel_dp_short_pulse() is called, which will be entry point and handle all logic for short pulse handling while intel_dp_check_link_status() will retain its original purpose of only doing link status related work. intel_dp_short_pulse: All existing code other than link status read and link training upon error status. intel_dp_check_link_status: The link status should be read on short pulse irrespective of panel being enabled or not so intel_dp_get_link_status() performs dpcd read first then based on crtc active / enabled it will perform the link training. This is because short pulse is a generic interrupt which should always be handled, because it may mean: 1. Hotplug/unplug of MST panel 2. Hotplug/unplug of dongle 3. Link status change for other DP panels v2: Added WARN_ON to intel_dp_check_link_status() Removed a call to intel_dp_get_link_status() (Ander) v3: Changed commit message to explain need of link status being read before performing encoder checks (Daniel) v4: Changed commit message to explain need of reading link status on short pulse (Ander) Tested-by: Nathan D Ciobanu Signed-off-by: Sivakumar Thulasimani Signed-off-by: Shubhangi Shrivastava Reviewed-by: Ander Conselvan de Oliveira [anderco: fix parenthesis alignment] Signed-off-by: Ander Conselvan de Oliveira Link: http://patchwork.freedesktop.org/patch/msgid/1459341326-13142-3-git-send-email-shubhangi.shrivastava@intel.com diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 01b9f18..9ee7a73 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4215,6 +4215,36 @@ go_again: return -EINVAL; } +static void +intel_dp_check_link_status(struct intel_dp *intel_dp) +{ + struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; + struct drm_device *dev = intel_dp_to_dev(intel_dp); + u8 link_status[DP_LINK_STATUS_SIZE]; + + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); + + if (!intel_dp_get_link_status(intel_dp, link_status)) { + DRM_ERROR("Failed to get link status\n"); + return; + } + + if (!intel_encoder->base.crtc) + return; + + if (!to_intel_crtc(intel_encoder->base.crtc)->active) + return; + + /* if link training is requested we should perform it always */ + if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) || + (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) { + DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", + intel_encoder->base.name); + intel_dp_start_link_train(intel_dp); + intel_dp_stop_link_train(intel_dp); + } +} + /* * According to DP spec * 5.1.2: @@ -4224,14 +4254,10 @@ go_again: * 4. Check link status on receipt of hot-plug interrupt */ static void -intel_dp_check_link_status(struct intel_dp *intel_dp) +intel_dp_short_pulse(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); - struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; u8 sink_irq_vector; - u8 link_status[DP_LINK_STATUS_SIZE]; - - WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); /* * Clearing compliance test variables to allow capturing @@ -4241,17 +4267,6 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) intel_dp->compliance_test_type = 0; intel_dp->compliance_test_data = 0; - if (!intel_encoder->base.crtc) - return; - - if (!to_intel_crtc(intel_encoder->base.crtc)->active) - return; - - /* Try to read receiver status if the link appears to be up */ - if (!intel_dp_get_link_status(intel_dp, link_status)) { - return; - } - /* Now read the DPCD to see if it's actually running */ if (!intel_dp_get_dpcd(intel_dp)) { return; @@ -4271,14 +4286,9 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n"); } - /* if link training is requested we should perform it always */ - if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) || - (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) { - DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", - intel_encoder->base.name); - intel_dp_start_link_train(intel_dp); - intel_dp_stop_link_train(intel_dp); - } + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + intel_dp_check_link_status(intel_dp); + drm_modeset_unlock(&dev->mode_config.connection_mutex); } /* XXX this is probably wrong for multiple downstream ports */ @@ -5017,11 +5027,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) } } - if (!intel_dp->is_mst) { - drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); - intel_dp_check_link_status(intel_dp); - drm_modeset_unlock(&dev->mode_config.connection_mutex); - } + if (!intel_dp->is_mst) + intel_dp_short_pulse(intel_dp); } ret = IRQ_HANDLED; -- cgit v0.10.2 From 30d9aa4265fe4b2b28239934770b2c2d59858df3 Mon Sep 17 00:00:00 2001 From: Shubhangi Shrivastava Date: Wed, 30 Mar 2016 18:05:25 +0530 Subject: drm/i915: Read sink_count dpcd always Sink count can change between short pulse hpd hence this patch adds a member variable to intel_dp so we can track any changes between short pulse interrupts. This patch reads sink_count dpcd always and removes its read operation based on values in downstream port dpcd. SINK_COUNT dpcd is not dependent on DOWNSTREAM_PORT_PRESENT dpcd. SINK_COUNT denotes if a display is attached, while DOWNSTREAM_PORT_PRESET indicates how many ports are available in the dongle where display can be attached. so it is possible for sink count to change irrespective of value in downstream port dpcd. Here is a table of possible values and scenarios sink_count downstream_port present 0 0 no display is attached 0 1 dongle is connected without display 1 0 display connected directly 1 1 display connected through dongle v2: Storing value of intel_dp->sink_count that is ready for consumption. (Ander) Squashing two commits into one. (Ander) v3: Added comment to explain the need of early return when sink count is 0. (Ander) Tested-by: Nathan D Ciobanu Signed-off-by: Sivakumar Thulasimani Signed-off-by: Shubhangi Shrivastava Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Ander Conselvan de Oliveira Link: http://patchwork.freedesktop.org/patch/msgid/1459341326-13142-4-git-send-email-shubhangi.shrivastava@intel.com diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9ee7a73..c8d22be 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3788,6 +3788,27 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) if (intel_dp->dpcd[DP_DPCD_REV] == 0) return false; /* DPCD not present */ + if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_COUNT, + &intel_dp->sink_count, 1) < 0) + return false; + + /* + * Sink count can change between short pulse hpd hence + * a member variable in intel_dp will track any changes + * between short pulse interrupts. + */ + intel_dp->sink_count = DP_GET_SINK_COUNT(intel_dp->sink_count); + + /* + * SINK_COUNT == 0 and DOWNSTREAM_PORT_PRESENT == 1 implies that + * a dongle is present but no display. Unless we require to know + * if a dongle is present or not, we don't need to update + * downstream port information. So, an early return here saves + * time from performing other operations which are not required. + */ + if (!intel_dp->sink_count) + return false; + /* Check if the panel supports PSR */ memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd)); if (is_edp(intel_dp)) { @@ -4308,14 +4329,9 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) /* If we're HPD-aware, SINK_COUNT changes dynamically */ if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) { - uint8_t reg; - - if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_COUNT, - ®, 1) < 0) - return connector_status_unknown; - return DP_GET_SINK_COUNT(reg) ? connector_status_connected - : connector_status_disconnected; + return intel_dp->sink_count ? + connector_status_connected : connector_status_disconnected; } /* If no HPD, poke DDC gently */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ed65a71..9255b56 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -796,6 +796,7 @@ struct intel_dp { uint32_t DP; int link_rate; uint8_t lane_count; + uint8_t sink_count; bool has_audio; bool detect_done; enum hdmi_force_audio force_audio; -- cgit v0.10.2 From 39ff747b2f8197de51dae540e742de4acdbd7763 Mon Sep 17 00:00:00 2001 From: Shubhangi Shrivastava Date: Wed, 30 Mar 2016 18:05:26 +0530 Subject: drm/i915: force full detect on sink count change This patch checks for changes in sink count between short pulse hpds and forces full detect when there is a change. This will allow both detection of hotplug and unplug of panels through dongles that give only short pulse for such events. v2: changed variable type from u8 to bool (Jani) return immediately if perform_full_detect is set(Siva) v3: changed method of determining full detection from using pointer to return code (Siva) v4: changed comments to indicate meaning of return value of intel_dp_short_pulse and explain the use of return value from intel_dp_get_dpcd in intel_dp_short_pulse (Ander) Tested-by: Nathan D Ciobanu Signed-off-by: Sivakumar Thulasimani Signed-off-by: Shubhangi Shrivastava Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Ander Conselvan de Oliveira Link: http://patchwork.freedesktop.org/patch/msgid/1459341326-13142-5-git-send-email-shubhangi.shrivastava@intel.com diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index c8d22be..da0c3d2 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -4273,12 +4273,19 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) * 2. Configure link according to Receiver Capabilities * 3. Use Link Training from 2.5.3.3 and 3.5.1.3 * 4. Check link status on receipt of hot-plug interrupt + * + * intel_dp_short_pulse - handles short pulse interrupts + * when full detection is not required. + * Returns %true if short pulse is handled and full detection + * is NOT required and %false otherwise. */ -static void +static bool intel_dp_short_pulse(struct intel_dp *intel_dp) { struct drm_device *dev = intel_dp_to_dev(intel_dp); u8 sink_irq_vector; + u8 old_sink_count = intel_dp->sink_count; + bool ret; /* * Clearing compliance test variables to allow capturing @@ -4288,9 +4295,17 @@ intel_dp_short_pulse(struct intel_dp *intel_dp) intel_dp->compliance_test_type = 0; intel_dp->compliance_test_data = 0; - /* Now read the DPCD to see if it's actually running */ - if (!intel_dp_get_dpcd(intel_dp)) { - return; + /* + * Now read the DPCD to see if it's actually running + * If the current value of sink count doesn't match with + * the value that was stored earlier or dpcd read failed + * we need to do full detection + */ + ret = intel_dp_get_dpcd(intel_dp); + + if ((old_sink_count != intel_dp->sink_count) || !ret) { + /* No need to proceed if we are going to do full detect */ + return false; } /* Try to read the source of the interrupt */ @@ -4310,6 +4325,8 @@ intel_dp_short_pulse(struct intel_dp *intel_dp) drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); intel_dp_check_link_status(intel_dp); drm_modeset_unlock(&dev->mode_config.connection_mutex); + + return true; } /* XXX this is probably wrong for multiple downstream ports */ @@ -5043,8 +5060,12 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) } } - if (!intel_dp->is_mst) - intel_dp_short_pulse(intel_dp); + if (!intel_dp->is_mst) { + if (!intel_dp_short_pulse(intel_dp)) { + intel_dp_long_pulse(intel_dp->attached_connector); + goto put_power; + } + } } ret = IRQ_HANDLED; -- cgit v0.10.2 From b61e79967a6f35043aa838ff36d9970658a0af3d Mon Sep 17 00:00:00 2001 From: Vandana Kannan Date: Thu, 31 Mar 2016 23:15:54 +0530 Subject: drm/i915: BXT DDI PHY sequence BUN According to the BSpec update, bit 7 of PORT_CL1CM_DW0 register needs to be checked to ensure that the register is in accessible state. Also, based on a BSpec update, changing the timeout value to check iphypwrgood, from 10ms to wait for up to 100us. v2: [Ville] use wait_for_us instead of the atomic call. v3: [Jani/Imre] read register only once Signed-off-by: Vandana Kannan Reported-by: Philippe Lecluse Cc: Deak, Imre Cc: Nikula, Jani Acked-by: Jani Nikula Reviewed-by: Imre Deak Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1459446354-19012-1-git-send-email-vandana.kannan@intel.com diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c839ce9..6df3c59 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1324,6 +1324,7 @@ enum skl_disp_power_wells { #define _PORT_CL1CM_DW0_A 0x162000 #define _PORT_CL1CM_DW0_BC 0x6C000 #define PHY_POWER_GOOD (1 << 16) +#define PHY_RESERVED (1 << 7) #define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC, \ _PORT_CL1CM_DW0_A) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 1e08385..3d62b60 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1732,9 +1732,18 @@ static void broxton_phy_init(struct drm_i915_private *dev_priv, val |= GT_DISPLAY_POWER_ON(phy); I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); - /* Considering 10ms timeout until BSpec is updated */ - if (wait_for(I915_READ(BXT_PORT_CL1CM_DW0(phy)) & PHY_POWER_GOOD, 10)) + /* + * The PHY registers start out inaccessible and respond to reads with + * all 1s. Eventually they become accessible as they power up, then + * the reserved bit will give the default 0. Poll on the reserved bit + * becoming 0 to find when the PHY is accessible. + * HW team confirmed that the time to reach phypowergood status is + * anywhere between 50 us and 100us. + */ + if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & + (PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) { DRM_ERROR("timeout during PHY%d power on\n", phy); + } for (port = (phy == DPIO_PHY0 ? PORT_B : PORT_A); port <= (phy == DPIO_PHY0 ? PORT_C : PORT_A); port++) { -- cgit v0.10.2 From 11b538cd6df398c86f4f0e09049c41e3058af10d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 1 Apr 2016 10:44:41 +0300 Subject: drm/i915: use for_each_port_masked in bxt phy init for clarity Make it easier to see which ports are configured for each phy. No functional changes. Signed-off-by: Jani Nikula Reviewed-by: Ander Conselvan de Oliveira Signed-off-by: Imre Deak Link: http://patchwork.freedesktop.org/patch/msgid/1459496681-398-1-git-send-email-jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 3d62b60..2758622 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1726,7 +1726,7 @@ static void broxton_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) { enum port port; - uint32_t val; + u32 ports, val; val = I915_READ(BXT_P_CR_GT_DISP_PWRON); val |= GT_DISPLAY_POWER_ON(phy); @@ -1745,8 +1745,12 @@ static void broxton_phy_init(struct drm_i915_private *dev_priv, DRM_ERROR("timeout during PHY%d power on\n", phy); } - for (port = (phy == DPIO_PHY0 ? PORT_B : PORT_A); - port <= (phy == DPIO_PHY0 ? PORT_C : PORT_A); port++) { + if (phy == DPIO_PHY0) + ports = BIT(PORT_B) | BIT(PORT_C); + else + ports = BIT(PORT_A); + + for_each_port_masked(port, ports) { int lane; for (lane = 0; lane < 4; lane++) { -- cgit v0.10.2 From e37788fdb2c8138a1e3733de1e780389242e52d9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 18 Mar 2016 13:11:09 +0200 Subject: drm/i915/dsi: refer to gpio index instead of gpio to avoid confusion The DSI sequence blocks contain gpio index references, not actual gpio numbers. No functional changes. Reviewed-by: Mika Kahola Signed-off-by: Jani Nikula Link: http://patchwork.freedesktop.org/patch/msgid/4a54778e56b507e8a0bd635ba02ed2a4734b00ac.1458299160.git.jani.nikula@intel.com diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 8302a97..f687b2e 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c @@ -198,7 +198,7 @@ static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data) static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) { - u8 gpio, action; + u8 gpio_index, action; u16 function, pad; u32 val; struct drm_device *dev = intel_dsi->base.base.dev; @@ -207,13 +207,13 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) if (dev_priv->vbt.dsi.seq_version >= 3) data++; - gpio = *data++; + gpio_index = *data++; /* pull up/down */ action = *data++ & 1; - if (gpio >= ARRAY_SIZE(gtable)) { - DRM_DEBUG_KMS("unknown gpio %u\n", gpio); + if (gpio_index >= ARRAY_SIZE(gtable)) { + DRM_DEBUG_KMS("unknown gpio index %u\n", gpio_index); goto out; } @@ -227,16 +227,16 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) goto out; } - function = gtable[gpio].function_reg; - pad = gtable[gpio].pad_reg; + function = gtable[gpio_index].function_reg; + pad = gtable[gpio_index].pad_reg; mutex_lock(&dev_priv->sb_lock); - if (!gtable[gpio].init) { + if (!gtable[gpio_index].init) { /* program the function */ /* FIXME: remove constant below */ vlv_iosf_sb_write(dev_priv, IOSF_PORT_GPIO_NC, function, 0x2000CC00); - gtable[gpio].init = 1; + gtable[gpio_index].init = 1; } val = 0x4 | action; -- cgit v0.10.2 From 934458c2c95df4077b426a00bfd9d62e818f914e Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Fri, 1 Apr 2016 14:41:01 +0300 Subject: Revert "drm/i915: Fix races on fbdev" This reverts commit a7442b93cf32c1e1ddb721a26cd1f92302e2a222. With the patch applied SNB, IVB and ILK are experiencing hard machine hangs. Original patch was to fix "just" kernel panics so it's not a good trade-off. Proper fix for the panic is on the way, lets revert until then. Fixes: a7442b93cf32 ("drm/i915: Fix races on fbdev") Cc: Lukas Wunner Cc: Daniel Vetter Cc: Chris Wilson Cc: Tomi Sarvela Cc: stable@vger.kernel.org Acked-by: Lukas Wunner Tested-by: Tomi Sarvela Suggested-by: Chris Wilson Signed-off-by: Joonas Lahtinen Link: http://patchwork.freedesktop.org/patch/msgid/1459510861-29035-1-git-send-email-joonas.lahtinen@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index a66ce49..b377753 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -493,9 +493,11 @@ static int i915_load_modeset_init(struct drm_device *dev) * Some ports require correctly set-up hpd registers for detection to * work properly (leading to ghost connected connector status), e.g. VGA * on gm45. Hence we can only set up the initial fbdev config after hpd - * irqs are fully enabled. We protect the fbdev initial config scanning - * against hotplug events by waiting in intel_fbdev_output_poll_changed - * until the asynchronous thread has finished. + * irqs are fully enabled. Now we should scan for the initial config + * only once hotplug handling is enabled, but due to screwed-up locking + * around kms/fbdev init we can't protect the fdbev initial config + * scanning against hotplug events. Hence do this first and ignore the + * tiny window where we will loose hotplug notifactions. */ intel_fbdev_initial_config_async(dev); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index 4cf04ce..79ac202 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -810,8 +810,6 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous void intel_fbdev_output_poll_changed(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - - async_synchronize_full(); if (dev_priv->fbdev) drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper); } @@ -823,7 +821,6 @@ void intel_fbdev_restore_mode(struct drm_device *dev) struct intel_fbdev *ifbdev = dev_priv->fbdev; struct drm_fb_helper *fb_helper; - async_synchronize_full(); if (!ifbdev) return; -- cgit v0.10.2 From 5b421c57e0a9cb1187c2fe203d01fbfb651cb061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 1 Mar 2016 16:16:23 +0200 Subject: drm/i915: Disable FDI RX before DDI_BUF_CTL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bspec is confused w.r.t. the HSW/BDW FDI disable sequence. It lists FDI RX disable both as step 13 and step 18 in the sequence. But I dug up an old BUN mail from Art that moved the FDI RX disable to happen before DDI_BUF_CTL disable. That BUN did not renumber the steps and just added a note: "Workaround: Disable PCH FDI Receiver before disabling DDI_BUF_CTL." The BUN described the symptoms of the fixed issue as: "PCH display underflow and a black screen on the analog CRT port that happened after a FDI re-train" I suppose later someone tried to renumber the steps to match, but forgot to remove the FDI RX disable from its old position in the sequence. They also forgot to update the note describing what should be done in case of an FDI training failure. Currently it says: "To retry FDI training, follow the Disable Sequence steps to Disable FDI, but skip the steps related to clocks and PLLs (16, 19, and 20), ..." It should really say "17, 20, and 21" with the current sequence because those are the steps that deal with PLLs and whatnot, after step 13 became FDI RX disable. And had the step 18 FDI RX disable been removed, as I suspect it should have, the note should actually say "17, 19, and 20". So, let's move the FDI RX disable to happen before DDI_BUF_CTL disable, as that would appear to be the correct order based on the BUN. Note that Art has since unconfused the spec, and so this patch should now match the steps listed in the spec. v2: Add a note that the spec is now correct Cc: Paulo Zanoni Cc: Art Runyan Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1456841783-4779-1-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Paulo Zanoni diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 2758622..766156f 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -629,6 +629,10 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) break; } + rx_ctl_val &= ~FDI_RX_ENABLE; + I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val); + POSTING_READ(FDI_RX_CTL(PIPE_A)); + temp = I915_READ(DDI_BUF_CTL(PORT_E)); temp &= ~DDI_BUF_CTL_ENABLE; I915_WRITE(DDI_BUF_CTL(PORT_E), temp); @@ -643,10 +647,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc) intel_wait_ddi_buf_idle(dev_priv, PORT_E); - rx_ctl_val &= ~FDI_RX_ENABLE; - I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val); - POSTING_READ(FDI_RX_CTL(PIPE_A)); - /* Reset FDI_RX_MISC pwrdn lanes */ temp = I915_READ(FDI_RX_MISC(PIPE_A)); temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); @@ -1911,12 +1911,18 @@ void intel_ddi_fdi_disable(struct drm_crtc *crtc) struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc); uint32_t val; - intel_ddi_post_disable(intel_encoder); - + /* + * Bspec lists this as both step 13 (before DDI_BUF_CTL disable) + * and step 18 (after clearing PORT_CLK_SEL). Based on a BUN, + * step 13 is the correct place for it. Step 18 is where it was + * originally before the BUN. + */ val = I915_READ(FDI_RX_CTL(PIPE_A)); val &= ~FDI_RX_ENABLE; I915_WRITE(FDI_RX_CTL(PIPE_A), val); + intel_ddi_post_disable(intel_encoder); + val = I915_READ(FDI_RX_MISC(PIPE_A)); val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2); -- cgit v0.10.2 From 27878ede4fec7b929c3010710ba4d55c617c621d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2016 16:39:54 +0200 Subject: drm/i915: Throw out BUGs from DPLL/PCH functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These BUGs don't serve any purpose IMO. Throw them out. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458052809-23426-2-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e6b5ee5..cc607ac 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1617,9 +1617,6 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) assert_pipe_disabled(dev_priv, crtc->pipe); - /* No really, not for ILK+ */ - BUG_ON(INTEL_INFO(dev)->gen >= 5); - /* PLL is protected by panel, make sure we can write it */ if (IS_MOBILE(dev) && !IS_I830(dev)) assert_panel_unlocked(dev_priv, crtc->pipe); @@ -1795,9 +1792,6 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, i915_reg_t reg; uint32_t val, pipeconf_val; - /* PCH only available on ILK+ */ - BUG_ON(!HAS_PCH_SPLIT(dev)); - /* Make sure PCH DPLL is enabled */ assert_shared_dpll_enabled(dev_priv, intel_crtc->config->shared_dpll); @@ -1851,9 +1845,6 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, { u32 val, pipeconf_val; - /* PCH only available on ILK+ */ - BUG_ON(!HAS_PCH_SPLIT(dev_priv->dev)); - /* FDI must be feeding us bits for PCH ports */ assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder); assert_fdi_rx_enabled(dev_priv, TRANSCODER_A); -- cgit v0.10.2 From 03ed5cbfacfb35a5d3aeeb39ebec63437917e7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2016 16:39:55 +0200 Subject: drm/i915: Make {vlv,chv}_{disable,update}_pll() more similar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VLV and CHV DPLL disable and update are almost identical in how the DPLL/DPLL_MD registers need to be set up. But the code looks more different than it really is. Try to bring them into line. Note that we now leave the refclock always enabled for both DPLLs in the dual channel PHY. But that's perfectly fine since it's the same clock, and we anyway already do that when turning the disp2d power well on. v2: s/chv_update_pll/chv_compute_dpll/ v3: Add a note that we leave refclocks enabled for both DPLLs (Jani) Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458052809-23426-3-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cc607ac..0528748 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1715,16 +1715,13 @@ static void vlv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) /* Make sure the pipe isn't still relying on us */ assert_pipe_disabled(dev_priv, pipe); - /* - * Leave integrated clock source and reference clock enabled for pipe B. - * The latter is needed for VGA hotplug / manual detection. - */ - val = DPLL_VGA_MODE_DIS; - if (pipe == PIPE_B) - val = DPLL_INTEGRATED_CRI_CLK_VLV | DPLL_REF_CLK_ENABLE_VLV; + val = DPLL_INTEGRATED_REF_CLK_VLV | + DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; + if (pipe != PIPE_A) + val |= DPLL_INTEGRATED_CRI_CLK_VLV; + I915_WRITE(DPLL(pipe), val); POSTING_READ(DPLL(pipe)); - } static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) @@ -1735,11 +1732,11 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) /* Make sure the pipe isn't still relying on us */ assert_pipe_disabled(dev_priv, pipe); - /* Set PLL en = 0 */ val = DPLL_SSC_REF_CLK_CHV | DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; if (pipe != PIPE_A) val |= DPLL_INTEGRATED_CRI_CLK_VLV; + I915_WRITE(DPLL(pipe), val); POSTING_READ(DPLL(pipe)); @@ -7156,24 +7153,27 @@ void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n) static void vlv_compute_dpll(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { - u32 dpll, dpll_md; + pipe_config->dpll_hw_state.dpll = DPLL_INTEGRATED_REF_CLK_VLV | + DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS | + DPLL_VCO_ENABLE | DPLL_EXT_BUFFER_ENABLE_VLV; + if (crtc->pipe != PIPE_A) + pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; - /* - * Enable DPIO clock input. We should never disable the reference - * clock for pipe B, since VGA hotplug / manual detection depends - * on it. - */ - dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REF_CLK_ENABLE_VLV | - DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_REF_CLK_VLV; - /* We should never disable this, set it here for state tracking */ - if (crtc->pipe == PIPE_B) - dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; - dpll |= DPLL_VCO_ENABLE; - pipe_config->dpll_hw_state.dpll = dpll; + pipe_config->dpll_hw_state.dpll_md = + (pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; +} + +static void chv_compute_dpll(struct intel_crtc *crtc, + struct intel_crtc_state *pipe_config) +{ + pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLK_CHV | + DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS | + DPLL_VCO_ENABLE; + if (crtc->pipe != PIPE_A) + pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; - dpll_md = (pipe_config->pixel_multiplier - 1) - << DPLL_MD_UDI_MULTIPLIER_SHIFT; - pipe_config->dpll_hw_state.dpll_md = dpll_md; + pipe_config->dpll_hw_state.dpll_md = + (pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; } static void vlv_prepare_pll(struct intel_crtc *crtc, @@ -7267,19 +7267,6 @@ static void vlv_prepare_pll(struct intel_crtc *crtc, mutex_unlock(&dev_priv->sb_lock); } -static void chv_compute_dpll(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) -{ - pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLK_CHV | - DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS | - DPLL_VCO_ENABLE; - if (crtc->pipe != PIPE_A) - pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; - - pipe_config->dpll_hw_state.dpll_md = - (pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; -} - static void chv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config) { -- cgit v0.10.2 From c231775c2df845abc193666a5aec552c3ad3740f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2016 16:39:56 +0200 Subject: drm/i915: Implement WaPixelRepeatModeFixForC0:chv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DPLL_MD(PIPE_C) is AWOL on CHV. Instead of fixing it someone added chicken bits to propagate the pixel multiplier from DPLL_MD(PIPE_B) to either pipe B or C. So do that to make pixel repeat work on pipes B and C. Pipe A is fine without any tricks. Fortunately the pixel repeat propagation appears to be a oneshot operation, so once the value has been written we can clear the chicken bits. So it is still possible to drive pipe B and C with different pixel multipliers simultaneosly. Looks like DPLL_VGA_MODE_DIS must also be set in DPLL(PIPE_B) for this to work. But since we keep that bit always set in all DPLLs there's no problem. This of course means we can't reliably read out the pixel multiplier for pipes B and C. That would make the state checker unhappy, so I added shadow copies of those registers in to dev_priv. The other option would have been to skip pixel multiplier, dpll_md an dotclock checks entirely on CHV, but that feels like a serious loss of cross checking, so just pretending that we have working DPLL MD registers seemed better. Obviously with the shadow copies we can't detect if the pixel multiplier was properly configured, nor can we take over its state from the BIOS, but hopefully people won't have displays that would be limitd to such crappy modes. There is one strange flicker still remaining. It's visible on pipe C/HDMID when HDMIB is enabled while driven by pipe B. It doesn't occur if pipe A drives HDMIB, nor is there any glitch on pipe B/HDMIB when port C/HDMID starts up. I don't have a board with HDMIC so not sure if it happens there too. So I'm not sure if it's somehow tied in with this strange linkage between pipe B and C. Sadly I was unable to find an enable sequence that would avoid the glitch, but at least it's not fatal ie. the output recovers afterwards. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458052809-23426-4-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d3ebb2f..dd18772 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1900,7 +1900,14 @@ struct drm_i915_private { u32 fdi_rx_config; + /* Shadow for DISPLAY_PHY_CONTROL which can't be safely read */ u32 chv_phy_control; + /* + * Shadows for CHV DPLL_MD regs to keep the state + * checker somewhat working in the presence hardware + * crappiness (can't read out DPLL_MD for pipes B & C). + */ + u32 chv_dpll_md[I915_MAX_PIPES]; u32 suspend_count; bool suspended_to_idle; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 6df3c59..12f5103 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4786,6 +4786,10 @@ enum skl_disp_power_wells { #define CBR_PND_DEADLINE_DISABLE (1<<31) #define CBR_PWM_CLOCK_MUX_SELECT (1<<30) +#define CBR4_VLV _MMIO(VLV_DISPLAY_BASE + 0x70450) +#define CBR_DPLLBMD_PIPE_C (1<<29) +#define CBR_DPLLBMD_PIPE_B (1<<18) + /* FIFO watermark sizes etc */ #define G4X_FIFO_LINE_SIZE 64 #define I915_FIFO_LINE_SIZE 64 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0528748..3fdce85 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1591,9 +1591,27 @@ static void chv_enable_pll(struct intel_crtc *crtc, if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) DRM_ERROR("PLL %d failed to lock\n", pipe); - /* not sure when this should be written */ - I915_WRITE(DPLL_MD(pipe), pipe_config->dpll_hw_state.dpll_md); - POSTING_READ(DPLL_MD(pipe)); + if (pipe != PIPE_A) { + /* + * WaPixelRepeatModeFixForC0:chv + * + * DPLLCMD is AWOL. Use chicken bits to propagate + * the value from DPLLBMD to either pipe B or C. + */ + I915_WRITE(CBR4_VLV, pipe == PIPE_B ? CBR_DPLLBMD_PIPE_B : CBR_DPLLBMD_PIPE_C); + I915_WRITE(DPLL_MD(PIPE_B), pipe_config->dpll_hw_state.dpll_md); + I915_WRITE(CBR4_VLV, 0); + dev_priv->chv_dpll_md[pipe] = pipe_config->dpll_hw_state.dpll_md; + + /* + * DPLLB VGA mode also seems to cause problems. + * We should always have it disabled. + */ + WARN_ON((I915_READ(DPLL(PIPE_B)) & DPLL_VGA_MODE_DIS) == 0); + } else { + I915_WRITE(DPLL_MD(pipe), pipe_config->dpll_hw_state.dpll_md); + POSTING_READ(DPLL_MD(pipe)); + } } static int intel_num_dvo_pipes(struct drm_device *dev) @@ -8156,7 +8174,11 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, i9xx_get_pfit_config(crtc, pipe_config); if (INTEL_INFO(dev)->gen >= 4) { - tmp = I915_READ(DPLL_MD(crtc->pipe)); + /* No way to read it out on pipes B and C */ + if (IS_CHERRYVIEW(dev) && crtc->pipe != PIPE_A) + tmp = dev_priv->chv_dpll_md[crtc->pipe]; + else + tmp = I915_READ(DPLL_MD(crtc->pipe)); pipe_config->pixel_multiplier = ((tmp & DPLL_MD_UDI_MULTIPLIER_MASK) >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1; -- cgit v0.10.2 From 8bd3f301ab6638d84f3e1c3c7e9ea2bf5b6880c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2016 16:39:57 +0200 Subject: drm/i915: Add a local pipe variable to vlv_enable_pll() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid redundant crtc->pipe lookups by giving vlv_enable_pll() a local pipe variable. Also makes it look more like the corresponding CHV code. While at is change the CHV code to enum pipe from int, Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458052809-23426-5-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3fdce85..6a95c31 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1528,24 +1528,25 @@ static void vlv_enable_pll(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - i915_reg_t reg = DPLL(crtc->pipe); + enum pipe pipe = crtc->pipe; + i915_reg_t reg = DPLL(pipe); u32 dpll = pipe_config->dpll_hw_state.dpll; - assert_pipe_disabled(dev_priv, crtc->pipe); + assert_pipe_disabled(dev_priv, pipe); /* PLL is protected by panel, make sure we can write it */ if (IS_MOBILE(dev_priv->dev)) - assert_panel_unlocked(dev_priv, crtc->pipe); + assert_panel_unlocked(dev_priv, pipe); I915_WRITE(reg, dpll); POSTING_READ(reg); udelay(150); if (wait_for(((I915_READ(reg) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) - DRM_ERROR("DPLL %d failed to lock\n", crtc->pipe); + DRM_ERROR("DPLL %d failed to lock\n", pipe); - I915_WRITE(DPLL_MD(crtc->pipe), pipe_config->dpll_hw_state.dpll_md); - POSTING_READ(DPLL_MD(crtc->pipe)); + I915_WRITE(DPLL_MD(pipe), pipe_config->dpll_hw_state.dpll_md); + POSTING_READ(DPLL_MD(pipe)); /* We do this three times for luck */ I915_WRITE(reg, dpll); @@ -1564,11 +1565,11 @@ static void chv_enable_pll(struct intel_crtc *crtc, { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - int pipe = crtc->pipe; + enum pipe pipe = crtc->pipe; enum dpio_channel port = vlv_pipe_to_channel(pipe); u32 tmp; - assert_pipe_disabled(dev_priv, crtc->pipe); + assert_pipe_disabled(dev_priv, pipe); mutex_lock(&dev_priv->sb_lock); -- cgit v0.10.2 From 7d1a83cb68172a225c45243e955d9ee41eada8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2016 16:39:58 +0200 Subject: drm/i915: assert_panel_unlocked() in chv_enable_pll() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supposedly the power sequencer still locks out the DPLL registers on CHV, so let's issue a warning if it's still locked when enabling the DPLL. Also drop the redundant IS_MOBILE() check for VLV when we check the same thing. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458052809-23426-6-git-send-email-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6a95c31..4fbff48 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1535,8 +1535,7 @@ static void vlv_enable_pll(struct intel_crtc *crtc, assert_pipe_disabled(dev_priv, pipe); /* PLL is protected by panel, make sure we can write it */ - if (IS_MOBILE(dev_priv->dev)) - assert_panel_unlocked(dev_priv, pipe); + assert_panel_unlocked(dev_priv, pipe); I915_WRITE(reg, dpll); POSTING_READ(reg); @@ -1571,6 +1570,9 @@ static void chv_enable_pll(struct intel_crtc *crtc, assert_pipe_disabled(dev_priv, pipe); + /* PLL is protected by panel, make sure we can write it */ + assert_panel_unlocked(dev_priv, pipe); + mutex_lock(&dev_priv->sb_lock); /* Enable back the 10bit clock to display controller */ -- cgit v0.10.2 From 5593946921834a63d89c595ef8459c50d30f5438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2016 16:39:59 +0200 Subject: drm/i915: Remove the "three times for luck" trick from vlv_enable_pll() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VLV DPLL is somewhat sane and doesn't run on luck. Signed-off-by: Ville Syrjälä Link: http://patchwork.freedesktop.org/patch/msgid/1458052809-23426-7-git-send-email-ville.syrjala@linux.intel.com Acked-by: Jani Nikula diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4fbff48..cf16bdb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1546,17 +1546,6 @@ static void vlv_enable_pll(struct intel_crtc *crtc, I915_WRITE(DPLL_MD(pipe), pipe_config->dpll_hw_state.dpll_md); POSTING_READ(DPLL_MD(pipe)); - - /* We do this three times for luck */ - I915_WRITE(reg, dpll); - POSTING_READ(reg); - udelay(150); /* wait for warmup */ - I915_WRITE(reg, dpll); - POSTING_READ(reg); - udelay(150); /* wait for warmup */ - I915_WRITE(reg, dpll); - POSTING_READ(reg); - udelay(150); /* wait for warmup */ } static void chv_enable_pll(struct intel_crtc *crtc, -- cgit v0.10.2 From fca0ce2a5caf6ae7d9d8510fb87ae6195b40057a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 21 Mar 2016 14:43:22 +0000 Subject: drm/i915: Fix plane init failure paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deal with errors from drm_universal_plane_init() in primary and cursor plane init paths (sprites were already covered). Also make the code neater by using goto for error handling. v2: Rebased due to drm_universal_plane_init() 'name' parameter v3: Another rebase due to s/""/NULL/ v4: Rebased on drm-nightly (Matthew Auld) v5: Fix email address (Matthew Auld) Signed-off-by: Ville Syrjälä Reviewed-by: Matthew Auld Link: http://patchwork.freedesktop.org/patch/msgid/1458571402-32749-1-git-send-email-matthew.auld@intel.com diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cf16bdb..af74cdb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13947,20 +13947,19 @@ const struct drm_plane_funcs intel_plane_funcs = { static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, int pipe) { - struct intel_plane *primary; - struct intel_plane_state *state; + struct intel_plane *primary = NULL; + struct intel_plane_state *state = NULL; const uint32_t *intel_primary_formats; unsigned int num_formats; + int ret; primary = kzalloc(sizeof(*primary), GFP_KERNEL); - if (primary == NULL) - return NULL; + if (!primary) + goto fail; state = intel_create_plane_state(&primary->base); - if (!state) { - kfree(primary); - return NULL; - } + if (!state) + goto fail; primary->base.state = &state->base; primary->can_scale = false; @@ -14002,10 +14001,12 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, primary->disable_plane = i9xx_disable_primary_plane; } - drm_universal_plane_init(dev, &primary->base, 0, - &intel_plane_funcs, - intel_primary_formats, num_formats, - DRM_PLANE_TYPE_PRIMARY, NULL); + ret = drm_universal_plane_init(dev, &primary->base, 0, + &intel_plane_funcs, + intel_primary_formats, num_formats, + DRM_PLANE_TYPE_PRIMARY, NULL); + if (ret) + goto fail; if (INTEL_INFO(dev)->gen >= 4) intel_create_rotation_property(dev, primary); @@ -14013,6 +14014,12 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs); return &primary->base; + +fail: + kfree(state); + kfree(primary); + + return NULL; } void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane) @@ -14129,18 +14136,17 @@ intel_update_cursor_plane(struct drm_plane *plane, static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, int pipe) { - struct intel_plane *cursor; - struct intel_plane_state *state; + struct intel_plane *cursor = NULL; + struct intel_plane_state *state = NULL; + int ret; cursor = kzalloc(sizeof(*cursor), GFP_KERNEL); - if (cursor == NULL) - return NULL; + if (!cursor) + goto fail; state = intel_create_plane_state(&cursor->base); - if (!state) { - kfree(cursor); - return NULL; - } + if (!state) + goto fail; cursor->base.state = &state->base; cursor->can_scale = false; @@ -14152,11 +14158,13 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, cursor->update_plane = intel_update_cursor_plane; cursor->disable_plane = intel_disable_cursor_plane; - drm_universal_plane_init(dev, &cursor->base, 0, - &intel_plane_funcs, - intel_cursor_formats, - ARRAY_SIZE(intel_cursor_formats), - DRM_PLANE_TYPE_CURSOR, NULL); + ret = drm_universal_plane_init(dev, &cursor->base, 0, + &intel_plane_funcs, + intel_cursor_formats, + ARRAY_SIZE(intel_cursor_formats), + DRM_PLANE_TYPE_CURSOR, NULL); + if (ret) + goto fail; if (INTEL_INFO(dev)->gen >= 4) { if (!dev->mode_config.rotation_property) @@ -14176,6 +14184,12 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs); return &cursor->base; + +fail: + kfree(state); + kfree(cursor); + + return NULL; } static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 8821533..0f3e230 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1025,8 +1025,8 @@ static uint32_t skl_plane_formats[] = { int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) { - struct intel_plane *intel_plane; - struct intel_plane_state *state; + struct intel_plane *intel_plane = NULL; + struct intel_plane_state *state = NULL; unsigned long possible_crtcs; const uint32_t *plane_formats; int num_plane_formats; @@ -1036,13 +1036,15 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) return -ENODEV; intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); - if (!intel_plane) - return -ENOMEM; + if (!intel_plane) { + ret = -ENOMEM; + goto fail; + } state = intel_create_plane_state(&intel_plane->base); if (!state) { - kfree(intel_plane); - return -ENOMEM; + ret = -ENOMEM; + goto fail; } intel_plane->base.state = &state->base; @@ -1097,28 +1099,34 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) num_plane_formats = ARRAY_SIZE(skl_plane_formats); break; default: - kfree(intel_plane); - return -ENODEV; + MISSING_CASE(INTEL_INFO(dev)->gen); + ret = -ENODEV; + goto fail; } intel_plane->pipe = pipe; intel_plane->plane = plane; intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane); intel_plane->check_plane = intel_check_sprite_plane; + possible_crtcs = (1 << pipe); + ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs, &intel_plane_funcs, plane_formats, num_plane_formats, DRM_PLANE_TYPE_OVERLAY, NULL); - if (ret) { - kfree(intel_plane); - goto out; - } + if (ret) + goto fail; intel_create_rotation_property(dev, intel_plane); drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs); -out: + return 0; + +fail: + kfree(state); + kfree(intel_plane); + return ret; } -- cgit v0.10.2 From 188c1ab7769dd7c092f9b1be5f69aa34d4a6f9d6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Apr 2016 14:14:20 +0100 Subject: drm/i915: Add struct_mutex locking for debugs/i915_gem_framebuffer Since describe_obj() looks at state guarded by the struct_mutex, we need to be holding it. [ 580.201054] drv_suspend: starting subtest debugfs-reader [ 580.239652] ------------[ cut here ]------------ [ 580.239696] WARNING: CPU: 0 PID: 920 at include/linux/list_check.h:25 describe_obj+0x419/0x440() [ 580.239725] CPU: 0 PID: 920 Comm: cat Not tainted 4.5.0-rc6+ #835 [ 580.239745] Hardware name: /NUC5CPYB, BIOS PYBSWCEL.86A.0027.2015.0507.1758 05/07/2015 [ 580.239767] 0000000000000000 ffff88027554fcf8 ffffffff812c1135 0000000000000000 [ 580.239815] ffffffff8193dc42 ffff88027554fd30 ffffffff8107419d ffff880071727c00 [ 580.239858] ffff8802757d8000 ffffffff818f693c ffffffff818f693c ffff8802757b9048 [ 580.239896] Call Trace: [ 580.239917] [] dump_stack+0x67/0x92 [ 580.239939] [] warn_slowpath_common+0x7d/0xb0 [ 580.239959] [] warn_slowpath_null+0x1a/0x20 [ 580.239981] [] describe_obj+0x419/0x440 [ 580.240006] [] i915_gem_framebuffer_info+0xa2/0x100 [ 580.240033] [] seq_read+0xe6/0x3b0 [ 580.240059] [] __vfs_read+0x28/0xd0 [ 580.240085] [] ? SyS_fadvise64+0x228/0x2c0 [ 580.240112] [] vfs_read+0x82/0x110 [ 580.240137] [] SyS_read+0x49/0xa0 [ 580.240162] [] entry_SYSCALL_64_fastpath+0x12/0x6b [ 580.240187] ---[ end trace 3e2cbf34576c9878 ]--- [ 580.281900] ------------[ cut here ]------------ Signed-off-by: Chris Wilson Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459689261-7920-1-git-send-email-chris@chris-wilson.co.uk diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 74f2274..6b384d7 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -134,6 +134,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) int pin_count = 0; enum intel_engine_id id; + lockdep_assert_held(&obj->base.dev->struct_mutex); + seq_printf(m, "%pK: %s%s%s%s %8zdKiB %02x %02x [ ", &obj->base, obj->active ? "*" : " ", @@ -1894,6 +1896,11 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct intel_framebuffer *fbdev_fb = NULL; struct drm_framebuffer *drm_fb; + int ret; + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; #ifdef CONFIG_DRM_FBDEV_EMULATION if (to_i915(dev)->fbdev) { @@ -1928,6 +1935,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) seq_putc(m, '\n'); } mutex_unlock(&dev->mode_config.fb_lock); + mutex_unlock(&dev->struct_mutex); return 0; } -- cgit v0.10.2 From a156e64dd6bf609ae5c366e1676e580dca239e3e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Apr 2016 14:14:21 +0100 Subject: drm/i915: Show PCI power state under debugfs/i915_runtime_pm_status As the current PCI power state is an essential feature of runtime pm, include it in the debugfs/i915_runtime_pm_status. v2: Use pci_power_name() Signed-off-by: Chris Wilson Cc: Imre Deak Reviewed-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1459689261-7920-2-git-send-email-chris@chris-wilson.co.uk diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6b384d7..0b25228 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2694,10 +2694,8 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; - if (!HAS_RUNTIME_PM(dev)) { - seq_puts(m, "not supported\n"); - return 0; - } + if (!HAS_RUNTIME_PM(dev_priv)) + seq_puts(m, "Runtime power management not supported\n"); seq_printf(m, "GPU idle: %s\n", yesno(!dev_priv->mm.busy)); seq_printf(m, "IRQs disabled: %s\n", @@ -2708,6 +2706,9 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused) #else seq_printf(m, "Device Power Management (CONFIG_PM) disabled\n"); #endif + seq_printf(m, "PCI device power state: %s [%d]\n", + pci_power_name(dev_priv->dev->pdev->current_state), + dev_priv->dev->pdev->current_state); return 0; } -- cgit v0.10.2 From 183aec16445f6e08c4ea6e3d5cb8f8c3d56339c1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 3 Apr 2016 21:59:14 +0100 Subject: drm/i915/ddi: Silence compiler warning for unknown output type Silences src/drivers/gpu/drm/i915/intel_ddi.c: warning: 'port' may be used uninitialized in this function [-Wuninitialized] Reported-by: Geert Uytterhoeven Signed-off-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1459717154-27607-1-git-send-email-chris@chris-wilson.co.uk diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 766156f..921edf1 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -315,6 +315,9 @@ static void ddi_get_encoder_port(struct intel_encoder *intel_encoder, *dig_port = enc_to_mst(encoder)->primary; *port = (*dig_port)->port; break; + default: + WARN(1, "Invalid DDI encoder type %d\n", intel_encoder->type); + /* fallthrough and treat as unknown */ case INTEL_OUTPUT_DISPLAYPORT: case INTEL_OUTPUT_EDP: case INTEL_OUTPUT_HDMI: @@ -326,9 +329,6 @@ static void ddi_get_encoder_port(struct intel_encoder *intel_encoder, *dig_port = NULL; *port = PORT_E; break; - default: - WARN(1, "Invalid DDI encoder type %d\n", intel_encoder->type); - break; } } -- cgit v0.10.2 From 27af5eea54d161e1636001a7f2b5efd3b7a3d1f9 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Mon, 4 Apr 2016 12:11:56 +0100 Subject: drm/i915: Move execlists irq handler to a bottom half Doing a lot of work in the interrupt handler introduces huge latencies to the system as a whole. Most dramatic effect can be seen by running an all engine stress test like igt/gem_exec_nop/all where, when the kernel config is lean enough, the whole system can be brought into multi-second periods of complete non-interactivty. That can look for example like this: NMI watchdog: BUG: soft lockup - CPU#0 stuck for 23s! [kworker/u8:3:143] Modules linked in: [redacted for brevity] CPU: 0 PID: 143 Comm: kworker/u8:3 Tainted: G U L 4.5.0-160321+ #183 Hardware name: Intel Corporation Broadwell Client platform/WhiteTip Mountain 1 Workqueue: i915 gen6_pm_rps_work [i915] task: ffff8800aae88000 ti: ffff8800aae90000 task.ti: ffff8800aae90000 RIP: 0010:[] [] __do_softirq+0x72/0x1d0 RSP: 0000:ffff88014f403f38 EFLAGS: 00000206 RAX: ffff8800aae94000 RBX: 0000000000000000 RCX: 00000000000006e0 RDX: 0000000000000020 RSI: 0000000004208060 RDI: 0000000000215d80 RBP: ffff88014f403f80 R08: 0000000b1b42c180 R09: 0000000000000022 R10: 0000000000000004 R11: 00000000ffffffff R12: 000000000000a030 R13: 0000000000000082 R14: ffff8800aa4d0080 R15: 0000000000000082 FS: 0000000000000000(0000) GS:ffff88014f400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fa53b90c000 CR3: 0000000001a0a000 CR4: 00000000001406f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Stack: 042080601b33869f ffff8800aae94000 00000000fffc2678 ffff88010000000a 0000000000000000 000000000000a030 0000000000005302 ffff8800aa4d0080 0000000000000206 ffff88014f403f90 ffffffff8104a716 ffff88014f403fa8 Call Trace: [] irq_exit+0x86/0x90 [] smp_apic_timer_interrupt+0x3d/0x50 [] apic_timer_interrupt+0x7c/0x90 [] ? gen8_write64+0x1a0/0x1a0 [i915] [] ? _raw_spin_unlock_irqrestore+0x9/0x20 [] gen8_write32+0x104/0x1a0 [i915] [] ? n_tty_receive_buf_common+0x372/0xae0 [] gen6_set_rps_thresholds+0x1be/0x330 [i915] [] gen6_set_rps+0x70/0x200 [i915] [] intel_set_rps+0x25/0x30 [i915] [] gen6_pm_rps_work+0x10d/0x2e0 [i915] [] ? finish_task_switch+0x72/0x1c0 [] process_one_work+0x139/0x350 [] worker_thread+0x126/0x490 [] ? rescuer_thread+0x320/0x320 [] kthread+0xc4/0xe0 [] ? kthread_create_on_node+0x170/0x170 [] ret_from_fork+0x3f/0x70 [] ? kthread_create_on_node+0x170/0x170 I could not explain, or find a code path, which would explain a +20 second lockup, but from some instrumentation it was apparent the interrupts off proportion of time was between 10-25% under heavy load which is quite bad. When a interrupt "cliff" is reached, which was >~320k irq/s on my machine, the whole system goes into a terrible state of the above described multi-second lockups. By moving the GT interrupt handling to a tasklet in a most simple way, the problem above disappears completely. Testing the effect on sytem-wide latencies using igt/gem_syslatency shows the following before this patch: gem_syslatency: cycles=1532739, latency mean=416531.829us max=2499237us gem_syslatency: cycles=1839434, latency mean=1458099.157us max=4998944us gem_syslatency: cycles=1432570, latency mean=2688.451us max=1201185us gem_syslatency: cycles=1533543, latency mean=416520.499us max=2498886us This shows that the unrelated process is experiencing huge delays in its wake-up latency. After the patch the results look like this: gem_syslatency: cycles=808907, latency mean=53.133us max=1640us gem_syslatency: cycles=862154, latency mean=62.778us max=2117us gem_syslatency: cycles=856039, latency mean=58.079us max=2123us gem_syslatency: cycles=841683, latency mean=56.914us max=1667us Showing a huge improvement in the unrelated process wake-up latency. It also shows an approximate halving in the number of total empty batches submitted during the test. This may not be worrying since the test puts the driver under a very unrealistic load with ncpu threads doing empty batch submission to all GPU engines each. Another benefit compared to the hard-irq handling is that now work on all engines can be dispatched in parallel since we can have up to number of CPUs active tasklets. (While previously a single hard-irq would serially dispatch on one engine after another.) More interesting scenario with regards to throughput is "gem_latency -n 100" which shows 25% better throughput and CPU usage, and 14% better dispatch latencies. I did not find any gains or regressions with Synmark2 or GLbench under light testing. More benchmarking is certainly required. v2: * execlists_lock should be taken as spin_lock_bh when queuing work from userspace now. (Chris Wilson) * uncore.lock must be taken with spin_lock_irq when submitting requests since that now runs from either softirq or process context. v3: * Expanded commit message with more testing data; * converted missed locking sites to _bh; * added execlist_lock comment. (Chris Wilson) v4: * Mention dispatch parallelism in commit. (Chris Wilson) * Do not hold uncore.lock over MMIO reads since the block is already serialised per-engine via the tasklet itself. (Chris Wilson) * intel_lrc_irq_handler should be static. (Chris Wilson) * Cancel/sync the tasklet on GPU reset. (Chris Wilson) * Document and WARN that tasklet cannot be active/pending on engine cleanup. (Chris Wilson/Imre Deak) Signed-off-by: Tvrtko Ursulin Cc: Chris Wilson Cc: Imre Deak Testcase: igt/gem_exec_nop/all Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=94350 Reviewed-by: Chris Wilson Link: http://patchwork.freedesktop.org/patch/msgid/1459768316-6670-1-git-send-email-tvrtko.ursulin@linux.intel.com diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0b25228..a2e3af0 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2100,7 +2100,6 @@ static int i915_execlists(struct seq_file *m, void *data) for_each_engine(engine, dev_priv) { struct drm_i915_gem_request *head_req = NULL; int count = 0; - unsigned long flags; seq_printf(m, "%s\n", engine->name); @@ -2127,13 +2126,13 @@ static int i915_execlists(struct seq_file *m, void *data) i, status, ctx_id); } - spin_lock_irqsave(&engine->execlist_lock, flags); + spin_lock_bh(&engine->execlist_lock); list_for_each(cursor, &engine->execlist_queue) count++; head_req = list_first_entry_or_null(&engine->execlist_queue, struct drm_i915_gem_request, execlist_link); - spin_unlock_irqrestore(&engine->execlist_lock, flags); + spin_unlock_bh(&engine->execlist_lock); seq_printf(m, "\t%d requests in queue\n", count); if (head_req) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ca96fc1..40f90c7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2842,13 +2842,15 @@ static void i915_gem_reset_engine_cleanup(struct drm_i915_private *dev_priv, */ if (i915.enable_execlists) { - spin_lock_irq(&engine->execlist_lock); + /* Ensure irq handler finishes or is cancelled. */ + tasklet_kill(&engine->irq_tasklet); + spin_lock_bh(&engine->execlist_lock); /* list_splice_tail_init checks for empty lists */ list_splice_tail_init(&engine->execlist_queue, &engine->execlist_retired_req_list); + spin_unlock_bh(&engine->execlist_lock); - spin_unlock_irq(&engine->execlist_lock); intel_execlists_retire_requests(engine); } @@ -2968,9 +2970,9 @@ i915_gem_retire_requests(struct drm_device *dev) i915_gem_retire_requests_ring(engine); idle &= list_empty(&engine->request_list); if (i915.enable_execlists) { - spin_lock_irq(&engine->execlist_lock); + spin_lock_bh(&engine->execlist_lock); idle &= list_empty(&engine->execlist_queue); - spin_unlock_irq(&engine->execlist_lock); + spin_unlock_bh(&engine->execlist_lock); intel_execlists_retire_requests(engine); } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a9c1813..c85eb8d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1323,7 +1323,7 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) notify_ring(engine); if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift)) - intel_lrc_irq_handler(engine); + tasklet_schedule(&engine->irq_tasklet); } static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 5d4ca3b..a1db6a0 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -131,6 +131,7 @@ * preemption, but just sampling the new tail pointer). * */ +#include #include #include @@ -418,20 +419,18 @@ static void execlists_submit_requests(struct drm_i915_gem_request *rq0, { struct drm_i915_private *dev_priv = rq0->i915; - /* BUG_ON(!irqs_disabled()); */ - execlists_update_context(rq0); if (rq1) execlists_update_context(rq1); - spin_lock(&dev_priv->uncore.lock); + spin_lock_irq(&dev_priv->uncore.lock); intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); execlists_elsp_write(rq0, rq1); intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); - spin_unlock(&dev_priv->uncore.lock); + spin_unlock_irq(&dev_priv->uncore.lock); } static void execlists_context_unqueue(struct intel_engine_cs *engine) @@ -538,13 +537,14 @@ get_context_status(struct intel_engine_cs *engine, unsigned int read_pointer, /** * intel_lrc_irq_handler() - handle Context Switch interrupts - * @ring: Engine Command Streamer to handle. + * @engine: Engine Command Streamer to handle. * * Check the unread Context Status Buffers and manage the submission of new * contexts to the ELSP accordingly. */ -void intel_lrc_irq_handler(struct intel_engine_cs *engine) +static void intel_lrc_irq_handler(unsigned long data) { + struct intel_engine_cs *engine = (struct intel_engine_cs *)data; struct drm_i915_private *dev_priv = engine->dev->dev_private; u32 status_pointer; unsigned int read_pointer, write_pointer; @@ -552,8 +552,7 @@ void intel_lrc_irq_handler(struct intel_engine_cs *engine) unsigned int csb_read = 0, i; unsigned int submit_contexts = 0; - spin_lock(&dev_priv->uncore.lock); - intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); status_pointer = I915_READ_FW(RING_CONTEXT_STATUS_PTR(engine)); @@ -578,8 +577,7 @@ void intel_lrc_irq_handler(struct intel_engine_cs *engine) _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, engine->next_context_status_buffer << 8)); - intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); - spin_unlock(&dev_priv->uncore.lock); + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); spin_lock(&engine->execlist_lock); @@ -621,7 +619,7 @@ static void execlists_context_queue(struct drm_i915_gem_request *request) i915_gem_request_reference(request); - spin_lock_irq(&engine->execlist_lock); + spin_lock_bh(&engine->execlist_lock); list_for_each_entry(cursor, &engine->execlist_queue, execlist_link) if (++num_elements > 2) @@ -646,7 +644,7 @@ static void execlists_context_queue(struct drm_i915_gem_request *request) if (num_elements == 0) execlists_context_unqueue(engine); - spin_unlock_irq(&engine->execlist_lock); + spin_unlock_bh(&engine->execlist_lock); } static int logical_ring_invalidate_all_caches(struct drm_i915_gem_request *req) @@ -1033,9 +1031,9 @@ void intel_execlists_retire_requests(struct intel_engine_cs *engine) return; INIT_LIST_HEAD(&retired_list); - spin_lock_irq(&engine->execlist_lock); + spin_lock_bh(&engine->execlist_lock); list_replace_init(&engine->execlist_retired_req_list, &retired_list); - spin_unlock_irq(&engine->execlist_lock); + spin_unlock_bh(&engine->execlist_lock); list_for_each_entry_safe(req, tmp, &retired_list, execlist_link) { struct intel_context *ctx = req->ctx; @@ -2016,6 +2014,13 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) if (!intel_engine_initialized(engine)) return; + /* + * Tasklet cannot be active at this point due intel_mark_active/idle + * so this is just for documentation. + */ + if (WARN_ON(test_bit(TASKLET_STATE_SCHED, &engine->irq_tasklet.state))) + tasklet_kill(&engine->irq_tasklet); + dev_priv = engine->dev->dev_private; if (engine->buffer) { @@ -2089,6 +2094,9 @@ logical_ring_init(struct drm_device *dev, struct intel_engine_cs *engine) INIT_LIST_HEAD(&engine->execlist_retired_req_list); spin_lock_init(&engine->execlist_lock); + tasklet_init(&engine->irq_tasklet, + intel_lrc_irq_handler, (unsigned long)engine); + logical_ring_init_platform_invariants(engine); ret = i915_cmd_parser_init_ring(engine); diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index a17cb12..0b0853e 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -118,7 +118,6 @@ int intel_execlists_submission(struct i915_execbuffer_params *params, struct drm_i915_gem_execbuffer2 *args, struct list_head *vmas); -void intel_lrc_irq_handler(struct intel_engine_cs *engine); void intel_execlists_retire_requests(struct intel_engine_cs *engine); #endif /* _INTEL_LRC_H_ */ diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 221a946..18074ab 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -266,7 +266,8 @@ struct intel_engine_cs { } semaphore; /* Execlists */ - spinlock_t execlist_lock; + struct tasklet_struct irq_tasklet; + spinlock_t execlist_lock; /* used inside tasklet, use spin_lock_bh */ struct list_head execlist_queue; struct list_head execlist_retired_req_list; unsigned int next_context_status_buffer; -- cgit v0.10.2 From 3424e3a4f844c0a62128feb388d04ed6b65f6b20 Mon Sep 17 00:00:00 2001 From: Yakir Yang Date: Tue, 29 Mar 2016 09:57:03 +0800 Subject: drm: bridge: analogix/dp: split exynos dp driver to bridge directory Split the dp core driver from exynos directory to bridge directory, and rename the core driver to analogix_dp_*, rename the platform code to exynos_dp. Beside the new analogix_dp driver would export six hooks. "analogix_dp_bind()" and "analogix_dp_unbind()" "analogix_dp_suspned()" and "analogix_dp_resume()" "analogix_dp_detect()" and "analogix_dp_get_modes()" The bind/unbind symbols is used for analogix platform driver to connect with analogix_dp core driver. And the detect/get_modes is used for analogix platform driver to init the connector. They reason why connector need register in helper driver is rockchip drm haven't implement the atomic API, but Exynos drm have implement it, so there would need two different connector helper functions, that's why we leave the connector register in helper driver. Acked-by: Inki Dae Tested-by: Caesar Wang Tested-by: Douglas Anderson Tested-by: Heiko Stuebner Tested-by: Javier Martinez Canillas Signed-off-by: Yakir Yang Signed-off-by: Heiko Stuebner diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 27e2022..efd94e0 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -40,4 +40,6 @@ config DRM_PARADE_PS8622 ---help--- Parade eDP-LVDS bridge chip driver. +source "drivers/gpu/drm/bridge/analogix/Kconfig" + endmenu diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index f13c33d..ff821f4 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o +obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/ diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig new file mode 100644 index 0000000..80f286f --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix/Kconfig @@ -0,0 +1,3 @@ +config DRM_ANALOGIX_DP + tristate + depends on DRM diff --git a/drivers/gpu/drm/bridge/analogix/Makefile b/drivers/gpu/drm/bridge/analogix/Makefile new file mode 100644 index 0000000..cd4010b --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix/Makefile @@ -0,0 +1,2 @@ +analogix_dp-objs := analogix_dp_core.o analogix_dp_reg.o +obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp.o diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c new file mode 100644 index 0000000..392c296 --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -0,0 +1,1351 @@ +/* +* Analogix DP (Display Port) core interface driver. +* +* Copyright (C) 2012 Samsung Electronics Co., Ltd. +* Author: Jingoo Han +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "analogix_dp_core.h" + +#define to_dp(nm) container_of(nm, struct analogix_dp_device, nm) + +struct bridge_init { + struct i2c_client *client; + struct device_node *node; +}; + +static void analogix_dp_init_dp(struct analogix_dp_device *dp) +{ + analogix_dp_reset(dp); + + analogix_dp_swreset(dp); + + analogix_dp_init_analog_param(dp); + analogix_dp_init_interrupt(dp); + + /* SW defined function Normal operation */ + analogix_dp_enable_sw_function(dp); + + analogix_dp_config_interrupt(dp); + analogix_dp_init_analog_func(dp); + + analogix_dp_init_hpd(dp); + analogix_dp_init_aux(dp); +} + +static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) +{ + int timeout_loop = 0; + + while (analogix_dp_get_plug_in_status(dp) != 0) { + timeout_loop++; + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { + dev_err(dp->dev, "failed to get hpd plug status\n"); + return -ETIMEDOUT; + } + usleep_range(10, 11); + } + + return 0; +} + +static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data) +{ + int i; + unsigned char sum = 0; + + for (i = 0; i < EDID_BLOCK_LENGTH; i++) + sum = sum + edid_data[i]; + + return sum; +} + +static int analogix_dp_read_edid(struct analogix_dp_device *dp) +{ + unsigned char edid[EDID_BLOCK_LENGTH * 2]; + unsigned int extend_block = 0; + unsigned char sum; + unsigned char test_vector; + int retval; + + /* + * EDID device address is 0x50. + * However, if necessary, you must have set upper address + * into E-EDID in I2C device, 0x30. + */ + + /* Read Extension Flag, Number of 128-byte EDID extension blocks */ + retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR, + EDID_EXTENSION_FLAG, + &extend_block); + if (retval) + return retval; + + if (extend_block > 0) { + dev_dbg(dp->dev, "EDID data includes a single extension!\n"); + + /* Read EDID data */ + retval = analogix_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR, + EDID_HEADER_PATTERN, + EDID_BLOCK_LENGTH, + &edid[EDID_HEADER_PATTERN]); + if (retval != 0) { + dev_err(dp->dev, "EDID Read failed!\n"); + return -EIO; + } + sum = analogix_dp_calc_edid_check_sum(edid); + if (sum != 0) { + dev_err(dp->dev, "EDID bad checksum!\n"); + return -EIO; + } + + /* Read additional EDID data */ + retval = analogix_dp_read_bytes_from_i2c(dp, + I2C_EDID_DEVICE_ADDR, + EDID_BLOCK_LENGTH, + EDID_BLOCK_LENGTH, + &edid[EDID_BLOCK_LENGTH]); + if (retval != 0) { + dev_err(dp->dev, "EDID Read failed!\n"); + return -EIO; + } + sum = analogix_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]); + if (sum != 0) { + dev_err(dp->dev, "EDID bad checksum!\n"); + return -EIO; + } + + analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, + &test_vector); + if (test_vector & DP_TEST_LINK_EDID_READ) { + analogix_dp_write_byte_to_dpcd(dp, + DP_TEST_EDID_CHECKSUM, + edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); + analogix_dp_write_byte_to_dpcd(dp, + DP_TEST_RESPONSE, + DP_TEST_EDID_CHECKSUM_WRITE); + } + } else { + dev_info(dp->dev, "EDID data does not include any extensions.\n"); + + /* Read EDID data */ + retval = analogix_dp_read_bytes_from_i2c(dp, + I2C_EDID_DEVICE_ADDR, + EDID_HEADER_PATTERN, + EDID_BLOCK_LENGTH, + &edid[EDID_HEADER_PATTERN]); + if (retval != 0) { + dev_err(dp->dev, "EDID Read failed!\n"); + return -EIO; + } + sum = analogix_dp_calc_edid_check_sum(edid); + if (sum != 0) { + dev_err(dp->dev, "EDID bad checksum!\n"); + return -EIO; + } + + analogix_dp_read_byte_from_dpcd(dp, + DP_TEST_REQUEST, + &test_vector); + if (test_vector & DP_TEST_LINK_EDID_READ) { + analogix_dp_write_byte_to_dpcd(dp, + DP_TEST_EDID_CHECKSUM, + edid[EDID_CHECKSUM]); + analogix_dp_write_byte_to_dpcd(dp, + DP_TEST_RESPONSE, + DP_TEST_EDID_CHECKSUM_WRITE); + } + } + + dev_dbg(dp->dev, "EDID Read success!\n"); + return 0; +} + +static int analogix_dp_handle_edid(struct analogix_dp_device *dp) +{ + u8 buf[12]; + int i; + int retval; + + /* Read DPCD DP_DPCD_REV~RECEIVE_PORT1_CAP_1 */ + retval = analogix_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, + 12, buf); + if (retval) + return retval; + + /* Read EDID */ + for (i = 0; i < 3; i++) { + retval = analogix_dp_read_edid(dp); + if (!retval) + break; + } + + return retval; +} + +static void analogix_dp_enable_rx_to_enhanced_mode(struct analogix_dp_device *dp, + bool enable) +{ + u8 data; + + analogix_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data); + + if (enable) + analogix_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET, + DP_LANE_COUNT_ENHANCED_FRAME_EN | + DPCD_LANE_COUNT_SET(data)); + else + analogix_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET, + DPCD_LANE_COUNT_SET(data)); +} + +static int analogix_dp_is_enhanced_mode_available(struct analogix_dp_device *dp) +{ + u8 data; + int retval; + + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); + retval = DPCD_ENHANCED_FRAME_CAP(data); + + return retval; +} + +static void analogix_dp_set_enhanced_mode(struct analogix_dp_device *dp) +{ + u8 data; + + data = analogix_dp_is_enhanced_mode_available(dp); + analogix_dp_enable_rx_to_enhanced_mode(dp, data); + analogix_dp_enable_enhanced_mode(dp, data); +} + +static void analogix_dp_training_pattern_dis(struct analogix_dp_device *dp) +{ + analogix_dp_set_training_pattern(dp, DP_NONE); + + analogix_dp_write_byte_to_dpcd(dp, + DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); +} + +static void analogix_dp_set_lane_lane_pre_emphasis(struct analogix_dp_device *dp, + int pre_emphasis, int lane) +{ + switch (lane) { + case 0: + analogix_dp_set_lane0_pre_emphasis(dp, pre_emphasis); + break; + case 1: + analogix_dp_set_lane1_pre_emphasis(dp, pre_emphasis); + break; + + case 2: + analogix_dp_set_lane2_pre_emphasis(dp, pre_emphasis); + break; + + case 3: + analogix_dp_set_lane3_pre_emphasis(dp, pre_emphasis); + break; + } +} + +static int analogix_dp_link_start(struct analogix_dp_device *dp) +{ + u8 buf[4]; + int lane, lane_count, pll_tries, retval; + + lane_count = dp->link_train.lane_count; + + dp->link_train.lt_state = CLOCK_RECOVERY; + dp->link_train.eq_loop = 0; + + for (lane = 0; lane < lane_count; lane++) + dp->link_train.cr_loop[lane] = 0; + + /* Set link rate and count as you want to establish*/ + analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); + analogix_dp_set_lane_count(dp, dp->link_train.lane_count); + + /* Setup RX configuration */ + buf[0] = dp->link_train.link_rate; + buf[1] = dp->link_train.lane_count; + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, + 2, buf); + if (retval) + return retval; + + /* Set TX pre-emphasis to minimum */ + for (lane = 0; lane < lane_count; lane++) + analogix_dp_set_lane_lane_pre_emphasis(dp, + PRE_EMPHASIS_LEVEL_0, lane); + + /* Wait for PLL lock */ + pll_tries = 0; + while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + if (pll_tries == DP_TIMEOUT_LOOP_COUNT) { + dev_err(dp->dev, "Wait for PLL lock timed out\n"); + return -ETIMEDOUT; + } + + pll_tries++; + usleep_range(90, 120); + } + + /* Set training pattern 1 */ + analogix_dp_set_training_pattern(dp, TRAINING_PTN1); + + /* Set RX training pattern */ + retval = analogix_dp_write_byte_to_dpcd(dp, + DP_TRAINING_PATTERN_SET, + DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_1); + if (retval) + return retval; + + for (lane = 0; lane < lane_count; lane++) + buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 | + DP_TRAIN_VOLTAGE_SWING_LEVEL_0; + + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, + lane_count, buf); + + return retval; +} + +static unsigned char analogix_dp_get_lane_status(u8 link_status[2], int lane) +{ + int shift = (lane & 1) * 4; + u8 link_value = link_status[lane>>1]; + + return (link_value >> shift) & 0xf; +} + +static int analogix_dp_clock_recovery_ok(u8 link_status[2], int lane_count) +{ + int lane; + u8 lane_status; + + for (lane = 0; lane < lane_count; lane++) { + lane_status = analogix_dp_get_lane_status(link_status, lane); + if ((lane_status & DP_LANE_CR_DONE) == 0) + return -EINVAL; + } + return 0; +} + +static int analogix_dp_channel_eq_ok(u8 link_status[2], u8 link_align, + int lane_count) +{ + int lane; + u8 lane_status; + + if ((link_align & DP_INTERLANE_ALIGN_DONE) == 0) + return -EINVAL; + + for (lane = 0; lane < lane_count; lane++) { + lane_status = analogix_dp_get_lane_status(link_status, lane); + lane_status &= DP_CHANNEL_EQ_BITS; + if (lane_status != DP_CHANNEL_EQ_BITS) + return -EINVAL; + } + + return 0; +} + +static unsigned char analogix_dp_get_adjust_request_voltage(u8 adjust_request[2], + int lane) +{ + int shift = (lane & 1) * 4; + u8 link_value = adjust_request[lane>>1]; + + return (link_value >> shift) & 0x3; +} + +static unsigned char analogix_dp_get_adjust_request_pre_emphasis( + u8 adjust_request[2], + int lane) +{ + int shift = (lane & 1) * 4; + u8 link_value = adjust_request[lane>>1]; + + return ((link_value >> shift) & 0xc) >> 2; +} + +static void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp, + u8 training_lane_set, int lane) +{ + switch (lane) { + case 0: + analogix_dp_set_lane0_link_training(dp, training_lane_set); + break; + case 1: + analogix_dp_set_lane1_link_training(dp, training_lane_set); + break; + + case 2: + analogix_dp_set_lane2_link_training(dp, training_lane_set); + break; + + case 3: + analogix_dp_set_lane3_link_training(dp, training_lane_set); + break; + } +} + +static unsigned int analogix_dp_get_lane_link_training( + struct analogix_dp_device *dp, + int lane) +{ + u32 reg; + + switch (lane) { + case 0: + reg = analogix_dp_get_lane0_link_training(dp); + break; + case 1: + reg = analogix_dp_get_lane1_link_training(dp); + break; + case 2: + reg = analogix_dp_get_lane2_link_training(dp); + break; + case 3: + reg = analogix_dp_get_lane3_link_training(dp); + break; + default: + WARN_ON(1); + return 0; + } + + return reg; +} + +static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp) +{ + analogix_dp_training_pattern_dis(dp); + analogix_dp_set_enhanced_mode(dp); + + dp->link_train.lt_state = FAILED; +} + +static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp, + u8 adjust_request[2]) +{ + int lane, lane_count; + u8 voltage_swing, pre_emphasis, training_lane; + + lane_count = dp->link_train.lane_count; + for (lane = 0; lane < lane_count; lane++) { + voltage_swing = analogix_dp_get_adjust_request_voltage( + adjust_request, lane); + pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( + adjust_request, lane); + training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | + DPCD_PRE_EMPHASIS_SET(pre_emphasis); + + if (voltage_swing == VOLTAGE_LEVEL_3) + training_lane |= DP_TRAIN_MAX_SWING_REACHED; + if (pre_emphasis == PRE_EMPHASIS_LEVEL_3) + training_lane |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + dp->link_train.training_lane[lane] = training_lane; + } +} + +static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) +{ + int lane, lane_count, retval; + u8 voltage_swing, pre_emphasis, training_lane; + u8 link_status[2], adjust_request[2]; + + usleep_range(100, 101); + + lane_count = dp->link_train.lane_count; + + retval = analogix_dp_read_bytes_from_dpcd(dp, + DP_LANE0_1_STATUS, 2, link_status); + if (retval) + return retval; + + retval = analogix_dp_read_bytes_from_dpcd(dp, + DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request); + if (retval) + return retval; + + if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) { + /* set training pattern 2 for EQ */ + analogix_dp_set_training_pattern(dp, TRAINING_PTN2); + + retval = analogix_dp_write_byte_to_dpcd(dp, + DP_TRAINING_PATTERN_SET, + DP_LINK_SCRAMBLING_DISABLE | + DP_TRAINING_PATTERN_2); + if (retval) + return retval; + + dev_info(dp->dev, "Link Training Clock Recovery success\n"); + dp->link_train.lt_state = EQUALIZER_TRAINING; + } else { + for (lane = 0; lane < lane_count; lane++) { + training_lane = analogix_dp_get_lane_link_training( + dp, lane); + voltage_swing = analogix_dp_get_adjust_request_voltage( + adjust_request, lane); + pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( + adjust_request, lane); + + if (DPCD_VOLTAGE_SWING_GET(training_lane) == + voltage_swing && + DPCD_PRE_EMPHASIS_GET(training_lane) == + pre_emphasis) + dp->link_train.cr_loop[lane]++; + + if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP || + voltage_swing == VOLTAGE_LEVEL_3 || + pre_emphasis == PRE_EMPHASIS_LEVEL_3) { + dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", + dp->link_train.cr_loop[lane], + voltage_swing, pre_emphasis); + analogix_dp_reduce_link_rate(dp); + return -EIO; + } + } + } + + analogix_dp_get_adjust_training_lane(dp, adjust_request); + + for (lane = 0; lane < lane_count; lane++) + analogix_dp_set_lane_link_training(dp, + dp->link_train.training_lane[lane], lane); + + retval = analogix_dp_write_bytes_to_dpcd(dp, + DP_TRAINING_LANE0_SET, lane_count, + dp->link_train.training_lane); + if (retval) + return retval; + + return retval; +} + +static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) +{ + int lane, lane_count, retval; + u32 reg; + u8 link_align, link_status[2], adjust_request[2]; + + usleep_range(400, 401); + + lane_count = dp->link_train.lane_count; + + retval = analogix_dp_read_bytes_from_dpcd(dp, + DP_LANE0_1_STATUS, 2, link_status); + if (retval) + return retval; + + if (analogix_dp_clock_recovery_ok(link_status, lane_count)) { + analogix_dp_reduce_link_rate(dp); + return -EIO; + } + + retval = analogix_dp_read_bytes_from_dpcd(dp, + DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request); + if (retval) + return retval; + + retval = analogix_dp_read_byte_from_dpcd(dp, + DP_LANE_ALIGN_STATUS_UPDATED, &link_align); + if (retval) + return retval; + + analogix_dp_get_adjust_training_lane(dp, adjust_request); + + if (!analogix_dp_channel_eq_ok(link_status, link_align, lane_count)) { + /* traing pattern Set to Normal */ + analogix_dp_training_pattern_dis(dp); + + dev_info(dp->dev, "Link Training success!\n"); + + analogix_dp_get_link_bandwidth(dp, ®); + dp->link_train.link_rate = reg; + dev_dbg(dp->dev, "final bandwidth = %.2x\n", + dp->link_train.link_rate); + + analogix_dp_get_lane_count(dp, ®); + dp->link_train.lane_count = reg; + dev_dbg(dp->dev, "final lane count = %.2x\n", + dp->link_train.lane_count); + + /* set enhanced mode if available */ + analogix_dp_set_enhanced_mode(dp); + dp->link_train.lt_state = FINISHED; + + return 0; + } + + /* not all locked */ + dp->link_train.eq_loop++; + + if (dp->link_train.eq_loop > MAX_EQ_LOOP) { + dev_err(dp->dev, "EQ Max loop\n"); + analogix_dp_reduce_link_rate(dp); + return -EIO; + } + + for (lane = 0; lane < lane_count; lane++) + analogix_dp_set_lane_link_training(dp, + dp->link_train.training_lane[lane], lane); + + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, + lane_count, dp->link_train.training_lane); + + return retval; +} + +static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp, + u8 *bandwidth) +{ + u8 data; + + /* + * For DP rev.1.1, Maximum link rate of Main Link lanes + * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps + */ + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data); + *bandwidth = data; +} + +static void analogix_dp_get_max_rx_lane_count(struct analogix_dp_device *dp, + u8 *lane_count) +{ + u8 data; + + /* + * For DP rev.1.1, Maximum number of Main Link lanes + * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes + */ + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); + *lane_count = DPCD_MAX_LANE_COUNT(data); +} + +static void analogix_dp_init_training(struct analogix_dp_device *dp, + enum link_lane_count_type max_lane, + enum link_rate_type max_rate) +{ + /* + * MACRO_RST must be applied after the PLL_LOCK to avoid + * the DP inter pair skew issue for at least 10 us + */ + analogix_dp_reset_macro(dp); + + /* Initialize by reading RX's DPCD */ + analogix_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); + analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); + + if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) && + (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { + dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n", + dp->link_train.link_rate); + dp->link_train.link_rate = LINK_RATE_1_62GBPS; + } + + if (dp->link_train.lane_count == 0) { + dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n", + dp->link_train.lane_count); + dp->link_train.lane_count = (u8)LANE_COUNT1; + } + + /* Setup TX lane count & rate */ + if (dp->link_train.lane_count > max_lane) + dp->link_train.lane_count = max_lane; + if (dp->link_train.link_rate > max_rate) + dp->link_train.link_rate = max_rate; + + /* All DP analog module power up */ + analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); +} + +static int analogix_dp_sw_link_training(struct analogix_dp_device *dp) +{ + int retval = 0, training_finished = 0; + + dp->link_train.lt_state = START; + + /* Process here */ + while (!retval && !training_finished) { + switch (dp->link_train.lt_state) { + case START: + retval = analogix_dp_link_start(dp); + if (retval) + dev_err(dp->dev, "LT link start failed!\n"); + break; + case CLOCK_RECOVERY: + retval = analogix_dp_process_clock_recovery(dp); + if (retval) + dev_err(dp->dev, "LT CR failed!\n"); + break; + case EQUALIZER_TRAINING: + retval = analogix_dp_process_equalizer_training(dp); + if (retval) + dev_err(dp->dev, "LT EQ failed!\n"); + break; + case FINISHED: + training_finished = 1; + break; + case FAILED: + return -EREMOTEIO; + } + } + if (retval) + dev_err(dp->dev, "eDP link training failed (%d)\n", retval); + + return retval; +} + +static int analogix_dp_set_link_train(struct analogix_dp_device *dp, + u32 count, + u32 bwtype) +{ + int i; + int retval; + + for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) { + analogix_dp_init_training(dp, count, bwtype); + retval = analogix_dp_sw_link_training(dp); + if (retval == 0) + break; + + usleep_range(100, 110); + } + + return retval; +} + +static int analogix_dp_config_video(struct analogix_dp_device *dp) +{ + int retval = 0; + int timeout_loop = 0; + int done_count = 0; + + analogix_dp_config_video_slave_mode(dp); + + analogix_dp_set_video_color_format(dp); + + if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + dev_err(dp->dev, "PLL is not locked yet.\n"); + return -EINVAL; + } + + for (;;) { + timeout_loop++; + if (analogix_dp_is_slave_video_stream_clock_on(dp) == 0) + break; + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { + dev_err(dp->dev, "Timeout of video streamclk ok\n"); + return -ETIMEDOUT; + } + + usleep_range(1, 2); + } + + /* Set to use the register calculated M/N video */ + analogix_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0); + + /* For video bist, Video timing must be generated by register */ + analogix_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE); + + /* Disable video mute */ + analogix_dp_enable_video_mute(dp, 0); + + /* Configure video slave mode */ + analogix_dp_enable_video_master(dp, 0); + + timeout_loop = 0; + + for (;;) { + timeout_loop++; + if (analogix_dp_is_video_stream_on(dp) == 0) { + done_count++; + if (done_count > 10) + break; + } else if (done_count) { + done_count = 0; + } + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { + dev_err(dp->dev, "Timeout of video streamclk ok\n"); + return -ETIMEDOUT; + } + + usleep_range(1000, 1001); + } + + if (retval != 0) + dev_err(dp->dev, "Video stream is not detected!\n"); + + return retval; +} + +static void analogix_dp_enable_scramble(struct analogix_dp_device *dp, bool enable) +{ + u8 data; + + if (enable) { + analogix_dp_enable_scrambling(dp); + + analogix_dp_read_byte_from_dpcd(dp, + DP_TRAINING_PATTERN_SET, + &data); + analogix_dp_write_byte_to_dpcd(dp, + DP_TRAINING_PATTERN_SET, + (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE)); + } else { + analogix_dp_disable_scrambling(dp); + + analogix_dp_read_byte_from_dpcd(dp, + DP_TRAINING_PATTERN_SET, + &data); + analogix_dp_write_byte_to_dpcd(dp, + DP_TRAINING_PATTERN_SET, + (u8)(data | DP_LINK_SCRAMBLING_DISABLE)); + } +} + +static irqreturn_t analogix_dp_irq_handler(int irq, void *arg) +{ + struct analogix_dp_device *dp = arg; + + enum dp_irq_type irq_type; + + irq_type = analogix_dp_get_irq_type(dp); + switch (irq_type) { + case DP_IRQ_TYPE_HP_CABLE_IN: + dev_dbg(dp->dev, "Received irq - cable in\n"); + schedule_work(&dp->hotplug_work); + analogix_dp_clear_hotplug_interrupts(dp); + break; + case DP_IRQ_TYPE_HP_CABLE_OUT: + dev_dbg(dp->dev, "Received irq - cable out\n"); + analogix_dp_clear_hotplug_interrupts(dp); + break; + case DP_IRQ_TYPE_HP_CHANGE: + /* + * We get these change notifications once in a while, but there + * is nothing we can do with them. Just ignore it for now and + * only handle cable changes. + */ + dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n"); + analogix_dp_clear_hotplug_interrupts(dp); + break; + default: + dev_err(dp->dev, "Received irq - unknown type!\n"); + break; + } + return IRQ_HANDLED; +} + +static void analogix_dp_hotplug(struct work_struct *work) +{ + struct analogix_dp_device *dp; + + dp = container_of(work, struct analogix_dp_device, hotplug_work); + + if (dp->drm_dev) + drm_helper_hpd_irq_event(dp->drm_dev); +} + +static void analogix_dp_commit(struct analogix_dp_device *dp) +{ + int ret; + + /* Keep the panel disabled while we configure video */ + if (dp->plat_data->panel) { + if (drm_panel_disable(dp->plat_data->panel)) + DRM_ERROR("failed to disable the panel\n"); + } + + ret = analogix_dp_detect_hpd(dp); + if (ret) { + /* Cable has been disconnected, we're done */ + return; + } + + ret = analogix_dp_handle_edid(dp); + if (ret) { + dev_err(dp->dev, "unable to handle edid\n"); + return; + } + + ret = analogix_dp_set_link_train(dp, dp->video_info->lane_count, + dp->video_info->link_rate); + if (ret) { + dev_err(dp->dev, "unable to do link train\n"); + return; + } + + analogix_dp_enable_scramble(dp, 1); + analogix_dp_enable_rx_to_enhanced_mode(dp, 1); + analogix_dp_enable_enhanced_mode(dp, 1); + + analogix_dp_set_lane_count(dp, dp->video_info->lane_count); + analogix_dp_set_link_bandwidth(dp, dp->video_info->link_rate); + + analogix_dp_init_video(dp); + ret = analogix_dp_config_video(dp); + if (ret) + dev_err(dp->dev, "unable to config video\n"); + + /* Safe to enable the panel now */ + if (dp->plat_data->panel) { + if (drm_panel_enable(dp->plat_data->panel)) + DRM_ERROR("failed to enable the panel\n"); + } + + /* Enable video */ + analogix_dp_start_video(dp); +} + +int analogix_dp_get_modes(struct drm_connector *connector) +{ + struct analogix_dp_device *dp = to_dp(connector); + int num_modes = 0; + + if (dp->plat_data->panel) + num_modes += drm_panel_get_modes(dp->plat_data->panel); + + if (dp->plat_data->get_modes) + num_modes += dp->plat_data->get_modes(dp->plat_data); + + return num_modes; +} + +static struct drm_encoder * +analogix_dp_best_encoder(struct drm_connector *connector) +{ + struct analogix_dp_device *dp = to_dp(connector); + + return dp->encoder; +} + +static const struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = { + .get_modes = analogix_dp_get_modes, + .best_encoder = analogix_dp_best_encoder, +}; + +enum drm_connector_status +analogix_dp_detect(struct drm_connector *connector, bool force) +{ + return connector_status_connected; +} + +static void analogix_dp_connector_destroy(struct drm_connector *connector) +{ + drm_connector_unregister(connector); + drm_connector_cleanup(connector); +} + +static const struct drm_connector_funcs analogix_dp_connector_funcs = { + .dpms = drm_atomic_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = analogix_dp_detect, + .destroy = analogix_dp_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int analogix_dp_bridge_attach(struct drm_bridge *bridge) +{ + struct analogix_dp_device *dp = bridge->driver_private; + struct drm_encoder *encoder = dp->encoder; + struct drm_connector *connector = &dp->connector; + int ret; + + if (!bridge->encoder) { + DRM_ERROR("Parent encoder object not found"); + return -ENODEV; + } + + connector->polled = DRM_CONNECTOR_POLL_HPD; + + ret = drm_connector_init(dp->drm_dev, connector, + &analogix_dp_connector_funcs, + DRM_MODE_CONNECTOR_eDP); + if (ret) { + DRM_ERROR("Failed to initialize connector with drm\n"); + return ret; + } + + drm_connector_helper_add(connector, + &analogix_dp_connector_helper_funcs); + drm_mode_connector_attach_encoder(connector, encoder); + + /* + * NOTE: the connector registration is implemented in analogix + * platform driver, that to say connector would be exist after + * plat_data->attch return, that's why we record the connector + * point after plat attached. + */ + if (dp->plat_data->attach) { + ret = dp->plat_data->attach(dp->plat_data, bridge, connector); + if (ret) { + DRM_ERROR("Failed at platform attch func\n"); + return ret; + } + } + + if (dp->plat_data->panel) { + ret = drm_panel_attach(dp->plat_data->panel, &dp->connector); + if (ret) { + DRM_ERROR("Failed to attach panel\n"); + return ret; + } + } + + return 0; +} + +static void analogix_dp_bridge_enable(struct drm_bridge *bridge) +{ + struct analogix_dp_device *dp = bridge->driver_private; + + if (dp->dpms_mode == DRM_MODE_DPMS_ON) + return; + + pm_runtime_get_sync(dp->dev); + + if (dp->plat_data->panel) { + if (drm_panel_prepare(dp->plat_data->panel)) { + DRM_ERROR("failed to setup the panel\n"); + return; + } + } + + if (dp->plat_data->power_on) + dp->plat_data->power_on(dp->plat_data); + + phy_power_on(dp->phy); + analogix_dp_init_dp(dp); + enable_irq(dp->irq); + analogix_dp_commit(dp); + + dp->dpms_mode = DRM_MODE_DPMS_ON; +} + +static void analogix_dp_bridge_disable(struct drm_bridge *bridge) +{ + struct analogix_dp_device *dp = bridge->driver_private; + + if (dp->dpms_mode != DRM_MODE_DPMS_ON) + return; + + if (dp->plat_data->panel) { + if (drm_panel_disable(dp->plat_data->panel)) { + DRM_ERROR("failed to disable the panel\n"); + return; + } + } + + disable_irq(dp->irq); + flush_work(&dp->hotplug_work); + phy_power_off(dp->phy); + + if (dp->plat_data->power_off) + dp->plat_data->power_off(dp->plat_data); + + if (dp->plat_data->panel) { + if (drm_panel_unprepare(dp->plat_data->panel)) + DRM_ERROR("failed to turnoff the panel\n"); + } + + pm_runtime_put_sync(dp->dev); + + dp->dpms_mode = DRM_MODE_DPMS_OFF; +} + +static void analogix_dp_bridge_nop(struct drm_bridge *bridge) +{ + /* do nothing */ +} + +static const struct drm_bridge_funcs analogix_dp_bridge_funcs = { + .enable = analogix_dp_bridge_enable, + .disable = analogix_dp_bridge_disable, + .pre_enable = analogix_dp_bridge_nop, + .post_disable = analogix_dp_bridge_nop, + .attach = analogix_dp_bridge_attach, +}; + +static int analogix_dp_create_bridge(struct drm_device *drm_dev, + struct analogix_dp_device *dp) +{ + struct drm_bridge *bridge; + int ret; + + bridge = devm_kzalloc(drm_dev->dev, sizeof(*bridge), GFP_KERNEL); + if (!bridge) { + DRM_ERROR("failed to allocate for drm bridge\n"); + return -ENOMEM; + } + + dp->bridge = bridge; + + dp->encoder->bridge = bridge; + bridge->driver_private = dp; + bridge->encoder = dp->encoder; + bridge->funcs = &analogix_dp_bridge_funcs; + + ret = drm_bridge_attach(drm_dev, bridge); + if (ret) { + DRM_ERROR("failed to attach drm bridge\n"); + return -EINVAL; + } + + return 0; +} + +static struct video_info *analogix_dp_dt_parse_pdata(struct device *dev) +{ + struct device_node *dp_node = dev->of_node; + struct video_info *dp_video_config; + + dp_video_config = devm_kzalloc(dev, + sizeof(*dp_video_config), GFP_KERNEL); + if (!dp_video_config) + return ERR_PTR(-ENOMEM); + + dp_video_config->h_sync_polarity = + of_property_read_bool(dp_node, "hsync-active-high"); + + dp_video_config->v_sync_polarity = + of_property_read_bool(dp_node, "vsync-active-high"); + + dp_video_config->interlaced = + of_property_read_bool(dp_node, "interlaced"); + + if (of_property_read_u32(dp_node, "samsung,color-space", + &dp_video_config->color_space)) { + dev_err(dev, "failed to get color-space\n"); + return ERR_PTR(-EINVAL); + } + + if (of_property_read_u32(dp_node, "samsung,dynamic-range", + &dp_video_config->dynamic_range)) { + dev_err(dev, "failed to get dynamic-range\n"); + return ERR_PTR(-EINVAL); + } + + if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff", + &dp_video_config->ycbcr_coeff)) { + dev_err(dev, "failed to get ycbcr-coeff\n"); + return ERR_PTR(-EINVAL); + } + + if (of_property_read_u32(dp_node, "samsung,color-depth", + &dp_video_config->color_depth)) { + dev_err(dev, "failed to get color-depth\n"); + return ERR_PTR(-EINVAL); + } + + if (of_property_read_u32(dp_node, "samsung,link-rate", + &dp_video_config->link_rate)) { + dev_err(dev, "failed to get link-rate\n"); + return ERR_PTR(-EINVAL); + } + + if (of_property_read_u32(dp_node, "samsung,lane-count", + &dp_video_config->lane_count)) { + dev_err(dev, "failed to get lane-count\n"); + return ERR_PTR(-EINVAL); + } + + return dp_video_config; +} + +int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, + struct analogix_dp_plat_data *plat_data) +{ + struct platform_device *pdev = to_platform_device(dev); + struct analogix_dp_device *dp; + struct resource *res; + unsigned int irq_flags; + int ret; + + if (!plat_data) { + dev_err(dev, "Invalided input plat_data\n"); + return -EINVAL; + } + + dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); + if (!dp) + return -ENOMEM; + + dev_set_drvdata(dev, dp); + + dp->dev = &pdev->dev; + dp->dpms_mode = DRM_MODE_DPMS_OFF; + + /* + * platform dp driver need containor_of the plat_data to get + * the driver private data, so we need to store the point of + * plat_data, not the context of plat_data. + */ + dp->plat_data = plat_data; + + dp->video_info = analogix_dp_dt_parse_pdata(&pdev->dev); + if (IS_ERR(dp->video_info)) + return PTR_ERR(dp->video_info); + + dp->phy = devm_phy_get(dp->dev, "dp"); + if (IS_ERR(dp->phy)) { + dev_err(dp->dev, "no DP phy configured\n"); + ret = PTR_ERR(dp->phy); + if (ret) { + /* + * phy itself is not enabled, so we can move forward + * assigning NULL to phy pointer. + */ + if (ret == -ENOSYS || ret == -ENODEV) + dp->phy = NULL; + else + return ret; + } + } + + dp->clock = devm_clk_get(&pdev->dev, "dp"); + if (IS_ERR(dp->clock)) { + dev_err(&pdev->dev, "failed to get clock\n"); + return PTR_ERR(dp->clock); + } + + clk_prepare_enable(dp->clock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + dp->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dp->reg_base)) + return PTR_ERR(dp->reg_base); + + dp->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpios", 0); + if (!gpio_is_valid(dp->hpd_gpio)) + dp->hpd_gpio = of_get_named_gpio(dev->of_node, + "samsung,hpd-gpio", 0); + + if (gpio_is_valid(dp->hpd_gpio)) { + /* + * Set up the hotplug GPIO from the device tree as an interrupt. + * Simply specifying a different interrupt in the device tree + * doesn't work since we handle hotplug rather differently when + * using a GPIO. We also need the actual GPIO specifier so + * that we can get the current state of the GPIO. + */ + ret = devm_gpio_request_one(&pdev->dev, dp->hpd_gpio, GPIOF_IN, + "hpd_gpio"); + if (ret) { + dev_err(&pdev->dev, "failed to get hpd gpio\n"); + return ret; + } + dp->irq = gpio_to_irq(dp->hpd_gpio); + irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + } else { + dp->hpd_gpio = -ENODEV; + dp->irq = platform_get_irq(pdev, 0); + irq_flags = 0; + } + + if (dp->irq == -ENXIO) { + dev_err(&pdev->dev, "failed to get irq\n"); + return -ENODEV; + } + + INIT_WORK(&dp->hotplug_work, analogix_dp_hotplug); + + pm_runtime_enable(dev); + + ret = devm_request_irq(&pdev->dev, dp->irq, analogix_dp_irq_handler, + irq_flags, "analogix-dp", dp); + if (ret) { + dev_err(&pdev->dev, "failed to request irq\n"); + goto err_disable_pm_runtime; + } + disable_irq(dp->irq); + + dp->drm_dev = drm_dev; + dp->encoder = dp->plat_data->encoder; + + ret = analogix_dp_create_bridge(drm_dev, dp); + if (ret) { + DRM_ERROR("failed to create bridge (%d)\n", ret); + drm_encoder_cleanup(dp->encoder); + goto err_disable_pm_runtime; + } + + return 0; + +err_disable_pm_runtime: + pm_runtime_disable(dev); + + return ret; +} +EXPORT_SYMBOL_GPL(analogix_dp_bind); + +void analogix_dp_unbind(struct device *dev, struct device *master, + void *data) +{ + struct analogix_dp_device *dp = dev_get_drvdata(dev); + + analogix_dp_bridge_disable(dp->bridge); + pm_runtime_disable(dev); +} +EXPORT_SYMBOL_GPL(analogix_dp_unbind); + +#ifdef CONFIG_PM +int analogix_dp_suspend(struct device *dev) +{ + struct analogix_dp_device *dp = dev_get_drvdata(dev); + + clk_disable_unprepare(dp->clock); + return 0; +} +EXPORT_SYMBOL_GPL(analogix_dp_suspend); + +int analogix_dp_resume(struct device *dev) +{ + struct analogix_dp_device *dp = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(dp->clock); + if (ret < 0) { + DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(analogix_dp_resume); +#endif + +MODULE_AUTHOR("Jingoo Han "); +MODULE_DESCRIPTION("Analogix DP Core Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h new file mode 100644 index 0000000..0fff745 --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -0,0 +1,277 @@ +/* + * Header file for Analogix DP (Display Port) core interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef _ANALOGIX_DP_CORE_H +#define _ANALOGIX_DP_CORE_H + +#include +#include + +#define DP_TIMEOUT_LOOP_COUNT 100 +#define MAX_CR_LOOP 5 +#define MAX_EQ_LOOP 5 + +enum link_rate_type { + LINK_RATE_1_62GBPS = 0x06, + LINK_RATE_2_70GBPS = 0x0a +}; + +enum link_lane_count_type { + LANE_COUNT1 = 1, + LANE_COUNT2 = 2, + LANE_COUNT4 = 4 +}; + +enum link_training_state { + START, + CLOCK_RECOVERY, + EQUALIZER_TRAINING, + FINISHED, + FAILED +}; + +enum voltage_swing_level { + VOLTAGE_LEVEL_0, + VOLTAGE_LEVEL_1, + VOLTAGE_LEVEL_2, + VOLTAGE_LEVEL_3, +}; + +enum pre_emphasis_level { + PRE_EMPHASIS_LEVEL_0, + PRE_EMPHASIS_LEVEL_1, + PRE_EMPHASIS_LEVEL_2, + PRE_EMPHASIS_LEVEL_3, +}; + +enum pattern_set { + PRBS7, + D10_2, + TRAINING_PTN1, + TRAINING_PTN2, + DP_NONE +}; + +enum color_space { + COLOR_RGB, + COLOR_YCBCR422, + COLOR_YCBCR444 +}; + +enum color_depth { + COLOR_6, + COLOR_8, + COLOR_10, + COLOR_12 +}; + +enum color_coefficient { + COLOR_YCBCR601, + COLOR_YCBCR709 +}; + +enum dynamic_range { + VESA, + CEA +}; + +enum pll_status { + PLL_UNLOCKED, + PLL_LOCKED +}; + +enum clock_recovery_m_value_type { + CALCULATED_M, + REGISTER_M +}; + +enum video_timing_recognition_type { + VIDEO_TIMING_FROM_CAPTURE, + VIDEO_TIMING_FROM_REGISTER +}; + +enum analog_power_block { + AUX_BLOCK, + CH0_BLOCK, + CH1_BLOCK, + CH2_BLOCK, + CH3_BLOCK, + ANALOG_TOTAL, + POWER_ALL +}; + +enum dp_irq_type { + DP_IRQ_TYPE_HP_CABLE_IN, + DP_IRQ_TYPE_HP_CABLE_OUT, + DP_IRQ_TYPE_HP_CHANGE, + DP_IRQ_TYPE_UNKNOWN, +}; + +struct video_info { + char *name; + + bool h_sync_polarity; + bool v_sync_polarity; + bool interlaced; + + enum color_space color_space; + enum dynamic_range dynamic_range; + enum color_coefficient ycbcr_coeff; + enum color_depth color_depth; + + enum link_rate_type link_rate; + enum link_lane_count_type lane_count; +}; + +struct link_train { + int eq_loop; + int cr_loop[4]; + + u8 link_rate; + u8 lane_count; + u8 training_lane[4]; + + enum link_training_state lt_state; +}; + +struct analogix_dp_device { + struct drm_encoder *encoder; + struct device *dev; + struct drm_device *drm_dev; + struct drm_connector connector; + struct drm_bridge *bridge; + struct clk *clock; + unsigned int irq; + void __iomem *reg_base; + + struct video_info *video_info; + struct link_train link_train; + struct work_struct hotplug_work; + struct phy *phy; + int dpms_mode; + int hpd_gpio; + + struct analogix_dp_plat_data *plat_data; +}; + +/* analogix_dp_reg.c */ +void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable); +void analogix_dp_stop_video(struct analogix_dp_device *dp); +void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable); +void analogix_dp_init_analog_param(struct analogix_dp_device *dp); +void analogix_dp_init_interrupt(struct analogix_dp_device *dp); +void analogix_dp_reset(struct analogix_dp_device *dp); +void analogix_dp_swreset(struct analogix_dp_device *dp); +void analogix_dp_config_interrupt(struct analogix_dp_device *dp); +enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp); +void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable); +void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, + enum analog_power_block block, + bool enable); +void analogix_dp_init_analog_func(struct analogix_dp_device *dp); +void analogix_dp_init_hpd(struct analogix_dp_device *dp); +enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp); +void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp); +void analogix_dp_reset_aux(struct analogix_dp_device *dp); +void analogix_dp_init_aux(struct analogix_dp_device *dp); +int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp); +void analogix_dp_enable_sw_function(struct analogix_dp_device *dp); +int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp); +int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char data); +int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char *data); +int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +int analogix_dp_select_i2c_device(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr); +int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int *data); +int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int count, + unsigned char edid[]); +void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype); +void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype); +void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count); +void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count); +void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, bool enable); +void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, + enum pattern_set pattern); +void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, u32 level); +void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, u32 level); +void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, u32 level); +void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, u32 level); +void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, + u32 training_lane); +void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, + u32 training_lane); +void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, + u32 training_lane); +void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, + u32 training_lane); +u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp); +void analogix_dp_reset_macro(struct analogix_dp_device *dp); +void analogix_dp_init_video(struct analogix_dp_device *dp); + +void analogix_dp_set_video_color_format(struct analogix_dp_device *dp); +int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp); +void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp, + enum clock_recovery_m_value_type type, + u32 m_value, + u32 n_value); +void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type); +void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable); +void analogix_dp_start_video(struct analogix_dp_device *dp); +int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp); +void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp); +void analogix_dp_enable_scrambling(struct analogix_dp_device *dp); +void analogix_dp_disable_scrambling(struct analogix_dp_device *dp); + +/* I2C EDID Chip ID, Slave Address */ +#define I2C_EDID_DEVICE_ADDR 0x50 +#define I2C_E_EDID_DEVICE_ADDR 0x30 + +#define EDID_BLOCK_LENGTH 0x80 +#define EDID_HEADER_PATTERN 0x00 +#define EDID_EXTENSION_FLAG 0x7e +#define EDID_CHECKSUM 0x7f + +/* DP_MAX_LANE_COUNT */ +#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) +#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) + +/* DP_LANE_COUNT_SET */ +#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f) + +/* DP_TRAINING_LANE0_SET */ +#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3) +#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3) +#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0) +#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3) + +#endif /* _ANALOGIX_DP_CORE_H */ diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c new file mode 100644 index 0000000..0b926ea --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -0,0 +1,1263 @@ +/* + * Analogix DP (Display port) core register interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include + +#include "analogix_dp_core.h" +#include "analogix_dp_reg.h" + +#define COMMON_INT_MASK_1 0 +#define COMMON_INT_MASK_2 0 +#define COMMON_INT_MASK_3 0 +#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG) +#define INT_STA_MASK INT_HPD + +void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); + reg |= HDCP_VIDEO_MUTE; + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); + reg &= ~HDCP_VIDEO_MUTE; + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); + } +} + +void analogix_dp_stop_video(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); + reg &= ~VIDEO_EN; + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); +} + +void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) + reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 | + LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3; + else + reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 | + LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0; + + writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP); +} + +void analogix_dp_init_analog_param(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = TX_TERMINAL_CTRL_50_OHM; + writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1); + + reg = SEL_24M | TX_DVDD_BIT_1_0625V; + writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2); + + reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO; + writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3); + + reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | + TX_CUR1_2X | TX_CUR_16_MA; + writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1); + + reg = CH3_AMP_400_MV | CH2_AMP_400_MV | + CH1_AMP_400_MV | CH0_AMP_400_MV; + writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL); +} + +void analogix_dp_init_interrupt(struct analogix_dp_device *dp) +{ + /* Set interrupt pin assertion polarity as high */ + writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL); + + /* Clear pending regisers */ + writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1); + writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2); + writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3); + writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4); + writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA); + + /* 0:mask,1: unmask */ + writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1); + writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2); + writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3); + writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4); + writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK); +} + +void analogix_dp_reset(struct analogix_dp_device *dp) +{ + u32 reg; + + analogix_dp_stop_video(dp); + analogix_dp_enable_video_mute(dp, 0); + + reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N | + AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N | + HDCP_FUNC_EN_N | SW_FUNC_EN_N; + writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1); + + reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N | + SERDES_FIFO_FUNC_EN_N | + LS_CLK_DOMAIN_FUNC_EN_N; + writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2); + + usleep_range(20, 30); + + analogix_dp_lane_swap(dp, 0); + + writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1); + writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2); + writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3); + writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4); + + writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL); + writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL); + + writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L); + writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H); + + writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL); + + writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST); + + writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD); + writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN); + + writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH); + writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH); + + writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); +} + +void analogix_dp_swreset(struct analogix_dp_device *dp) +{ + writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET); +} + +void analogix_dp_config_interrupt(struct analogix_dp_device *dp) +{ + u32 reg; + + /* 0: mask, 1: unmask */ + reg = COMMON_INT_MASK_1; + writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1); + + reg = COMMON_INT_MASK_2; + writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2); + + reg = COMMON_INT_MASK_3; + writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3); + + reg = COMMON_INT_MASK_4; + writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4); + + reg = INT_STA_MASK; + writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK); +} + +enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL); + if (reg & PLL_LOCK) + return PLL_LOCKED; + else + return PLL_UNLOCKED; +} + +void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL); + reg |= DP_PLL_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL); + reg &= ~DP_PLL_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL); + } +} + +void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, + enum analog_power_block block, + bool enable) +{ + u32 reg; + + switch (block) { + case AUX_BLOCK: + if (enable) { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg |= AUX_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg &= ~AUX_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } + break; + case CH0_BLOCK: + if (enable) { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg |= CH0_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg &= ~CH0_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } + break; + case CH1_BLOCK: + if (enable) { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg |= CH1_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg &= ~CH1_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } + break; + case CH2_BLOCK: + if (enable) { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg |= CH2_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg &= ~CH2_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } + break; + case CH3_BLOCK: + if (enable) { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg |= CH3_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg &= ~CH3_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } + break; + case ANALOG_TOTAL: + if (enable) { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg |= DP_PHY_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); + reg &= ~DP_PHY_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } + break; + case POWER_ALL: + if (enable) { + reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD | + CH1_PD | CH0_PD; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); + } else { + writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD); + } + break; + default: + break; + } +} + +void analogix_dp_init_analog_func(struct analogix_dp_device *dp) +{ + u32 reg; + int timeout_loop = 0; + + analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); + + reg = PLL_LOCK_CHG; + writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1); + + reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL); + reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL); + writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL); + + /* Power up PLL */ + if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + analogix_dp_set_pll_power_down(dp, 0); + + while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + timeout_loop++; + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { + dev_err(dp->dev, "failed to get pll lock status\n"); + return; + } + usleep_range(10, 20); + } + } + + /* Enable Serdes FIFO function and Link symbol clock domain module */ + reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2); + reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N + | AUX_FUNC_EN_N); + writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2); +} + +void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) + return; + + reg = HOTPLUG_CHG | HPD_LOST | PLUG; + writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4); + + reg = INT_HPD; + writel(reg, dp->reg_base + EXYNOS_DP_INT_STA); +} + +void analogix_dp_init_hpd(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) + return; + + analogix_dp_clear_hotplug_interrupts(dp); + + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); + reg &= ~(F_HPD | HPD_CTRL); + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3); +} + +enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) { + reg = gpio_get_value(dp->hpd_gpio); + if (reg) + return DP_IRQ_TYPE_HP_CABLE_IN; + else + return DP_IRQ_TYPE_HP_CABLE_OUT; + } else { + /* Parse hotplug interrupt status register */ + reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4); + + if (reg & PLUG) + return DP_IRQ_TYPE_HP_CABLE_IN; + + if (reg & HPD_LOST) + return DP_IRQ_TYPE_HP_CABLE_OUT; + + if (reg & HOTPLUG_CHG) + return DP_IRQ_TYPE_HP_CHANGE; + + return DP_IRQ_TYPE_UNKNOWN; + } +} + +void analogix_dp_reset_aux(struct analogix_dp_device *dp) +{ + u32 reg; + + /* Disable AUX channel module */ + reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2); + reg |= AUX_FUNC_EN_N; + writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2); +} + +void analogix_dp_init_aux(struct analogix_dp_device *dp) +{ + u32 reg; + + /* Clear inerrupts related to AUX channel */ + reg = RPLY_RECEIV | AUX_ERR; + writel(reg, dp->reg_base + EXYNOS_DP_INT_STA); + + analogix_dp_reset_aux(dp); + + /* Disable AUX transaction H/W retry */ + reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)| + AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; + writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL); + + /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */ + reg = DEFER_CTRL_EN | DEFER_COUNT(1); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL); + + /* Enable AUX channel module */ + reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2); + reg &= ~AUX_FUNC_EN_N; + writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2); +} + +int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) { + if (gpio_get_value(dp->hpd_gpio)) + return 0; + } else { + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); + if (reg & HPD_STATUS) + return 0; + } + + return -EINVAL; +} + +void analogix_dp_enable_sw_function(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1); + reg &= ~SW_FUNC_EN_N; + writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1); +} + +int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp) +{ + int reg; + int retval = 0; + int timeout_loop = 0; + + /* Enable AUX CH operation */ + reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2); + reg |= AUX_EN; + writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2); + + /* Is AUX CH command reply received? */ + reg = readl(dp->reg_base + EXYNOS_DP_INT_STA); + while (!(reg & RPLY_RECEIV)) { + timeout_loop++; + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { + dev_err(dp->dev, "AUX CH command reply failed!\n"); + return -ETIMEDOUT; + } + reg = readl(dp->reg_base + EXYNOS_DP_INT_STA); + usleep_range(10, 11); + } + + /* Clear interrupt source for AUX CH command reply */ + writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA); + + /* Clear interrupt source for AUX CH access error */ + reg = readl(dp->reg_base + EXYNOS_DP_INT_STA); + if (reg & AUX_ERR) { + writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA); + return -EREMOTEIO; + } + + /* Check AUX CH error access status */ + reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA); + if ((reg & AUX_STATUS_MASK) != 0) { + dev_err(dp->dev, "AUX CH error happens: %d\n\n", + reg & AUX_STATUS_MASK); + return -EREMOTEIO; + } + + return retval; +} + +int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char data) +{ + u32 reg; + int i; + int retval; + + for (i = 0; i < 3; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); + + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16); + + /* Write data buffer */ + reg = (unsigned int)data; + writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0); + + /* + * Set DisplayPort transaction and write 1 byte + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; + writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + else + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + + return retval; +} + +int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char *data) +{ + u32 reg; + int i; + int retval; + + for (i = 0; i < 3; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); + + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16); + + /* + * Set DisplayPort transaction and read 1 byte + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; + writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + else + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + + /* Read data buffer */ + reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0); + *data = (unsigned char)(reg & 0xff); + + return retval; +} + +int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) +{ + u32 reg; + unsigned int start_offset; + unsigned int cur_data_count; + unsigned int cur_data_idx; + int i; + int retval = 0; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); + + start_offset = 0; + while (start_offset < count) { + /* Buffer size of AUX CH is 16 * 4bytes */ + if ((count - start_offset) > 16) + cur_data_count = 16; + else + cur_data_count = count - start_offset; + + for (i = 0; i < 3; i++) { + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr + start_offset); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr + start_offset); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr + start_offset); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16); + + for (cur_data_idx = 0; cur_data_idx < cur_data_count; + cur_data_idx++) { + reg = data[start_offset + cur_data_idx]; + writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0 + + 4 * cur_data_idx); + } + + /* + * Set DisplayPort transaction and write + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_LENGTH(cur_data_count) | + AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; + writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + else + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + + start_offset += cur_data_count; + } + + return retval; +} + +int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) +{ + u32 reg; + unsigned int start_offset; + unsigned int cur_data_count; + unsigned int cur_data_idx; + int i; + int retval = 0; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); + + start_offset = 0; + while (start_offset < count) { + /* Buffer size of AUX CH is 16 * 4bytes */ + if ((count - start_offset) > 16) + cur_data_count = 16; + else + cur_data_count = count - start_offset; + + /* AUX CH Request Transaction process */ + for (i = 0; i < 3; i++) { + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr + start_offset); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr + start_offset); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr + start_offset); + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16); + + /* + * Set DisplayPort transaction and read + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_LENGTH(cur_data_count) | + AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; + writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + else + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + + for (cur_data_idx = 0; cur_data_idx < cur_data_count; + cur_data_idx++) { + reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0 + + 4 * cur_data_idx); + data[start_offset + cur_data_idx] = + (unsigned char)reg; + } + + start_offset += cur_data_count; + } + + return retval; +} + +int analogix_dp_select_i2c_device(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr) +{ + u32 reg; + int retval; + + /* Set EDID device address */ + reg = device_addr; + writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); + writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8); + writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16); + + /* Set offset from base address of EDID device */ + writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0); + + /* + * Set I2C transaction and write address + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT | + AUX_TX_COMM_WRITE; + writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval != 0) + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); + + return retval; +} + +int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int *data) +{ + u32 reg; + int i; + int retval; + + for (i = 0; i < 3; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); + + /* Select EDID device */ + retval = analogix_dp_select_i2c_device(dp, device_addr, reg_addr); + if (retval != 0) + continue; + + /* + * Set I2C transaction and read data + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_I2C_TRANSACTION | + AUX_TX_COMM_READ; + writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + else + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + + /* Read data */ + if (retval == 0) + *data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0); + + return retval; +} + +int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int count, + unsigned char edid[]) +{ + u32 reg; + unsigned int i, j; + unsigned int cur_data_idx; + unsigned int defer = 0; + int retval = 0; + + for (i = 0; i < count; i += 16) { + for (j = 0; j < 3; j++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); + + /* Set normal AUX CH command */ + reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2); + reg &= ~ADDR_ONLY; + writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2); + + /* + * If Rx sends defer, Tx sends only reads + * request without sending address + */ + if (!defer) + retval = analogix_dp_select_i2c_device(dp, + device_addr, reg_addr + i); + else + defer = 0; + + if (retval == 0) { + /* + * Set I2C transaction and write data + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_LENGTH(16) | + AUX_TX_COMM_I2C_TRANSACTION | + AUX_TX_COMM_READ; + writel(reg, dp->reg_base + + EXYNOS_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + else + dev_dbg(dp->dev, + "%s: Aux Transaction fail!\n", + __func__); + } + /* Check if Rx sends defer */ + reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM); + if (reg == AUX_RX_COMM_AUX_DEFER || + reg == AUX_RX_COMM_I2C_DEFER) { + dev_err(dp->dev, "Defer: %d\n\n", reg); + defer = 1; + } + } + + for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) { + reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0 + + 4 * cur_data_idx); + edid[i + cur_data_idx] = (unsigned char)reg; + } + } + + return retval; +} + +void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype) +{ + u32 reg; + + reg = bwtype; + if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS)) + writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET); +} + +void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET); + *bwtype = reg; +} + +void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count) +{ + u32 reg; + + reg = count; + writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET); +} + +void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET); + *count = reg; +} + +void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4); + reg |= ENHANCED; + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4); + reg &= ~ENHANCED; + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4); + } +} + +void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, + enum pattern_set pattern) +{ + u32 reg; + + switch (pattern) { + case PRBS7: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7; + writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); + break; + case D10_2: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2; + writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); + break; + case TRAINING_PTN1: + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1; + writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); + break; + case TRAINING_PTN2: + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2; + writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); + break; + case DP_NONE: + reg = SCRAMBLING_ENABLE | + LINK_QUAL_PATTERN_SET_DISABLE | + SW_TRAINING_PATTERN_SET_NORMAL; + writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); + break; + default: + break; + } +} + +void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL); +} + +u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL); + return reg; +} + +u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL); + return reg; +} + +u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL); + return reg; +} + +u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL); + return reg; +} + +void analogix_dp_reset_macro(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST); + reg |= MACRO_RST; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST); + + /* 10 us is the minimum reset time. */ + usleep_range(10, 20); + + reg &= ~MACRO_RST; + writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST); +} + +void analogix_dp_init_video(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; + writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1); + + reg = 0x0; + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1); + + reg = CHA_CRI(4) | CHA_CTRL; + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2); + + reg = 0x0; + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3); + + reg = VID_HRES_TH(2) | VID_VRES_TH(0); + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8); +} + +void analogix_dp_set_video_color_format(struct analogix_dp_device *dp) +{ + u32 reg; + + /* Configure the input color depth, color space, dynamic range */ + reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) | + (dp->video_info->color_depth << IN_BPC_SHIFT) | + (dp->video_info->color_space << IN_COLOR_F_SHIFT); + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2); + + /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ + reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3); + reg &= ~IN_YC_COEFFI_MASK; + if (dp->video_info->ycbcr_coeff) + reg |= IN_YC_COEFFI_ITU709; + else + reg |= IN_YC_COEFFI_ITU601; + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3); +} + +int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1); + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1); + + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1); + + if (!(reg & DET_STA)) { + dev_dbg(dp->dev, "Input stream clock not detected.\n"); + return -EINVAL; + } + + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2); + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2); + + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2); + dev_dbg(dp->dev, "wait SYS_CTL_2.\n"); + + if (reg & CHA_STA) { + dev_dbg(dp->dev, "Input stream clk is changing\n"); + return -EINVAL; + } + + return 0; +} + +void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp, + enum clock_recovery_m_value_type type, + u32 m_value, + u32 n_value) +{ + u32 reg; + + if (type == REGISTER_M) { + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4); + reg |= FIX_M_VID; + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4); + reg = m_value & 0xff; + writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0); + reg = (m_value >> 8) & 0xff; + writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1); + reg = (m_value >> 16) & 0xff; + writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2); + + reg = n_value & 0xff; + writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0); + reg = (n_value >> 8) & 0xff; + writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1); + reg = (n_value >> 16) & 0xff; + writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4); + reg &= ~FIX_M_VID; + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4); + + writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0); + writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1); + writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2); + } +} + +void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type) +{ + u32 reg; + + if (type == VIDEO_TIMING_FROM_CAPTURE) { + reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); + reg &= ~FORMAT_SEL; + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); + reg |= FORMAT_SEL; + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); + } +} + +void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); + reg &= ~VIDEO_MODE_MASK; + reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE; + writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); + } else { + reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); + reg &= ~VIDEO_MODE_MASK; + reg |= VIDEO_MODE_SLAVE_MODE; + writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); + } +} + +void analogix_dp_start_video(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); + reg |= VIDEO_EN; + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); +} + +int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); + writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3); + + reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); + if (!(reg & STRM_VALID)) { + dev_dbg(dp->dev, "Input video stream is not detected.\n"); + return -EINVAL; + } + + return 0; +} + +void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1); + reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N); + reg |= MASTER_VID_FUNC_EN_N; + writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1); + + reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); + reg &= ~INTERACE_SCAN_CFG; + reg |= (dp->video_info->interlaced << 2); + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); + + reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); + reg &= ~VSYNC_POLARITY_CFG; + reg |= (dp->video_info->v_sync_polarity << 1); + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); + + reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); + reg &= ~HSYNC_POLARITY_CFG; + reg |= (dp->video_info->h_sync_polarity << 0); + writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); + + reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; + writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); +} + +void analogix_dp_enable_scrambling(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); + reg &= ~SCRAMBLING_DISABLE; + writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); +} + +void analogix_dp_disable_scrambling(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); + reg |= SCRAMBLING_DISABLE; + writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); +} diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h new file mode 100644 index 0000000..b9661c9 --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h @@ -0,0 +1,366 @@ +/* + * Register definition file for Analogix DP core driver + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef _ANALOGIX_DP_REG_H +#define _ANALOGIX_DP_REG_H + +#define EXYNOS_DP_TX_SW_RESET 0x14 +#define EXYNOS_DP_FUNC_EN_1 0x18 +#define EXYNOS_DP_FUNC_EN_2 0x1C +#define EXYNOS_DP_VIDEO_CTL_1 0x20 +#define EXYNOS_DP_VIDEO_CTL_2 0x24 +#define EXYNOS_DP_VIDEO_CTL_3 0x28 + +#define EXYNOS_DP_VIDEO_CTL_8 0x3C +#define EXYNOS_DP_VIDEO_CTL_10 0x44 + +#define EXYNOS_DP_LANE_MAP 0x35C + +#define EXYNOS_DP_ANALOG_CTL_1 0x370 +#define EXYNOS_DP_ANALOG_CTL_2 0x374 +#define EXYNOS_DP_ANALOG_CTL_3 0x378 +#define EXYNOS_DP_PLL_FILTER_CTL_1 0x37C +#define EXYNOS_DP_TX_AMP_TUNING_CTL 0x380 + +#define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390 + +#define EXYNOS_DP_COMMON_INT_STA_1 0x3C4 +#define EXYNOS_DP_COMMON_INT_STA_2 0x3C8 +#define EXYNOS_DP_COMMON_INT_STA_3 0x3CC +#define EXYNOS_DP_COMMON_INT_STA_4 0x3D0 +#define EXYNOS_DP_INT_STA 0x3DC +#define EXYNOS_DP_COMMON_INT_MASK_1 0x3E0 +#define EXYNOS_DP_COMMON_INT_MASK_2 0x3E4 +#define EXYNOS_DP_COMMON_INT_MASK_3 0x3E8 +#define EXYNOS_DP_COMMON_INT_MASK_4 0x3EC +#define EXYNOS_DP_INT_STA_MASK 0x3F8 +#define EXYNOS_DP_INT_CTL 0x3FC + +#define EXYNOS_DP_SYS_CTL_1 0x600 +#define EXYNOS_DP_SYS_CTL_2 0x604 +#define EXYNOS_DP_SYS_CTL_3 0x608 +#define EXYNOS_DP_SYS_CTL_4 0x60C + +#define EXYNOS_DP_PKT_SEND_CTL 0x640 +#define EXYNOS_DP_HDCP_CTL 0x648 + +#define EXYNOS_DP_LINK_BW_SET 0x680 +#define EXYNOS_DP_LANE_COUNT_SET 0x684 +#define EXYNOS_DP_TRAINING_PTN_SET 0x688 +#define EXYNOS_DP_LN0_LINK_TRAINING_CTL 0x68C +#define EXYNOS_DP_LN1_LINK_TRAINING_CTL 0x690 +#define EXYNOS_DP_LN2_LINK_TRAINING_CTL 0x694 +#define EXYNOS_DP_LN3_LINK_TRAINING_CTL 0x698 + +#define EXYNOS_DP_DEBUG_CTL 0x6C0 +#define EXYNOS_DP_HPD_DEGLITCH_L 0x6C4 +#define EXYNOS_DP_HPD_DEGLITCH_H 0x6C8 +#define EXYNOS_DP_LINK_DEBUG_CTL 0x6E0 + +#define EXYNOS_DP_M_VID_0 0x700 +#define EXYNOS_DP_M_VID_1 0x704 +#define EXYNOS_DP_M_VID_2 0x708 +#define EXYNOS_DP_N_VID_0 0x70C +#define EXYNOS_DP_N_VID_1 0x710 +#define EXYNOS_DP_N_VID_2 0x714 + +#define EXYNOS_DP_PLL_CTL 0x71C +#define EXYNOS_DP_PHY_PD 0x720 +#define EXYNOS_DP_PHY_TEST 0x724 + +#define EXYNOS_DP_VIDEO_FIFO_THRD 0x730 +#define EXYNOS_DP_AUDIO_MARGIN 0x73C + +#define EXYNOS_DP_M_VID_GEN_FILTER_TH 0x764 +#define EXYNOS_DP_M_AUD_GEN_FILTER_TH 0x778 +#define EXYNOS_DP_AUX_CH_STA 0x780 +#define EXYNOS_DP_AUX_CH_DEFER_CTL 0x788 +#define EXYNOS_DP_AUX_RX_COMM 0x78C +#define EXYNOS_DP_BUFFER_DATA_CTL 0x790 +#define EXYNOS_DP_AUX_CH_CTL_1 0x794 +#define EXYNOS_DP_AUX_ADDR_7_0 0x798 +#define EXYNOS_DP_AUX_ADDR_15_8 0x79C +#define EXYNOS_DP_AUX_ADDR_19_16 0x7A0 +#define EXYNOS_DP_AUX_CH_CTL_2 0x7A4 + +#define EXYNOS_DP_BUF_DATA_0 0x7C0 + +#define EXYNOS_DP_SOC_GENERAL_CTL 0x800 + +/* EXYNOS_DP_TX_SW_RESET */ +#define RESET_DP_TX (0x1 << 0) + +/* EXYNOS_DP_FUNC_EN_1 */ +#define MASTER_VID_FUNC_EN_N (0x1 << 7) +#define SLAVE_VID_FUNC_EN_N (0x1 << 5) +#define AUD_FIFO_FUNC_EN_N (0x1 << 4) +#define AUD_FUNC_EN_N (0x1 << 3) +#define HDCP_FUNC_EN_N (0x1 << 2) +#define CRC_FUNC_EN_N (0x1 << 1) +#define SW_FUNC_EN_N (0x1 << 0) + +/* EXYNOS_DP_FUNC_EN_2 */ +#define SSC_FUNC_EN_N (0x1 << 7) +#define AUX_FUNC_EN_N (0x1 << 2) +#define SERDES_FIFO_FUNC_EN_N (0x1 << 1) +#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0) + +/* EXYNOS_DP_VIDEO_CTL_1 */ +#define VIDEO_EN (0x1 << 7) +#define HDCP_VIDEO_MUTE (0x1 << 6) + +/* EXYNOS_DP_VIDEO_CTL_1 */ +#define IN_D_RANGE_MASK (0x1 << 7) +#define IN_D_RANGE_SHIFT (7) +#define IN_D_RANGE_CEA (0x1 << 7) +#define IN_D_RANGE_VESA (0x0 << 7) +#define IN_BPC_MASK (0x7 << 4) +#define IN_BPC_SHIFT (4) +#define IN_BPC_12_BITS (0x3 << 4) +#define IN_BPC_10_BITS (0x2 << 4) +#define IN_BPC_8_BITS (0x1 << 4) +#define IN_BPC_6_BITS (0x0 << 4) +#define IN_COLOR_F_MASK (0x3 << 0) +#define IN_COLOR_F_SHIFT (0) +#define IN_COLOR_F_YCBCR444 (0x2 << 0) +#define IN_COLOR_F_YCBCR422 (0x1 << 0) +#define IN_COLOR_F_RGB (0x0 << 0) + +/* EXYNOS_DP_VIDEO_CTL_3 */ +#define IN_YC_COEFFI_MASK (0x1 << 7) +#define IN_YC_COEFFI_SHIFT (7) +#define IN_YC_COEFFI_ITU709 (0x1 << 7) +#define IN_YC_COEFFI_ITU601 (0x0 << 7) +#define VID_CHK_UPDATE_TYPE_MASK (0x1 << 4) +#define VID_CHK_UPDATE_TYPE_SHIFT (4) +#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4) +#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4) + +/* EXYNOS_DP_VIDEO_CTL_8 */ +#define VID_HRES_TH(x) (((x) & 0xf) << 4) +#define VID_VRES_TH(x) (((x) & 0xf) << 0) + +/* EXYNOS_DP_VIDEO_CTL_10 */ +#define FORMAT_SEL (0x1 << 4) +#define INTERACE_SCAN_CFG (0x1 << 2) +#define VSYNC_POLARITY_CFG (0x1 << 1) +#define HSYNC_POLARITY_CFG (0x1 << 0) + +/* EXYNOS_DP_LANE_MAP */ +#define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) +#define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6) +#define LANE3_MAP_LOGIC_LANE_2 (0x2 << 6) +#define LANE3_MAP_LOGIC_LANE_3 (0x3 << 6) +#define LANE2_MAP_LOGIC_LANE_0 (0x0 << 4) +#define LANE2_MAP_LOGIC_LANE_1 (0x1 << 4) +#define LANE2_MAP_LOGIC_LANE_2 (0x2 << 4) +#define LANE2_MAP_LOGIC_LANE_3 (0x3 << 4) +#define LANE1_MAP_LOGIC_LANE_0 (0x0 << 2) +#define LANE1_MAP_LOGIC_LANE_1 (0x1 << 2) +#define LANE1_MAP_LOGIC_LANE_2 (0x2 << 2) +#define LANE1_MAP_LOGIC_LANE_3 (0x3 << 2) +#define LANE0_MAP_LOGIC_LANE_0 (0x0 << 0) +#define LANE0_MAP_LOGIC_LANE_1 (0x1 << 0) +#define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0) +#define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0) + +/* EXYNOS_DP_ANALOG_CTL_1 */ +#define TX_TERMINAL_CTRL_50_OHM (0x1 << 4) + +/* EXYNOS_DP_ANALOG_CTL_2 */ +#define SEL_24M (0x1 << 3) +#define TX_DVDD_BIT_1_0625V (0x4 << 0) + +/* EXYNOS_DP_ANALOG_CTL_3 */ +#define DRIVE_DVDD_BIT_1_0625V (0x4 << 5) +#define VCO_BIT_600_MICRO (0x5 << 0) + +/* EXYNOS_DP_PLL_FILTER_CTL_1 */ +#define PD_RING_OSC (0x1 << 6) +#define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4) +#define TX_CUR1_2X (0x1 << 2) +#define TX_CUR_16_MA (0x3 << 0) + +/* EXYNOS_DP_TX_AMP_TUNING_CTL */ +#define CH3_AMP_400_MV (0x0 << 24) +#define CH2_AMP_400_MV (0x0 << 16) +#define CH1_AMP_400_MV (0x0 << 8) +#define CH0_AMP_400_MV (0x0 << 0) + +/* EXYNOS_DP_AUX_HW_RETRY_CTL */ +#define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8) +#define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3) +#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3) +#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS (0x1 << 3) +#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS (0x2 << 3) +#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3) +#define AUX_HW_RETRY_COUNT_SEL(x) (((x) & 0x7) << 0) + +/* EXYNOS_DP_COMMON_INT_STA_1 */ +#define VSYNC_DET (0x1 << 7) +#define PLL_LOCK_CHG (0x1 << 6) +#define SPDIF_ERR (0x1 << 5) +#define SPDIF_UNSTBL (0x1 << 4) +#define VID_FORMAT_CHG (0x1 << 3) +#define AUD_CLK_CHG (0x1 << 2) +#define VID_CLK_CHG (0x1 << 1) +#define SW_INT (0x1 << 0) + +/* EXYNOS_DP_COMMON_INT_STA_2 */ +#define ENC_EN_CHG (0x1 << 6) +#define HW_BKSV_RDY (0x1 << 3) +#define HW_SHA_DONE (0x1 << 2) +#define HW_AUTH_STATE_CHG (0x1 << 1) +#define HW_AUTH_DONE (0x1 << 0) + +/* EXYNOS_DP_COMMON_INT_STA_3 */ +#define AFIFO_UNDER (0x1 << 7) +#define AFIFO_OVER (0x1 << 6) +#define R0_CHK_FLAG (0x1 << 5) + +/* EXYNOS_DP_COMMON_INT_STA_4 */ +#define PSR_ACTIVE (0x1 << 7) +#define PSR_INACTIVE (0x1 << 6) +#define SPDIF_BI_PHASE_ERR (0x1 << 5) +#define HOTPLUG_CHG (0x1 << 2) +#define HPD_LOST (0x1 << 1) +#define PLUG (0x1 << 0) + +/* EXYNOS_DP_INT_STA */ +#define INT_HPD (0x1 << 6) +#define HW_TRAINING_FINISH (0x1 << 5) +#define RPLY_RECEIV (0x1 << 1) +#define AUX_ERR (0x1 << 0) + +/* EXYNOS_DP_INT_CTL */ +#define SOFT_INT_CTRL (0x1 << 2) +#define INT_POL1 (0x1 << 1) +#define INT_POL0 (0x1 << 0) + +/* EXYNOS_DP_SYS_CTL_1 */ +#define DET_STA (0x1 << 2) +#define FORCE_DET (0x1 << 1) +#define DET_CTRL (0x1 << 0) + +/* EXYNOS_DP_SYS_CTL_2 */ +#define CHA_CRI(x) (((x) & 0xf) << 4) +#define CHA_STA (0x1 << 2) +#define FORCE_CHA (0x1 << 1) +#define CHA_CTRL (0x1 << 0) + +/* EXYNOS_DP_SYS_CTL_3 */ +#define HPD_STATUS (0x1 << 6) +#define F_HPD (0x1 << 5) +#define HPD_CTRL (0x1 << 4) +#define HDCP_RDY (0x1 << 3) +#define STRM_VALID (0x1 << 2) +#define F_VALID (0x1 << 1) +#define VALID_CTRL (0x1 << 0) + +/* EXYNOS_DP_SYS_CTL_4 */ +#define FIX_M_AUD (0x1 << 4) +#define ENHANCED (0x1 << 3) +#define FIX_M_VID (0x1 << 2) +#define M_VID_UPDATE_CTRL (0x3 << 0) + +/* EXYNOS_DP_TRAINING_PTN_SET */ +#define SCRAMBLER_TYPE (0x1 << 9) +#define HW_LINK_TRAINING_PATTERN (0x1 << 8) +#define SCRAMBLING_DISABLE (0x1 << 5) +#define SCRAMBLING_ENABLE (0x0 << 5) +#define LINK_QUAL_PATTERN_SET_MASK (0x3 << 2) +#define LINK_QUAL_PATTERN_SET_PRBS7 (0x3 << 2) +#define LINK_QUAL_PATTERN_SET_D10_2 (0x1 << 2) +#define LINK_QUAL_PATTERN_SET_DISABLE (0x0 << 2) +#define SW_TRAINING_PATTERN_SET_MASK (0x3 << 0) +#define SW_TRAINING_PATTERN_SET_PTN2 (0x2 << 0) +#define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0) +#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0) + +/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */ +#define PRE_EMPHASIS_SET_MASK (0x3 << 3) +#define PRE_EMPHASIS_SET_SHIFT (3) + +/* EXYNOS_DP_DEBUG_CTL */ +#define PLL_LOCK (0x1 << 4) +#define F_PLL_LOCK (0x1 << 3) +#define PLL_LOCK_CTRL (0x1 << 2) +#define PN_INV (0x1 << 0) + +/* EXYNOS_DP_PLL_CTL */ +#define DP_PLL_PD (0x1 << 7) +#define DP_PLL_RESET (0x1 << 6) +#define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4) +#define DP_PLL_REF_BIT_1_1250V (0x5 << 0) +#define DP_PLL_REF_BIT_1_2500V (0x7 << 0) + +/* EXYNOS_DP_PHY_PD */ +#define DP_PHY_PD (0x1 << 5) +#define AUX_PD (0x1 << 4) +#define CH3_PD (0x1 << 3) +#define CH2_PD (0x1 << 2) +#define CH1_PD (0x1 << 1) +#define CH0_PD (0x1 << 0) + +/* EXYNOS_DP_PHY_TEST */ +#define MACRO_RST (0x1 << 5) +#define CH1_TEST (0x1 << 1) +#define CH0_TEST (0x1 << 0) + +/* EXYNOS_DP_AUX_CH_STA */ +#define AUX_BUSY (0x1 << 4) +#define AUX_STATUS_MASK (0xf << 0) + +/* EXYNOS_DP_AUX_CH_DEFER_CTL */ +#define DEFER_CTRL_EN (0x1 << 7) +#define DEFER_COUNT(x) (((x) & 0x7f) << 0) + +/* EXYNOS_DP_AUX_RX_COMM */ +#define AUX_RX_COMM_I2C_DEFER (0x2 << 2) +#define AUX_RX_COMM_AUX_DEFER (0x2 << 0) + +/* EXYNOS_DP_BUFFER_DATA_CTL */ +#define BUF_CLR (0x1 << 7) +#define BUF_DATA_COUNT(x) (((x) & 0x1f) << 0) + +/* EXYNOS_DP_AUX_CH_CTL_1 */ +#define AUX_LENGTH(x) (((x - 1) & 0xf) << 4) +#define AUX_TX_COMM_MASK (0xf << 0) +#define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3) +#define AUX_TX_COMM_I2C_TRANSACTION (0x0 << 3) +#define AUX_TX_COMM_MOT (0x1 << 2) +#define AUX_TX_COMM_WRITE (0x0 << 0) +#define AUX_TX_COMM_READ (0x1 << 0) + +/* EXYNOS_DP_AUX_ADDR_7_0 */ +#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff) + +/* EXYNOS_DP_AUX_ADDR_15_8 */ +#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff) + +/* EXYNOS_DP_AUX_ADDR_19_16 */ +#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f) + +/* EXYNOS_DP_AUX_CH_CTL_2 */ +#define ADDR_ONLY (0x1 << 1) +#define AUX_EN (0x1 << 0) + +/* EXYNOS_DP_SOC_GENERAL_CTL */ +#define AUDIO_MODE_SPDIF_MODE (0x1 << 8) +#define AUDIO_MODE_MASTER_MODE (0x0 << 8) +#define MASTER_VIDEO_INTERLACE_EN (0x1 << 4) +#define VIDEO_MASTER_CLK_SEL (0x1 << 2) +#define VIDEO_MASTER_MODE_EN (0x1 << 1) +#define VIDEO_MODE_MASK (0x1 << 0) +#define VIDEO_MODE_SLAVE_MODE (0x1 << 0) +#define VIDEO_MODE_MASTER_MODE (0x0 << 0) + +#endif /* _ANALOGIX_DP_REG_H */ diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index f17d392..2fadd82 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -71,8 +71,9 @@ config DRM_EXYNOS_DSI This enables support for Exynos MIPI-DSI device. config DRM_EXYNOS_DP - bool "Display Port" + bool "EXYNOS specific extensions for Analogix DP driver" depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON + select DRM_ANALOGIX_DP default DRM_EXYNOS select DRM_PANEL help diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 968b31c..2bdd949 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -12,7 +12,7 @@ exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON) += exynos5433_drm_decon.o exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON) += exynos7_drm_decon.o exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o exynosdrm-$(CONFIG_DRM_EXYNOS_DSI) += exynos_drm_dsi.o -exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o +exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp_core.o exynosdrm-$(CONFIG_DRM_EXYNOS_MIXER) += exynos_mixer.o exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index cff8dc7..8456794 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -14,967 +14,76 @@ #include #include #include -#include -#include -#include -#include #include -#include #include -#include #include