From patchwork Mon Sep 10 04:31:54 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Airlie X-Patchwork-Id: 1429751 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 44792DF28C for ; Mon, 10 Sep 2012 04:39:57 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 352789EB34 for ; Sun, 9 Sep 2012 21:39:57 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by gabe.freedesktop.org (Postfix) with ESMTP id 258689E88F for ; Sun, 9 Sep 2012 21:32:04 -0700 (PDT) Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q8A4W3fX014100 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 10 Sep 2012 00:32:03 -0400 Received: from prime.bne.redhat.com (dhcp-40-183.bne.redhat.com [10.64.40.183]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q8A4VvW1023447 for ; Mon, 10 Sep 2012 00:32:03 -0400 From: Dave Airlie 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 Message-Id: <1347251515-10136-5-git-send-email-airlied@gmail.com> In-Reply-To: <1347251515-10136-1-git-send-email-airlied@gmail.com> References: <1347251515-10136-1-git-send-email-airlied@gmail.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org From: Dave Airlie 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 #include #include - +#include #include "drmP.h" - +#include "drm_crtc_helper.h" #include "nouveau_drm.h" #include "nouveau_pm.h" - +#include "nouveau_acpi.h" #include #include #include @@ -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