diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile index fdaac639deb8b48f0d160f11bfb28793e3647ae4..e93cbe3c440e95b0b8a8a8113edd220ddcbd381f 100644 --- a/drivers/staging/gma500/Makefile +++ b/drivers/staging/gma500/Makefile @@ -4,6 +4,7 @@ ccflags-y += -Iinclude/drm psb_gfx-y += gem_glue.o \ + power.o \ psb_bl.o \ psb_drv.o \ psb_gem.o \ @@ -19,11 +20,13 @@ psb_gfx-y += gem_glue.o \ psb_intel_sdvo.o \ psb_lid.o \ psb_mmu.o \ - psb_powermgmt.o \ psb_irq.o \ + psb_device.o \ + mrst_device.o \ mrst_crtc.o \ mrst_lvds.o \ mrst_bios.o \ + mdfld_device.o \ mdfld_output.o \ mdfld_pyr_cmd.o \ mdfld_tmd_vid.o \ diff --git a/drivers/staging/gma500/psb_powermgmt.c b/drivers/staging/gma500/mdfld_device.c similarity index 54% rename from drivers/staging/gma500/psb_powermgmt.c rename to drivers/staging/gma500/mdfld_device.c index 2253ecbfd61c57d3e5ef0d9b4a583296723e66c0..7caa7cd25acc34459f20bf1810a45b608d836f08 100644 --- a/drivers/staging/gma500/psb_powermgmt.c +++ b/drivers/staging/gma500/mdfld_device.c @@ -1,166 +1,38 @@ /************************************************************************** - * Copyright (c) 2009-2011, Intel Corporation. + * Copyright (c) 2011, 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: + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. * - * 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. + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * - * Authors: - * Benjamin Defnet - * Rajesh Poornachandran - * Massively reworked - * Alan Cox - */ -#include "psb_powermgmt.h" -#include "psb_drv.h" + **************************************************************************/ + +#include +#include #include "psb_reg.h" #include "psb_intel_reg.h" +#include "psb_drm.h" +#include "psb_drv.h" #include "mdfld_output.h" #include "mdfld_dsi_output.h" -#include -#include -#include - -/* IPC message and command defines used to enable/disable mipi panel voltages */ -#define IPC_MSG_PANEL_ON_OFF 0xE9 -#define IPC_CMD_PANEL_ON 1 -#define IPC_CMD_PANEL_OFF 0 - -static struct mutex power_mutex; - -/** - * gma_power_init - initialise power manager - * @dev: our device - * - * Set up for power management tracking of our hardware. - */ -void gma_power_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - - /* FIXME: need to sort out fetching apm_reg for both platforms ?? */ - - dev_priv->apm_base = dev_priv->apm_reg & 0xffff; - dev_priv->ospm_base &= 0xffff; - dev_priv->display_power = true; /* We start active */ - dev_priv->display_count = 0; /* Currently no users */ - dev_priv->suspended = false; /* And not suspended */ - mutex_init(&power_mutex); - - if (!IS_MRST(dev) && !IS_MFLD(dev)) { - /* FIXME: wants further review */ - u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL); - /* Disable 2D clock gating */ - gating &= ~3; - gating |= 1; - PSB_WSGX32(gating, PSB_CR_CLKGATECTL); - PSB_RSGX32(PSB_CR_CLKGATECTL); - } -} - -/** - * gma_power_uninit - end power manager - * @dev: device to end for - * - * Undo the effects of gma_power_init +/* + * Provide the Medfield specific chip logic and low level methods */ -void gma_power_uninit(struct drm_device *dev) -{ - mutex_destroy(&power_mutex); - pm_runtime_disable(&dev->pdev->dev); - pm_runtime_set_suspended(&dev->pdev->dev); -} - -/** - * save_display_registers - save registers lost on suspend - * @dev: our DRM device - * - * Save the state we need in order to be able to restore the interface - * upon resume from suspend - */ -static int save_display_registers(struct drm_device *dev) +static void mdfld_init_pm(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); - return 0; -} - -/** - * restore_display_registers - restore lost register state - * @dev: our DRM device - * - * Restore register state that was lost during suspend and resume. - */ -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); - return 0; + /* No work needed here yet */ } /** @@ -679,373 +551,60 @@ static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev) } /** - * power_down - power down the display island + * mdfld_save_display_registers - save registers lost on suspend * @dev: our DRM device * - * Power down the display interface of our device + * Save the state we need in order to be able to restore the interface + * upon resume from suspend */ -static void power_down(struct drm_device *dev) +static int mdfld_save_registers(struct drm_device *dev) { - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pwr_mask ; - u32 pwr_sts; - - if (IS_MRST(dev)) { - 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); - } - dev_priv->display_power = false; - } + /* FIXME: We need to shut down panels here if using them + and once the right bits are merged */ + mdfld_save_cursor_overlay_registers(dev); + mdfld_save_display_registers(dev, 0); + mdfld_save_display_registers(dev, 0); + mdfld_save_display_registers(dev, 2); + mdfld_save_display_registers(dev, 1); + mdfld_disable_crtc(dev, 0); + mdfld_disable_crtc(dev, 2); + mdfld_disable_crtc(dev, 1); + return 0; } - /** - * gma_suspend_display - suspend the display logic + * mdfld_restore_display_registers - restore lost register state * @dev: our DRM device * - * Suspend the display logic of the graphics interface - * - * FIXME: This ought to be replaced by a dev_priv-> ops interface - * where the various platforms register their save/restore methods - * and keep them in their own support files. - */ -static void gma_suspend_display(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - int pp_stat; - - if (dev_priv->suspended) - return; - - if (IS_MFLD(dev)) { - /* FIXME: We need to shut down panels here if using them - and once the right bits are merged */ - mdfld_save_cursor_overlay_registers(dev); - mdfld_save_display_registers(dev, 0); - mdfld_save_display_registers(dev, 0); - mdfld_save_display_registers(dev, 2); - mdfld_save_display_registers(dev, 1); - mdfld_disable_crtc(dev, 0); - mdfld_disable_crtc(dev, 2); - mdfld_disable_crtc(dev, 1); - } else { - 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) - cpu_relax(); - while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY) - != DPI_FIFO_EMPTY) - cpu_relax(); - PSB_WVDC32(0, DEVICE_READY_REG); - /* Turn off panel power */ -#ifdef CONFIG_X86_MRST - intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF, - IPC_CMD_PANEL_OFF); -#endif - } - } - power_down(dev); -} - -/* - * power_up - * - * Description: Restore power to the specified island(s) (powergating) - */ -static void power_up(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK; - u32 pwr_sts, pwr_cnt; - - if (IS_MRST(dev)) { - 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); - } - } - dev_priv->suspended = false; - dev_priv->display_power = true; -} - -/** - * gma_resume_display - resume display side logic - * - * Resume the display hardware restoring state and enabling - * as necessary. - */ -static void gma_resume_display(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - struct drm_psb_private *dev_priv = dev->dev_private; - - if (dev_priv->suspended == false) - return; - - /* turn on the display power island */ - power_up(dev); - - PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); - pci_write_config_word(pdev, PSB_GMCH_CTRL, - dev_priv->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);*/ - if (IS_MFLD(dev)) { - mdfld_restore_display_registers(dev, 1); - mdfld_restore_display_registers(dev, 0); - mdfld_restore_display_registers(dev, 2); - mdfld_restore_cursor_overlay_registers(dev); - } else if (IS_MRST(dev)) { - if (!dev_priv->iLVDS_enable) { -#ifdef CONFIG_X86_MRST - intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF, - IPC_CMD_PANEL_ON); - /* FIXME: can we avoid this delay ? */ - msleep(2000); /* wait 2 seconds */ -#endif - } - } - restore_display_registers(dev); -} - -/** - * gma_suspend_pci - suspend PCI side - * @pdev: PCI device - * - * Perform the suspend processing on our PCI device state - */ -static void gma_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 (dev_priv->suspended) - return; - - 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); - - dev_priv->suspended = true; -} - -/** - * gma_resume_pci - resume helper - * @dev: our PCI device - * - * Perform the resume processing on our PCI device state - rewrite - * register state and re-enable the PCI device - */ -static bool gma_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; - - if (!dev_priv->suspended) - return true; - - 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) - dev_err(&pdev->dev, "pci_enable failed: %d\n", ret); - else - dev_priv->suspended = false; - return !dev_priv->suspended; -} - -/** - * gma_power_suspend - bus callback for suspend - * @pdev: our PCI device - * @state: suspend type - * - * Called back by the PCI layer during a suspend of the system. We - * perform the necessary shut down steps and save enough state that - * we can undo this when resume is called. + * Restore register state that was lost during suspend and resume. */ -int gma_power_suspend(struct pci_dev *pdev, pm_message_t state) +static int mdfld_restore_registers(struct drm_device *dev) { - struct drm_device *dev = pci_get_drvdata(pdev); - struct drm_psb_private *dev_priv = dev->dev_private; - - mutex_lock(&power_mutex); - if (!dev_priv->suspended) { - if (dev_priv->display_count) { - mutex_unlock(&power_mutex); - return -EBUSY; - } - psb_irq_uninstall(dev); - gma_suspend_display(dev); - gma_suspend_pci(pdev); - } - mutex_unlock(&power_mutex); + mdfld_restore_display_registers(dev, 1); + mdfld_restore_display_registers(dev, 0); + mdfld_restore_display_registers(dev, 2); + mdfld_restore_cursor_overlay_registers(dev); return 0; } - -/** - * gma_power_resume - resume power - * @pdev: PCI device - * - * Resume the PCI side of the graphics and then the displays - */ -int gma_power_resume(struct pci_dev *pdev) +static int mdfld_power_down(struct drm_device *dev) { - struct drm_device *dev = pci_get_drvdata(pdev); - - mutex_lock(&power_mutex); - gma_resume_pci(pdev); - gma_resume_display(pdev); - psb_irq_preinstall(dev); - psb_irq_postinstall(dev); - mutex_unlock(&power_mutex); + /* FIXME */ return 0; } - - -/** - * gma_power_is_on - returne true if power is on - * @dev: our DRM device - * - * Returns true if the display island power is on at this moment - */ -bool gma_power_is_on(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - return dev_priv->display_power; -} - - -/** - * gma_power_begin - begin requiring power - * @dev: our DRM device - * @force_on: true to force power on - * - * Begin an action that requires the display power island is enabled. - * We refcount the islands. - * - * FIXME: locking - */ -bool gma_power_begin(struct drm_device *dev, bool force_on) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - int ret; - - /* Power already on ? */ - if (dev_priv->display_power) { - dev_priv->display_count++; - pm_runtime_get(&dev->pdev->dev); - return true; - } - if (force_on == false) - return false; - - /* Ok power up needed */ - ret = gma_resume_pci(dev->pdev); - if (ret == 0) { - psb_irq_preinstall(dev); - psb_irq_postinstall(dev); - pm_runtime_get(&dev->pdev->dev); - dev_priv->display_count++; - return true; - } - return false; -} - - -/** - * gma_power_end - end use of power - * @dev: Our DRM device - * - * Indicate that one of our gma_power_begin() requested periods when - * the diplay island power is needed has completed. - */ -void gma_power_end(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = dev->dev_private; - dev_priv->display_count--; - WARN_ON(dev_priv->display_count < 0); - pm_runtime_put(&dev->pdev->dev); -} - -int psb_runtime_suspend(struct device *dev) -{ - static pm_message_t dummy; - return gma_power_suspend(to_pci_dev(dev), dummy); -} - -int psb_runtime_resume(struct device *dev) +static int mdfld_power_up(struct drm_device *dev) { + /* FIXME */ return 0; } -int psb_runtime_idle(struct device *dev) -{ - struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev)); - struct drm_psb_private *dev_priv = drmdev->dev_private; - if (dev_priv->display_count) - return 0; - else - return 1; -} +const struct psb_ops mdfld_chip_ops = { + .output_init = mdfld_output_init, + .init_pm = mdfld_init_pm, + .save_regs = mdfld_save_registers, + .restore_regs = mdfld_restore_registers, + .power_down = mdfld_power_down, + .power_up = mdfld_power_up, +}; diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c index b1fc7656b2de34ee03e4d09a68b98ab8c3105994..7e11401d67bb28ea096e79c4c127ab7686793f7b 100644 --- a/drivers/staging/gma500/mdfld_output.c +++ b/drivers/staging/gma500/mdfld_output.c @@ -63,14 +63,20 @@ int mdfld_panel_dpi(struct drm_device *dev) } } -static void init_panel(struct drm_device *dev, int mipi_pipe, int p_type) +static int init_panel(struct drm_device *dev, int mipi_pipe, int p_type) { struct panel_funcs *p_cmd_funcs; struct panel_funcs *p_vid_funcs; /* Oh boy ... FIXME */ p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL); + if (p_cmd_funcs == NULL) + return -ENODEV; p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL); + if (p_vid_funcs == NULL) { + kfree(p_cmd_funcs); + return -ENODEV; + } switch (p_type) { case TPO_CMD: @@ -115,11 +121,12 @@ static void init_panel(struct drm_device *dev, int mipi_pipe, int p_type) #endif default: dev_err(dev->dev, "Unsupported interface %d", p_type); - break; + return -ENODEV; } + return 0; } -void mdfld_output_init(struct drm_device *dev) +int mdfld_output_init(struct drm_device *dev) { int type; @@ -132,4 +139,6 @@ void mdfld_output_init(struct drm_device *dev) type = mdfld_get_panel_type(dev, 2); dev_info(dev->dev, "panel 2: type is %d\n", type); init_panel(dev, 2, type); + + return 0; } diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h index 36f43e1ac98e95d8339ae6a2be0237afbea5742c..53b57db2c4f4a112d9570214b1aa77a00d478556 100644 --- a/drivers/staging/gma500/mdfld_output.h +++ b/drivers/staging/gma500/mdfld_output.h @@ -69,7 +69,7 @@ struct panel_funcs { int (*get_panel_info) (struct drm_device *, int, struct panel_info *); }; -void mdfld_output_init(struct drm_device *dev); +int mdfld_output_init(struct drm_device *dev); int mdfld_panel_dpi(struct drm_device *dev); int mdfld_get_panel_type(struct drm_device *dev, int pipe); void mdfld_disable_crtc (struct drm_device *dev, int pipe); diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c new file mode 100644 index 0000000000000000000000000000000000000000..5cd82838a052777c1067f096ee6a61d43cac90a2 --- /dev/null +++ b/drivers/staging/gma500/mrst_device.c @@ -0,0 +1,230 @@ +/************************************************************************** + * Copyright (c) 2011, Intel Corporation. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + **************************************************************************/ + +#include +#include +#include "psb_drm.h" +#include "psb_drv.h" +#include "psb_reg.h" +#include "psb_intel_reg.h" +#include + +/* IPC message and command defines used to enable/disable mipi panel voltages */ +#define IPC_MSG_PANEL_ON_OFF 0xE9 +#define IPC_CMD_PANEL_ON 1 +#define IPC_CMD_PANEL_OFF 0 + +static int mrst_output_init(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + if (dev_priv->iLVDS_enable) { + mrst_lvds_init(dev, &dev_priv->mode_dev); + return 0; + } + dev_err(dev->dev, "DSI is not supported\n"); + return -ENODEV; +} + +/* + * Provide the Moorestown specific chip logic and low level methods + */ + +static void mrst_init_pm(struct drm_device *dev) +{ +} + +/** + * mrst_save_display_registers - save registers lost on suspend + * @dev: our DRM device + * + * Save the state we need in order to be able to restore the interface + * upon resume from suspend + */ +static int mrst_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); + return 0; +} + +/** + * mrst_restore_display_registers - restore lost register state + * @dev: our DRM device + * + * Restore register state that was lost during suspend and resume. + */ +static int mrst_restore_display_registers(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc; + struct drm_connector *connector; + int pp_stat; + + if (!dev_priv->iLVDS_enable) { +#ifdef CONFIG_X86_MRST + intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF, + IPC_CMD_PANEL_ON); + /* FIXME: can we avoid this delay ? */ + msleep(2000); /* wait 2 seconds */ +#endif + } + + /* 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); + + 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) + cpu_relax(); + while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY) + != DPI_FIFO_EMPTY) + cpu_relax(); + PSB_WVDC32(0, DEVICE_READY_REG); + /* Turn off panel power */ +#ifdef CONFIG_X86_MRST /* FIXME: kill define once modular */ + intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF, + IPC_CMD_PANEL_OFF); +#endif + } + return 0; +} + +/** + * mrst_power_down - power down the display island + * @dev: our DRM device + * + * Power down the display interface of our device + */ +static int mrst_power_down(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + u32 pwr_mask ; + u32 pwr_sts; + + 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); + } + return 0; +} + +/* + * mrst_power_up + * + * Restore power to the specified island(s) (powergating) + */ +static int mrst_power_up(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK; + u32 pwr_sts, pwr_cnt; + + 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); + } + return 0; +} + +const struct psb_ops mrst_chip_ops = { + .output_init = mrst_output_init, + .init_pm = mrst_init_pm, + .save_regs = mrst_save_display_registers, + .restore_regs = mrst_restore_display_registers, + .power_down = mrst_power_down, + .power_up = mrst_power_up, +}; + diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c new file mode 100644 index 0000000000000000000000000000000000000000..fc2324e26eca68824466d97109dc3bf153972050 --- /dev/null +++ b/drivers/staging/gma500/power.c @@ -0,0 +1,320 @@ +/************************************************************************** + * Copyright (c) 2009-2011, 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 + * Rajesh Poornachandran + * Massively reworked + * Alan Cox + */ +#include "psb_powermgmt.h" +#include "psb_drv.h" +#include "psb_reg.h" +#include "psb_intel_reg.h" +#include +#include + +static struct mutex power_mutex; + +/** + * gma_power_init - initialise power manager + * @dev: our device + * + * Set up for power management tracking of our hardware. + */ +void gma_power_init(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + + /* FIXME: need to sort out fetching apm_reg for both platforms ?? */ + + dev_priv->apm_base = dev_priv->apm_reg & 0xffff; + dev_priv->ospm_base &= 0xffff; + + dev_priv->display_power = true; /* We start active */ + dev_priv->display_count = 0; /* Currently no users */ + dev_priv->suspended = false; /* And not suspended */ + mutex_init(&power_mutex); + + dev_priv->ops->init_pm(dev); +} + +/** + * gma_power_uninit - end power manager + * @dev: device to end for + * + * Undo the effects of gma_power_init + */ +void gma_power_uninit(struct drm_device *dev) +{ + mutex_destroy(&power_mutex); + pm_runtime_disable(&dev->pdev->dev); + pm_runtime_set_suspended(&dev->pdev->dev); +} + + + + +/** + * gma_suspend_display - suspend the display logic + * @dev: our DRM device + * + * Suspend the display logic of the graphics interface + * + * FIXME: This ought to be replaced by a dev_priv-> ops interface + * where the various platforms register their save/restore methods + * and keep them in their own support files. + */ +static void gma_suspend_display(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + + if (dev_priv->suspended) + return; + dev_priv->ops->save_regs(dev); + dev_priv->ops->power_down(dev); + dev_priv->display_power = false; +} + +/** + * gma_resume_display - resume display side logic + * + * Resume the display hardware restoring state and enabling + * as necessary. + */ +static void gma_resume_display(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct drm_psb_private *dev_priv = dev->dev_private; + + if (dev_priv->suspended == false) + return; + + /* turn on the display power island */ + dev_priv->ops->power_up(dev); + dev_priv->suspended = false; + dev_priv->display_power = true; + + PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); + pci_write_config_word(pdev, PSB_GMCH_CTRL, + dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); + dev_priv->ops->restore_regs(dev); +} + +/** + * gma_suspend_pci - suspend PCI side + * @pdev: PCI device + * + * Perform the suspend processing on our PCI device state + */ +static void gma_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 (dev_priv->suspended) + return; + + 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); + + dev_priv->suspended = true; +} + +/** + * gma_resume_pci - resume helper + * @dev: our PCI device + * + * Perform the resume processing on our PCI device state - rewrite + * register state and re-enable the PCI device + */ +static bool gma_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; + + if (!dev_priv->suspended) + return true; + + 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); + /* restoring 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) + dev_err(&pdev->dev, "pci_enable failed: %d\n", ret); + else + dev_priv->suspended = false; + return !dev_priv->suspended; +} + +/** + * gma_power_suspend - bus callback for suspend + * @pdev: our PCI device + * @state: suspend type + * + * Called back by the PCI layer during a suspend of the system. We + * perform the necessary shut down steps and save enough state that + * we can undo this when resume is called. + */ +int gma_power_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + struct drm_psb_private *dev_priv = dev->dev_private; + + mutex_lock(&power_mutex); + if (!dev_priv->suspended) { + if (dev_priv->display_count) { + mutex_unlock(&power_mutex); + return -EBUSY; + } + psb_irq_uninstall(dev); + gma_suspend_display(dev); + gma_suspend_pci(pdev); + } + mutex_unlock(&power_mutex); + return 0; +} + + +/** + * gma_power_resume - resume power + * @pdev: PCI device + * + * Resume the PCI side of the graphics and then the displays + */ +int gma_power_resume(struct pci_dev *pdev) +{ + struct drm_device *dev = pci_get_drvdata(pdev); + + mutex_lock(&power_mutex); + gma_resume_pci(pdev); + gma_resume_display(pdev); + psb_irq_preinstall(dev); + psb_irq_postinstall(dev); + mutex_unlock(&power_mutex); + return 0; +} + + + +/** + * gma_power_is_on - returne true if power is on + * @dev: our DRM device + * + * Returns true if the display island power is on at this moment + */ +bool gma_power_is_on(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + return dev_priv->display_power; +} + + +/** + * gma_power_begin - begin requiring power + * @dev: our DRM device + * @force_on: true to force power on + * + * Begin an action that requires the display power island is enabled. + * We refcount the islands. + * + * FIXME: locking + */ +bool gma_power_begin(struct drm_device *dev, bool force_on) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + int ret; + + /* Power already on ? */ + if (dev_priv->display_power) { + dev_priv->display_count++; + pm_runtime_get(&dev->pdev->dev); + return true; + } + if (force_on == false) + return false; + + /* Ok power up needed */ + ret = gma_resume_pci(dev->pdev); + if (ret == 0) { + psb_irq_preinstall(dev); + psb_irq_postinstall(dev); + pm_runtime_get(&dev->pdev->dev); + dev_priv->display_count++; + return true; + } + return false; +} + + +/** + * gma_power_end - end use of power + * @dev: Our DRM device + * + * Indicate that one of our gma_power_begin() requested periods when + * the diplay island power is needed has completed. + */ +void gma_power_end(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + dev_priv->display_count--; + WARN_ON(dev_priv->display_count < 0); + pm_runtime_put(&dev->pdev->dev); +} + +int psb_runtime_suspend(struct device *dev) +{ + static pm_message_t dummy; + return gma_power_suspend(to_pci_dev(dev), dummy); +} + +int psb_runtime_resume(struct device *dev) +{ + return 0; +} + +int psb_runtime_idle(struct device *dev) +{ + struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev)); + struct drm_psb_private *dev_priv = drmdev->dev_private; + if (dev_priv->display_count) + return 0; + else + return 1; +} + diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c new file mode 100644 index 0000000000000000000000000000000000000000..97e25ab3182fa82a3fbdd79b8e82b6d04946f4ce --- /dev/null +++ b/drivers/staging/gma500/psb_device.c @@ -0,0 +1,174 @@ +/************************************************************************** + * Copyright (c) 2011, Intel Corporation. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * + **************************************************************************/ + +#include +#include +#include "psb_drm.h" +#include "psb_drv.h" +#include "psb_reg.h" +#include "psb_intel_reg.h" + +static int psb_output_init(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + psb_intel_lvds_init(dev, &dev_priv->mode_dev); + psb_intel_sdvo_init(dev, SDVOB); + return 0; +} + +/* + * Provide the Poulsbo specific chip logic and low level methods + */ + +static void psb_init_pm(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + + u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL); + gating &= ~3; /* Disable 2D clock gating */ + gating |= 1; + PSB_WSGX32(gating, PSB_CR_CLKGATECTL); + PSB_RSGX32(PSB_CR_CLKGATECTL); +} + +/** + * psb_save_display_registers - save registers lost on suspend + * @dev: our DRM device + * + * Save the state we need in order to be able to restore the interface + * upon resume from suspend + */ +static int psb_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); + return 0; +} + +/** + * psb_restore_display_registers - restore lost register state + * @dev: our DRM device + * + * Restore register state that was lost during suspend and resume. + */ +static int psb_restore_display_registers(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct drm_crtc *crtc; + struct drm_connector *connector; + int pp_stat; + + /* 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); + + 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) + cpu_relax(); + while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY) + != DPI_FIFO_EMPTY) + cpu_relax(); + PSB_WVDC32(0, DEVICE_READY_REG); + } + return 0; +} + +int psb_power_down(struct drm_device *dev) +{ + return 0; +} + +int psb_power_up(struct drm_device *dev) +{ + return 0; +} + +const struct psb_ops psb_chip_ops = { + .output_init = psb_output_init, + .init_pm = psb_init_pm, + .save_regs = psb_save_display_registers, + .restore_regs = psb_restore_display_registers, + .power_down = psb_power_down, + .power_up = psb_power_up, +}; + diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c index 0d65f75f95e7c31035451bdb8e46f4aef1728a59..6c5723441121fb4a9297893a844893df7a7d0da1 100644 --- a/drivers/staging/gma500/psb_drv.c +++ b/drivers/staging/gma500/psb_drv.c @@ -49,24 +49,24 @@ module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600); static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { - { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8108 }, - { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8109 }, - { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, - { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, - { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, - { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, - { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, - { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, - { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, - { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100}, - { 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130}, - { 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130}, - { 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130}, - { 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130}, - { 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130}, - { 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130}, - { 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130}, - { 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130}, + { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, + { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, + { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, + { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, + { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, + { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, + { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, + { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, + { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, + { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, + { 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, + { 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, + { 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, + { 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, + { 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, + { 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, + { 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, + { 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, { 0, 0, 0} }; MODULE_DEVICE_TABLE(pci, pciidlist); @@ -257,8 +257,7 @@ static int psb_do_init(struct drm_device *dev) static int psb_driver_unload(struct drm_device *dev) { - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; + struct drm_psb_private *dev_priv = dev->dev_private; /* Kill vblank etc here */ @@ -332,6 +331,10 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) if (dev_priv == NULL) return -ENOMEM; + dev_priv->ops = (struct psb_ops *)chipset; + dev_priv->dev = dev; + dev->dev_private = (void *) dev_priv; + if (IS_MRST(dev)) dev_priv->num_pipe = 1; else if (IS_MFLD(dev)) @@ -339,10 +342,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) else dev_priv->num_pipe = 2; - dev_priv->dev = dev; - - dev->dev_private = (void *) dev_priv; - dev_priv->chipset = chipset; resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE); diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h index 3b2ee083e4749dd7be5ddfebc3c987b4957fc98c..d1c49e74f5718a91d72da2fcb06fd124aaa20d74 100644 --- a/drivers/staging/gma500/psb_drv.h +++ b/drivers/staging/gma500/psb_drv.h @@ -258,11 +258,11 @@ struct psb_intel_opregion { int enabled; }; +struct psb_ops; struct drm_psb_private { struct drm_device *dev; - - unsigned long chipset; + const struct psb_ops *ops; struct psb_gtt *pg; @@ -612,6 +612,23 @@ struct drm_psb_private { }; +/* + * Operations for each board type + */ + +struct psb_ops { + /* Display management hooks */ + int (*output_init)(struct drm_device *dev); + /* Power management hooks */ + void (*init_pm)(struct drm_device *dev); + int (*save_regs)(struct drm_device *dev); + int (*restore_regs)(struct drm_device *dev); + int (*power_up)(struct drm_device *dev); + int (*power_down)(struct drm_device *dev); +}; + + + struct psb_mmu_driver; extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int); @@ -761,6 +778,14 @@ extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, uint32_t handle, uint64_t *offset); extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); +/* psb_device.c */ +extern const struct psb_ops psb_chip_ops; + +/* mrst_device.c */ +extern const struct psb_ops mrst_chip_ops; + +/* mdfld_device.c */ +extern const struct psb_ops mdfld_chip_ops; /* * Debug print bits setting diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c index 83095fc8a14a8869c7744415c322638f57befff4..32d9016b6b1cf16b98c89f3c6cba1f94dd396ea5 100644 --- a/drivers/staging/gma500/psb_fb.c +++ b/drivers/staging/gma500/psb_fb.c @@ -725,17 +725,7 @@ static void psb_setup_outputs(struct drm_device *dev) drm_mode_create_scaling_mode_property(dev); psb_create_backlight_property(dev); - if (IS_MRST(dev)) { - if (dev_priv->iLVDS_enable) - mrst_lvds_init(dev, &dev_priv->mode_dev); - else - dev_err(dev->dev, "DSI is not supported\n"); - } else if (IS_MFLD(dev)) { - mdfld_output_init(dev); - } else { - psb_intel_lvds_init(dev, &dev_priv->mode_dev); - psb_intel_sdvo_init(dev, SDVOB); - } + dev_priv->ops->output_init(dev); list_for_each_entry(connector, &dev->mode_config.connector_list, head) {