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