All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Airlie <airlied@gmail.com>
To: dri-devel@lists.freedesktop.org
Subject: [PATCH 4/5] nouveau: add dynamic gpu power off support.
Date: Mon, 10 Sep 2012 14:31:54 +1000	[thread overview]
Message-ID: <1347251515-10136-5-git-send-email-airlied@gmail.com> (raw)
In-Reply-To: <1347251515-10136-1-git-send-email-airlied@gmail.com>

From: Dave Airlie <airlied@redhat.com>

This adds the interfaces for nouveau to dynamically power off
the GPU in an optimus system.

It's based on nouveau git so may not apply everywhere.

Signed-off-by: Dave Airlie <airlied@redhat.com
---
 drivers/gpu/drm/nouveau/nouveau_drm.c |  2 ++
 drivers/gpu/drm/nouveau/nouveau_drm.h |  3 ++
 drivers/gpu/drm/nouveau/nouveau_pm.c  | 57 +++++++++++++++++++++++++++++++++--
 drivers/gpu/drm/nouveau/nouveau_vga.c |  4 ++-
 4 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 9fb56b3..e7735a8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -604,6 +604,8 @@ driver = {
 	.dumb_map_offset = nouveau_display_dumb_map_offset,
 	.dumb_destroy = nouveau_display_dumb_destroy,
 
+	.dynamic_off_check = nouveau_dynamic_power_check,
+	.dynamic_set_state = nouveau_dynamic_power_set_state,
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 #ifdef GIT_REVISION
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h
index ab0c174..f39f814 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.h
@@ -148,4 +148,7 @@ int nouveau_drm_resume(struct pci_dev *);
 		NV_PRINTK(KERN_DEBUG, "D", drm, fmt, ##args);                  \
 } while (0)
 
+bool nouveau_dynamic_power_check(struct drm_device *dev);
+int nouveau_dynamic_power_set_state(struct drm_device *dev, int state);
+
 #endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c
index 3c55ec2..fc132c3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -28,12 +28,12 @@
 #include <linux/power_supply.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
-
+#include <linux/vga_switcheroo.h>
 #include "drmP.h"
-
+#include "drm_crtc_helper.h"
 #include "nouveau_drm.h"
 #include "nouveau_pm.h"
-
+#include "nouveau_acpi.h"
 #include <subdev/bios/gpio.h>
 #include <subdev/gpio.h>
 #include <subdev/timer.h>
@@ -962,6 +962,7 @@ nouveau_pm_init(struct drm_device *dev)
 	register_acpi_notifier(&pm->acpi_nb);
 #endif
 
+	drm_dynamic_power_init(dev);
 	return 0;
 }
 
@@ -1007,3 +1008,53 @@ nouveau_pm_resume(struct drm_device *dev)
 	nouveau_pm_perflvl_set(dev, perflvl);
 	nouveau_pwmfan_set(dev, pm->fan.percent);
 }
+
+/* rules for what we want
+   if we are an optimus laptop,
+   with no active crtc/encoders/connectors
+   with no channel activity for 4-5s
+*/
+
+bool nouveau_dynamic_power_check(struct drm_device *dev)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct drm_crtc *crtc;
+
+	/* are we optimus enabled? */
+	if (!nouveau_is_optimus()) {
+		DRM_DEBUG_DRIVER("failing to power off - not optimus\n");
+		return false;
+	}
+
+	list_for_each_entry(crtc, &drm->dev->mode_config.crtc_list, head) {
+		if (crtc->enabled) {
+			DRM_DEBUG_DRIVER("failing to power off - crtc active\n");
+			return false;
+		}
+	}
+	return true;
+}
+
+int nouveau_dynamic_power_set_state(struct drm_device *dev, int state)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
+
+	if (state == DRM_SWITCH_POWER_DYNAMIC_OFF) {
+		dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
+		drm_kms_helper_poll_disable(drm->dev);
+		vga_switcheroo_set_dynamic_switch(dev->pdev, VGA_SWITCHEROO_OFF, false);
+		nouveau_switcheroo_optimus_dsm();
+		nouveau_drm_suspend(drm->dev->pdev, pmm);
+		vga_switcheroo_set_dynamic_switch(dev->pdev, VGA_SWITCHEROO_OFF, true);
+	} else if (state == DRM_SWITCH_POWER_ON) {
+		vga_switcheroo_set_dynamic_switch(dev->pdev, VGA_SWITCHEROO_ON, true);
+		nouveau_drm_resume(dev->pdev);
+		vga_switcheroo_set_dynamic_switch(dev->pdev, VGA_SWITCHEROO_ON, false);
+		drm_kms_helper_poll_enable(dev);
+		dev->switch_power_state = DRM_SWITCH_POWER_ON;
+	}
+
+	return 0;
+}
+
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index 37fcc9d..539722f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -33,6 +33,8 @@ nouveau_switcheroo_set_state(struct pci_dev *pdev,
 	struct drm_device *dev = pci_get_drvdata(pdev);
 	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
 
+	if (nouveau_is_optimus() && state == VGA_SWITCHEROO_OFF)
+		return;
 	if (state == VGA_SWITCHEROO_ON) {
 		printk(KERN_ERR "VGA switcheroo: switched nouveau on\n");
 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
@@ -80,7 +82,7 @@ nouveau_vga_init(struct nouveau_drm *drm)
 {
 	struct drm_device *dev = drm->dev;
 	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
-	vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, false);
+	vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops, nouveau_is_optimus());
 }
 
 void
-- 
1.7.12

  parent reply	other threads:[~2012-09-10  4:32 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-10  4:31 [RFC] drm dynamic power off support Dave Airlie
2012-09-10  4:31 ` [PATCH 1/5] gpu/vga_switcheroo: add driver control power feature Dave Airlie
2012-09-10  4:31 ` [PATCH 2/5] drm: Add initial dnyamic power off feature Dave Airlie
2012-09-10  7:18   ` Daniel Vetter
2012-09-10  8:23     ` Dave Airlie
2012-09-10  8:36       ` Chris Wilson
2012-09-10 10:55         ` Alan Cox
2012-09-10  9:00       ` Daniel Vetter
2012-09-10 11:07   ` Alan Cox
2012-09-10 11:16     ` Dave Airlie
2012-09-10  4:31 ` [PATCH 3/5] nouveau: Add interface to detect optimus support Dave Airlie
2012-09-10 16:25   ` Lekensteyn
2012-09-10 20:24     ` Dave Airlie
2012-09-10  4:31 ` Dave Airlie [this message]
2012-09-10 16:30   ` [PATCH 4/5] nouveau: add dynamic gpu power off support Peter Wu
2012-09-10  4:31 ` [PATCH 5/5] radeon: add dynamic " Dave Airlie
2012-09-10  5:04 ` [RFC] drm " Dave Airlie
2012-09-10  8:47   ` Takashi Iwai
2012-09-10  8:50     ` Dave Airlie
2012-09-11 13:32       ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1347251515-10136-5-git-send-email-airlied@gmail.com \
    --to=airlied@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.