diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2015-07-08 23:45:54 +0300 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-08-26 14:34:41 +0200 |
commit | e0fce78f041014846d77940d3a350a4cffe4ab2b (patch) | |
tree | 9dc6d4a2d889ae3b21138ed20627f9fa49976359 /drivers/gpu/drm/i915/i915_reg.h | |
parent | 5a8fbb7d192b96de3d258164e5fc95b769d698c3 (diff) | |
download | lwn-e0fce78f041014846d77940d3a350a4cffe4ab2b.tar.gz lwn-e0fce78f041014846d77940d3a350a4cffe4ab2b.zip |
drm/i915: Implement PHY lane power gating for CHV
Powergate the PHY lanes when they're not needed. For HDMI all four lanes
are needed always, but for DP we can enable only the needed lanes. To
power down the unused lanes we use some power down override bits in the
DISPLAY_PHY_CONTROL register. Without the overrides it appears that the
hardware always powers on all the lanes. When the port is disabled the
power down override is not needed and the lanes will shut off on their
own. That also means the override is critical to actually be able to
access the DPIO registers before the port is actually enabled.
Additionally the common lanes will power down when not needed. CL1
remains on as long as anything else is on, CL2 will shut down when
all the lanes in the same channel will shut down. There is one exception
for CL2 that will be dealt in a separate patch for clarity.
With potentially some lanes powered down, the DP code now has to check
the number of active lanes before accessing PCS/TX registers. All
registers in powered down blocks will reads as 0xffffffff, and soe we
would drown in warnings from vlv_dpio_read() if we allowed the code
to access all those registers.
Another important detail in the DP code is the "TX latency optimal"
setting. Normally the second TX lane acts as some kind of reset master,
with the other lanes as slaves. But when only a single lane is enabled,
that single lane obviously has to be the master.
A bit of extra care is needed to reconstruct the initial state of the
DISPLAY_PHY_CONTROL register since it can't be read safely. So instead
read the actual lane status from the DPLL/PHY_STATUS registers and
use that to determine which lanes ought to be powergated initially.
We also need to switch the PHY power modes to "deep PSR" to avoid
a hard system hang when powering down the single channel PHY.
Also sprinkle a few debug prints around so that we can monitor the
DISPLAY_PHY_STATUS changes without having to read it and risk
corrupting it.
v2: Add locking to chv_powergate_phy_lanes()
v3: Actually enable dynamic powerdown in the PHY and deal with the
fallout
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_reg.h')
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 211b73ab7780..6918ffab168e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1135,9 +1135,15 @@ enum skl_disp_power_wells { #define _CHV_CMN_DW19_CH0 0x814c #define _CHV_CMN_DW6_CH1 0x8098 +#define DPIO_DYNPWRDOWNEN_CH1 (1 << 28) /* CL2 DW6 only */ #define CHV_CMN_USEDCLKCHANNEL (1 << 13) + #define CHV_CMN_DW19(ch) _PIPE(ch, _CHV_CMN_DW19_CH0, _CHV_CMN_DW6_CH1) +#define CHV_CMN_DW28 0x8170 +#define DPIO_CL1POWERDOWNEN (1 << 23) +#define DPIO_DYNPWRDOWNEN_CH0 (1 << 22) + #define CHV_CMN_DW30 0x8178 #define DPIO_LRC_BYPASS (1 << 3) @@ -2192,10 +2198,12 @@ enum skl_disp_power_wells { #define DPIO_PHY_STATUS (VLV_DISPLAY_BASE + 0x6240) #define DPLL_PORTD_READY_MASK (0xf) #define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100) +#define PHY_CH_POWER_DOWN_OVRD_EN(phy, ch) (1 << (2*(phy)+(ch)+27)) #define PHY_LDO_DELAY_0NS 0x0 #define PHY_LDO_DELAY_200NS 0x1 #define PHY_LDO_DELAY_600NS 0x2 #define PHY_LDO_SEQ_DELAY(delay, phy) ((delay) << (2*(phy)+23)) +#define PHY_CH_POWER_DOWN_OVRD(mask, phy, ch) ((mask) << (8*(phy)+4*(ch)+11)) #define PHY_CH_SU_PSR 0x1 #define PHY_CH_DEEP_PSR 0x7 #define PHY_CH_POWER_MODE(mode, phy, ch) ((mode) << (6*(phy)+3*(ch)+2)) |