diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_display.c | 219 |
1 files changed, 103 insertions, 116 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6c2686ecb62a..d3994e2a7d63 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -24,15 +24,15 @@ * Eric Anholt <eric@anholt.net> */ -#include <acpi/video.h> +#include <linux/dma-resv.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/dma-resv.h> #include <linux/slab.h> #include <linux/string_helpers.h> #include <linux/vga_switcheroo.h> +#include <acpi/video.h> #include <drm/display/drm_dp_helper.h> #include <drm/drm_atomic.h> @@ -45,65 +45,57 @@ #include <drm/drm_probe_helper.h> #include <drm/drm_rect.h> -#include "display/intel_audio.h" -#include "display/intel_crt.h" -#include "display/intel_ddi.h" -#include "display/intel_display_debugfs.h" -#include "display/intel_display_power.h" -#include "display/intel_dp.h" -#include "display/intel_dp_mst.h" -#include "display/intel_dpll.h" -#include "display/intel_dpll_mgr.h" -#include "display/intel_drrs.h" -#include "display/intel_dsi.h" -#include "display/intel_dvo.h" -#include "display/intel_fb.h" -#include "display/intel_gmbus.h" -#include "display/intel_hdmi.h" -#include "display/intel_lvds.h" -#include "display/intel_sdvo.h" -#include "display/intel_snps_phy.h" -#include "display/intel_tv.h" -#include "display/intel_vdsc.h" -#include "display/intel_vrr.h" - #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_object.h" -#include "gt/gen8_ppgtt.h" - #include "g4x_dp.h" #include "g4x_hdmi.h" #include "hsw_ips.h" #include "i915_drv.h" #include "i915_reg.h" #include "i915_utils.h" +#include "i9xx_plane.h" #include "icl_dsi.h" #include "intel_acpi.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" +#include "intel_audio.h" #include "intel_bw.h" #include "intel_cdclk.h" #include "intel_color.h" +#include "intel_crt.h" #include "intel_crtc.h" #include "intel_crtc_state_dump.h" +#include "intel_ddi.h" #include "intel_de.h" +#include "intel_display_debugfs.h" +#include "intel_display_power.h" #include "intel_display_types.h" #include "intel_dmc.h" +#include "intel_dp.h" #include "intel_dp_link_training.h" +#include "intel_dp_mst.h" #include "intel_dpio_phy.h" +#include "intel_dpll.h" +#include "intel_dpll_mgr.h" #include "intel_dpt.h" -#include "intel_dsb.h" +#include "intel_drrs.h" +#include "intel_dsi.h" +#include "intel_dvo.h" +#include "intel_fb.h" #include "intel_fbc.h" #include "intel_fbdev.h" #include "intel_fdi.h" #include "intel_fifo_underrun.h" #include "intel_frontbuffer.h" +#include "intel_gmbus.h" #include "intel_hdcp.h" +#include "intel_hdmi.h" #include "intel_hotplug.h" #include "intel_hti.h" -#include "intel_modeset_verify.h" +#include "intel_lvds.h" #include "intel_modeset_setup.h" +#include "intel_modeset_verify.h" #include "intel_overlay.h" #include "intel_panel.h" #include "intel_pch_display.h" @@ -115,10 +107,15 @@ #include "intel_pps.h" #include "intel_psr.h" #include "intel_quirks.h" +#include "intel_sdvo.h" +#include "intel_snps_phy.h" #include "intel_sprite.h" #include "intel_tc.h" +#include "intel_tv.h" +#include "intel_vblank.h" +#include "intel_vdsc.h" #include "intel_vga.h" -#include "i9xx_plane.h" +#include "intel_vrr.h" #include "skl_scaler.h" #include "skl_universal_plane.h" #include "skl_watermark.h" @@ -388,41 +385,6 @@ struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state) return to_intel_crtc(crtc_state->uapi.crtc); } -static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - i915_reg_t reg = PIPEDSL(pipe); - u32 line1, line2; - - line1 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; - msleep(5); - line2 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; - - return line1 != line2; -} - -static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - - /* Wait for the display line to settle/start moving */ - if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100)) - drm_err(&dev_priv->drm, - "pipe %c scanline %s wait timed out\n", - pipe_name(pipe), str_on_off(state)); -} - -static void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc) -{ - wait_for_pipe_scanline_moving(crtc, false); -} - -static void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) -{ - wait_for_pipe_scanline_moving(crtc, true); -} - static void intel_wait_for_pipe_off(const struct intel_crtc_state *old_crtc_state) { @@ -1098,22 +1060,6 @@ intel_get_crtc_new_encoder(const struct intel_atomic_state *state, return encoder; } -static void cpt_verify_modeset(struct drm_i915_private *dev_priv, - enum pipe pipe) -{ - i915_reg_t dslreg = PIPEDSL(pipe); - u32 temp; - - temp = intel_de_read(dev_priv, dslreg); - udelay(500); - if (wait_for(intel_de_read(dev_priv, dslreg) != temp, 5)) { - if (wait_for(intel_de_read(dev_priv, dslreg) != temp, 5)) - drm_err(&dev_priv->drm, - "mode set failed: pipe %c stuck\n", - pipe_name(pipe)); - } -} - static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -1246,7 +1192,6 @@ static void intel_post_plane_update(struct intel_atomic_state *state, if (new_crtc_state->update_wm_post && new_crtc_state->hw.active) intel_update_watermarks(dev_priv); - hsw_ips_post_update(state, crtc); intel_fbc_post_update(state, crtc); if (needs_async_flip_vtd_wa(old_crtc_state) && @@ -1809,7 +1754,7 @@ static void ilk_crtc_enable(struct intel_atomic_state *state, intel_encoders_enable(state, crtc); if (HAS_PCH_CPT(dev_priv)) - cpt_verify_modeset(dev_priv, pipe); + intel_wait_for_pipe_scanline_moving(crtc); /* * Must wait for vblank to avoid spurious PCH FIFO underruns. @@ -1922,6 +1867,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (drm_WARN_ON(&dev_priv->drm, crtc->active)) return; + intel_dmc_enable_pipe(dev_priv, crtc->pipe); + if (!new_crtc_state->bigjoiner_pipes) { intel_encoders_pre_pll_enable(state, crtc); @@ -2057,6 +2004,7 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, { const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); /* * FIXME collapse everything to one hook. @@ -2066,6 +2014,8 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_encoders_disable(state, crtc); intel_encoders_post_disable(state, crtc); } + + intel_dmc_disable_pipe(i915, crtc->pipe); } static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) @@ -3296,7 +3246,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, if (DISPLAY_VER(dev_priv) >= 4) { /* No way to read it out on pipes B and C */ if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A) - tmp = dev_priv->chv_dpll_md[crtc->pipe]; + tmp = dev_priv->display.state.chv_dpll_md[crtc->pipe]; else tmp = intel_de_read(dev_priv, DPLL_MD(crtc->pipe)); pipe_config->pixel_multiplier = @@ -5433,6 +5383,12 @@ intel_compare_dp_vsc_sdp(const struct drm_dp_vsc_sdp *a, return memcmp(a, b, sizeof(*a)) == 0; } +static bool +intel_compare_buffer(const u8 *a, const u8 *b, size_t len) +{ + return memcmp(a, b, len) == 0; +} + static void pipe_config_infoframe_mismatch(struct drm_i915_private *dev_priv, bool fastset, const char *name, @@ -5483,6 +5439,30 @@ pipe_config_dp_vsc_sdp_mismatch(struct drm_i915_private *dev_priv, } } +static void +pipe_config_buffer_mismatch(struct drm_i915_private *dev_priv, + bool fastset, const char *name, + const u8 *a, const u8 *b, size_t len) +{ + if (fastset) { + if (!drm_debug_enabled(DRM_UT_KMS)) + return; + + drm_dbg_kms(&dev_priv->drm, + "fastset mismatch in %s buffer\n", name); + print_hex_dump(KERN_DEBUG, "expected: ", DUMP_PREFIX_NONE, + 16, 0, a, len, false); + print_hex_dump(KERN_DEBUG, "found: ", DUMP_PREFIX_NONE, + 16, 0, b, len, false); + } else { + drm_err(&dev_priv->drm, "mismatch in %s buffer\n", name); + print_hex_dump(KERN_ERR, "expected: ", DUMP_PREFIX_NONE, + 16, 0, a, len, false); + print_hex_dump(KERN_ERR, "found: ", DUMP_PREFIX_NONE, + 16, 0, b, len, false); + } +} + static void __printf(4, 5) pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc, const char *name, const char *format, ...) @@ -5531,7 +5511,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; - u32 bp_gamma = 0; bool fixup_inherited = fastset && current_config->inherited && !pipe_config->inherited; @@ -5682,21 +5661,26 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } \ } while (0) -#define PIPE_CONF_CHECK_COLOR_LUT(name1, name2, bit_precision) do { \ - if (current_config->name1 != pipe_config->name1) { \ - pipe_config_mismatch(fastset, crtc, __stringify(name1), \ - "(expected %i, found %i, won't compare lut values)", \ - current_config->name1, \ - pipe_config->name1); \ - ret = false;\ - } else { \ - if (!intel_color_lut_equal(current_config->name2, \ - pipe_config->name2, pipe_config->name1, \ - bit_precision)) { \ - pipe_config_mismatch(fastset, crtc, __stringify(name2), \ - "hw_state doesn't match sw_state"); \ - ret = false; \ - } \ +#define PIPE_CONF_CHECK_BUFFER(name, len) do { \ + 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), \ + current_config->name, \ + pipe_config->name, \ + (len)); \ + ret = false; \ + } \ +} while (0) + +#define PIPE_CONF_CHECK_COLOR_LUT(lut, is_pre_csc_lut) do { \ + if (current_config->gamma_mode == pipe_config->gamma_mode && \ + !intel_color_lut_equal(current_config, \ + current_config->lut, pipe_config->lut, \ + is_pre_csc_lut)) { \ + pipe_config_mismatch(fastset, crtc, __stringify(lut), \ + "hw_state doesn't match sw_state"); \ + ret = false; \ } \ } while (0) @@ -5760,6 +5744,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(fec_enable); PIPE_CONF_CHECK_BOOL_INCOMPLETE(has_audio); + PIPE_CONF_CHECK_BUFFER(eld, MAX_ELD_BYTES); PIPE_CONF_CHECK_X(gmch_pfit.control); /* pfit ratios are autocomputed by the hw on gen4+ */ @@ -5793,9 +5778,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(linetime); PIPE_CONF_CHECK_I(ips_linetime); - bp_gamma = intel_color_get_gamma_bit_precision(pipe_config); - if (bp_gamma) - PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, post_csc_lut, bp_gamma); + PIPE_CONF_CHECK_COLOR_LUT(pre_csc_lut, true); + PIPE_CONF_CHECK_COLOR_LUT(post_csc_lut, false); if (current_config->active_planes) { PIPE_CONF_CHECK_BOOL(has_psr); @@ -5950,6 +5934,10 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state, if (ret) return ret; + ret = intel_dp_mst_add_topology_state_for_crtc(state, crtc); + if (ret) + return ret; + ret = intel_atomic_add_affected_planes(state, crtc); if (ret) return ret; @@ -6941,7 +6929,7 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state) for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { if (intel_crtc_needs_color_update(crtc_state)) - intel_dsb_prepare(crtc_state); + intel_color_prepare_commit(crtc_state); } return 0; @@ -7392,24 +7380,18 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat &wait_reset); } -static void intel_cleanup_dsbs(struct intel_atomic_state *state) -{ - struct intel_crtc_state *old_crtc_state, *new_crtc_state; - struct intel_crtc *crtc; - int i; - - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) - intel_dsb_cleanup(old_crtc_state); -} - static void intel_atomic_cleanup_work(struct work_struct *work) { struct intel_atomic_state *state = container_of(work, struct intel_atomic_state, base.commit_work); struct drm_i915_private *i915 = to_i915(state->base.dev); + struct intel_crtc_state *old_crtc_state; + struct intel_crtc *crtc; + int i; + + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) + intel_color_cleanup_commit(old_crtc_state); - intel_cleanup_dsbs(state); drm_atomic_helper_cleanup_planes(&i915->drm, &state->base); drm_atomic_helper_commit_cleanup_done(&state->base); drm_atomic_state_put(&state->base); @@ -7587,6 +7569,9 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state); + /* Must be done after gamma readout due to HSW split gamma vs. IPS w/a */ + hsw_ips_post_update(state, crtc); + /* * Activate DRRS after state readout to avoid * dp_m_n vs. dp_m2_n2 confusion on BDW+. @@ -7597,6 +7582,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) * DSB cleanup is done in cleanup_work aligning with framebuffer * cleanup. So copy and reset the dsb structure to sync with * commit_done and later do dsb cleanup in cleanup_work. + * + * FIXME get rid of this funny new->old swapping */ old_crtc_state->dsb = fetch_and_zero(&new_crtc_state->dsb); } @@ -7747,7 +7734,7 @@ static int intel_atomic_commit(struct drm_device *dev, i915_sw_fence_commit(&state->commit_ready); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) - intel_dsb_cleanup(new_crtc_state); + intel_color_cleanup_commit(new_crtc_state); drm_atomic_helper_cleanup_planes(dev, &state->base); intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref); |