aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Zanoni <paulo.r.zanoni@intel.com>2013-12-06 17:32:13 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-12-10 16:43:14 -0500
commit8a1874559f222efcae0c0c41b180f6e1af6b9d2e (patch)
tree8341b7653d73b4671a88b4d889dc2c255378ed7c
parentd62292c8f778772d1b6ec125d461c8c16fdc0417 (diff)
drm/i915: add initial Runtime PM functions
This patch adds the initial infrastructure to allow a Runtime PM implementation that sets the device to its D3 state. The patch just adds the necessary callbacks and the initial infrastructure. We still don't have any platform that actually uses this infrastructure, we still don't call get/put in all the places we need to, and we don't have any function to save/restore the state of the registers. This is not a problem since no platform uses the code added by this patch. We have a few people simultaneously working on runtime PM, so this initial code could help everybody make their plans. V2: - Move some functions to intel_pm.c - Remove useless pm_runtime_allow() call at init - Remove useless pm_runtime_mark_last_busy() call at get - Use pm_runtime_get_sync() instead of 2 calls - Add a WARN to check if we're really awake V3: - Rebase. V4: - Don't need to call pci_{save,restore}_state and pci_set_power_sate, since they're already called by the PCI layer - Remove wrong pm_runtime_enable() call at init_runtime_pm Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c6
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c36
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h7
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h4
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c55
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c9
6 files changed, 117 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index a5d010c86368..b49571df555f 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -42,6 +42,8 @@
42#include <linux/vga_switcheroo.h> 42#include <linux/vga_switcheroo.h>
43#include <linux/slab.h> 43#include <linux/slab.h>
44#include <acpi/video.h> 44#include <acpi/video.h>
45#include <linux/pm.h>
46#include <linux/pm_runtime.h>
45 47
46#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS]) 48#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
47 49
@@ -1663,6 +1665,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1663 if (IS_GEN5(dev)) 1665 if (IS_GEN5(dev))
1664 intel_gpu_ips_init(dev_priv); 1666 intel_gpu_ips_init(dev_priv);
1665 1667
1668 intel_init_runtime_pm(dev_priv);
1669
1666 return 0; 1670 return 0;
1667 1671
1668out_power_well: 1672out_power_well:
@@ -1708,6 +1712,8 @@ int i915_driver_unload(struct drm_device *dev)
1708 return ret; 1712 return ret;
1709 } 1713 }
1710 1714
1715 intel_fini_runtime_pm(dev_priv);
1716
1711 intel_gpu_ips_teardown(); 1717 intel_gpu_ips_teardown();
1712 1718
1713 /* The i915.ko module is still not prepared to be loaded when 1719 /* The i915.ko module is still not prepared to be loaded when
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 13076db65eb9..7d2136170293 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -502,6 +502,8 @@ static int i915_drm_freeze(struct drm_device *dev)
502 struct drm_i915_private *dev_priv = dev->dev_private; 502 struct drm_i915_private *dev_priv = dev->dev_private;
503 struct drm_crtc *crtc; 503 struct drm_crtc *crtc;
504 504
505 intel_runtime_pm_get(dev_priv);
506
505 /* ignore lid events during suspend */ 507 /* ignore lid events during suspend */
506 mutex_lock(&dev_priv->modeset_restore_lock); 508 mutex_lock(&dev_priv->modeset_restore_lock);
507 dev_priv->modeset_restore = MODESET_SUSPENDED; 509 dev_priv->modeset_restore = MODESET_SUSPENDED;
@@ -686,6 +688,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
686 mutex_lock(&dev_priv->modeset_restore_lock); 688 mutex_lock(&dev_priv->modeset_restore_lock);
687 dev_priv->modeset_restore = MODESET_DONE; 689 dev_priv->modeset_restore = MODESET_DONE;
688 mutex_unlock(&dev_priv->modeset_restore_lock); 690 mutex_unlock(&dev_priv->modeset_restore_lock);
691
692 intel_runtime_pm_put(dev_priv);
689 return error; 693 return error;
690} 694}
691 695
@@ -900,6 +904,36 @@ static int i915_pm_poweroff(struct device *dev)
900 return i915_drm_freeze(drm_dev); 904 return i915_drm_freeze(drm_dev);
901} 905}
902 906
907static int i915_runtime_suspend(struct device *device)
908{
909 struct pci_dev *pdev = to_pci_dev(device);
910 struct drm_device *dev = pci_get_drvdata(pdev);
911 struct drm_i915_private *dev_priv = dev->dev_private;
912
913 WARN_ON(!HAS_RUNTIME_PM(dev));
914
915 DRM_DEBUG_KMS("Suspending device\n");
916
917 dev_priv->pm.suspended = true;
918
919 return 0;
920}
921
922static int i915_runtime_resume(struct device *device)
923{
924 struct pci_dev *pdev = to_pci_dev(device);
925 struct drm_device *dev = pci_get_drvdata(pdev);
926 struct drm_i915_private *dev_priv = dev->dev_private;
927
928 WARN_ON(!HAS_RUNTIME_PM(dev));
929
930 DRM_DEBUG_KMS("Resuming device\n");
931
932 dev_priv->pm.suspended = false;
933
934 return 0;
935}
936
903static const struct dev_pm_ops i915_pm_ops = { 937static const struct dev_pm_ops i915_pm_ops = {
904 .suspend = i915_pm_suspend, 938 .suspend = i915_pm_suspend,
905 .resume = i915_pm_resume, 939 .resume = i915_pm_resume,
@@ -907,6 +941,8 @@ static const struct dev_pm_ops i915_pm_ops = {
907 .thaw = i915_pm_thaw, 941 .thaw = i915_pm_thaw,
908 .poweroff = i915_pm_poweroff, 942 .poweroff = i915_pm_poweroff,
909 .restore = i915_pm_resume, 943 .restore = i915_pm_resume,
944 .runtime_suspend = i915_runtime_suspend,
945 .runtime_resume = i915_runtime_resume,
910}; 946};
911 947
912static const struct vm_operations_struct i915_gem_vm_ops = { 948static const struct vm_operations_struct i915_gem_vm_ops = {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 780f815b6c9f..98fd1c043777 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1289,6 +1289,10 @@ struct i915_package_c8 {
1289 } regsave; 1289 } regsave;
1290}; 1290};
1291 1291
1292struct i915_runtime_pm {
1293 bool suspended;
1294};
1295
1292enum intel_pipe_crc_source { 1296enum intel_pipe_crc_source {
1293 INTEL_PIPE_CRC_SOURCE_NONE, 1297 INTEL_PIPE_CRC_SOURCE_NONE,
1294 INTEL_PIPE_CRC_SOURCE_PLANE1, 1298 INTEL_PIPE_CRC_SOURCE_PLANE1,
@@ -1519,6 +1523,8 @@ typedef struct drm_i915_private {
1519 1523
1520 struct i915_package_c8 pc8; 1524 struct i915_package_c8 pc8;
1521 1525
1526 struct i915_runtime_pm pm;
1527
1522 /* Old dri1 support infrastructure, beware the dragons ya fools entering 1528 /* Old dri1 support infrastructure, beware the dragons ya fools entering
1523 * here! */ 1529 * here! */
1524 struct i915_dri1_state dri1; 1530 struct i915_dri1_state dri1;
@@ -1843,6 +1849,7 @@ struct drm_i915_file_private {
1843#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) 1849#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg)
1844#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) 1850#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev))
1845#define HAS_PC8(dev) (IS_HASWELL(dev)) /* XXX HSW:ULX */ 1851#define HAS_PC8(dev) (IS_HASWELL(dev)) /* XXX HSW:ULX */
1852#define HAS_RUNTIME_PM(dev) false
1846 1853
1847#define INTEL_PCH_DEVICE_ID_MASK 0xff00 1854#define INTEL_PCH_DEVICE_ID_MASK 0xff00
1848#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00 1855#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 79585cddc2cd..4a4effba134b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -862,6 +862,10 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv);
862void gen6_rps_boost(struct drm_i915_private *dev_priv); 862void gen6_rps_boost(struct drm_i915_private *dev_priv);
863void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv); 863void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv);
864void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv); 864void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv);
865void intel_runtime_pm_get(struct drm_i915_private *dev_priv);
866void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
867void intel_init_runtime_pm(struct drm_i915_private *dev_priv);
868void intel_fini_runtime_pm(struct drm_i915_private *dev_priv);
865void ilk_wm_get_hw_state(struct drm_device *dev); 869void ilk_wm_get_hw_state(struct drm_device *dev);
866 870
867 871
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index cd3f511847ec..2590a5c90725 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -31,6 +31,7 @@
31#include "../../../platform/x86/intel_ips.h" 31#include "../../../platform/x86/intel_ips.h"
32#include <linux/module.h> 32#include <linux/module.h>
33#include <drm/i915_powerwell.h> 33#include <drm/i915_powerwell.h>
34#include <linux/pm_runtime.h>
34 35
35/** 36/**
36 * RC6 is a special power stage which allows the GPU to enter an very 37 * RC6 is a special power stage which allows the GPU to enter an very
@@ -5961,6 +5962,60 @@ void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv)
5961 hsw_enable_package_c8(dev_priv); 5962 hsw_enable_package_c8(dev_priv);
5962} 5963}
5963 5964
5965void intel_runtime_pm_get(struct drm_i915_private *dev_priv)
5966{
5967 struct drm_device *dev = dev_priv->dev;
5968 struct device *device = &dev->pdev->dev;
5969
5970 if (!HAS_RUNTIME_PM(dev))
5971 return;
5972
5973 pm_runtime_get_sync(device);
5974 WARN(dev_priv->pm.suspended, "Device still suspended.\n");
5975}
5976
5977void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
5978{
5979 struct drm_device *dev = dev_priv->dev;
5980 struct device *device = &dev->pdev->dev;
5981
5982 if (!HAS_RUNTIME_PM(dev))
5983 return;
5984
5985 pm_runtime_mark_last_busy(device);
5986 pm_runtime_put_autosuspend(device);
5987}
5988
5989void intel_init_runtime_pm(struct drm_i915_private *dev_priv)
5990{
5991 struct drm_device *dev = dev_priv->dev;
5992 struct device *device = &dev->pdev->dev;
5993
5994 dev_priv->pm.suspended = false;
5995
5996 if (!HAS_RUNTIME_PM(dev))
5997 return;
5998
5999 pm_runtime_set_active(device);
6000
6001 pm_runtime_set_autosuspend_delay(device, 10000); /* 10s */
6002 pm_runtime_mark_last_busy(device);
6003 pm_runtime_use_autosuspend(device);
6004}
6005
6006void intel_fini_runtime_pm(struct drm_i915_private *dev_priv)
6007{
6008 struct drm_device *dev = dev_priv->dev;
6009 struct device *device = &dev->pdev->dev;
6010
6011 if (!HAS_RUNTIME_PM(dev))
6012 return;
6013
6014 /* Make sure we're not suspended first. */
6015 pm_runtime_get_sync(device);
6016 pm_runtime_disable(device);
6017}
6018
5964/* Set up chip specific power management-related functions */ 6019/* Set up chip specific power management-related functions */
5965void intel_init_pm(struct drm_device *dev) 6020void intel_init_pm(struct drm_device *dev)
5966{ 6021{
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index e63658e0cfd3..0c4c302aa38c 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -437,6 +437,13 @@ hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
437 } 437 }
438} 438}
439 439
440static void
441assert_device_not_suspended(struct drm_i915_private *dev_priv)
442{
443 WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
444 "Device suspended\n");
445}
446
440#define REG_READ_HEADER(x) \ 447#define REG_READ_HEADER(x) \
441 unsigned long irqflags; \ 448 unsigned long irqflags; \
442 u##x val = 0; \ 449 u##x val = 0; \
@@ -568,6 +575,7 @@ gen6_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace
568 if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ 575 if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
569 __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ 576 __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
570 } \ 577 } \
578 assert_device_not_suspended(dev_priv); \
571 __raw_i915_write##x(dev_priv, reg, val); \ 579 __raw_i915_write##x(dev_priv, reg, val); \
572 if (unlikely(__fifo_ret)) { \ 580 if (unlikely(__fifo_ret)) { \
573 gen6_gt_check_fifodbg(dev_priv); \ 581 gen6_gt_check_fifodbg(dev_priv); \
@@ -583,6 +591,7 @@ hsw_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace)
583 if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ 591 if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
584 __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ 592 __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
585 } \ 593 } \
594 assert_device_not_suspended(dev_priv); \
586 hsw_unclaimed_reg_clear(dev_priv, reg); \ 595 hsw_unclaimed_reg_clear(dev_priv, reg); \
587 __raw_i915_write##x(dev_priv, reg, val); \ 596 __raw_i915_write##x(dev_priv, reg, val); \
588 if (unlikely(__fifo_ret)) { \ 597 if (unlikely(__fifo_ret)) { \