@@ -5411,6 +5411,140 @@ static bool i9xx_always_on_power_well_enabled(struct drm_i915_private *dev_priv,
54115411 return true;
54125412}
54135413
5414+ static void vlv_set_power_well (struct drm_i915_private * dev_priv ,
5415+ struct i915_power_well * power_well , bool enable )
5416+ {
5417+ enum punit_power_well power_well_id = power_well -> data ;
5418+ u32 mask ;
5419+ u32 state ;
5420+ u32 ctrl ;
5421+
5422+ mask = PUNIT_PWRGT_MASK (power_well_id );
5423+ state = enable ? PUNIT_PWRGT_PWR_ON (power_well_id ) :
5424+ PUNIT_PWRGT_PWR_GATE (power_well_id );
5425+
5426+ mutex_lock (& dev_priv -> rps .hw_lock );
5427+
5428+ #define COND \
5429+ ((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
5430+
5431+ if (COND )
5432+ goto out ;
5433+
5434+ ctrl = vlv_punit_read (dev_priv , PUNIT_REG_PWRGT_CTRL );
5435+ ctrl &= ~mask ;
5436+ ctrl |= state ;
5437+ vlv_punit_write (dev_priv , PUNIT_REG_PWRGT_CTRL , ctrl );
5438+
5439+ if (wait_for (COND , 100 ))
5440+ DRM_ERROR ("timout setting power well state %08x (%08x)\n" ,
5441+ state ,
5442+ vlv_punit_read (dev_priv , PUNIT_REG_PWRGT_CTRL ));
5443+
5444+ #undef COND
5445+
5446+ out :
5447+ mutex_unlock (& dev_priv -> rps .hw_lock );
5448+ }
5449+
5450+ static void vlv_power_well_sync_hw (struct drm_i915_private * dev_priv ,
5451+ struct i915_power_well * power_well )
5452+ {
5453+ vlv_set_power_well (dev_priv , power_well , power_well -> count > 0 );
5454+ }
5455+
5456+ static void vlv_power_well_enable (struct drm_i915_private * dev_priv ,
5457+ struct i915_power_well * power_well )
5458+ {
5459+ vlv_set_power_well (dev_priv , power_well , true);
5460+ }
5461+
5462+ static void vlv_power_well_disable (struct drm_i915_private * dev_priv ,
5463+ struct i915_power_well * power_well )
5464+ {
5465+ vlv_set_power_well (dev_priv , power_well , false);
5466+ }
5467+
5468+ static bool vlv_power_well_enabled (struct drm_i915_private * dev_priv ,
5469+ struct i915_power_well * power_well )
5470+ {
5471+ int power_well_id = power_well -> data ;
5472+ bool enabled = false;
5473+ u32 mask ;
5474+ u32 state ;
5475+ u32 ctrl ;
5476+
5477+ mask = PUNIT_PWRGT_MASK (power_well_id );
5478+ ctrl = PUNIT_PWRGT_PWR_ON (power_well_id );
5479+
5480+ mutex_lock (& dev_priv -> rps .hw_lock );
5481+
5482+ state = vlv_punit_read (dev_priv , PUNIT_REG_PWRGT_STATUS ) & mask ;
5483+ /*
5484+ * We only ever set the power-on and power-gate states, anything
5485+ * else is unexpected.
5486+ */
5487+ WARN_ON (state != PUNIT_PWRGT_PWR_ON (power_well_id ) &&
5488+ state != PUNIT_PWRGT_PWR_GATE (power_well_id ));
5489+ if (state == ctrl )
5490+ enabled = true;
5491+
5492+ /*
5493+ * A transient state at this point would mean some unexpected party
5494+ * is poking at the power controls too.
5495+ */
5496+ ctrl = vlv_punit_read (dev_priv , PUNIT_REG_PWRGT_CTRL ) & mask ;
5497+ WARN_ON (ctrl != state );
5498+
5499+ mutex_unlock (& dev_priv -> rps .hw_lock );
5500+
5501+ return enabled ;
5502+ }
5503+
5504+ static void vlv_display_power_well_enable (struct drm_i915_private * dev_priv ,
5505+ struct i915_power_well * power_well )
5506+ {
5507+ WARN_ON_ONCE (power_well -> data != PUNIT_POWER_WELL_DISP2D );
5508+
5509+ vlv_set_power_well (dev_priv , power_well , true);
5510+
5511+ spin_lock_irq (& dev_priv -> irq_lock );
5512+ valleyview_enable_display_irqs (dev_priv );
5513+ spin_unlock_irq (& dev_priv -> irq_lock );
5514+
5515+ /*
5516+ * During driver initialization we need to defer enabling hotplug
5517+ * processing until fbdev is set up.
5518+ */
5519+ if (dev_priv -> enable_hotplug_processing )
5520+ intel_hpd_init (dev_priv -> dev );
5521+
5522+ i915_redisable_vga_power_on (dev_priv -> dev );
5523+ }
5524+
5525+ static void vlv_display_power_well_disable (struct drm_i915_private * dev_priv ,
5526+ struct i915_power_well * power_well )
5527+ {
5528+ struct drm_device * dev = dev_priv -> dev ;
5529+ enum pipe pipe ;
5530+
5531+ WARN_ON_ONCE (power_well -> data != PUNIT_POWER_WELL_DISP2D );
5532+
5533+ spin_lock_irq (& dev_priv -> irq_lock );
5534+ for_each_pipe (pipe )
5535+ __intel_set_cpu_fifo_underrun_reporting (dev , pipe , false );
5536+
5537+ valleyview_disable_display_irqs (dev_priv );
5538+ spin_unlock_irq (& dev_priv -> irq_lock );
5539+
5540+ spin_lock_irq (& dev -> vbl_lock );
5541+ for_each_pipe (pipe )
5542+ reset_vblank_counter (dev , pipe );
5543+ spin_unlock_irq (& dev -> vbl_lock );
5544+
5545+ vlv_set_power_well (dev_priv , power_well , false);
5546+ }
5547+
54145548static void check_power_well_state (struct drm_i915_private * dev_priv ,
54155549 struct i915_power_well * power_well )
54165550{
@@ -5543,6 +5677,35 @@ EXPORT_SYMBOL_GPL(i915_release_power_well);
55435677 (POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) | \
55445678 BIT(POWER_DOMAIN_INIT))
55455679
5680+ #define VLV_ALWAYS_ON_POWER_DOMAINS BIT(POWER_DOMAIN_INIT)
5681+ #define VLV_DISPLAY_POWER_DOMAINS POWER_DOMAIN_MASK
5682+
5683+ #define VLV_DPIO_CMN_BC_POWER_DOMAINS ( \
5684+ BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
5685+ BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
5686+ BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
5687+ BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
5688+ BIT(POWER_DOMAIN_PORT_CRT) | \
5689+ BIT(POWER_DOMAIN_INIT))
5690+
5691+ #define VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS ( \
5692+ BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) | \
5693+ BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
5694+ BIT(POWER_DOMAIN_INIT))
5695+
5696+ #define VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS ( \
5697+ BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) | \
5698+ BIT(POWER_DOMAIN_INIT))
5699+
5700+ #define VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS ( \
5701+ BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) | \
5702+ BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
5703+ BIT(POWER_DOMAIN_INIT))
5704+
5705+ #define VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS ( \
5706+ BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) | \
5707+ BIT(POWER_DOMAIN_INIT))
5708+
55465709static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
55475710 .sync_hw = i9xx_always_on_power_well_noop ,
55485711 .enable = i9xx_always_on_power_well_noop ,
@@ -5594,6 +5757,77 @@ static struct i915_power_well bdw_power_wells[] = {
55945757 },
55955758};
55965759
5760+ static const struct i915_power_well_ops vlv_display_power_well_ops = {
5761+ .sync_hw = vlv_power_well_sync_hw ,
5762+ .enable = vlv_display_power_well_enable ,
5763+ .disable = vlv_display_power_well_disable ,
5764+ .is_enabled = vlv_power_well_enabled ,
5765+ };
5766+
5767+ static const struct i915_power_well_ops vlv_dpio_power_well_ops = {
5768+ .sync_hw = vlv_power_well_sync_hw ,
5769+ .enable = vlv_power_well_enable ,
5770+ .disable = vlv_power_well_disable ,
5771+ .is_enabled = vlv_power_well_enabled ,
5772+ };
5773+
5774+ static struct i915_power_well vlv_power_wells [] = {
5775+ {
5776+ .name = "always-on" ,
5777+ .always_on = 1 ,
5778+ .domains = VLV_ALWAYS_ON_POWER_DOMAINS ,
5779+ .ops = & i9xx_always_on_power_well_ops ,
5780+ },
5781+ {
5782+ .name = "display" ,
5783+ .domains = VLV_DISPLAY_POWER_DOMAINS ,
5784+ .data = PUNIT_POWER_WELL_DISP2D ,
5785+ .ops = & vlv_display_power_well_ops ,
5786+ },
5787+ {
5788+ .name = "dpio-common" ,
5789+ .domains = VLV_DPIO_CMN_BC_POWER_DOMAINS ,
5790+ .data = PUNIT_POWER_WELL_DPIO_CMN_BC ,
5791+ .ops = & vlv_dpio_power_well_ops ,
5792+ },
5793+ {
5794+ .name = "dpio-tx-b-01" ,
5795+ .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
5796+ VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
5797+ VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
5798+ VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS ,
5799+ .ops = & vlv_dpio_power_well_ops ,
5800+ .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01 ,
5801+ },
5802+ {
5803+ .name = "dpio-tx-b-23" ,
5804+ .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
5805+ VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
5806+ VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
5807+ VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS ,
5808+ .ops = & vlv_dpio_power_well_ops ,
5809+ .data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23 ,
5810+ },
5811+ {
5812+ .name = "dpio-tx-c-01" ,
5813+ .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
5814+ VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
5815+ VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
5816+ VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS ,
5817+ .ops = & vlv_dpio_power_well_ops ,
5818+ .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01 ,
5819+ },
5820+ {
5821+ .name = "dpio-tx-c-23" ,
5822+ .domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
5823+ VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
5824+ VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
5825+ VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS ,
5826+ .ops = & vlv_dpio_power_well_ops ,
5827+ .data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23 ,
5828+ },
5829+ };
5830+
55975831#define set_power_wells (power_domains , __power_wells ) ({ \
55985832 (power_domains)->power_wells = (__power_wells); \
55995833 (power_domains)->power_well_count = ARRAY_SIZE(__power_wells); \
@@ -5615,6 +5849,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
56155849 } else if (IS_BROADWELL (dev_priv -> dev )) {
56165850 set_power_wells (power_domains , bdw_power_wells );
56175851 hsw_pwr = power_domains ;
5852+ } else if (IS_VALLEYVIEW (dev_priv -> dev )) {
5853+ set_power_wells (power_domains , vlv_power_wells );
56185854 } else {
56195855 set_power_wells (power_domains , i9xx_always_on_power_well );
56205856 }
0 commit comments