Re: [Intel-gfx] [PATCH v2 25/25] drm/i915: vlv: add runtime PM support

2014-04-16 Thread Ville Syrjälä
On Mon, Apr 14, 2014 at 08:24:46PM +0300, Imre Deak wrote:
 Add runtime PM support for VLV, but leave it disabled. The next patch
 enables it.
 
 The suspend/resume sequence used is based on [1] and [2]. In practice we
 depend on the GT RC6 mechanism to save the HW context depending on the
 render and media power wells. By the time we run the runtime suspend
 callback the display side is also off and the HW context for that is
 managed by the display power domain framework.
 
 Besides the above there are Gunit registers that depend on a system-wide
 power well. This power well goes off once the device enters any of the
 S0i[R123] states. To handle this scenario, save/restore these Gunit
 registers. Note that this is not the complete register set dictated by
 [2], to remove some overhead, registers that are known not to be used are
 ignored. Also some registers are fully setup by initialization functions
 called during resume, these are not saved either. The list of registers
 can be further reduced, see the TODO note in the code.
 
 [1] VLV_gfx_clocking_PM_reset_y12w21d3 / Driver D3 entry/exit
 [2] VLV2_S0IXRegs
 
 Signed-off-by: Imre Deak imre.d...@intel.com
 ---
  drivers/gpu/drm/i915/i915_drv.c | 327 
 
  drivers/gpu/drm/i915/i915_drv.h |  62 
  2 files changed, 389 insertions(+)
 
 diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
 index 08e210c..bc206dd 100644
 --- a/drivers/gpu/drm/i915/i915_drv.c
 +++ b/drivers/gpu/drm/i915/i915_drv.c
 @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private 
 *dev_priv)
   return 0;
  }
  
 +/*
 + * Save all Gunit registers that may be lost after a D3 and a subsequent
 + * S0i[R123] transition. The list of registers needing a save/restore is
 + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
 + * registers in the following way:
 + * - Driver: saved/restored by the driver
 + * - Punit : saved/restored by the Punit firmware
 + * - No, w/o marking: no need to save/restore, since the register is R/O or
 + *used internally by the HW in a way that doesn't depend
 + *keeping the content across a suspend/resume.
 + * - Debug : used for debugging
 + *
 + * We save/restore all registers marked with 'Driver', with the following
 + * exceptions:
 + * - Registers out of use, including also registers marked with 'Debug'.
 + *   These have no effect on the driver's operation, so we don't save/restore
 + *   them to reduce the overhead.
 + * - Registers that are fully setup by an initialization function called from
 + *   the resume path. For example many clock gating and RPS/RC6 registers.
 + * - Registers that provide the right functionality with their reset 
 defaults.
 + *
 + * TODO: Except for registers that based on the above 3 criteria can be 
 safely
 + * ignored, we save/restore all others, practically treating the HW context 
 as
 + * a black-box for the driver. Further investigation is needed to reduce the
 + * saved/restored registers even further, by following the same 3 criteria.
 + */
 +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
 +{
 + struct vlv_s0ix_state *s = dev_priv-vlv_s0ix_state;
 + int i;
 +
 + /* GAM 0x4000-0x4770 */
 + s-wr_watermark = I915_READ(GEN7_WR_WATERMARK);
 + s-gfx_prio_ctrl= I915_READ(GEN7_GFX_PRIO_CTRL);
 + s-arb_mode = I915_READ(ARB_MODE);
 + s-gfx_pend_tlb0= I915_READ(GEN7_GFX_PEND_TLB0);
 + s-gfx_pend_tlb1= I915_READ(GEN7_GFX_PEND_TLB1);
 +
 + for (i = 0; i  ARRAY_SIZE(s-lra_limits); i++)
 + s-lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
 +
 + s-media_max_req_count  = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
 + s-gfx_max_req_count= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
 +
 + s-render_hwsp  = I915_READ(RENDER_HWS_PGA_GEN7);
 + s-ecochk   = I915_READ(GAM_ECOCHK);
 + s-bsd_hwsp = I915_READ(BSD_HWS_PGA_GEN7);
 + s-blt_hwsp = I915_READ(BLT_HWS_PGA_GEN7);
 +
 + s-tlb_rd_addr  = I915_READ(GEN7_TLB_RD_ADDR);
 +
 + /* MBC 0x9024-0x91D0, 0x8500 */
 + s-g3dctl   = I915_READ(GEN7_G3DCTL);
 + s-gsckgctl = I915_READ(GEN7_GSCKGCTL);
 + s-mbctl= I915_READ(GEN6_MBCTL);
 +
 + /* GCP 0x9400-0x9424, 0x8100-0x810C */
 + s-ucgctl1  = I915_READ(GEN6_UCGCTL1);
 + s-ucgctl3  = I915_READ(GEN7_UCGCTL3);
 + s-rcgctl1  = I915_READ(GEN7_RCGCTL1);
 + s-rcgctl2  = I915_READ(GEN7_RCGCTL2);
 + s-rstctl   = I915_READ(GEN7_RSTCTL);
 + s-misccpctl= I915_READ(GEN7_MISCCPCTL);
 +
 + /* GPM 0xA000-0xAA84, 0x8000-0x80FC */
 + s-gfxpause = I915_READ(GEN7_GFXPAUSE);
 + s-rpdeuhwtc= I915_READ(GEN7_RPDEUHWTC);
 + s-rpdeuc   

Re: [Intel-gfx] [PATCH v2 25/25] drm/i915: vlv: add runtime PM support

2014-04-16 Thread Daniel Vetter
On Mon, Apr 14, 2014 at 08:24:46PM +0300, Imre Deak wrote:
 Add runtime PM support for VLV, but leave it disabled. The next patch
 enables it.
 
 The suspend/resume sequence used is based on [1] and [2]. In practice we
 depend on the GT RC6 mechanism to save the HW context depending on the
 render and media power wells. By the time we run the runtime suspend
 callback the display side is also off and the HW context for that is
 managed by the display power domain framework.
 
 Besides the above there are Gunit registers that depend on a system-wide
 power well. This power well goes off once the device enters any of the
 S0i[R123] states. To handle this scenario, save/restore these Gunit
 registers. Note that this is not the complete register set dictated by
 [2], to remove some overhead, registers that are known not to be used are
 ignored. Also some registers are fully setup by initialization functions
 called during resume, these are not saved either. The list of registers
 can be further reduced, see the TODO note in the code.
 
 [1] VLV_gfx_clocking_PM_reset_y12w21d3 / Driver D3 entry/exit
 [2] VLV2_S0IXRegs
 
 Signed-off-by: Imre Deak imre.d...@intel.com
 ---
  drivers/gpu/drm/i915/i915_drv.c | 327 
 
  drivers/gpu/drm/i915/i915_drv.h |  62 
  2 files changed, 389 insertions(+)
 
 diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
 index 08e210c..bc206dd 100644
 --- a/drivers/gpu/drm/i915/i915_drv.c
 +++ b/drivers/gpu/drm/i915/i915_drv.c
 @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private 
 *dev_priv)
   return 0;
  }
  
 +/*
 + * Save all Gunit registers that may be lost after a D3 and a subsequent
 + * S0i[R123] transition. The list of registers needing a save/restore is
 + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
 + * registers in the following way:
 + * - Driver: saved/restored by the driver
 + * - Punit : saved/restored by the Punit firmware
 + * - No, w/o marking: no need to save/restore, since the register is R/O or
 + *used internally by the HW in a way that doesn't depend
 + *keeping the content across a suspend/resume.
 + * - Debug : used for debugging
 + *
 + * We save/restore all registers marked with 'Driver', with the following
 + * exceptions:
 + * - Registers out of use, including also registers marked with 'Debug'.
 + *   These have no effect on the driver's operation, so we don't save/restore
 + *   them to reduce the overhead.
 + * - Registers that are fully setup by an initialization function called from
 + *   the resume path. For example many clock gating and RPS/RC6 registers.
 + * - Registers that provide the right functionality with their reset 
 defaults.
 + *
 + * TODO: Except for registers that based on the above 3 criteria can be 
 safely
 + * ignored, we save/restore all others, practically treating the HW context 
 as
 + * a black-box for the driver. Further investigation is needed to reduce the
 + * saved/restored registers even further, by following the same 3 criteria.
 + */
 +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
 +{
 + struct vlv_s0ix_state *s = dev_priv-vlv_s0ix_state;
 + int i;
 +
 + /* GAM 0x4000-0x4770 */
 + s-wr_watermark = I915_READ(GEN7_WR_WATERMARK);
 + s-gfx_prio_ctrl= I915_READ(GEN7_GFX_PRIO_CTRL);
 + s-arb_mode = I915_READ(ARB_MODE);
 + s-gfx_pend_tlb0= I915_READ(GEN7_GFX_PEND_TLB0);
 + s-gfx_pend_tlb1= I915_READ(GEN7_GFX_PEND_TLB1);
 +
 + for (i = 0; i  ARRAY_SIZE(s-lra_limits); i++)
 + s-lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
 +
 + s-media_max_req_count  = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
 + s-gfx_max_req_count= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
 +
 + s-render_hwsp  = I915_READ(RENDER_HWS_PGA_GEN7);
 + s-ecochk   = I915_READ(GAM_ECOCHK);
 + s-bsd_hwsp = I915_READ(BSD_HWS_PGA_GEN7);
 + s-blt_hwsp = I915_READ(BLT_HWS_PGA_GEN7);
 +
 + s-tlb_rd_addr  = I915_READ(GEN7_TLB_RD_ADDR);
 +
 + /* MBC 0x9024-0x91D0, 0x8500 */
 + s-g3dctl   = I915_READ(GEN7_G3DCTL);
 + s-gsckgctl = I915_READ(GEN7_GSCKGCTL);
 + s-mbctl= I915_READ(GEN6_MBCTL);
 +
 + /* GCP 0x9400-0x9424, 0x8100-0x810C */
 + s-ucgctl1  = I915_READ(GEN6_UCGCTL1);
 + s-ucgctl3  = I915_READ(GEN7_UCGCTL3);
 + s-rcgctl1  = I915_READ(GEN7_RCGCTL1);
 + s-rcgctl2  = I915_READ(GEN7_RCGCTL2);
 + s-rstctl   = I915_READ(GEN7_RSTCTL);
 + s-misccpctl= I915_READ(GEN7_MISCCPCTL);
 +
 + /* GPM 0xA000-0xAA84, 0x8000-0x80FC */
 + s-gfxpause = I915_READ(GEN7_GFXPAUSE);
 + s-rpdeuhwtc= I915_READ(GEN7_RPDEUHWTC);
 + s-rpdeuc   

Re: [Intel-gfx] [PATCH v2 25/25] drm/i915: vlv: add runtime PM support

2014-04-16 Thread Imre Deak
On Wed, 2014-04-16 at 16:53 +0200, Daniel Vetter wrote:
 On Mon, Apr 14, 2014 at 08:24:46PM +0300, Imre Deak wrote:
  Add runtime PM support for VLV, but leave it disabled. The next patch
  enables it.
  
  The suspend/resume sequence used is based on [1] and [2]. In practice we
  depend on the GT RC6 mechanism to save the HW context depending on the
  render and media power wells. By the time we run the runtime suspend
  callback the display side is also off and the HW context for that is
  managed by the display power domain framework.
  
  Besides the above there are Gunit registers that depend on a system-wide
  power well. This power well goes off once the device enters any of the
  S0i[R123] states. To handle this scenario, save/restore these Gunit
  registers. Note that this is not the complete register set dictated by
  [2], to remove some overhead, registers that are known not to be used are
  ignored. Also some registers are fully setup by initialization functions
  called during resume, these are not saved either. The list of registers
  can be further reduced, see the TODO note in the code.
  
  [1] VLV_gfx_clocking_PM_reset_y12w21d3 / Driver D3 entry/exit
  [2] VLV2_S0IXRegs
  
  Signed-off-by: Imre Deak imre.d...@intel.com
  ---
   drivers/gpu/drm/i915/i915_drv.c | 327 
  
   drivers/gpu/drm/i915/i915_drv.h |  62 
   2 files changed, 389 insertions(+)
  
  diff --git a/drivers/gpu/drm/i915/i915_drv.c 
  b/drivers/gpu/drm/i915/i915_drv.c
  index 08e210c..bc206dd 100644
  --- a/drivers/gpu/drm/i915/i915_drv.c
  +++ b/drivers/gpu/drm/i915/i915_drv.c
  @@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private 
  *dev_priv)
  return 0;
   }
   
  +/*
  + * Save all Gunit registers that may be lost after a D3 and a subsequent
  + * S0i[R123] transition. The list of registers needing a save/restore is
  + * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
  + * registers in the following way:
  + * - Driver: saved/restored by the driver
  + * - Punit : saved/restored by the Punit firmware
  + * - No, w/o marking: no need to save/restore, since the register is R/O or
  + *used internally by the HW in a way that doesn't 
  depend
  + *keeping the content across a suspend/resume.
  + * - Debug : used for debugging
  + *
  + * We save/restore all registers marked with 'Driver', with the following
  + * exceptions:
  + * - Registers out of use, including also registers marked with 'Debug'.
  + *   These have no effect on the driver's operation, so we don't 
  save/restore
  + *   them to reduce the overhead.
  + * - Registers that are fully setup by an initialization function called 
  from
  + *   the resume path. For example many clock gating and RPS/RC6 registers.
  + * - Registers that provide the right functionality with their reset 
  defaults.
  + *
  + * TODO: Except for registers that based on the above 3 criteria can be 
  safely
  + * ignored, we save/restore all others, practically treating the HW 
  context as
  + * a black-box for the driver. Further investigation is needed to reduce 
  the
  + * saved/restored registers even further, by following the same 3 criteria.
  + */
  +static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
  +{
  +   struct vlv_s0ix_state *s = dev_priv-vlv_s0ix_state;
  +   int i;
  +
  +   /* GAM 0x4000-0x4770 */
  +   s-wr_watermark = I915_READ(GEN7_WR_WATERMARK);
  +   s-gfx_prio_ctrl= I915_READ(GEN7_GFX_PRIO_CTRL);
  +   s-arb_mode = I915_READ(ARB_MODE);
  +   s-gfx_pend_tlb0= I915_READ(GEN7_GFX_PEND_TLB0);
  +   s-gfx_pend_tlb1= I915_READ(GEN7_GFX_PEND_TLB1);
  +
  +   for (i = 0; i  ARRAY_SIZE(s-lra_limits); i++)
  +   s-lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
  +
  +   s-media_max_req_count  = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
  +   s-gfx_max_req_count= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
  +
  +   s-render_hwsp  = I915_READ(RENDER_HWS_PGA_GEN7);
  +   s-ecochk   = I915_READ(GAM_ECOCHK);
  +   s-bsd_hwsp = I915_READ(BSD_HWS_PGA_GEN7);
  +   s-blt_hwsp = I915_READ(BLT_HWS_PGA_GEN7);
  +
  +   s-tlb_rd_addr  = I915_READ(GEN7_TLB_RD_ADDR);
  +
  +   /* MBC 0x9024-0x91D0, 0x8500 */
  +   s-g3dctl   = I915_READ(GEN7_G3DCTL);
  +   s-gsckgctl = I915_READ(GEN7_GSCKGCTL);
  +   s-mbctl= I915_READ(GEN6_MBCTL);
  +
  +   /* GCP 0x9400-0x9424, 0x8100-0x810C */
  +   s-ucgctl1  = I915_READ(GEN6_UCGCTL1);
  +   s-ucgctl3  = I915_READ(GEN7_UCGCTL3);
  +   s-rcgctl1  = I915_READ(GEN7_RCGCTL1);
  +   s-rcgctl2  = I915_READ(GEN7_RCGCTL2);
  +   s-rstctl   = I915_READ(GEN7_RSTCTL);
  +   s-misccpctl= I915_READ(GEN7_MISCCPCTL);
  +
  +   /* GPM 0xA000-0xAA84, 0x8000-0x80FC */
  +   s-gfxpause  

[Intel-gfx] [PATCH v2 25/25] drm/i915: vlv: add runtime PM support

2014-04-14 Thread Imre Deak
Add runtime PM support for VLV, but leave it disabled. The next patch
enables it.

The suspend/resume sequence used is based on [1] and [2]. In practice we
depend on the GT RC6 mechanism to save the HW context depending on the
render and media power wells. By the time we run the runtime suspend
callback the display side is also off and the HW context for that is
managed by the display power domain framework.

Besides the above there are Gunit registers that depend on a system-wide
power well. This power well goes off once the device enters any of the
S0i[R123] states. To handle this scenario, save/restore these Gunit
registers. Note that this is not the complete register set dictated by
[2], to remove some overhead, registers that are known not to be used are
ignored. Also some registers are fully setup by initialization functions
called during resume, these are not saved either. The list of registers
can be further reduced, see the TODO note in the code.

[1] VLV_gfx_clocking_PM_reset_y12w21d3 / Driver D3 entry/exit
[2] VLV2_S0IXRegs

Signed-off-by: Imre Deak imre.d...@intel.com
---
 drivers/gpu/drm/i915/i915_drv.c | 327 
 drivers/gpu/drm/i915/i915_drv.h |  62 
 2 files changed, 389 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 08e210c..bc206dd 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -911,6 +911,198 @@ static int hsw_runtime_resume(struct drm_i915_private 
*dev_priv)
return 0;
 }
 
+/*
+ * Save all Gunit registers that may be lost after a D3 and a subsequent
+ * S0i[R123] transition. The list of registers needing a save/restore is
+ * defined in the VLV2_S0IXRegs document. This documents marks all Gunit
+ * registers in the following way:
+ * - Driver: saved/restored by the driver
+ * - Punit : saved/restored by the Punit firmware
+ * - No, w/o marking: no need to save/restore, since the register is R/O or
+ *used internally by the HW in a way that doesn't depend
+ *keeping the content across a suspend/resume.
+ * - Debug : used for debugging
+ *
+ * We save/restore all registers marked with 'Driver', with the following
+ * exceptions:
+ * - Registers out of use, including also registers marked with 'Debug'.
+ *   These have no effect on the driver's operation, so we don't save/restore
+ *   them to reduce the overhead.
+ * - Registers that are fully setup by an initialization function called from
+ *   the resume path. For example many clock gating and RPS/RC6 registers.
+ * - Registers that provide the right functionality with their reset defaults.
+ *
+ * TODO: Except for registers that based on the above 3 criteria can be safely
+ * ignored, we save/restore all others, practically treating the HW context as
+ * a black-box for the driver. Further investigation is needed to reduce the
+ * saved/restored registers even further, by following the same 3 criteria.
+ */
+static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
+{
+   struct vlv_s0ix_state *s = dev_priv-vlv_s0ix_state;
+   int i;
+
+   /* GAM 0x4000-0x4770 */
+   s-wr_watermark = I915_READ(GEN7_WR_WATERMARK);
+   s-gfx_prio_ctrl= I915_READ(GEN7_GFX_PRIO_CTRL);
+   s-arb_mode = I915_READ(ARB_MODE);
+   s-gfx_pend_tlb0= I915_READ(GEN7_GFX_PEND_TLB0);
+   s-gfx_pend_tlb1= I915_READ(GEN7_GFX_PEND_TLB1);
+
+   for (i = 0; i  ARRAY_SIZE(s-lra_limits); i++)
+   s-lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
+
+   s-media_max_req_count  = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
+   s-gfx_max_req_count= I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
+
+   s-render_hwsp  = I915_READ(RENDER_HWS_PGA_GEN7);
+   s-ecochk   = I915_READ(GAM_ECOCHK);
+   s-bsd_hwsp = I915_READ(BSD_HWS_PGA_GEN7);
+   s-blt_hwsp = I915_READ(BLT_HWS_PGA_GEN7);
+
+   s-tlb_rd_addr  = I915_READ(GEN7_TLB_RD_ADDR);
+
+   /* MBC 0x9024-0x91D0, 0x8500 */
+   s-g3dctl   = I915_READ(GEN7_G3DCTL);
+   s-gsckgctl = I915_READ(GEN7_GSCKGCTL);
+   s-mbctl= I915_READ(GEN6_MBCTL);
+
+   /* GCP 0x9400-0x9424, 0x8100-0x810C */
+   s-ucgctl1  = I915_READ(GEN6_UCGCTL1);
+   s-ucgctl3  = I915_READ(GEN7_UCGCTL3);
+   s-rcgctl1  = I915_READ(GEN7_RCGCTL1);
+   s-rcgctl2  = I915_READ(GEN7_RCGCTL2);
+   s-rstctl   = I915_READ(GEN7_RSTCTL);
+   s-misccpctl= I915_READ(GEN7_MISCCPCTL);
+
+   /* GPM 0xA000-0xAA84, 0x8000-0x80FC */
+   s-gfxpause = I915_READ(GEN7_GFXPAUSE);
+   s-rpdeuhwtc= I915_READ(GEN7_RPDEUHWTC);
+   s-rpdeuc   = I915_READ(GEN7_RPDEUC);
+   s-ecobus   = I915_READ(ECOBUS);
+