1bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/************************************************************************** 2bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Copyright (c) 2009-2011, Intel Corporation. 3bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * All Rights Reserved. 4bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 5bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Permission is hereby granted, free of charge, to any person obtaining a 6bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * copy of this software and associated documentation files (the "Software"), 7bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * to deal in the Software without restriction, including without limitation 8bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * and/or sell copies of the Software, and to permit persons to whom the 10bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Software is furnished to do so, subject to the following conditions: 11bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 12bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * The above copyright notice and this permission notice (including the next 13bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * paragraph) shall be included in all copies or substantial portions of the 14bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Software. 15bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 16bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * SOFTWARE. 23bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 24bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Authors: 25bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Benjamin Defnet <benjamin.r.defnet@intel.com> 26bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Rajesh Poornachandran <rajesh.poornachandran@intel.com> 27bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Massively reworked 28bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Alan Cox <alan@linux.intel.com> 29bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 30bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 31bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox#include "power.h" 32bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox#include "psb_drv.h" 33bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox#include "psb_reg.h" 34bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox#include "psb_intel_reg.h" 35bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox#include <linux/mutex.h> 36bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox#include <linux/pm_runtime.h> 37bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 38bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxstatic struct mutex power_mutex; /* Serialize power ops */ 39bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxstatic spinlock_t power_ctrl_lock; /* Serialize power claim */ 40bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 41bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 42bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_power_init - initialise power manager 43bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @dev: our device 44bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 45bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Set up for power management tracking of our hardware. 46bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 47bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxvoid gma_power_init(struct drm_device *dev) 48bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 49bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_psb_private *dev_priv = dev->dev_private; 50bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 51bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox /* FIXME: Move APM/OSPM base into relevant device code */ 52bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->apm_base = dev_priv->apm_reg & 0xffff; 53bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->ospm_base &= 0xffff; 54bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 55bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->display_power = true; /* We start active */ 56bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->display_count = 0; /* Currently no users */ 57bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->suspended = false; /* And not suspended */ 58bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox spin_lock_init(&power_ctrl_lock); 59bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox mutex_init(&power_mutex); 60bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 61c715bc1bf422543731b8833e899266b8be982a52Kirill A. Shutemov if (dev_priv->ops->init_pm) 62c715bc1bf422543731b8833e899266b8be982a52Kirill A. Shutemov dev_priv->ops->init_pm(dev); 63bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 64bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 65bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 66bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_power_uninit - end power manager 67bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @dev: device to end for 68bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 69bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Undo the effects of gma_power_init 70bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 71bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxvoid gma_power_uninit(struct drm_device *dev) 72bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 73bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pm_runtime_disable(&dev->pdev->dev); 74bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pm_runtime_set_suspended(&dev->pdev->dev); 75bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 76bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 77bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 78bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_suspend_display - suspend the display logic 79bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @dev: our DRM device 80bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 81bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Suspend the display logic of the graphics interface 82bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 83bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxstatic void gma_suspend_display(struct drm_device *dev) 84bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 85bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_psb_private *dev_priv = dev->dev_private; 86bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 87bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox if (dev_priv->suspended) 88bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return; 89bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->ops->save_regs(dev); 90bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->ops->power_down(dev); 91bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->display_power = false; 92bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 93bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 94bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 95bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_resume_display - resume display side logic 96bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 97bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Resume the display hardware restoring state and enabling 98bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * as necessary. 99bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 100bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxstatic void gma_resume_display(struct pci_dev *pdev) 101bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 102bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_device *dev = pci_get_drvdata(pdev); 103bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_psb_private *dev_priv = dev->dev_private; 104bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 105bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox /* turn on the display power island */ 106bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->ops->power_up(dev); 107bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->suspended = false; 108bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->display_power = true; 109bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 110bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); 111bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_write_config_word(pdev, PSB_GMCH_CTRL, 112bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); 113bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->ops->restore_regs(dev); 114bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 115bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 116bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 117bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_suspend_pci - suspend PCI side 118bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @pdev: PCI device 119bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 120bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Perform the suspend processing on our PCI device state 121bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 122bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxstatic void gma_suspend_pci(struct pci_dev *pdev) 123bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 124bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_device *dev = pci_get_drvdata(pdev); 125bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_psb_private *dev_priv = dev->dev_private; 126bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox int bsm, vbt; 127bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 128bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox if (dev_priv->suspended) 129bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return; 130bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 131bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_save_state(pdev); 132bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_read_config_dword(pdev, 0x5C, &bsm); 133648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox dev_priv->regs.saveBSM = bsm; 134bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_read_config_dword(pdev, 0xFC, &vbt); 135648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox dev_priv->regs.saveVBT = vbt; 136bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr); 137bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data); 138bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 139bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_disable_device(pdev); 140bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_set_power_state(pdev, PCI_D3hot); 141bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 142bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->suspended = true; 143bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 144bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 145bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 146bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_resume_pci - resume helper 147bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @dev: our PCI device 148bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 149bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Perform the resume processing on our PCI device state - rewrite 150bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * register state and re-enable the PCI device 151bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 152bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxstatic bool gma_resume_pci(struct pci_dev *pdev) 153bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 154bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_device *dev = pci_get_drvdata(pdev); 155bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_psb_private *dev_priv = dev->dev_private; 156bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox int ret; 157bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 158bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox if (!dev_priv->suspended) 159bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return true; 160bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 161bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_set_power_state(pdev, PCI_D0); 162bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_restore_state(pdev); 163648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox pci_write_config_dword(pdev, 0x5c, dev_priv->regs.saveBSM); 164648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox pci_write_config_dword(pdev, 0xFC, dev_priv->regs.saveVBT); 165bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox /* restoring MSI address and data in PCIx space */ 166bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr); 167bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data); 168bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox ret = pci_enable_device(pdev); 169bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 170bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox if (ret != 0) 171bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_err(&pdev->dev, "pci_enable failed: %d\n", ret); 172bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox else 173bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->suspended = false; 174bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return !dev_priv->suspended; 175bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 176bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 177bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 178bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_power_suspend - bus callback for suspend 179bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @pdev: our PCI device 180bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @state: suspend type 181bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 182bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Called back by the PCI layer during a suspend of the system. We 183bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * perform the necessary shut down steps and save enough state that 184bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * we can undo this when resume is called. 185bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 186bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxint gma_power_suspend(struct device *_dev) 187bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 188bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); 189bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_device *dev = pci_get_drvdata(pdev); 190bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_psb_private *dev_priv = dev->dev_private; 191bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 192bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox mutex_lock(&power_mutex); 193bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox if (!dev_priv->suspended) { 194bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox if (dev_priv->display_count) { 195bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox mutex_unlock(&power_mutex); 19609016a11fc738e82ca1303e2332473b517bbd660Alan Cox dev_err(dev->dev, "GPU hardware busy, cannot suspend\n"); 197bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return -EBUSY; 198bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox } 199bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox psb_irq_uninstall(dev); 200bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox gma_suspend_display(dev); 201bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox gma_suspend_pci(pdev); 202bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox } 203bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox mutex_unlock(&power_mutex); 204bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return 0; 205bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 206bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 207bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 208bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_power_resume - resume power 209bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @pdev: PCI device 210bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 211bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Resume the PCI side of the graphics and then the displays 212bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 213bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxint gma_power_resume(struct device *_dev) 214bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 215bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); 216bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_device *dev = pci_get_drvdata(pdev); 217bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 218bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox mutex_lock(&power_mutex); 219bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox gma_resume_pci(pdev); 220bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox gma_resume_display(pdev); 221bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox psb_irq_preinstall(dev); 222bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox psb_irq_postinstall(dev); 223bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox mutex_unlock(&power_mutex); 224bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return 0; 225bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 226bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 227bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 228bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_power_is_on - returne true if power is on 229bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @dev: our DRM device 230bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 231bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Returns true if the display island power is on at this moment 232bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 233bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxbool gma_power_is_on(struct drm_device *dev) 234bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 235bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_psb_private *dev_priv = dev->dev_private; 236bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return dev_priv->display_power; 237bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 238bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 239bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 240bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_power_begin - begin requiring power 241bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @dev: our DRM device 242bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @force_on: true to force power on 243bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 244bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Begin an action that requires the display power island is enabled. 245bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * We refcount the islands. 246bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 247bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxbool gma_power_begin(struct drm_device *dev, bool force_on) 248bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 249bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_psb_private *dev_priv = dev->dev_private; 250bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox int ret; 251bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox unsigned long flags; 252bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 253bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox spin_lock_irqsave(&power_ctrl_lock, flags); 254bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox /* Power already on ? */ 255bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox if (dev_priv->display_power) { 256bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->display_count++; 257bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pm_runtime_get(&dev->pdev->dev); 258bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox spin_unlock_irqrestore(&power_ctrl_lock, flags); 259bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return true; 260bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox } 261bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox if (force_on == false) 262bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox goto out_false; 263bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 264bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox /* Ok power up needed */ 265bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox ret = gma_resume_pci(dev->pdev); 266bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox if (ret == 0) { 267bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox psb_irq_preinstall(dev); 268bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox psb_irq_postinstall(dev); 269bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pm_runtime_get(&dev->pdev->dev); 270bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->display_count++; 271bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox spin_unlock_irqrestore(&power_ctrl_lock, flags); 272bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return true; 273bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox } 274bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxout_false: 275bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox spin_unlock_irqrestore(&power_ctrl_lock, flags); 276bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return false; 277bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 278bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 279bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox/** 280bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * gma_power_end - end use of power 281bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * @dev: Our DRM device 282bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * 283bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * Indicate that one of our gma_power_begin() requested periods when 284bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox * the diplay island power is needed has completed. 285bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox */ 286bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxvoid gma_power_end(struct drm_device *dev) 287bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 288bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_psb_private *dev_priv = dev->dev_private; 289bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox unsigned long flags; 290bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox spin_lock_irqsave(&power_ctrl_lock, flags); 291bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox dev_priv->display_count--; 292bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox WARN_ON(dev_priv->display_count < 0); 293bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox spin_unlock_irqrestore(&power_ctrl_lock, flags); 294bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox pm_runtime_put(&dev->pdev->dev); 295bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 296bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 297bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxint psb_runtime_suspend(struct device *dev) 298bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 299bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return gma_power_suspend(dev); 300bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 301bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 302bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxint psb_runtime_resume(struct device *dev) 303bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 30409016a11fc738e82ca1303e2332473b517bbd660Alan Cox return gma_power_resume(dev); 305bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 306bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox 307bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Coxint psb_runtime_idle(struct device *dev) 308bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox{ 309bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev)); 310bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox struct drm_psb_private *dev_priv = drmdev->dev_private; 311bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox if (dev_priv->display_count) 312bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return 0; 313bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox else 314bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox return 1; 315bbbb262d375140a27ed9fe45a13f19a04a0c51b2Alan Cox} 316