|
|
|
@ -5411,6 +5411,140 @@ static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv,
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vlv_set_power_well(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct i915_power_well *power_well, bool enable)
|
|
|
|
|
{
|
|
|
|
|
enum punit_power_well power_well_id = power_well->data;
|
|
|
|
|
u32 mask;
|
|
|
|
|
u32 state;
|
|
|
|
|
u32 ctrl;
|
|
|
|
|
|
|
|
|
|
mask = PUNIT_PWRGT_MASK(power_well_id);
|
|
|
|
|
state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
|
|
|
|
|
PUNIT_PWRGT_PWR_GATE(power_well_id);
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
|
|
|
|
|
#define COND \
|
|
|
|
|
((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
|
|
|
|
|
|
|
|
|
|
if (COND)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
|
|
|
|
|
ctrl &= ~mask;
|
|
|
|
|
ctrl |= state;
|
|
|
|
|
vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
|
|
|
|
|
|
|
|
|
|
if (wait_for(COND, 100))
|
|
|
|
|
DRM_ERROR("timout setting power well state %08x (%08x)\n",
|
|
|
|
|
state,
|
|
|
|
|
vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));
|
|
|
|
|
|
|
|
|
|
#undef COND
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vlv_power_well_sync_hw(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct i915_power_well *power_well)
|
|
|
|
|
{
|
|
|
|
|
vlv_set_power_well(dev_priv, power_well, power_well->count > 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vlv_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct i915_power_well *power_well)
|
|
|
|
|
{
|
|
|
|
|
vlv_set_power_well(dev_priv, power_well, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vlv_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct i915_power_well *power_well)
|
|
|
|
|
{
|
|
|
|
|
vlv_set_power_well(dev_priv, power_well, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct i915_power_well *power_well)
|
|
|
|
|
{
|
|
|
|
|
int power_well_id = power_well->data;
|
|
|
|
|
bool enabled = false;
|
|
|
|
|
u32 mask;
|
|
|
|
|
u32 state;
|
|
|
|
|
u32 ctrl;
|
|
|
|
|
|
|
|
|
|
mask = PUNIT_PWRGT_MASK(power_well_id);
|
|
|
|
|
ctrl = PUNIT_PWRGT_PWR_ON(power_well_id);
|
|
|
|
|
|
|
|
|
|
mutex_lock(&dev_priv->rps.hw_lock);
|
|
|
|
|
|
|
|
|
|
state = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask;
|
|
|
|
|
/*
|
|
|
|
|
* We only ever set the power-on and power-gate states, anything
|
|
|
|
|
* else is unexpected.
|
|
|
|
|
*/
|
|
|
|
|
WARN_ON(state != PUNIT_PWRGT_PWR_ON(power_well_id) &&
|
|
|
|
|
state != PUNIT_PWRGT_PWR_GATE(power_well_id));
|
|
|
|
|
if (state == ctrl)
|
|
|
|
|
enabled = true;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A transient state at this point would mean some unexpected party
|
|
|
|
|
* is poking at the power controls too.
|
|
|
|
|
*/
|
|
|
|
|
ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL) & mask;
|
|
|
|
|
WARN_ON(ctrl != state);
|
|
|
|
|
|
|
|
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
|
|
|
|
|
|
return enabled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct i915_power_well *power_well)
|
|
|
|
|
{
|
|
|
|
|
WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
|
|
|
|
|
|
|
|
|
|
vlv_set_power_well(dev_priv, power_well, true);
|
|
|
|
|
|
|
|
|
|
spin_lock_irq(&dev_priv->irq_lock);
|
|
|
|
|
valleyview_enable_display_irqs(dev_priv);
|
|
|
|
|
spin_unlock_irq(&dev_priv->irq_lock);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* During driver initialization we need to defer enabling hotplug
|
|
|
|
|
* processing until fbdev is set up.
|
|
|
|
|
*/
|
|
|
|
|
if (dev_priv->enable_hotplug_processing)
|
|
|
|
|
intel_hpd_init(dev_priv->dev);
|
|
|
|
|
|
|
|
|
|
i915_redisable_vga_power_on(dev_priv->dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct i915_power_well *power_well)
|
|
|
|
|
{
|
|
|
|
|
struct drm_device *dev = dev_priv->dev;
|
|
|
|
|
enum pipe pipe;
|
|
|
|
|
|
|
|
|
|
WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
|
|
|
|
|
|
|
|
|
|
spin_lock_irq(&dev_priv->irq_lock);
|
|
|
|
|
for_each_pipe(pipe)
|
|
|
|
|
__intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
|
|
|
|
|
|
|
|
|
|
valleyview_disable_display_irqs(dev_priv);
|
|
|
|
|
spin_unlock_irq(&dev_priv->irq_lock);
|
|
|
|
|
|
|
|
|
|
spin_lock_irq(&dev->vbl_lock);
|
|
|
|
|
for_each_pipe(pipe)
|
|
|
|
|
reset_vblank_counter(dev, pipe);
|
|
|
|
|
spin_unlock_irq(&dev->vbl_lock);
|
|
|
|
|
|
|
|
|
|
vlv_set_power_well(dev_priv, power_well, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void check_power_well_state(struct drm_i915_private *dev_priv,
|
|
|
|
|
struct i915_power_well *power_well)
|
|
|
|
|
{
|
|
|
|
@ -5543,6 +5677,35 @@ EXPORT_SYMBOL_GPL(i915_release_power_well);
|
|
|
|
|
(POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) | \
|
|
|
|
|
BIT(POWER_DOMAIN_INIT))
|
|
|
|
|
|
|
|
|
|
#define VLV_ALWAYS_ON_POWER_DOMAINS BIT(POWER_DOMAIN_INIT)
|
|
|
|
|
#define VLV_DISPLAY_POWER_DOMAINS POWER_DOMAIN_MASK
|
|
|
|
|
|
|
|
|
|
#define VLV_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_PORT_CRT) | \
|
|
|
|
|
BIT(POWER_DOMAIN_INIT))
|
|
|
|
|
|
|
|
|
|
#define VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS ( \
|
|
|
|
|
BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
|
|
|
|
|
BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
|
|
|
|
|
BIT(POWER_DOMAIN_INIT))
|
|
|
|
|
|
|
|
|
|
#define VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS ( \
|
|
|
|
|
BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
|
|
|
|
|
BIT(POWER_DOMAIN_INIT))
|
|
|
|
|
|
|
|
|
|
#define VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS ( \
|
|
|
|
|
BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
|
|
|
|
|
BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
|
|
|
|
|
BIT(POWER_DOMAIN_INIT))
|
|
|
|
|
|
|
|
|
|
#define VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS ( \
|
|
|
|
|
BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
|
|
|
|
|
BIT(POWER_DOMAIN_INIT))
|
|
|
|
|
|
|
|
|
|
static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
|
|
|
|
|
.sync_hw = i9xx_always_on_power_well_noop,
|
|
|
|
|
.enable = i9xx_always_on_power_well_noop,
|
|
|
|
@ -5594,6 +5757,77 @@ static struct i915_power_well bdw_power_wells[] = {
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct i915_power_well_ops vlv_display_power_well_ops = {
|
|
|
|
|
.sync_hw = vlv_power_well_sync_hw,
|
|
|
|
|
.enable = vlv_display_power_well_enable,
|
|
|
|
|
.disable = vlv_display_power_well_disable,
|
|
|
|
|
.is_enabled = vlv_power_well_enabled,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const struct i915_power_well_ops vlv_dpio_power_well_ops = {
|
|
|
|
|
.sync_hw = vlv_power_well_sync_hw,
|
|
|
|
|
.enable = vlv_power_well_enable,
|
|
|
|
|
.disable = vlv_power_well_disable,
|
|
|
|
|
.is_enabled = vlv_power_well_enabled,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct i915_power_well vlv_power_wells[] = {
|
|
|
|
|
{
|
|
|
|
|
.name = "always-on",
|
|
|
|
|
.always_on = 1,
|
|
|
|
|
.domains = VLV_ALWAYS_ON_POWER_DOMAINS,
|
|
|
|
|
.ops = &i9xx_always_on_power_well_ops,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.name = "display",
|
|
|
|
|
.domains = VLV_DISPLAY_POWER_DOMAINS,
|
|
|
|
|
.data = PUNIT_POWER_WELL_DISP2D,
|
|
|
|
|
.ops = &vlv_display_power_well_ops,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.name = "dpio-common",
|
|
|
|
|
.domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
|
|
|
|
|
.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
|
|
|
|
|
.ops = &vlv_dpio_power_well_ops,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.name = "dpio-tx-b-01",
|
|
|
|
|
.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
|
|
|
|
|
.ops = &vlv_dpio_power_well_ops,
|
|
|
|
|
.data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.name = "dpio-tx-b-23",
|
|
|
|
|
.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
|
|
|
|
|
.ops = &vlv_dpio_power_well_ops,
|
|
|
|
|
.data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.name = "dpio-tx-c-01",
|
|
|
|
|
.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
|
|
|
|
|
.ops = &vlv_dpio_power_well_ops,
|
|
|
|
|
.data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.name = "dpio-tx-c-23",
|
|
|
|
|
.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
|
|
|
|
|
VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
|
|
|
|
|
.ops = &vlv_dpio_power_well_ops,
|
|
|
|
|
.data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define set_power_wells(power_domains, __power_wells) ({ \
|
|
|
|
|
(power_domains)->power_wells = (__power_wells); \
|
|
|
|
|
(power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \
|
|
|
|
@ -5615,6 +5849,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
|
|
|
|
|
} else if (IS_BROADWELL(dev_priv->dev)) {
|
|
|
|
|
set_power_wells(power_domains, bdw_power_wells);
|
|
|
|
|
hsw_pwr = power_domains;
|
|
|
|
|
} else if (IS_VALLEYVIEW(dev_priv->dev)) {
|
|
|
|
|
set_power_wells(power_domains, vlv_power_wells);
|
|
|
|
|
} else {
|
|
|
|
|
set_power_wells(power_domains, i9xx_always_on_power_well);
|
|
|
|
|
}
|
|
|
|
|