From patchwork Wed Oct 7 21:41:55 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 52355 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n97Lg8Im009561 for ; Wed, 7 Oct 2009 21:42:08 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 45ED59EC53; Wed, 7 Oct 2009 14:42:08 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from outbound-mail-121.bluehost.com (outbound-mail-121.bluehost.com [67.222.38.21]) by gabe.freedesktop.org (Postfix) with SMTP id 5D5139EC4B for ; Wed, 7 Oct 2009 14:42:06 -0700 (PDT) Received: (qmail 14806 invoked by uid 0); 7 Oct 2009 21:42:06 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by outboundproxy4.bluehost.com with SMTP; 7 Oct 2009 21:42:06 -0000 Received: from [75.111.28.251] (helo=jbarnes-g45) by box514.bluehost.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.69) (envelope-from ) id 1MveGs-0002Mx-JY; Wed, 07 Oct 2009 15:42:06 -0600 Date: Wed, 7 Oct 2009 14:41:55 -0700 From: Jesse Barnes To: eric@anholt.net, intel-gfx@lists.freedesktop.org Message-ID: <20091007144155.57b84ad6@jbarnes-g45> X-Mailer: Claws Mail 3.7.2 (GTK+ 2.17.5; i486-pc-linux-gnu) Mime-Version: 1.0 X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 75.111.28.251 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] [PATCH] drm/i915: add render standby support X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.9 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d378a1a..6c1ae48 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -187,6 +187,7 @@ typedef struct drm_i915_private { unsigned int status_gfx_addr; drm_local_map_t hws_map; struct drm_gem_object *hws_obj; + struct drm_gem_object *pwrctx; struct resource mch_res; @@ -279,6 +280,7 @@ typedef struct drm_i915_private { u32 saveDSPBCNTR; u32 saveDSPARB; u32 saveRENDERSTANDBY; + u32 savePWRCTXA; u32 saveHWS; u32 savePIPEACONF; u32 savePIPEBCONF; @@ -979,8 +981,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IGDNG(dev)) #define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IGDNG(dev)) -#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_I965G(dev) || IS_GM45(dev)) \ - && !IS_IGDNG(dev)) +#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_I965G(dev) || \ + IS_GM45(dev)) && !IS_IGDNG(dev)) +#define I915_HAS_RC6(dev) (IS_I965GM(dev) || IS_GM45(dev) || IS_IGDNG_M(dev)) #define PRIMARY_RINGBUFFER_SIZE (128*1024) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index efcfe64..76b74c6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -260,6 +260,8 @@ #define HWS_PGA 0x02080 #define HWS_ADDRESS_MASK 0xfffff000 #define HWS_START_ADDRESS_SHIFT 4 +#define PWRCTXA 0x2088 /* 965GM+ only */ +#define PWRCTX_EN (1<<0) #define IPEIR 0x02088 #define IPEHR 0x0208c #define INSTDONE 0x02090 @@ -769,6 +771,8 @@ /** GM965 GM45 render standby register */ #define MCHBAR_RENDER_STANDBY 0x111B8 +#define RCX_SW_EXIT (1<<23) +#define RSX_STATUS_MASK 0x00700000 #define MCHBAR_GFXEC 0x112f4 /* Energy counter */ #define PEG_BAND_GAP_DATA 0x14d68 diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index bd6d8d9..d561fd9 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -534,8 +534,10 @@ int i915_save_state(struct drm_device *dev) pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); /* Render Standby */ - if (IS_I965G(dev) && IS_MOBILE(dev)) + if (IS_I965G(dev) && IS_MOBILE(dev)) { dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); + dev_priv->savePWRCTXA = I915_READ(PWRCTXA); + } /* Hardware status page */ dev_priv->saveHWS = I915_READ(HWS_PGA); @@ -588,8 +590,10 @@ int i915_restore_state(struct drm_device *dev) pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); /* Render Standby */ - if (IS_I965G(dev) && IS_MOBILE(dev)) + if (IS_I965G(dev) && IS_MOBILE(dev)) { I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY); + I915_WRITE(PWRCTXA, dev_priv->savePWRCTXA); + } /* Hardware status page */ I915_WRITE(HWS_PGA, dev_priv->saveHWS); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 12514ca..a87c1fd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4159,6 +4159,42 @@ void intel_init_clock_gating(struct drm_device *dev) } else if (IS_I830(dev)) { I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE); } + + /* + * GPU can automatically power down the render unit if given a page + * to save state. + */ + if (I915_HAS_RC6(dev)) { + struct drm_gem_object *pwrctx; + struct drm_i915_gem_object *obj_priv; + int ret; + + pwrctx = drm_gem_object_alloc(dev, 4096); + if (!pwrctx) { + DRM_DEBUG("failed to alloc power context, RC6 disabled\n"); + goto out; + } + + ret = i915_gem_object_pin(pwrctx, PAGE_SIZE); + if (ret) { + DRM_DEBUG("failed to pin power context: %d\n", ret); + drm_gem_object_unreference(pwrctx); + goto out; + } + + i915_gem_object_set_to_gtt_domain(pwrctx, 1); + + obj_priv = pwrctx->driver_private; + + I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN); + I915_WRITE(MCHBAR_RENDER_STANDBY, + I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT); + + dev_priv->pwrctx = pwrctx; + } + +out: + return; } /* Set up chip specific display functions */ @@ -4313,6 +4349,11 @@ void intel_modeset_cleanup(struct drm_device *dev) if (dev_priv->display.disable_fbc) dev_priv->display.disable_fbc(dev); + if (dev_priv->pwrctx) { + i915_gem_object_unpin(dev_priv->pwrctx); + drm_gem_object_unreference(dev_priv->pwrctx); + } + drm_mode_config_cleanup(dev); }