Commit 5d6f7ea7 authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Daniel Vetter

drm/i915: Add chv cmnlane power wells

CHV has two display PHYs so there are also two cmnlane power wells. Add
the approriate code to power the wells up/down.

Like on VLV we do the cmnreset assert/deassert and the DPLL refclock
enabling at approriate times.

This code actually works on my bsw.
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarImre Deak <imre.deak@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 4811ff4f
...@@ -514,6 +514,7 @@ enum punit_power_well { ...@@ -514,6 +514,7 @@ enum punit_power_well {
PUNIT_POWER_WELL_DPIO_TX_C_LANES_23 = 9, PUNIT_POWER_WELL_DPIO_TX_C_LANES_23 = 9,
PUNIT_POWER_WELL_DPIO_RX0 = 10, PUNIT_POWER_WELL_DPIO_RX0 = 10,
PUNIT_POWER_WELL_DPIO_RX1 = 11, PUNIT_POWER_WELL_DPIO_RX1 = 11,
PUNIT_POWER_WELL_DPIO_CMN_D = 12,
PUNIT_POWER_WELL_NUM, PUNIT_POWER_WELL_NUM,
}; };
......
...@@ -6254,6 +6254,64 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, ...@@ -6254,6 +6254,64 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
vlv_set_power_well(dev_priv, power_well, false); vlv_set_power_well(dev_priv, power_well, false);
} }
static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
enum dpio_phy phy;
WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
/*
* Enable the CRI clock source so we can get at the
* display and the reference clock for VGA
* hotplug / manual detection.
*/
if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
phy = DPIO_PHY0;
I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
DPLL_REFA_CLK_ENABLE_VLV);
I915_WRITE(DPLL(PIPE_B), I915_READ(DPLL(PIPE_B)) |
DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
} else {
phy = DPIO_PHY1;
I915_WRITE(DPLL(PIPE_C), I915_READ(DPLL(PIPE_C)) |
DPLL_REFA_CLK_ENABLE_VLV | DPLL_INTEGRATED_CRI_CLK_VLV);
}
udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
vlv_set_power_well(dev_priv, power_well, true);
/* Poll for phypwrgood signal */
if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1))
DRM_ERROR("Display PHY %d is not power up\n", phy);
I915_WRITE(DISPLAY_PHY_CONTROL,
PHY_COM_LANE_RESET_DEASSERT(phy, I915_READ(DISPLAY_PHY_CONTROL)));
}
static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
enum dpio_phy phy;
WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
phy = DPIO_PHY0;
assert_pll_disabled(dev_priv, PIPE_A);
assert_pll_disabled(dev_priv, PIPE_B);
} else {
phy = DPIO_PHY1;
assert_pll_disabled(dev_priv, PIPE_C);
}
I915_WRITE(DISPLAY_PHY_CONTROL,
PHY_COM_LANE_RESET_ASSERT(phy, I915_READ(DISPLAY_PHY_CONTROL)));
vlv_set_power_well(dev_priv, power_well, false);
}
static void check_power_well_state(struct drm_i915_private *dev_priv, static void check_power_well_state(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well) struct i915_power_well *power_well)
{ {
...@@ -6445,6 +6503,18 @@ EXPORT_SYMBOL_GPL(i915_get_cdclk_freq); ...@@ -6445,6 +6503,18 @@ EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);
BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \ BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
BIT(POWER_DOMAIN_INIT)) BIT(POWER_DOMAIN_INIT))
#define CHV_DPIO_CMN_BC_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
BIT(POWER_DOMAIN_INIT))
#define CHV_DPIO_CMN_D_POWER_DOMAINS ( \
BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) | \
BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) | \
BIT(POWER_DOMAIN_INIT))
static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
.sync_hw = i9xx_always_on_power_well_noop, .sync_hw = i9xx_always_on_power_well_noop,
.enable = i9xx_always_on_power_well_noop, .enable = i9xx_always_on_power_well_noop,
...@@ -6452,6 +6522,13 @@ static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { ...@@ -6452,6 +6522,13 @@ static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
.is_enabled = i9xx_always_on_power_well_enabled, .is_enabled = i9xx_always_on_power_well_enabled,
}; };
static const struct i915_power_well_ops chv_dpio_cmn_power_well_ops = {
.sync_hw = vlv_power_well_sync_hw,
.enable = chv_dpio_cmn_power_well_enable,
.disable = chv_dpio_cmn_power_well_disable,
.is_enabled = vlv_power_well_enabled,
};
static struct i915_power_well i9xx_always_on_power_well[] = { static struct i915_power_well i9xx_always_on_power_well[] = {
{ {
.name = "always-on", .name = "always-on",
...@@ -6581,6 +6658,18 @@ static struct i915_power_well chv_power_wells[] = { ...@@ -6581,6 +6658,18 @@ static struct i915_power_well chv_power_wells[] = {
.domains = VLV_ALWAYS_ON_POWER_DOMAINS, .domains = VLV_ALWAYS_ON_POWER_DOMAINS,
.ops = &i9xx_always_on_power_well_ops, .ops = &i9xx_always_on_power_well_ops,
}, },
{
.name = "dpio-common-bc",
.domains = CHV_DPIO_CMN_BC_POWER_DOMAINS,
.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
.ops = &chv_dpio_cmn_power_well_ops,
},
{
.name = "dpio-common-d",
.domains = CHV_DPIO_CMN_D_POWER_DOMAINS,
.data = PUNIT_POWER_WELL_DPIO_CMN_D,
.ops = &chv_dpio_cmn_power_well_ops,
},
}; };
static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv, static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment