2008-08-25 15:11:06 -07:00
/*
*
* Copyright 2008 ( c ) Intel Corporation
* Jesse Barnes < jbarnes @ virtuousgeek . org >
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the
* " Software " ) , to deal in the Software without restriction , including
* without limitation the rights to use , copy , modify , merge , publish ,
* distribute , sub license , and / or sell copies of the Software , and to
* permit persons to whom the Software is furnished to do so , subject to
* the following conditions :
*
* The above copyright notice and this permission notice ( including the
* next paragraph ) shall be included in all copies or substantial portions
* of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS
* OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND NON - INFRINGEMENT .
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND / OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN ACTION OF CONTRACT ,
* TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE .
*/
2012-10-02 18:01:07 +01:00
# include <drm/drmP.h>
# include <drm/i915_drm.h>
2009-12-01 11:56:30 -08:00
# include "intel_drv.h"
2012-01-07 23:40:34 -02:00
# include "i915_reg.h"
2008-08-25 15:11:06 -07:00
2011-06-29 00:30:34 -07:00
static void i915_save_display ( struct drm_device * dev )
2009-07-08 14:13:14 +08:00
{
struct drm_i915_private * dev_priv = dev - > dev_private ;
/* Display arbitration control */
2013-01-18 18:29:03 -02:00
if ( INTEL_INFO ( dev ) - > gen < = 4 )
dev_priv - > regfile . saveDSPARB = I915_READ ( DSPARB ) ;
2009-07-08 14:13:14 +08:00
2008-08-25 15:11:06 -07:00
/* LVDS state */
2014-11-12 17:01:10 +02:00
if ( HAS_PCH_IBX ( dev ) | | HAS_PCH_CPT ( dev ) )
dev_priv - > regfile . saveLVDS = I915_READ ( PCH_LVDS ) ;
else if ( INTEL_INFO ( dev ) - > gen < = 4 & & IS_MOBILE ( dev ) & & ! IS_I830 ( dev ) )
dev_priv - > regfile . saveLVDS = I915_READ ( LVDS ) ;
2009-10-21 15:27:01 +08:00
2014-11-12 17:01:10 +02:00
/* Panel power sequencer */
2010-08-14 14:41:23 +01:00
if ( HAS_PCH_SPLIT ( dev ) ) {
2014-11-12 17:01:10 +02:00
dev_priv - > regfile . savePP_CONTROL = I915_READ ( PCH_PP_CONTROL ) ;
2012-11-02 19:55:02 +01:00
dev_priv - > regfile . savePP_ON_DELAYS = I915_READ ( PCH_PP_ON_DELAYS ) ;
dev_priv - > regfile . savePP_OFF_DELAYS = I915_READ ( PCH_PP_OFF_DELAYS ) ;
dev_priv - > regfile . savePP_DIVISOR = I915_READ ( PCH_PP_DIVISOR ) ;
2016-01-06 09:53:41 -08:00
} else if ( INTEL_INFO ( dev ) - > gen < = 4 ) {
2014-11-12 17:01:10 +02:00
dev_priv - > regfile . savePP_CONTROL = I915_READ ( PP_CONTROL ) ;
2012-11-02 19:55:02 +01:00
dev_priv - > regfile . savePP_ON_DELAYS = I915_READ ( PP_ON_DELAYS ) ;
dev_priv - > regfile . savePP_OFF_DELAYS = I915_READ ( PP_OFF_DELAYS ) ;
dev_priv - > regfile . savePP_DIVISOR = I915_READ ( PP_DIVISOR ) ;
2009-10-21 15:27:01 +08:00
}
2008-08-25 15:11:06 -07:00
2014-01-23 16:49:15 +02:00
/* save FBC interval */
if ( HAS_FBC ( dev ) & & INTEL_INFO ( dev ) - > gen < = 4 & & ! IS_G4X ( dev ) )
dev_priv - > regfile . saveFBC_CONTROL = I915_READ ( FBC_CONTROL ) ;
2008-08-25 15:11:06 -07:00
}
2011-06-29 00:30:34 -07:00
static void i915_restore_display ( struct drm_device * dev )
2008-08-25 15:11:06 -07:00
{
struct drm_i915_private * dev_priv = dev - > dev_private ;
2013-02-19 12:11:38 -08:00
u32 mask = 0xffffffff ;
2008-11-18 12:39:02 +08:00
2008-11-02 23:08:44 -08:00
/* Display arbitration */
2013-01-18 18:29:03 -02:00
if ( INTEL_INFO ( dev ) - > gen < = 4 )
I915_WRITE ( DSPARB , dev_priv - > regfile . saveDSPARB ) ;
2008-08-25 15:11:06 -07:00
2015-02-23 12:03:30 +01:00
mask = ~ LVDS_PORT_EN ;
2013-02-19 12:11:38 -08:00
2014-11-12 17:01:10 +02:00
/* LVDS state */
2013-03-06 20:03:20 -03:00
if ( HAS_PCH_IBX ( dev ) | | HAS_PCH_CPT ( dev ) )
2013-02-19 12:11:38 -08:00
I915_WRITE ( PCH_LVDS , dev_priv - > regfile . saveLVDS & mask ) ;
2013-03-06 20:03:20 -03:00
else if ( INTEL_INFO ( dev ) - > gen < = 4 & & IS_MOBILE ( dev ) & & ! IS_I830 ( dev ) )
2013-02-19 12:11:38 -08:00
I915_WRITE ( LVDS , dev_priv - > regfile . saveLVDS & mask ) ;
2009-10-21 15:27:01 +08:00
2014-11-12 17:01:10 +02:00
/* Panel power sequencer */
2010-08-14 14:41:23 +01:00
if ( HAS_PCH_SPLIT ( dev ) ) {
2012-11-02 19:55:02 +01:00
I915_WRITE ( PCH_PP_ON_DELAYS , dev_priv - > regfile . savePP_ON_DELAYS ) ;
I915_WRITE ( PCH_PP_OFF_DELAYS , dev_priv - > regfile . savePP_OFF_DELAYS ) ;
I915_WRITE ( PCH_PP_DIVISOR , dev_priv - > regfile . savePP_DIVISOR ) ;
I915_WRITE ( PCH_PP_CONTROL , dev_priv - > regfile . savePP_CONTROL ) ;
2016-01-06 09:53:41 -08:00
} else if ( INTEL_INFO ( dev ) - > gen < = 4 ) {
2012-11-02 19:55:02 +01:00
I915_WRITE ( PP_ON_DELAYS , dev_priv - > regfile . savePP_ON_DELAYS ) ;
I915_WRITE ( PP_OFF_DELAYS , dev_priv - > regfile . savePP_OFF_DELAYS ) ;
I915_WRITE ( PP_DIVISOR , dev_priv - > regfile . savePP_DIVISOR ) ;
I915_WRITE ( PP_CONTROL , dev_priv - > regfile . savePP_CONTROL ) ;
2009-10-21 15:27:01 +08:00
}
2008-08-25 15:11:06 -07:00
2010-03-19 17:05:10 +08:00
/* only restore FBC info on the platform that supports FBC*/
2016-01-19 11:35:46 -02:00
intel_fbc_global_disable ( dev_priv ) ;
2014-01-23 16:49:15 +02:00
/* restore FBC interval */
if ( HAS_FBC ( dev ) & & INTEL_INFO ( dev ) - > gen < = 4 & & ! IS_G4X ( dev ) )
I915_WRITE ( FBC_CONTROL , dev_priv - > regfile . saveFBC_CONTROL ) ;
2013-01-25 17:53:22 +01:00
2015-02-23 12:03:30 +01:00
i915_redisable_vga ( dev ) ;
2009-09-14 17:48:42 -04:00
}
int i915_save_state ( struct drm_device * dev )
{
struct drm_i915_private * dev_priv = dev - > dev_private ;
int i ;
2011-06-29 00:30:34 -07:00
mutex_lock ( & dev - > struct_mutex ) ;
2009-09-14 17:48:42 -04:00
i915_save_display ( dev ) ;
2014-12-10 12:16:05 -08:00
if ( IS_GEN4 ( dev ) )
pci_read_config_word ( dev - > pdev , GCDGMBUS ,
& dev_priv - > regfile . saveGCDGMBUS ) ;
2009-09-14 17:48:42 -04:00
/* Cache mode state */
2013-10-11 12:09:29 -07:00
if ( INTEL_INFO ( dev ) - > gen < 7 )
dev_priv - > regfile . saveCACHE_MODE_0 = I915_READ ( CACHE_MODE_0 ) ;
2009-09-14 17:48:42 -04:00
/* Memory Arbitration state */
2012-11-02 19:55:02 +01:00
dev_priv - > regfile . saveMI_ARB_STATE = I915_READ ( MI_ARB_STATE ) ;
2009-09-14 17:48:42 -04:00
/* Scratch space */
2015-09-18 20:03:43 +03:00
if ( IS_GEN2 ( dev_priv ) & & IS_MOBILE ( dev_priv ) ) {
for ( i = 0 ; i < 7 ; i + + ) {
dev_priv - > regfile . saveSWF0 [ i ] = I915_READ ( SWF0 ( i ) ) ;
dev_priv - > regfile . saveSWF1 [ i ] = I915_READ ( SWF1 ( i ) ) ;
}
for ( i = 0 ; i < 3 ; i + + )
dev_priv - > regfile . saveSWF3 [ i ] = I915_READ ( SWF3 ( i ) ) ;
} else if ( IS_GEN2 ( dev_priv ) ) {
for ( i = 0 ; i < 7 ; i + + )
dev_priv - > regfile . saveSWF1 [ i ] = I915_READ ( SWF1 ( i ) ) ;
} else if ( HAS_GMCH_DISPLAY ( dev_priv ) ) {
for ( i = 0 ; i < 16 ; i + + ) {
dev_priv - > regfile . saveSWF0 [ i ] = I915_READ ( SWF0 ( i ) ) ;
dev_priv - > regfile . saveSWF1 [ i ] = I915_READ ( SWF1 ( i ) ) ;
}
for ( i = 0 ; i < 3 ; i + + )
dev_priv - > regfile . saveSWF3 [ i ] = I915_READ ( SWF3 ( i ) ) ;
2009-09-14 17:48:42 -04:00
}
2011-06-29 00:30:34 -07:00
mutex_unlock ( & dev - > struct_mutex ) ;
2009-09-14 17:48:42 -04:00
return 0 ;
}
int i915_restore_state ( struct drm_device * dev )
{
struct drm_i915_private * dev_priv = dev - > dev_private ;
int i ;
2011-06-29 00:30:34 -07:00
mutex_lock ( & dev - > struct_mutex ) ;
2013-06-12 10:15:12 +01:00
i915_gem_restore_fences ( dev ) ;
2014-12-10 12:16:05 -08:00
if ( IS_GEN4 ( dev ) )
pci_write_config_word ( dev - > pdev , GCDGMBUS ,
dev_priv - > regfile . saveGCDGMBUS ) ;
2009-09-14 17:48:42 -04:00
i915_restore_display ( dev ) ;
2008-08-25 15:11:06 -07:00
/* Cache mode state */
2013-10-11 12:09:29 -07:00
if ( INTEL_INFO ( dev ) - > gen < 7 )
I915_WRITE ( CACHE_MODE_0 , dev_priv - > regfile . saveCACHE_MODE_0 |
0xffff0000 ) ;
2008-08-25 15:11:06 -07:00
/* Memory arbitration state */
2012-11-02 19:55:02 +01:00
I915_WRITE ( MI_ARB_STATE , dev_priv - > regfile . saveMI_ARB_STATE | 0xffff0000 ) ;
2008-08-25 15:11:06 -07:00
2015-09-18 20:03:43 +03:00
/* Scratch space */
if ( IS_GEN2 ( dev_priv ) & & IS_MOBILE ( dev_priv ) ) {
for ( i = 0 ; i < 7 ; i + + ) {
I915_WRITE ( SWF0 ( i ) , dev_priv - > regfile . saveSWF0 [ i ] ) ;
I915_WRITE ( SWF1 ( i ) , dev_priv - > regfile . saveSWF1 [ i ] ) ;
}
for ( i = 0 ; i < 3 ; i + + )
I915_WRITE ( SWF3 ( i ) , dev_priv - > regfile . saveSWF3 [ i ] ) ;
} else if ( IS_GEN2 ( dev_priv ) ) {
for ( i = 0 ; i < 7 ; i + + )
I915_WRITE ( SWF1 ( i ) , dev_priv - > regfile . saveSWF1 [ i ] ) ;
} else if ( HAS_GMCH_DISPLAY ( dev_priv ) ) {
for ( i = 0 ; i < 16 ; i + + ) {
I915_WRITE ( SWF0 ( i ) , dev_priv - > regfile . saveSWF0 [ i ] ) ;
I915_WRITE ( SWF1 ( i ) , dev_priv - > regfile . saveSWF1 [ i ] ) ;
}
for ( i = 0 ; i < 3 ; i + + )
I915_WRITE ( SWF3 ( i ) , dev_priv - > regfile . saveSWF3 [ i ] ) ;
2008-08-25 15:11:06 -07:00
}
2011-06-29 00:30:34 -07:00
mutex_unlock ( & dev - > struct_mutex ) ;
2010-07-20 15:44:45 -07:00
intel_i2c_reset ( dev ) ;
2009-12-01 11:56:30 -08:00
2008-08-25 15:11:06 -07:00
return 0 ;
}