summaryrefslogtreecommitdiff
path: root/drivers/staging/gma500/psb_powermgmt.c
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2011-02-22 14:27:58 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2011-02-23 13:37:34 -0800
commit0867b42113ec4eb8646eb361b15cbcfb741ddf5b (patch)
tree7af589f3b3599ebd36a6c4e0a3a608a8b3a3836e /drivers/staging/gma500/psb_powermgmt.c
parent008536e8458613ce569595e43b0e71afa8b48ae8 (diff)
staging: gma500: Intel GMA500 staging driver
This is an initial staging driver for the GMA500. It's been stripped out of the PVR drivers and crunched together from various bits of code and different kernels. Currently it's unaccelerated but still pretty snappy even compositing with the frame buffer X server. Lots of work is needed to rework the ttm and bo interfaces from being ripped out and then 2D acceleration wants putting back for framebuffer and somehow eventually via DRM. There is no support for the parts without open source userspace (video accelerators, 3D) as per kernel policy. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/gma500/psb_powermgmt.c')
-rw-r--r--drivers/staging/gma500/psb_powermgmt.c797
1 files changed, 797 insertions, 0 deletions
diff --git a/drivers/staging/gma500/psb_powermgmt.c b/drivers/staging/gma500/psb_powermgmt.c
new file mode 100644
index 000000000000..3a6ffb7ff11f
--- /dev/null
+++ b/drivers/staging/gma500/psb_powermgmt.c
@@ -0,0 +1,797 @@
+/**************************************************************************
+ * Copyright (c) 2009, Intel Corporation.
+ * All Rights Reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Benjamin Defnet <benjamin.r.defnet@intel.com>
+ * Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ */
+#include "psb_powermgmt.h"
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+
+#undef OSPM_GFX_DPK
+
+extern u32 gui32SGXDeviceID;
+extern u32 gui32MRSTDisplayDeviceID;
+extern u32 gui32MRSTMSVDXDeviceID;
+extern u32 gui32MRSTTOPAZDeviceID;
+
+struct drm_device *gpDrmDevice = NULL;
+static struct mutex power_mutex;
+static bool gbSuspendInProgress = false;
+static bool gbResumeInProgress = false;
+static int g_hw_power_status_mask;
+static atomic_t g_display_access_count;
+static atomic_t g_graphics_access_count;
+static atomic_t g_videoenc_access_count;
+static atomic_t g_videodec_access_count;
+int allow_runtime_pm = 0;
+
+void ospm_power_island_up(int hw_islands);
+void ospm_power_island_down(int hw_islands);
+static bool gbSuspended = false;
+bool gbgfxsuspended = false;
+
+/*
+ * ospm_power_init
+ *
+ * Description: Initialize this ospm power management module
+ */
+void ospm_power_init(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private;
+
+ gpDrmDevice = dev;
+
+ dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
+ dev_priv->ospm_base &= 0xffff;
+
+ mutex_init(&power_mutex);
+ g_hw_power_status_mask = OSPM_ALL_ISLANDS;
+ atomic_set(&g_display_access_count, 0);
+ atomic_set(&g_graphics_access_count, 0);
+ atomic_set(&g_videoenc_access_count, 0);
+ atomic_set(&g_videodec_access_count, 0);
+}
+
+/*
+ * ospm_power_uninit
+ *
+ * Description: Uninitialize this ospm power management module
+ */
+void ospm_power_uninit(void)
+{
+ mutex_destroy(&power_mutex);
+ pm_runtime_disable(&gpDrmDevice->pdev->dev);
+ pm_runtime_set_suspended(&gpDrmDevice->pdev->dev);
+}
+
+
+/*
+ * save_display_registers
+ *
+ * Description: We are going to suspend so save current display
+ * register state.
+ */
+static int save_display_registers(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_crtc * crtc;
+ struct drm_connector * connector;
+
+ /* Display arbitration control + watermarks */
+ dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+ dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+ dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+ dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+ dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+ dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+ dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+ dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+ /*save crtc and output state*/
+ mutex_lock(&dev->mode_config.mutex);
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if(drm_helper_crtc_in_use(crtc)) {
+ crtc->funcs->save(crtc);
+ }
+ }
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ connector->funcs->save(connector);
+ }
+ mutex_unlock(&dev->mode_config.mutex);
+
+ /* Interrupt state */
+ /*
+ * Handled in psb_irq.c
+ */
+
+ return 0;
+}
+
+/*
+ * restore_display_registers
+ *
+ * Description: We are going to resume so restore display register state.
+ */
+static int restore_display_registers(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct drm_crtc * crtc;
+ struct drm_connector * connector;
+
+ /* Display arbitration + watermarks */
+ PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+ PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+ PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+ PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+ PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+ PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+ PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+ PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+ /*make sure VGA plane is off. it initializes to on after reset!*/
+ PSB_WVDC32(0x80000000, VGACNTRL);
+
+ mutex_lock(&dev->mode_config.mutex);
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if(drm_helper_crtc_in_use(crtc))
+ crtc->funcs->restore(crtc);
+ }
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ connector->funcs->restore(connector);
+ }
+ mutex_unlock(&dev->mode_config.mutex);
+
+ /*Interrupt state*/
+ /*
+ * Handled in psb_irq.c
+ */
+
+ return 0;
+}
+/*
+ * powermgmt_suspend_display
+ *
+ * Description: Suspend the display hardware saving state and disabling
+ * as necessary.
+ */
+void ospm_suspend_display(struct drm_device *dev)
+{
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int pp_stat, ret=0;
+
+ printk(KERN_ALERT "%s \n", __func__);
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "%s \n", __func__);
+#endif
+ if (!(g_hw_power_status_mask & OSPM_DISPLAY_ISLAND))
+ return;
+
+ save_display_registers(dev);
+
+ if (dev_priv->iLVDS_enable) {
+ /*shutdown the panel*/
+ PSB_WVDC32(0, PP_CONTROL);
+
+ do {
+ pp_stat = PSB_RVDC32(PP_STATUS);
+ } while (pp_stat & 0x80000000);
+
+ /*turn off the plane*/
+ PSB_WVDC32(0x58000000, DSPACNTR);
+ PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
+ /*wait ~4 ticks*/
+ msleep(4);
+
+ /*turn off pipe*/
+ PSB_WVDC32(0x0, PIPEACONF);
+ /*wait ~8 ticks*/
+ msleep(8);
+
+ /*turn off PLLs*/
+ PSB_WVDC32(0, MRST_DPLL_A);
+ } else {
+ PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
+ PSB_WVDC32(0x0, PIPEACONF);
+ PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
+ while (REG_READ(0x70008) & 0x40000000);
+ while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
+ != DPI_FIFO_EMPTY);
+ PSB_WVDC32(0, DEVICE_READY_REG);
+ /* turn off panel power */
+ ret = 0;
+ }
+ ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+}
+
+/*
+ * ospm_resume_display
+ *
+ * Description: Resume the display hardware restoring state and enabling
+ * as necessary.
+ */
+void ospm_resume_display(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ struct psb_gtt *pg = dev_priv->pg;
+
+ printk(KERN_ALERT "%s \n", __func__);
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "%s \n", __func__);
+#endif
+ if (g_hw_power_status_mask & OSPM_DISPLAY_ISLAND)
+ return;
+
+ /* turn on the display power island */
+ ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+
+ PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+ pci_write_config_word(pdev, PSB_GMCH_CTRL,
+ pg->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+ /* Don't reinitialize the GTT as it is unnecessary. The gtt is
+ * stored in memory so it will automatically be restored. All
+ * we need to do is restore the PGETBL_CTL which we already do
+ * above.
+ */
+ /*psb_gtt_init(dev_priv->pg, 1);*/
+
+ restore_display_registers(dev);
+}
+
+#if 1
+/*
+ * ospm_suspend_pci
+ *
+ * Description: Suspend the pci device saving state and disabling
+ * as necessary.
+ */
+static void ospm_suspend_pci(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int bsm, vbt;
+
+ if (gbSuspended)
+ return;
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "ospm_suspend_pci\n");
+#endif
+
+#ifdef CONFIG_MDFD_GL3
+ // Power off GL3 after all GFX sub-systems are powered off.
+ ospm_power_island_down(OSPM_GL3_CACHE_ISLAND);
+#endif
+
+ pci_save_state(pdev);
+ pci_read_config_dword(pdev, 0x5C, &bsm);
+ dev_priv->saveBSM = bsm;
+ pci_read_config_dword(pdev, 0xFC, &vbt);
+ dev_priv->saveVBT = vbt;
+ pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
+ pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
+
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ gbSuspended = true;
+ gbgfxsuspended = true;
+}
+
+/*
+ * ospm_resume_pci
+ *
+ * Description: Resume the pci device restoring state and enabling
+ * as necessary.
+ */
+static bool ospm_resume_pci(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+ struct drm_psb_private *dev_priv = dev->dev_private;
+ int ret = 0;
+
+ if (!gbSuspended)
+ return true;
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "ospm_resume_pci\n");
+#endif
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
+ pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
+ /* retoring MSI address and data in PCIx space */
+ pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
+ pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
+ ret = pci_enable_device(pdev);
+
+ if (ret != 0)
+ printk(KERN_ALERT "ospm_resume_pci: pci_enable_device failed: %d\n", ret);
+ else
+ gbSuspended = false;
+
+ return !gbSuspended;
+}
+#endif
+/*
+ * ospm_power_suspend
+ *
+ * Description: OSPM is telling our driver to suspend so save state
+ * and power down all hardware.
+ */
+int ospm_power_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ int ret = 0;
+ int graphics_access_count;
+ int videoenc_access_count;
+ int videodec_access_count;
+ int display_access_count;
+ bool suspend_pci = true;
+
+ if(gbSuspendInProgress || gbResumeInProgress)
+ {
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: %s system BUSY \n", __func__);
+#endif
+ return -EBUSY;
+ }
+
+ mutex_lock(&power_mutex);
+
+ if (!gbSuspended) {
+ graphics_access_count = atomic_read(&g_graphics_access_count);
+ videoenc_access_count = atomic_read(&g_videoenc_access_count);
+ videodec_access_count = atomic_read(&g_videodec_access_count);
+ display_access_count = atomic_read(&g_display_access_count);
+
+ if (graphics_access_count ||
+ videoenc_access_count ||
+ videodec_access_count ||
+ display_access_count)
+ ret = -EBUSY;
+
+ if (!ret) {
+ gbSuspendInProgress = true;
+
+ psb_irq_uninstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ ospm_suspend_display(gpDrmDevice);
+ if (suspend_pci == true) {
+ ospm_suspend_pci(pdev);
+ }
+ gbSuspendInProgress = false;
+ } else {
+ printk(KERN_ALERT "ospm_power_suspend: device busy: graphics %d videoenc %d videodec %d display %d\n", graphics_access_count, videoenc_access_count, videodec_access_count, display_access_count);
+ }
+ }
+
+
+ mutex_unlock(&power_mutex);
+ return ret;
+}
+
+/*
+ * ospm_power_island_up
+ *
+ * Description: Restore power to the specified island(s) (powergating)
+ */
+void ospm_power_island_up(int hw_islands)
+{
+ u32 pwr_cnt = 0;
+ u32 pwr_sts = 0;
+ u32 pwr_mask = 0;
+
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+
+ if (hw_islands & OSPM_DISPLAY_ISLAND) {
+ pwr_mask = PSB_PWRGT_DISPLAY_MASK;
+
+ pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
+ pwr_cnt &= ~pwr_mask;
+ outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
+
+ while (true) {
+ pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+ if ((pwr_sts & pwr_mask) == 0)
+ break;
+ else
+ udelay(10);
+ }
+ }
+
+ g_hw_power_status_mask |= hw_islands;
+}
+
+/*
+ * ospm_power_resume
+ */
+int ospm_power_resume(struct pci_dev *pdev)
+{
+ if(gbSuspendInProgress || gbResumeInProgress)
+ {
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: %s hw_island: Suspend || gbResumeInProgress!!!! \n", __func__);
+#endif
+ return 0;
+ }
+
+ mutex_lock(&power_mutex);
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: ospm_power_resume \n");
+#endif
+
+ gbResumeInProgress = true;
+
+ ospm_resume_pci(pdev);
+
+ ospm_resume_display(gpDrmDevice->pdev);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+
+ gbResumeInProgress = false;
+
+ mutex_unlock(&power_mutex);
+
+ return 0;
+}
+
+
+/*
+ * ospm_power_island_down
+ *
+ * Description: Cut power to the specified island(s) (powergating)
+ */
+void ospm_power_island_down(int islands)
+{
+#if 0
+ u32 pwr_cnt = 0;
+ u32 pwr_mask = 0;
+ u32 pwr_sts = 0;
+
+ struct drm_psb_private *dev_priv =
+ (struct drm_psb_private *) gpDrmDevice->dev_private;
+
+ g_hw_power_status_mask &= ~islands;
+
+ if (islands & OSPM_GRAPHICS_ISLAND) {
+ pwr_cnt |= PSB_PWRGT_GFX_MASK;
+ pwr_mask |= PSB_PWRGT_GFX_MASK;
+ if (dev_priv->graphics_state == PSB_PWR_STATE_ON) {
+ dev_priv->gfx_on_time += (jiffies - dev_priv->gfx_last_mode_change) * 1000 / HZ;
+ dev_priv->gfx_last_mode_change = jiffies;
+ dev_priv->graphics_state = PSB_PWR_STATE_OFF;
+ dev_priv->gfx_off_cnt++;
+ }
+ }
+ if (islands & OSPM_VIDEO_ENC_ISLAND) {
+ pwr_cnt |= PSB_PWRGT_VID_ENC_MASK;
+ pwr_mask |= PSB_PWRGT_VID_ENC_MASK;
+ }
+ if (islands & OSPM_VIDEO_DEC_ISLAND) {
+ pwr_cnt |= PSB_PWRGT_VID_DEC_MASK;
+ pwr_mask |= PSB_PWRGT_VID_DEC_MASK;
+ }
+ if (pwr_cnt) {
+ pwr_cnt |= inl(dev_priv->apm_base);
+ outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
+ while (true) {
+ pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
+
+ if ((pwr_sts & pwr_mask) == pwr_mask)
+ break;
+ else
+ udelay(10);
+ }
+ }
+
+ if (islands & OSPM_DISPLAY_ISLAND) {
+ pwr_mask = PSB_PWRGT_DISPLAY_MASK;
+
+ outl(pwr_mask, (dev_priv->ospm_base + PSB_PM_SSC));
+
+ while (true) {
+ pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+ if ((pwr_sts & pwr_mask) == pwr_mask)
+ break;
+ else
+ udelay(10);
+ }
+ }
+#endif
+}
+
+
+/*
+ * ospm_power_is_hw_on
+ *
+ * Description: do an instantaneous check for if the specified islands
+ * are on. Only use this in cases where you know the g_state_change_mutex
+ * is already held such as in irq install/uninstall. Otherwise, use
+ * ospm_power_using_hw_begin().
+ */
+bool ospm_power_is_hw_on(int hw_islands)
+{
+ return ((g_hw_power_status_mask & hw_islands) == hw_islands) ? true:false;
+}
+
+/*
+ * ospm_power_using_hw_begin
+ *
+ * Description: Notify PowerMgmt module that you will be accessing the
+ * specified island's hw so don't power it off. If force_on is true,
+ * this will power on the specified island if it is off.
+ * Otherwise, this will return false and the caller is expected to not
+ * access the hw.
+ *
+ * NOTE *** If this is called from and interrupt handler or other atomic
+ * context, then it will return false if we are in the middle of a
+ * power state transition and the caller will be expected to handle that
+ * even if force_on is set to true.
+ */
+bool ospm_power_using_hw_begin(int hw_island, UHBUsage usage)
+{
+ return 1; /*FIXMEAC */
+#if 0
+ bool ret = true;
+ bool island_is_off = false;
+ bool b_atomic = (in_interrupt() || in_atomic());
+ bool locked = true;
+ struct pci_dev *pdev = gpDrmDevice->pdev;
+ u32 deviceID = 0;
+ bool force_on = usage ? true: false;
+ /*quick path, not 100% race safe, but should be enough comapre to current other code in this file */
+ if (!force_on) {
+ if (hw_island & (OSPM_ALL_ISLANDS & ~g_hw_power_status_mask))
+ return false;
+ else {
+ locked = false;
+#ifdef CONFIG_PM_RUNTIME
+ /* increment pm_runtime_refcount */
+ pm_runtime_get(&pdev->dev);
+#endif
+ goto increase_count;
+ }
+ }
+
+
+ if (!b_atomic)
+ mutex_lock(&power_mutex);
+
+ island_is_off = hw_island & (OSPM_ALL_ISLANDS & ~g_hw_power_status_mask);
+
+ if (b_atomic && (gbSuspendInProgress || gbResumeInProgress || gbSuspended) && force_on && island_is_off)
+ ret = false;
+
+ if (ret && island_is_off && !force_on)
+ ret = false;
+
+ if (ret && island_is_off && force_on) {
+ gbResumeInProgress = true;
+
+ ret = ospm_resume_pci(pdev);
+
+ if (ret) {
+ switch(hw_island)
+ {
+ case OSPM_DISPLAY_ISLAND:
+ deviceID = gui32MRSTDisplayDeviceID;
+ ospm_resume_display(pdev);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ break;
+ case OSPM_GRAPHICS_ISLAND:
+ deviceID = gui32SGXDeviceID;
+ ospm_power_island_up(OSPM_GRAPHICS_ISLAND);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+ break;
+#if 1
+ case OSPM_VIDEO_DEC_ISLAND:
+ if(!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ //printk(KERN_ALERT "%s power on display for video decode use\n", __func__);
+ deviceID = gui32MRSTDisplayDeviceID;
+ ospm_resume_display(pdev);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ }
+ else{
+ //printk(KERN_ALERT "%s display is already on for video decode use\n", __func__);
+ }
+
+ if(!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) {
+ //printk(KERN_ALERT "%s power on video decode\n", __func__);
+ deviceID = gui32MRSTMSVDXDeviceID;
+ ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND);
+ }
+ else{
+ //printk(KERN_ALERT "%s video decode is already on\n", __func__);
+ }
+
+ break;
+ case OSPM_VIDEO_ENC_ISLAND:
+ if(!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+ //printk(KERN_ALERT "%s power on display for video encode\n", __func__);
+ deviceID = gui32MRSTDisplayDeviceID;
+ ospm_resume_display(pdev);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+ }
+ else{
+ //printk(KERN_ALERT "%s display is already on for video encode use\n", __func__);
+ }
+
+ if(!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
+ //printk(KERN_ALERT "%s power on video encode\n", __func__);
+ deviceID = gui32MRSTTOPAZDeviceID;
+ ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND);
+ psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+ psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+ }
+ else{
+ //printk(KERN_ALERT "%s video decode is already on\n", __func__);
+ }
+#endif
+ break;
+
+ default:
+ printk(KERN_ALERT "%s unknown island !!!! \n", __func__);
+ break;
+ }
+
+ }
+
+ if (!ret)
+ printk(KERN_ALERT "ospm_power_using_hw_begin: forcing on %d failed\n", hw_island);
+
+ gbResumeInProgress = false;
+ }
+increase_count:
+ if (ret) {
+ switch(hw_island)
+ {
+ case OSPM_GRAPHICS_ISLAND:
+ atomic_inc(&g_graphics_access_count);
+ break;
+ case OSPM_VIDEO_ENC_ISLAND:
+ atomic_inc(&g_videoenc_access_count);
+ break;
+ case OSPM_VIDEO_DEC_ISLAND:
+ atomic_inc(&g_videodec_access_count);
+ break;
+ case OSPM_DISPLAY_ISLAND:
+ atomic_inc(&g_display_access_count);
+ break;
+ }
+ }
+
+ if (!b_atomic && locked)
+ mutex_unlock(&power_mutex);
+
+ return ret;
+#endif
+}
+
+
+/*
+ * ospm_power_using_hw_end
+ *
+ * Description: Notify PowerMgmt module that you are done accessing the
+ * specified island's hw so feel free to power it off. Note that this
+ * function doesn't actually power off the islands.
+ */
+void ospm_power_using_hw_end(int hw_island)
+{
+#if 0 /* FIXMEAC */
+ switch(hw_island)
+ {
+ case OSPM_GRAPHICS_ISLAND:
+ atomic_dec(&g_graphics_access_count);
+ break;
+ case OSPM_VIDEO_ENC_ISLAND:
+ atomic_dec(&g_videoenc_access_count);
+ break;
+ case OSPM_VIDEO_DEC_ISLAND:
+ atomic_dec(&g_videodec_access_count);
+ break;
+ case OSPM_DISPLAY_ISLAND:
+ atomic_dec(&g_display_access_count);
+ break;
+ }
+
+ //decrement runtime pm ref count
+ pm_runtime_put(&gpDrmDevice->pdev->dev);
+
+ WARN_ON(atomic_read(&g_graphics_access_count) < 0);
+ WARN_ON(atomic_read(&g_videoenc_access_count) < 0);
+ WARN_ON(atomic_read(&g_videodec_access_count) < 0);
+ WARN_ON(atomic_read(&g_display_access_count) < 0);
+#endif
+}
+
+int ospm_runtime_pm_allow(struct drm_device * dev)
+{
+ return 0;
+}
+
+void ospm_runtime_pm_forbid(struct drm_device * dev)
+{
+ struct drm_psb_private * dev_priv = dev->dev_private;
+
+ DRM_INFO("%s\n", __FUNCTION__);
+
+ pm_runtime_forbid(&dev->pdev->dev);
+ dev_priv->rpm_enabled = 0;
+}
+
+int psb_runtime_suspend(struct device *dev)
+{
+ pm_message_t state;
+ int ret = 0;
+ state.event = 0;
+
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: %s \n", __func__);
+#endif
+ if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count)
+ || atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count)){
+#ifdef OSPM_GFX_DPK
+ printk(KERN_ALERT "OSPM_GFX_DPK: GFX: %d VEC: %d VED: %d DC: %d DSR: %d \n", atomic_read(&g_graphics_access_count),
+ atomic_read(&g_videoenc_access_count), atomic_read(&g_videodec_access_count), atomic_read(&g_display_access_count));
+#endif
+ return -EBUSY;
+ }
+ else
+ ret = ospm_power_suspend(gpDrmDevice->pdev, state);
+
+ return ret;
+}
+
+int psb_runtime_resume(struct device *dev)
+{
+ return 0;
+}
+
+int psb_runtime_idle(struct device *dev)
+{
+ /*printk (KERN_ALERT "lvds:%d,mipi:%d\n", dev_priv->is_lvds_on, dev_priv->is_mipi_on);*/
+ if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count)
+ || atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count))
+ return 1;
+ else
+ return 0;
+}
+