diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_display.c | 132 |
1 files changed, 70 insertions, 62 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7db0655d8c9e..ab2f52d21bad 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -33,6 +33,7 @@ #include <linux/string_helpers.h> #include <drm/display/drm_dp_helper.h> +#include <drm/display/drm_dp_tunnel.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> @@ -73,6 +74,7 @@ #include "intel_dp.h" #include "intel_dp_link_training.h" #include "intel_dp_mst.h" +#include "intel_dp_tunnel.h" #include "intel_dpll.h" #include "intel_dpll_mgr.h" #include "intel_dpt.h" @@ -2478,7 +2480,7 @@ intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes, u32 link_symbol_clock = intel_dp_link_symbol_clock(link_clock); u32 data_m = intel_dp_effective_data_rate(pixel_clock, bits_per_pixel_x16, bw_overhead); - u32 data_n = intel_dp_max_data_rate(link_clock, nlanes); + u32 data_n = drm_dp_max_dprx_data_rate(link_clock, nlanes); /* * Windows/BIOS uses fixed M/N values always. Follow suit. @@ -4490,6 +4492,8 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state, saved_state->crc_enabled = slave_crtc_state->crc_enabled; intel_crtc_free_hw_state(slave_crtc_state); + if (slave_crtc_state->dp_tunnel_ref.tunnel) + drm_dp_tunnel_ref_put(&slave_crtc_state->dp_tunnel_ref); memcpy(slave_crtc_state, saved_state, sizeof(*slave_crtc_state)); kfree(saved_state); @@ -4505,6 +4509,10 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state, &master_crtc_state->hw.adjusted_mode); slave_crtc_state->hw.scaling_filter = master_crtc_state->hw.scaling_filter; + if (master_crtc_state->dp_tunnel_ref.tunnel) + drm_dp_tunnel_ref_get(master_crtc_state->dp_tunnel_ref.tunnel, + &slave_crtc_state->dp_tunnel_ref); + copy_bigjoiner_crtc_state_nomodeset(state, slave_crtc); slave_crtc_state->uapi.mode_changed = master_crtc_state->uapi.mode_changed; @@ -4533,6 +4541,8 @@ intel_crtc_prepare_cleared_state(struct intel_atomic_state *state, /* free the old crtc_state->hw members */ intel_crtc_free_hw_state(crtc_state); + intel_dp_tunnel_atomic_clear_stream_bw(state, crtc_state); + /* FIXME: before the switch to atomic started, a new pipe_config was * kzalloc'd. Code that depends on any field being zero should be * fixed, so that the crtc_state can be safely duplicated. For now, @@ -4851,10 +4861,12 @@ memcmp_diff_len(const u8 *a, const u8 *b, size_t len) } static void -pipe_config_buffer_mismatch(struct drm_i915_private *dev_priv, - bool fastset, const char *name, +pipe_config_buffer_mismatch(bool fastset, const struct intel_crtc *crtc, + const char *name, const u8 *a, const u8 *b, size_t len) { + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + if (fastset) { if (!drm_debug_enabled(DRM_UT_KMS)) return; @@ -4863,7 +4875,8 @@ pipe_config_buffer_mismatch(struct drm_i915_private *dev_priv, len = memcmp_diff_len(a, b, len); drm_dbg_kms(&dev_priv->drm, - "fastset requirement not met in %s buffer\n", name); + "[CRTC:%d:%s] fastset requirement not met in %s buffer\n", + crtc->base.base.id, crtc->base.name, name); print_hex_dump(KERN_DEBUG, "expected: ", DUMP_PREFIX_NONE, 16, 0, a, len, false); print_hex_dump(KERN_DEBUG, "found: ", DUMP_PREFIX_NONE, @@ -4872,7 +4885,8 @@ pipe_config_buffer_mismatch(struct drm_i915_private *dev_priv, /* only dump up to the last difference */ len = memcmp_diff_len(a, b, len); - drm_err(&dev_priv->drm, "mismatch in %s buffer\n", name); + drm_err(&dev_priv->drm, "[CRTC:%d:%s] mismatch in %s buffer\n", + crtc->base.base.id, crtc->base.name, name); print_hex_dump(KERN_ERR, "expected: ", DUMP_PREFIX_NONE, 16, 0, a, len, false); print_hex_dump(KERN_ERR, "found: ", DUMP_PREFIX_NONE, @@ -4903,18 +4917,34 @@ pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc, va_end(args); } -static bool fastboot_enabled(struct drm_i915_private *dev_priv) +static void +pipe_config_pll_mismatch(bool fastset, + const struct intel_crtc *crtc, + const char *name, + const struct intel_dpll_hw_state *a, + const struct intel_dpll_hw_state *b) { - /* Enable fastboot by default on Skylake and newer */ - if (DISPLAY_VER(dev_priv) >= 9) - return true; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); - /* Enable fastboot by default on VLV and CHV */ - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - return true; + if (fastset) { + if (!drm_debug_enabled(DRM_UT_KMS)) + return; - /* Disabled by default on all others */ - return false; + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] fastset requirement not met in %s\n", + crtc->base.base.id, crtc->base.name, name); + drm_dbg_kms(&i915->drm, "expected:\n"); + intel_dpll_dump_hw_state(i915, a); + drm_dbg_kms(&i915->drm, "found:\n"); + intel_dpll_dump_hw_state(i915, b); + } else { + drm_err(&i915->drm, "[CRTC:%d:%s] mismatch in %s buffer\n", + crtc->base.base.id, crtc->base.name, name); + drm_err(&i915->drm, "expected:\n"); + intel_dpll_dump_hw_state(i915, a); + drm_err(&i915->drm, "found:\n"); + intel_dpll_dump_hw_state(i915, b); + } } bool @@ -4925,14 +4955,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); bool ret = true; - bool fixup_inherited = fastset && - current_config->inherited && !pipe_config->inherited; - - if (fixup_inherited && !fastboot_enabled(dev_priv)) { - drm_dbg_kms(&dev_priv->drm, - "initial modeset and fastboot not set\n"); - ret = false; - } #define PIPE_CONF_CHECK_X(name) do { \ if (current_config->name != pipe_config->name) { \ @@ -5012,7 +5034,17 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) -#define PIPE_CONF_CHECK_TIMINGS(name) do { \ +#define PIPE_CONF_CHECK_PLL(name) do { \ + if (!intel_dpll_compare_hw_state(dev_priv, ¤t_config->name, \ + &pipe_config->name)) { \ + pipe_config_pll_mismatch(fastset, crtc, __stringify(name), \ + ¤t_config->name, \ + &pipe_config->name); \ + ret = false; \ + } \ +} while (0) + +#define PIPE_CONF_CHECK_TIMINGS(name) do { \ PIPE_CONF_CHECK_I(name.crtc_hdisplay); \ PIPE_CONF_CHECK_I(name.crtc_htotal); \ PIPE_CONF_CHECK_I(name.crtc_hblank_start); \ @@ -5071,7 +5103,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, BUILD_BUG_ON(sizeof(current_config->name) != (len)); \ BUILD_BUG_ON(sizeof(pipe_config->name) != (len)); \ if (!intel_compare_buffer(current_config->name, pipe_config->name, (len))) { \ - pipe_config_buffer_mismatch(dev_priv, fastset, __stringify(name), \ + pipe_config_buffer_mismatch(fastset, crtc, __stringify(name), \ current_config->name, \ pipe_config->name, \ (len)); \ @@ -5215,42 +5247,12 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(double_wide); - if (dev_priv->display.dpll.mgr) { + if (dev_priv->display.dpll.mgr) 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); - PIPE_CONF_CHECK_X(dpll_hw_state.fp1); - PIPE_CONF_CHECK_X(dpll_hw_state.wrpll); - PIPE_CONF_CHECK_X(dpll_hw_state.spll); - PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1); - PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1); - PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2); - PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr0); - PIPE_CONF_CHECK_X(dpll_hw_state.div0); - PIPE_CONF_CHECK_X(dpll_hw_state.ebb0); - PIPE_CONF_CHECK_X(dpll_hw_state.ebb4); - PIPE_CONF_CHECK_X(dpll_hw_state.pll0); - PIPE_CONF_CHECK_X(dpll_hw_state.pll1); - PIPE_CONF_CHECK_X(dpll_hw_state.pll2); - PIPE_CONF_CHECK_X(dpll_hw_state.pll3); - PIPE_CONF_CHECK_X(dpll_hw_state.pll6); - PIPE_CONF_CHECK_X(dpll_hw_state.pll8); - PIPE_CONF_CHECK_X(dpll_hw_state.pll9); - PIPE_CONF_CHECK_X(dpll_hw_state.pll10); - PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias); - PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias); - } + /* FIXME convert everything over the dpll_mgr */ + if (dev_priv->display.dpll.mgr || HAS_GMCH(dev_priv)) + PIPE_CONF_CHECK_PLL(dpll_hw_state); PIPE_CONF_CHECK_X(dsi_pll.ctrl); PIPE_CONF_CHECK_X(dsi_pll.div); @@ -5373,6 +5375,10 @@ static int intel_modeset_pipe(struct intel_atomic_state *state, if (ret) return ret; + ret = intel_dp_tunnel_atomic_add_state_for_crtc(state, crtc); + if (ret) + return ret; + ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc); if (ret) return ret; @@ -6260,12 +6266,11 @@ static int intel_atomic_check_config(struct intel_atomic_state *state, static int intel_atomic_check_config_and_link(struct intel_atomic_state *state) { - struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_link_bw_limits new_limits; struct intel_link_bw_limits old_limits; int ret; - intel_link_bw_init_limits(i915, &new_limits); + intel_link_bw_init_limits(state, &new_limits); old_limits = new_limits; while (true) { @@ -7118,6 +7123,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_commit_modeset_disables(state); + intel_dp_tunnel_atomic_alloc_bw(state); + /* FIXME: Eventually get rid of our crtc->config pointer */ for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) crtc->config = new_crtc_state; @@ -8094,8 +8101,9 @@ void intel_hpd_poll_fini(struct drm_i915_private *i915) /* Kill all the work that may have been queued by hpd. */ drm_connector_list_iter_begin(&i915->drm, &conn_iter); for_each_intel_connector_iter(connector, &conn_iter) { - if (connector->modeset_retry_work.func) - cancel_work_sync(&connector->modeset_retry_work); + if (connector->modeset_retry_work.func && + cancel_work_sync(&connector->modeset_retry_work)) + drm_connector_put(&connector->base); if (connector->hdcp.shim) { cancel_delayed_work_sync(&connector->hdcp.check_work); cancel_work_sync(&connector->hdcp.prop_work); |