diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-11-21 14:56:17 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-11-21 14:56:17 -0800 |
| commit | 28eb75e178d389d325f1666e422bc13bbbb9804c (patch) | |
| tree | 20417b4e798f98fc5687e80c1e0126afcf437c70 /drivers/gpu/drm/i915/display/intel_pps.c | |
| parent | 071b34dcf71523a559b6c39f5d21a268a9531b50 (diff) | |
| parent | a163b895077861598be48c1cf7f4a88413c28b22 (diff) | |
Merge tag 'drm-next-2024-11-21' of https://gitlab.freedesktop.org/drm/kernel
Pull drm updates from Dave Airlie:
"There's a lot of rework, the panic helper support is being added to
more drivers, v3d gets support for HW superpages, scheduler
documentation, drm client and video aperture reworks, some new
MAINTAINERS added, amdgpu has the usual lots of IP refactors, Intel
has some Pantherlake enablement and xe is getting some SRIOV bits, but
just lots of stuff everywhere.
core:
- split DSC helpers from DP helpers
- clang build fixes for drm/mm test
- drop simple pipeline support for gem vram
- document submission error signaling
- move drm_rect to drm core module from kms helper
- add default client setup to most drivers
- move to video aperture helpers instead of drm ones
tests:
- new framebuffer tests
ttm:
- remove swapped and pinned BOs from TTM lru
panic:
- fix uninit spinlock
- add ABGR2101010 support
bridge:
- add TI TDP158 support
- use standard PM OPS
dma-fence:
- use read_trylock instead of read_lock to help lockdep
scheduler:
- add errno to sched start to report different errors
- add locking to drm_sched_entity_modify_sched
- improve documentation
xe:
- add drm_line_printer
- lots of refactoring
- Enable Xe2 + PES disaggregation
- add new ARL PCI ID
- SRIOV development work
- fix exec unnecessary implicit fence
- define and parse OA sync props
- forcewake refactoring
i915:
- Enable BMG/LNL ultra joiner
- Enable 10bpx + CCS scanout on ICL+, fp16/CCS on TGL+
- use DSB for plane/color mgmt
- Arrow lake PCI IDs
- lots of i915/xe display refactoring
- enable PXP GuC autoteardown
- Pantherlake (PTL) Xe3 LPD display enablement
- Allow fastset HDR infoframe changes
- write DP source OUI for non-eDP sinks
- share PCI IDs between i915 and xe
amdgpu:
- SDMA queue reset support
- SMU 13.0.6, JPEG 4.0.3 updates
- Initial runtime repartitioning support
- rework IP structs for multiple IP instances
- Fetch EDID from _DDC if available
- SMU13 zero rpm user control
- lots of fixes/cleanups
amdkfd:
- Increase event FIFO size
- add topology cap flag for per queue reset
msm:
- DPU:
- SA8775P support
- (disabled by default) MSM8917, MSM8937, MSM8953 and MSM8996 support
- Enable large framebuffer support
- Drop MSM8998 and SDM845
- DP:
- SA8775P support
- GPU:
- a7xx preemption support
- Adreno A663 support
ast:
- warn about unsupported TX chips
ivpu:
- add coredump
- add pantherlake support
rockchip:
- 4K@60Hz display enablement
- generate pll programming tables
panthor:
- add timestamp query API
- add realtime group priority
- add fdinfo support
etnaviv:
- improve handling of DMA address limits
- improve GPU hangcheck
exynos:
- Decon Exynos7870 support
mediatek:
- add OF graph support
omap:
- locking fixes
bochs:
- convert to gem/shmem from simpledrm
v3d:
- support big/super pages
- add gemfs
vc4:
- BCM2712 support refactoring
- add YUV444 format support
udmabuf:
- folio related fixes
nouveau:
- add panic support on nv50+"
* tag 'drm-next-2024-11-21' of https://gitlab.freedesktop.org/drm/kernel: (1583 commits)
drm/xe/guc: Fix dereference before NULL check
drm/amd: Fix initialization mistake for NBIO 7.7.0
Revert "drm/amd/display: parse umc_info or vram_info based on ASIC"
drm/amd/display: Fix failure to read vram info due to static BP_RESULT
drm/amdgpu: enable GTT fallback handling for dGPUs only
drm/amd/amdgpu: limit single process inside MES
drm/fourcc: add AMD_FMT_MOD_TILE_GFX9_4K_D_X
drm/amdgpu/mes12: correct kiq unmap latency
drm/amdgpu: Support vcn and jpeg error info parsing
drm/amd : Update MES API header file for v11 & v12
drm/amd/amdkfd: add/remove kfd queues on start/stop KFD scheduling
drm/amdkfd: change kfd process kref count at creation
drm/amdgpu: Cleanup shift coding style
drm/amd/amdgpu: Increase MES log buffer to dump mes scratch data
drm/amdgpu: Implement virt req_ras_err_count
drm/amdgpu: VF Query RAS Caps from Host if supported
drm/amdgpu: Add msg handlers for SRIOV RAS Telemetry
drm/amdgpu: Update SRIOV Exchange Headers for RAS Telemetry Support
drm/amd/display: 3.2.309
drm/amd/display: Adjust VSDB parser for replay feature
...
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_pps.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_pps.c | 283 |
1 files changed, 181 insertions, 102 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index feddc30e3375..093fe37a3983 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -3,6 +3,8 @@ * Copyright © 2020 Intel Corporation */ +#include <linux/debugfs.h> + #include "g4x_dp.h" #include "i915_drv.h" #include "i915_reg.h" @@ -27,11 +29,10 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd static const char *pps_name(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); - struct drm_i915_private *i915 = to_i915(display->drm); struct intel_pps *pps = &intel_dp->pps; - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { - switch (pps->pps_pipe) { + if (display->platform.valleyview || display->platform.cherryview) { + switch (pps->vlv_pps_pipe) { case INVALID_PIPE: /* * FIXME would be nice if we can guarantee @@ -43,7 +44,7 @@ static const char *pps_name(struct intel_dp *intel_dp) case PIPE_B: return "PPS B"; default: - MISSING_CASE(pps->pps_pipe); + MISSING_CASE(pps->vlv_pps_pipe); break; } } else { @@ -68,7 +69,7 @@ intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp) intel_wakeref_t wakeref; /* - * See intel_pps_reset_all() why we need a power domain reference here. + * See vlv_pps_reset_all() why we need a power domain reference here. */ wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE); mutex_lock(&display->pps.mutex); @@ -85,7 +86,7 @@ intel_wakeref_t intel_pps_unlock(struct intel_dp *intel_dp, mutex_unlock(&display->pps.mutex); intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); - return 0; + return NULL; } static void @@ -94,7 +95,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) struct intel_display *display = to_intel_display(intel_dp); struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - enum pipe pipe = intel_dp->pps.pps_pipe; + enum pipe pipe = intel_dp->pps.vlv_pps_pipe; bool pll_enabled, release_cl_override = false; enum dpio_phy phy = vlv_pipe_to_phy(pipe); enum dpio_channel ch = vlv_pipe_to_channel(pipe); @@ -120,7 +121,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) DP |= DP_PORT_WIDTH(1); DP |= DP_LINK_TRAIN_PAT_1; - if (IS_CHERRYVIEW(dev_priv)) + if (display->platform.cherryview) DP |= DP_PIPE_SEL_CHV(pipe); else DP |= DP_PIPE_SEL(pipe); @@ -132,7 +133,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) * So enable temporarily it if it's not already enabled. */ if (!pll_enabled) { - release_cl_override = IS_CHERRYVIEW(dev_priv) && + release_cl_override = display->platform.cherryview && !chv_phy_powergate_ch(dev_priv, phy, ch, true); if (vlv_force_pll_on(dev_priv, pipe, vlv_get_dpll(dev_priv))) { @@ -180,18 +181,18 @@ static enum pipe vlv_find_free_pps(struct intel_display *display) if (encoder->type == INTEL_OUTPUT_EDP) { drm_WARN_ON(display->drm, - intel_dp->pps.active_pipe != INVALID_PIPE && - intel_dp->pps.active_pipe != - intel_dp->pps.pps_pipe); + intel_dp->pps.vlv_active_pipe != INVALID_PIPE && + intel_dp->pps.vlv_active_pipe != + intel_dp->pps.vlv_pps_pipe); - if (intel_dp->pps.pps_pipe != INVALID_PIPE) - pipes &= ~(1 << intel_dp->pps.pps_pipe); + if (intel_dp->pps.vlv_pps_pipe != INVALID_PIPE) + pipes &= ~(1 << intel_dp->pps.vlv_pps_pipe); } else { drm_WARN_ON(display->drm, - intel_dp->pps.pps_pipe != INVALID_PIPE); + intel_dp->pps.vlv_pps_pipe != INVALID_PIPE); - if (intel_dp->pps.active_pipe != INVALID_PIPE) - pipes &= ~(1 << intel_dp->pps.active_pipe); + if (intel_dp->pps.vlv_active_pipe != INVALID_PIPE) + pipes &= ~(1 << intel_dp->pps.vlv_active_pipe); } } @@ -213,11 +214,11 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) /* We should never land here with regular DP ports */ drm_WARN_ON(display->drm, !intel_dp_is_edp(intel_dp)); - drm_WARN_ON(display->drm, intel_dp->pps.active_pipe != INVALID_PIPE && - intel_dp->pps.active_pipe != intel_dp->pps.pps_pipe); + drm_WARN_ON(display->drm, intel_dp->pps.vlv_active_pipe != INVALID_PIPE && + intel_dp->pps.vlv_active_pipe != intel_dp->pps.vlv_pps_pipe); - if (intel_dp->pps.pps_pipe != INVALID_PIPE) - return intel_dp->pps.pps_pipe; + if (intel_dp->pps.vlv_pps_pipe != INVALID_PIPE) + return intel_dp->pps.vlv_pps_pipe; pipe = vlv_find_free_pps(display); @@ -229,7 +230,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) pipe = PIPE_A; vlv_steal_power_sequencer(display, pipe); - intel_dp->pps.pps_pipe = pipe; + intel_dp->pps.vlv_pps_pipe = pipe; drm_dbg_kms(display->drm, "picked %s for [ENCODER:%d:%s]\n", @@ -246,7 +247,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp) */ vlv_power_sequencer_kick(intel_dp); - return intel_dp->pps.pps_pipe; + return intel_dp->pps.vlv_pps_pipe; } static int @@ -260,10 +261,10 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp) /* We should never land here with regular DP ports */ drm_WARN_ON(display->drm, !intel_dp_is_edp(intel_dp)); - if (!intel_dp->pps.pps_reset) + if (!intel_dp->pps.bxt_pps_reset) return pps_idx; - intel_dp->pps.pps_reset = false; + intel_dp->pps.bxt_pps_reset = false; /* * Only the HW needs to be reprogrammed, the SW state is fixed and @@ -325,19 +326,19 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp) /* try to find a pipe with this port selected */ /* first pick one where the panel is on */ - intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(display, port, - pps_has_pp_on); + intel_dp->pps.vlv_pps_pipe = vlv_initial_pps_pipe(display, port, + pps_has_pp_on); /* didn't find one? pick one where vdd is on */ - if (intel_dp->pps.pps_pipe == INVALID_PIPE) - intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(display, port, - pps_has_vdd_on); + if (intel_dp->pps.vlv_pps_pipe == INVALID_PIPE) + intel_dp->pps.vlv_pps_pipe = vlv_initial_pps_pipe(display, port, + pps_has_vdd_on); /* didn't find one? pick one with just the correct port */ - if (intel_dp->pps.pps_pipe == INVALID_PIPE) - intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(display, port, - pps_any); + if (intel_dp->pps.vlv_pps_pipe == INVALID_PIPE) + intel_dp->pps.vlv_pps_pipe = vlv_initial_pps_pipe(display, port, + pps_any); /* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */ - if (intel_dp->pps.pps_pipe == INVALID_PIPE) { + if (intel_dp->pps.vlv_pps_pipe == INVALID_PIPE) { drm_dbg_kms(display->drm, "[ENCODER:%d:%s] no initial power sequencer\n", dig_port->base.base.base.id, dig_port->base.base.name); @@ -354,10 +355,10 @@ static int intel_num_pps(struct intel_display *display) { struct drm_i915_private *i915 = to_i915(display->drm); - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + if (display->platform.valleyview || display->platform.cherryview) return 2; - if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) + if (display->platform.geminilake || display->platform.broxton) return 2; if (INTEL_PCH_TYPE(i915) >= PCH_MTL) @@ -404,11 +405,10 @@ pps_initial_setup(struct intel_dp *intel_dp) struct intel_display *display = to_intel_display(intel_dp); struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; struct intel_connector *connector = intel_dp->attached_connector; - struct drm_i915_private *i915 = to_i915(encoder->base.dev); lockdep_assert_held(&display->pps.mutex); - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + if (display->platform.valleyview || display->platform.cherryview) { vlv_initial_power_sequencer_setup(intel_dp); return true; } @@ -446,21 +446,17 @@ pps_initial_setup(struct intel_dp *intel_dp) return intel_pps_is_valid(intel_dp); } -void intel_pps_reset_all(struct intel_display *display) +void vlv_pps_reset_all(struct intel_display *display) { - struct drm_i915_private *dev_priv = to_i915(display->drm); struct intel_encoder *encoder; - if (drm_WARN_ON(display->drm, !IS_LP(dev_priv))) - return; - if (!HAS_DISPLAY(display)) return; /* * We can't grab pps_mutex here due to deadlock with power_domain * mutex when power_domain functions are called while holding pps_mutex. - * That also means that in order to use pps_pipe the code needs to + * That also means that in order to use vlv_pps_pipe the code needs to * hold both a power domain reference and pps_mutex, and the power domain * reference get/put must be done while _not_ holding pps_mutex. * pps_{lock,unlock}() do these steps in the correct order, so one @@ -470,16 +466,27 @@ void intel_pps_reset_all(struct intel_display *display) for_each_intel_dp(display->drm, encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - drm_WARN_ON(display->drm, - intel_dp->pps.active_pipe != INVALID_PIPE); + drm_WARN_ON(display->drm, intel_dp->pps.vlv_active_pipe != INVALID_PIPE); - if (encoder->type != INTEL_OUTPUT_EDP) - continue; + if (encoder->type == INTEL_OUTPUT_EDP) + intel_dp->pps.vlv_pps_pipe = INVALID_PIPE; + } +} + +void bxt_pps_reset_all(struct intel_display *display) +{ + struct intel_encoder *encoder; + + if (!HAS_DISPLAY(display)) + return; + + /* See vlv_pps_reset_all() for why we can't grab pps_mutex here. */ + + for_each_intel_dp(display->drm, encoder) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - if (DISPLAY_VER(display) >= 9) - intel_dp->pps.pps_reset = true; - else - intel_dp->pps.pps_pipe = INVALID_PIPE; + if (encoder->type == INTEL_OUTPUT_EDP) + intel_dp->pps.bxt_pps_reset = true; } } @@ -500,9 +507,9 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp, memset(regs, 0, sizeof(*regs)); - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) + if (display->platform.valleyview || display->platform.cherryview) pps_idx = vlv_power_sequencer_pipe(intel_dp); - else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) + else if (display->platform.geminilake || display->platform.broxton) pps_idx = bxt_power_sequencer_idx(intel_dp); else pps_idx = intel_dp->pps.pps_idx; @@ -513,7 +520,7 @@ static void intel_pps_get_registers(struct intel_dp *intel_dp, regs->pp_off = PP_OFF_DELAYS(display, pps_idx); /* Cycle delay moved from PP_DIVISOR to PP_CONTROL */ - if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv) || + if (display->platform.geminilake || display->platform.broxton || INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) regs->pp_div = INVALID_MMIO_REG; else @@ -543,12 +550,11 @@ _pp_stat_reg(struct intel_dp *intel_dp) static bool edp_have_panel_power(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); - struct drm_i915_private *dev_priv = to_i915(display->drm); lockdep_assert_held(&display->pps.mutex); - if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && - intel_dp->pps.pps_pipe == INVALID_PIPE) + if ((display->platform.valleyview || display->platform.cherryview) && + intel_dp->pps.vlv_pps_pipe == INVALID_PIPE) return false; return (intel_de_read(display, _pp_stat_reg(intel_dp)) & PP_ON) != 0; @@ -557,12 +563,11 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp) static bool edp_have_panel_vdd(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); - struct drm_i915_private *dev_priv = to_i915(display->drm); lockdep_assert_held(&display->pps.mutex); - if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && - intel_dp->pps.pps_pipe == INVALID_PIPE) + if ((display->platform.valleyview || display->platform.cherryview) && + intel_dp->pps.vlv_pps_pipe == INVALID_PIPE) return false; return intel_de_read(display, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD; @@ -792,7 +797,8 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) } /* - * Must be paired with intel_pps_off(). + * Must be paired with intel_pps_vdd_off() or - to disable + * both VDD and panel power - intel_pps_off(). * Nested calls to these functions are not allowed since * we drop the lock. Caller must use some higher level * locking to prevent nested calls from other threads. @@ -800,7 +806,6 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp) void intel_pps_vdd_on(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); - struct drm_i915_private *i915 = to_i915(display->drm); intel_wakeref_t wakeref; bool vdd; @@ -810,10 +815,10 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp) vdd = false; with_intel_pps_lock(intel_dp, wakeref) vdd = intel_pps_vdd_on_unlocked(intel_dp); - I915_STATE_WARN(i915, !vdd, "[ENCODER:%d:%s] %s VDD already requested on\n", - dp_to_dig_port(intel_dp)->base.base.base.id, - dp_to_dig_port(intel_dp)->base.base.name, - pps_name(intel_dp)); + INTEL_DISPLAY_STATE_WARN(display, !vdd, "[ENCODER:%d:%s] %s VDD already requested on\n", + dp_to_dig_port(intel_dp)->base.base.base.id, + dp_to_dig_port(intel_dp)->base.base.name, + pps_name(intel_dp)); } static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp) @@ -852,8 +857,10 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp) intel_de_read(display, pp_stat_reg), intel_de_read(display, pp_ctrl_reg)); - if ((pp & PANEL_POWER_ON) == 0) + if ((pp & PANEL_POWER_ON) == 0) { intel_dp->pps.panel_power_off_time = ktime_get_boottime(); + intel_dp_invalidate_source_oui(intel_dp); + } intel_display_power_put(dev_priv, intel_aux_power_domain(dig_port), @@ -920,18 +927,17 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp) void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync) { struct intel_display *display = to_intel_display(intel_dp); - struct drm_i915_private *dev_priv = to_i915(display->drm); lockdep_assert_held(&display->pps.mutex); if (!intel_dp_is_edp(intel_dp)) return; - I915_STATE_WARN(dev_priv, !intel_dp->pps.want_panel_vdd, - "[ENCODER:%d:%s] %s VDD not forced on", - dp_to_dig_port(intel_dp)->base.base.base.id, - dp_to_dig_port(intel_dp)->base.base.name, - pps_name(intel_dp)); + INTEL_DISPLAY_STATE_WARN(display, !intel_dp->pps.want_panel_vdd, + "[ENCODER:%d:%s] %s VDD not forced on", + dp_to_dig_port(intel_dp)->base.base.base.id, + dp_to_dig_port(intel_dp)->base.base.name, + pps_name(intel_dp)); intel_dp->pps.want_panel_vdd = false; @@ -941,10 +947,20 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync) edp_panel_vdd_schedule_off(intel_dp); } +void intel_pps_vdd_off(struct intel_dp *intel_dp) +{ + intel_wakeref_t wakeref; + + if (!intel_dp_is_edp(intel_dp)) + return; + + with_intel_pps_lock(intel_dp, wakeref) + intel_pps_vdd_off_unlocked(intel_dp, false); +} + void intel_pps_on_unlocked(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); - struct drm_i915_private *dev_priv = to_i915(display->drm); u32 pp; i915_reg_t pp_ctrl_reg; @@ -969,7 +985,7 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) pp_ctrl_reg = _pp_ctrl_reg(intel_dp); pp = ilk_get_pp_control(intel_dp); - if (IS_IRONLAKE(dev_priv)) { + if (display->platform.ironlake) { /* ILK workaround: disable reset around power sequence */ pp &= ~PANEL_POWER_RESET; intel_de_write(display, pp_ctrl_reg, pp); @@ -985,7 +1001,7 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) 0, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); pp |= PANEL_POWER_ON; - if (!IS_IRONLAKE(dev_priv)) + if (!display->platform.ironlake) pp |= PANEL_POWER_RESET; intel_de_write(display, pp_ctrl_reg, pp); @@ -998,7 +1014,7 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) intel_de_rmw(display, SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE, 0); - if (IS_IRONLAKE(dev_priv)) { + if (display->platform.ironlake) { pp |= PANEL_POWER_RESET; /* restore panel reset bit */ intel_de_write(display, pp_ctrl_reg, pp); intel_de_posting_read(display, pp_ctrl_reg); @@ -1054,6 +1070,8 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp) wait_panel_off(intel_dp); intel_dp->pps.panel_power_off_time = ktime_get_boottime(); + intel_dp_invalidate_source_oui(intel_dp); + /* We got a reference when we enabled the VDD. */ intel_display_power_put(dev_priv, intel_aux_power_domain(dig_port), @@ -1139,7 +1157,7 @@ void intel_pps_backlight_power(struct intel_connector *connector, bool enable) return; drm_dbg_kms(display->drm, "panel power control backlight %s\n", - enable ? "enable" : "disable"); + str_enable_disable(enable)); if (enable) intel_pps_backlight_on(intel_dp); @@ -1151,10 +1169,10 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - enum pipe pipe = intel_dp->pps.pps_pipe; + enum pipe pipe = intel_dp->pps.vlv_pps_pipe; i915_reg_t pp_on_reg = PP_ON_DELAYS(display, pipe); - drm_WARN_ON(display->drm, intel_dp->pps.active_pipe != INVALID_PIPE); + drm_WARN_ON(display->drm, intel_dp->pps.vlv_active_pipe != INVALID_PIPE); if (drm_WARN_ON(display->drm, pipe != PIPE_A && pipe != PIPE_B)) return; @@ -1177,7 +1195,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp) intel_de_write(display, pp_on_reg, 0); intel_de_posting_read(display, pp_on_reg); - intel_dp->pps.pps_pipe = INVALID_PIPE; + intel_dp->pps.vlv_pps_pipe = INVALID_PIPE; } static void vlv_steal_power_sequencer(struct intel_display *display, @@ -1190,12 +1208,12 @@ static void vlv_steal_power_sequencer(struct intel_display *display, for_each_intel_dp(display->drm, encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - drm_WARN(display->drm, intel_dp->pps.active_pipe == pipe, + drm_WARN(display->drm, intel_dp->pps.vlv_active_pipe == pipe, "stealing PPS %c from active [ENCODER:%d:%s]\n", pipe_name(pipe), encoder->base.base.id, encoder->base.name); - if (intel_dp->pps.pps_pipe != pipe) + if (intel_dp->pps.vlv_pps_pipe != pipe) continue; drm_dbg_kms(display->drm, @@ -1208,8 +1226,59 @@ static void vlv_steal_power_sequencer(struct intel_display *display, } } -void vlv_pps_init(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +static enum pipe vlv_active_pipe(struct intel_dp *intel_dp) +{ + struct intel_display *display = to_intel_display(intel_dp); + struct drm_i915_private *dev_priv = to_i915(display->drm); + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + enum pipe pipe; + + if (g4x_dp_port_enabled(dev_priv, intel_dp->output_reg, + encoder->port, &pipe)) + return pipe; + + return INVALID_PIPE; +} + +/* Call on all DP, not just eDP */ +void vlv_pps_pipe_init(struct intel_dp *intel_dp) +{ + intel_dp->pps.vlv_pps_pipe = INVALID_PIPE; + intel_dp->pps.vlv_active_pipe = vlv_active_pipe(intel_dp); +} + +/* Call on all DP, not just eDP */ +void vlv_pps_pipe_reset(struct intel_dp *intel_dp) +{ + intel_wakeref_t wakeref; + + with_intel_pps_lock(intel_dp, wakeref) + intel_dp->pps.vlv_active_pipe = vlv_active_pipe(intel_dp); +} + +enum pipe vlv_pps_backlight_initial_pipe(struct intel_dp *intel_dp) +{ + enum pipe pipe; + + /* + * Figure out the current pipe for the initial backlight setup. If the + * current pipe isn't valid, try the PPS pipe, and if that fails just + * assume pipe A. + */ + pipe = vlv_active_pipe(intel_dp); + + if (pipe != PIPE_A && pipe != PIPE_B) + pipe = intel_dp->pps.vlv_pps_pipe; + + if (pipe != PIPE_A && pipe != PIPE_B) + pipe = PIPE_A; + + return pipe; +} + +/* Call on all DP, not just eDP */ +void vlv_pps_port_enable_unlocked(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(encoder); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -1217,10 +1286,10 @@ void vlv_pps_init(struct intel_encoder *encoder, lockdep_assert_held(&display->pps.mutex); - drm_WARN_ON(display->drm, intel_dp->pps.active_pipe != INVALID_PIPE); + drm_WARN_ON(display->drm, intel_dp->pps.vlv_active_pipe != INVALID_PIPE); - if (intel_dp->pps.pps_pipe != INVALID_PIPE && - intel_dp->pps.pps_pipe != crtc->pipe) { + if (intel_dp->pps.vlv_pps_pipe != INVALID_PIPE && + intel_dp->pps.vlv_pps_pipe != crtc->pipe) { /* * If another power sequencer was being used on this * port previously make sure to turn off vdd there while @@ -1235,13 +1304,13 @@ void vlv_pps_init(struct intel_encoder *encoder, */ vlv_steal_power_sequencer(display, crtc->pipe); - intel_dp->pps.active_pipe = crtc->pipe; + intel_dp->pps.vlv_active_pipe = crtc->pipe; if (!intel_dp_is_edp(intel_dp)) return; /* now it's all ours */ - intel_dp->pps.pps_pipe = crtc->pipe; + intel_dp->pps.vlv_pps_pipe = crtc->pipe; drm_dbg_kms(display->drm, "initializing %s for [ENCODER:%d:%s]\n", @@ -1253,6 +1322,18 @@ void vlv_pps_init(struct intel_encoder *encoder, pps_init_registers(intel_dp, true); } +/* Call on all DP, not just eDP */ +void vlv_pps_port_disable(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + intel_wakeref_t wakeref; + + with_intel_pps_lock(intel_dp, wakeref) + intel_dp->pps.vlv_active_pipe = INVALID_PIPE; +} + static void pps_vdd_init(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); @@ -1555,7 +1636,7 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd /* Haswell doesn't have any port selection bits for the panel * power sequencer any more. */ - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + if (display->platform.valleyview || display->platform.cherryview) { port_sel = PANEL_PORT_SELECT_VLV(port); } else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) { switch (port) { @@ -1602,7 +1683,6 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd void intel_pps_encoder_reset(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); - struct drm_i915_private *i915 = to_i915(display->drm); intel_wakeref_t wakeref; if (!intel_dp_is_edp(intel_dp)) @@ -1613,7 +1693,7 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp) * Reinit the power sequencer also on the resume path, in case * BIOS did something nasty with it. */ - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + if (display->platform.valleyview || display->platform.cherryview) vlv_initial_power_sequencer_setup(intel_dp); pps_init_delays(intel_dp); @@ -1649,11 +1729,10 @@ bool intel_pps_init(struct intel_dp *intel_dp) static void pps_init_late(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); - struct drm_i915_private *i915 = to_i915(display->drm); struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; struct intel_connector *connector = intel_dp->attached_connector; - if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + if (display->platform.valleyview || display->platform.cherryview) return; if (intel_num_pps(display) < 2) @@ -1711,9 +1790,9 @@ void intel_pps_setup(struct intel_display *display) { struct drm_i915_private *i915 = to_i915(display->drm); - if (HAS_PCH_SPLIT(i915) || IS_GEMINILAKE(i915) || IS_BROXTON(i915)) + if (HAS_PCH_SPLIT(i915) || display->platform.geminilake || display->platform.broxton) display->pps.mmio_base = PCH_PPS_BASE; - else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + else if (display->platform.valleyview || display->platform.cherryview) display->pps.mmio_base = VLV_PPS_BASE; else display->pps.mmio_base = PPS_BASE; @@ -1785,7 +1864,7 @@ void assert_pps_unlocked(struct intel_display *display, enum pipe pipe) MISSING_CASE(port_sel); break; } - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + } else if (display->platform.valleyview || display->platform.cherryview) { /* presumably write lock depends on pipe, not port select */ pp_reg = PP_CONTROL(display, pipe); panel_pipe = pipe; @@ -1806,7 +1885,7 @@ void assert_pps_unlocked(struct intel_display *display, enum pipe pipe) ((val & PANEL_UNLOCK_MASK) == PANEL_UNLOCK_REGS)) locked = false; - I915_STATE_WARN(dev_priv, panel_pipe == pipe && locked, - "panel assertion failure, pipe %c regs locked\n", - pipe_name(pipe)); + INTEL_DISPLAY_STATE_WARN(display, panel_pipe == pipe && locked, + "panel assertion failure, pipe %c regs locked\n", + pipe_name(pipe)); } |
