]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
gma500: Add the core DRM files and headers
authorAlan Cox <alan@linux.intel.com>
Thu, 3 Nov 2011 18:22:04 +0000 (18:22 +0000)
committerDave Airlie <airlied@redhat.com>
Wed, 16 Nov 2011 11:26:35 +0000 (11:26 +0000)
Not really a nice way to split this up further for submission. This
provides all the DRM interfacing logic, the headers and relevant glue.

Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/gma500/psb_drm.h [new file with mode: 0644]
drivers/gpu/drm/gma500/psb_drv.c [new file with mode: 0644]
drivers/gpu/drm/gma500/psb_drv.h [new file with mode: 0644]
drivers/gpu/drm/gma500/psb_irq.c [new file with mode: 0644]
drivers/gpu/drm/gma500/psb_irq.h [new file with mode: 0644]
drivers/gpu/drm/gma500/psb_reg.h [new file with mode: 0644]

diff --git a/drivers/gpu/drm/gma500/psb_drm.h b/drivers/gpu/drm/gma500/psb_drm.h
new file mode 100644 (file)
index 0000000..dca7b20
--- /dev/null
@@ -0,0 +1,207 @@
+/**************************************************************************
+ * Copyright (c) 2007-2011, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA.
+ * 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.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_DRM_H_
+#define _PSB_DRM_H_
+
+#define PSB_NUM_PIPE 3
+
+#define PSB_GPU_ACCESS_READ         (1ULL << 32)
+#define PSB_GPU_ACCESS_WRITE        (1ULL << 33)
+#define PSB_GPU_ACCESS_MASK         (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)
+
+#define PSB_BO_FLAG_COMMAND         (1ULL << 52)
+
+/*
+ * Feedback components:
+ */
+
+struct drm_psb_sizes_arg {
+       u32 ta_mem_size;
+       u32 mmu_size;
+       u32 pds_size;
+       u32 rastgeom_size;
+       u32 tt_size;
+       u32 vram_size;
+};
+
+struct drm_psb_dpst_lut_arg {
+       uint8_t lut[256];
+       int output_id;
+};
+
+#define PSB_DC_CRTC_SAVE 0x01
+#define PSB_DC_CRTC_RESTORE 0x02
+#define PSB_DC_OUTPUT_SAVE 0x04
+#define PSB_DC_OUTPUT_RESTORE 0x08
+#define PSB_DC_CRTC_MASK 0x03
+#define PSB_DC_OUTPUT_MASK 0x0C
+
+struct drm_psb_dc_state_arg {
+       u32 flags;
+       u32 obj_id;
+};
+
+struct drm_psb_mode_operation_arg {
+       u32 obj_id;
+       u16 operation;
+       struct drm_mode_modeinfo mode;
+       void *data;
+};
+
+struct drm_psb_stolen_memory_arg {
+       u32 base;
+       u32 size;
+};
+
+/*Display Register Bits*/
+#define REGRWBITS_PFIT_CONTROLS                        (1 << 0)
+#define REGRWBITS_PFIT_AUTOSCALE_RATIOS                (1 << 1)
+#define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS (1 << 2)
+#define REGRWBITS_PIPEASRC                     (1 << 3)
+#define REGRWBITS_PIPEBSRC                     (1 << 4)
+#define REGRWBITS_VTOTAL_A                     (1 << 5)
+#define REGRWBITS_VTOTAL_B                     (1 << 6)
+#define REGRWBITS_DSPACNTR     (1 << 8)
+#define REGRWBITS_DSPBCNTR     (1 << 9)
+#define REGRWBITS_DSPCCNTR     (1 << 10)
+
+/*Overlay Register Bits*/
+#define OV_REGRWBITS_OVADD                     (1 << 0)
+#define OV_REGRWBITS_OGAM_ALL                  (1 << 1)
+
+#define OVC_REGRWBITS_OVADD                  (1 << 2)
+#define OVC_REGRWBITS_OGAM_ALL                 (1 << 3)
+
+struct drm_psb_register_rw_arg {
+       u32 b_force_hw_on;
+
+       u32 display_read_mask;
+       u32 display_write_mask;
+
+       struct {
+               u32 pfit_controls;
+               u32 pfit_autoscale_ratios;
+               u32 pfit_programmed_scale_ratios;
+               u32 pipeasrc;
+               u32 pipebsrc;
+               u32 vtotal_a;
+               u32 vtotal_b;
+       } display;
+
+       u32 overlay_read_mask;
+       u32 overlay_write_mask;
+
+       struct {
+               u32 OVADD;
+               u32 OGAMC0;
+               u32 OGAMC1;
+               u32 OGAMC2;
+               u32 OGAMC3;
+               u32 OGAMC4;
+               u32 OGAMC5;
+               u32 IEP_ENABLED;
+               u32 IEP_BLE_MINMAX;
+               u32 IEP_BSSCC_CONTROL;
+               u32 b_wait_vblank;
+       } overlay;
+
+       u32 sprite_enable_mask;
+       u32 sprite_disable_mask;
+
+       struct {
+               u32 dspa_control;
+               u32 dspa_key_value;
+               u32 dspa_key_mask;
+               u32 dspc_control;
+               u32 dspc_stride;
+               u32 dspc_position;
+               u32 dspc_linear_offset;
+               u32 dspc_size;
+               u32 dspc_surface;
+       } sprite;
+
+       u32 subpicture_enable_mask;
+       u32 subpicture_disable_mask;
+};
+
+/* Controlling the kernel modesetting buffers */
+
+#define DRM_PSB_SIZES           0x07
+#define DRM_PSB_FUSE_REG       0x08
+#define DRM_PSB_DC_STATE       0x0A
+#define DRM_PSB_ADB            0x0B
+#define DRM_PSB_MODE_OPERATION 0x0C
+#define DRM_PSB_STOLEN_MEMORY  0x0D
+#define DRM_PSB_REGISTER_RW    0x0E
+
+/*
+ * NOTE: Add new commands here, but increment
+ * the values below and increment their
+ * corresponding defines where they're
+ * defined elsewhere.
+ */
+
+#define DRM_PSB_GEM_CREATE     0x10
+#define DRM_PSB_2D_OP          0x11            /* Will be merged later */
+#define DRM_PSB_GEM_MMAP       0x12
+#define DRM_PSB_DPST           0x1B
+#define DRM_PSB_GAMMA          0x1C
+#define DRM_PSB_DPST_BL                0x1D
+#define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F
+
+#define PSB_MODE_OPERATION_MODE_VALID  0x01
+#define PSB_MODE_OPERATION_SET_DC_BASE  0x02
+
+struct drm_psb_get_pipe_from_crtc_id_arg {
+       /** ID of CRTC being requested **/
+       u32 crtc_id;
+
+       /** pipe of requested CRTC **/
+       u32 pipe;
+};
+
+/* FIXME: move this into a medfield header once we are sure it isn't needed for an
+   ioctl  */
+struct psb_drm_dpu_rect {  
+       int x, y;             
+       int width, height;    
+};  
+
+struct drm_psb_gem_create {
+       __u64 size;
+       __u32 handle;
+       __u32 flags;
+#define PSB_GEM_CREATE_STOLEN          1       /* Stolen memory can be used */
+};
+
+struct drm_psb_gem_mmap {
+       __u32 handle;
+       __u32 pad;
+       /**
+        * Fake offset to use for subsequent mmap call
+        *
+        * This is a fixed-size type for 32/64 compatibility.
+        */
+       __u64 offset;
+};
+
+#endif
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
new file mode 100644 (file)
index 0000000..b317a8b
--- /dev/null
@@ -0,0 +1,1210 @@
+/**************************************************************************
+ * Copyright (c) 2007-2011, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA.
+ * 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 <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "framebuffer.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "intel_bios.h"
+#include "mid_bios.h"
+#include <drm/drm_pciids.h>
+#include "power.h"
+#include <linux/cpu.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+#include <acpi/video.h>
+
+static int drm_psb_trap_pagefaults;
+
+int drm_psb_no_fb;
+
+static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+MODULE_PARM_DESC(no_fb, "Disable FBdev");
+MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
+module_param_named(no_fb, drm_psb_no_fb, int, 0600);
+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, (long) &psb_chip_ops },
+       { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
+#if defined(CONFIG_DRM_OAKTRAIL)
+       { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
+       { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
+       { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
+       { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
+       { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
+       { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
+       { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
+       { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
+#endif
+#if defined(CONFIG_DRM_CDV)
+       { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+       { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
+#endif
+       { 0, 0, 0}
+};
+MODULE_DEVICE_TABLE(pci, pciidlist);
+
+/*
+ * Standard IOCTLs.
+ */
+
+#define DRM_IOCTL_PSB_SIZES    \
+               DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
+                       struct drm_psb_sizes_arg)
+#define DRM_IOCTL_PSB_FUSE_REG \
+               DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t)
+#define DRM_IOCTL_PSB_DC_STATE \
+               DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \
+                       struct drm_psb_dc_state_arg)
+#define DRM_IOCTL_PSB_ADB      \
+               DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t)
+#define DRM_IOCTL_PSB_MODE_OPERATION   \
+               DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \
+                        struct drm_psb_mode_operation_arg)
+#define DRM_IOCTL_PSB_STOLEN_MEMORY    \
+               DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \
+                        struct drm_psb_stolen_memory_arg)
+#define DRM_IOCTL_PSB_REGISTER_RW      \
+               DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \
+                        struct drm_psb_register_rw_arg)
+#define DRM_IOCTL_PSB_DPST     \
+               DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \
+                        uint32_t)
+#define DRM_IOCTL_PSB_GAMMA    \
+               DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \
+                        struct drm_psb_dpst_lut_arg)
+#define DRM_IOCTL_PSB_DPST_BL  \
+               DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \
+                        uint32_t)
+#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID    \
+               DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
+                        struct drm_psb_get_pipe_from_crtc_id_arg)
+#define DRM_IOCTL_PSB_GEM_CREATE       \
+               DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \
+                        struct drm_psb_gem_create)
+#define DRM_IOCTL_PSB_GEM_MMAP \
+               DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \
+                        struct drm_psb_gem_mmap)
+
+static int psb_sizes_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
+                             struct drm_file *file_priv);
+static int psb_adb_ioctl(struct drm_device *dev, void *data,
+                        struct drm_file *file_priv);
+static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
+                                   struct drm_file *file_priv);
+static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv);
+static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv);
+static int psb_dpst_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv);
+static int psb_gamma_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv);
+static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
+                            struct drm_file *file_priv);
+
+#define PSB_IOCTL_DEF(ioctl, func, flags) \
+       [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
+
+static struct drm_ioctl_desc psb_ioctls[] = {
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl,
+                     DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl,
+                     DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl,
+                     DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID,
+                                       psb_intel_get_pipe_from_crtc_id, 0),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl,
+                                               DRM_UNLOCKED | DRM_AUTH),
+       PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_MMAP, psb_gem_mmap_ioctl,
+                                               DRM_UNLOCKED | DRM_AUTH),
+};
+
+static void psb_lastclose(struct drm_device *dev)
+{
+       return;
+}
+
+static void psb_do_takedown(struct drm_device *dev)
+{
+       /* FIXME: do we need to clean up the gtt here ? */
+}
+
+static int psb_do_init(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       struct psb_gtt *pg = &dev_priv->gtt;
+
+       uint32_t stolen_gtt;
+
+       int ret = -ENOMEM;
+
+       if (pg->mmu_gatt_start & 0x0FFFFFFF) {
+               dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n");
+               ret = -EINVAL;
+               goto out_err;
+       }
+
+
+       stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4;
+       stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       stolen_gtt =
+           (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
+
+       dev_priv->gatt_free_offset = pg->mmu_gatt_start +
+           (stolen_gtt << PAGE_SHIFT) * 1024;
+
+       if (1 || drm_debug) {
+               uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID);
+               uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION);
+               DRM_INFO("SGX core id = 0x%08x\n", core_id);
+               DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n",
+                        (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >>
+                        _PSB_CC_REVISION_MAJOR_SHIFT,
+                        (core_rev & _PSB_CC_REVISION_MINOR_MASK) >>
+                        _PSB_CC_REVISION_MINOR_SHIFT);
+               DRM_INFO
+                   ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n",
+                    (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >>
+                    _PSB_CC_REVISION_MAINTENANCE_SHIFT,
+                    (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >>
+                    _PSB_CC_REVISION_DESIGNER_SHIFT);
+       }
+
+
+       spin_lock_init(&dev_priv->irqmask_lock);
+       mutex_init(&dev_priv->mutex_2d);
+
+       PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
+       PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
+       PSB_RSGX32(PSB_CR_BIF_BANK1);
+       PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK,
+                                                       PSB_CR_BIF_CTRL);
+       psb_spank(dev_priv);
+
+       /* mmu_gatt ?? */
+       PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
+       return 0;
+out_err:
+       psb_do_takedown(dev);
+       return ret;
+}
+
+static int psb_driver_unload(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+
+       /* Kill vblank etc here */
+
+       gma_backlight_exit(dev);
+
+       if (drm_psb_no_fb == 0)
+               psb_modeset_cleanup(dev);
+
+       if (dev_priv) {
+               psb_lid_timer_takedown(dev_priv);
+               gma_intel_opregion_exit(dev);
+
+               if (dev_priv->ops->chip_teardown)
+                       dev_priv->ops->chip_teardown(dev);
+               psb_do_takedown(dev);
+
+
+               if (dev_priv->pf_pd) {
+                       psb_mmu_free_pagedir(dev_priv->pf_pd);
+                       dev_priv->pf_pd = NULL;
+               }
+               if (dev_priv->mmu) {
+                       struct psb_gtt *pg = &dev_priv->gtt;
+
+                       down_read(&pg->sem);
+                       psb_mmu_remove_pfn_sequence(
+                               psb_mmu_get_default_pd
+                               (dev_priv->mmu),
+                               pg->mmu_gatt_start,
+                               dev_priv->vram_stolen_size >> PAGE_SHIFT);
+                       up_read(&pg->sem);
+                       psb_mmu_driver_takedown(dev_priv->mmu);
+                       dev_priv->mmu = NULL;
+               }
+               psb_gtt_takedown(dev);
+               if (dev_priv->scratch_page) {
+                       __free_page(dev_priv->scratch_page);
+                       dev_priv->scratch_page = NULL;
+               }
+               if (dev_priv->vdc_reg) {
+                       iounmap(dev_priv->vdc_reg);
+                       dev_priv->vdc_reg = NULL;
+               }
+               if (dev_priv->sgx_reg) {
+                       iounmap(dev_priv->sgx_reg);
+                       dev_priv->sgx_reg = NULL;
+               }
+
+               kfree(dev_priv);
+               dev->dev_private = NULL;
+
+               /*destroy VBT data*/
+               psb_intel_destroy_bios(dev);
+       }
+
+       gma_power_uninit(dev);
+
+       return 0;
+}
+
+
+static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+       struct drm_psb_private *dev_priv;
+       unsigned long resource_start;
+       struct psb_gtt *pg;
+       unsigned long irqflags;
+       int ret = -ENOMEM;
+       uint32_t tt_pages;
+       struct drm_connector *connector;
+       struct psb_intel_output *psb_intel_output;
+
+       dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       dev_priv->ops = (struct psb_ops *)chipset;
+       dev_priv->dev = dev;
+       dev->dev_private = (void *) dev_priv;
+
+       dev_priv->num_pipe = dev_priv->ops->pipes;
+
+       resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
+
+       dev_priv->vdc_reg =
+           ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE);
+       if (!dev_priv->vdc_reg)
+               goto out_err;
+
+       dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset,
+                                                       PSB_SGX_SIZE);
+       if (!dev_priv->sgx_reg)
+               goto out_err;
+
+       ret = dev_priv->ops->chip_setup(dev);
+       if (ret)
+               goto out_err;
+
+       /* Init OSPM support */
+       gma_power_init(dev);
+
+       ret = -ENOMEM;
+
+       dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
+       if (!dev_priv->scratch_page)
+               goto out_err;
+
+       set_pages_uc(dev_priv->scratch_page, 1);
+
+       ret = psb_gtt_init(dev, 0);
+       if (ret)
+               goto out_err;
+
+       dev_priv->mmu = psb_mmu_driver_init((void *)0,
+                                       drm_psb_trap_pagefaults, 0,
+                                       dev_priv);
+       if (!dev_priv->mmu)
+               goto out_err;
+
+       pg = &dev_priv->gtt;
+
+       tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+               (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+
+       dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0);
+       if (!dev_priv->pf_pd)
+               goto out_err;
+
+       psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
+       psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
+
+       ret = psb_do_init(dev);
+       if (ret)
+               return ret;
+
+       PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE);
+       PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE);
+
+/*     igd_opregion_init(&dev_priv->opregion_dev); */
+       acpi_video_register();
+       if (dev_priv->lid_state)
+               psb_lid_timer_init(dev_priv);
+
+       ret = drm_vblank_init(dev, dev_priv->num_pipe);
+       if (ret)
+               goto out_err;
+
+       /*
+        * Install interrupt handlers prior to powering off SGX or else we will
+        * crash.
+        */
+       dev_priv->vdc_irq_mask = 0;
+       dev_priv->pipestat[0] = 0;
+       dev_priv->pipestat[1] = 0;
+       dev_priv->pipestat[2] = 0;
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+       PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
+       PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
+       PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               drm_irq_install(dev);
+
+       dev->vblank_disable_allowed = 1;
+
+       dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+
+       dev->driver->get_vblank_counter = psb_get_vblank_counter;
+
+       if (drm_psb_no_fb == 0) {
+               psb_modeset_init(dev);
+               psb_fbdev_init(dev);
+               drm_kms_helper_poll_init(dev);
+       }
+
+       /* Only add backlight support if we have LVDS output */
+       list_for_each_entry(connector, &dev->mode_config.connector_list,
+                           head) {
+               psb_intel_output = to_psb_intel_output(connector);
+
+               switch (psb_intel_output->type) {
+               case INTEL_OUTPUT_LVDS:
+               case INTEL_OUTPUT_MIPI:
+                       ret = gma_backlight_init(dev);
+                       break;
+               }
+       }
+
+       if (ret)
+               return ret;
+#if 0
+       /*enable runtime pm at last*/
+       pm_runtime_enable(&dev->pdev->dev);
+       pm_runtime_set_active(&dev->pdev->dev);
+#endif
+       /*Intel drm driver load is done, continue doing pvr load*/
+       return 0;
+out_err:
+       psb_driver_unload(dev);
+       return ret;
+}
+
+int psb_driver_device_is_agp(struct drm_device *dev)
+{
+       return 0;
+}
+
+
+static int psb_sizes_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct drm_psb_sizes_arg *arg =
+               (struct drm_psb_sizes_arg *) data;
+
+       *arg = dev_priv->sizes;
+       return 0;
+}
+
+static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
+                               struct drm_file *file_priv)
+{
+       uint32_t flags;
+       uint32_t obj_id;
+       struct drm_mode_object *obj;
+       struct drm_connector *connector;
+       struct drm_crtc *crtc;
+       struct drm_psb_dc_state_arg *arg = data;
+
+
+       /* Double check MRST case */
+       if (IS_MRST(dev) || IS_MFLD(dev))
+               return -EOPNOTSUPP;
+
+       flags = arg->flags;
+       obj_id = arg->obj_id;
+
+       if (flags & PSB_DC_CRTC_MASK) {
+               obj = drm_mode_object_find(dev, obj_id,
+                               DRM_MODE_OBJECT_CRTC);
+               if (!obj) {
+                       dev_dbg(dev->dev, "Invalid CRTC object.\n");
+                       return -EINVAL;
+               }
+
+               crtc = obj_to_crtc(obj);
+
+               mutex_lock(&dev->mode_config.mutex);
+               if (drm_helper_crtc_in_use(crtc)) {
+                       if (flags & PSB_DC_CRTC_SAVE)
+                               crtc->funcs->save(crtc);
+                       else
+                               crtc->funcs->restore(crtc);
+               }
+               mutex_unlock(&dev->mode_config.mutex);
+
+               return 0;
+       } else if (flags & PSB_DC_OUTPUT_MASK) {
+               obj = drm_mode_object_find(dev, obj_id,
+                               DRM_MODE_OBJECT_CONNECTOR);
+               if (!obj) {
+                       dev_dbg(dev->dev, "Invalid connector id.\n");
+                       return -EINVAL;
+               }
+
+               connector = obj_to_connector(obj);
+               if (flags & PSB_DC_OUTPUT_SAVE)
+                       connector->funcs->save(connector);
+               else
+                       connector->funcs->restore(connector);
+
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static inline void get_brightness(struct backlight_device *bd)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+       if (bd) {
+               bd->props.brightness = bd->ops->get_brightness(bd);
+               backlight_update_status(bd);
+       }
+#endif
+}
+
+static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
+                      struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       uint32_t *arg = data;
+
+       dev_priv->blc_adj2 = *arg;
+       get_brightness(dev_priv->backlight_device);
+       return 0;
+}
+
+static int psb_adb_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       uint32_t *arg = data;
+
+       dev_priv->blc_adj1 = *arg;
+       get_brightness(dev_priv->backlight_device);
+       return 0;
+}
+
+/* return the current mode to the dpst module */
+static int psb_dpst_ioctl(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       uint32_t *arg = data;
+       uint32_t x;
+       uint32_t y;
+       uint32_t reg;
+
+       if (!gma_power_begin(dev, 0))
+               return -EIO;
+
+       reg = PSB_RVDC32(PIPEASRC);
+
+       gma_power_end(dev);
+
+       /* horizontal is the left 16 bits */
+       x = reg >> 16;
+       /* vertical is the right 16 bits */
+       y = reg & 0x0000ffff;
+
+       /* the values are the image size minus one */
+       x++;
+       y++;
+
+       *arg = (x << 16) | y;
+
+       return 0;
+}
+static int psb_gamma_ioctl(struct drm_device *dev, void *data,
+                          struct drm_file *file_priv)
+{
+       struct drm_psb_dpst_lut_arg *lut_arg = data;
+       struct drm_mode_object *obj;
+       struct drm_crtc *crtc;
+       struct drm_connector *connector;
+       struct psb_intel_crtc *psb_intel_crtc;
+       int i = 0;
+       int32_t obj_id;
+
+       obj_id = lut_arg->output_id;
+       obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
+       if (!obj) {
+               dev_dbg(dev->dev, "Invalid Connector object.\n");
+               return -EINVAL;
+       }
+
+       connector = obj_to_connector(obj);
+       crtc = connector->encoder->crtc;
+       psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+       for (i = 0; i < 256; i++)
+               psb_intel_crtc->lut_adj[i] = lut_arg->lut[i];
+
+       psb_intel_crtc_load_lut(crtc);
+
+       return 0;
+}
+
+static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *file_priv)
+{
+       uint32_t obj_id;
+       uint16_t op;
+       struct drm_mode_modeinfo *umode;
+       struct drm_display_mode *mode = NULL;
+       struct drm_psb_mode_operation_arg *arg;
+       struct drm_mode_object *obj;
+       struct drm_connector *connector;
+       struct drm_framebuffer *drm_fb;
+       struct psb_framebuffer *psb_fb;
+       struct drm_connector_helper_funcs *connector_funcs;
+       int ret = 0;
+       int resp = MODE_OK;
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+
+       arg = (struct drm_psb_mode_operation_arg *)data;
+       obj_id = arg->obj_id;
+       op = arg->operation;
+
+       switch (op) {
+       case PSB_MODE_OPERATION_SET_DC_BASE:
+               obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB);
+               if (!obj) {
+                       dev_dbg(dev->dev, "Invalid FB id %d\n", obj_id);
+                       return -EINVAL;
+               }
+
+               drm_fb = obj_to_fb(obj);
+               psb_fb = to_psb_fb(drm_fb);
+
+               if (gma_power_begin(dev, 0)) {
+                       REG_WRITE(DSPASURF, psb_fb->gtt->offset);
+                       REG_READ(DSPASURF);
+                       gma_power_end(dev);
+               } else {
+                       dev_priv->saveDSPASURF = psb_fb->gtt->offset;
+               }
+
+               return 0;
+       case PSB_MODE_OPERATION_MODE_VALID:
+               umode = &arg->mode;
+
+               mutex_lock(&dev->mode_config.mutex);
+
+               obj = drm_mode_object_find(dev, obj_id,
+                                       DRM_MODE_OBJECT_CONNECTOR);
+               if (!obj) {
+                       ret = -EINVAL;
+                       goto mode_op_out;
+               }
+
+               connector = obj_to_connector(obj);
+
+               mode = drm_mode_create(dev);
+               if (!mode) {
+                       ret = -ENOMEM;
+                       goto mode_op_out;
+               }
+
+               /* drm_crtc_convert_umode(mode, umode); */
+               {
+                       mode->clock = umode->clock;
+                       mode->hdisplay = umode->hdisplay;
+                       mode->hsync_start = umode->hsync_start;
+                       mode->hsync_end = umode->hsync_end;
+                       mode->htotal = umode->htotal;
+                       mode->hskew = umode->hskew;
+                       mode->vdisplay = umode->vdisplay;
+                       mode->vsync_start = umode->vsync_start;
+                       mode->vsync_end = umode->vsync_end;
+                       mode->vtotal = umode->vtotal;
+                       mode->vscan = umode->vscan;
+                       mode->vrefresh = umode->vrefresh;
+                       mode->flags = umode->flags;
+                       mode->type = umode->type;
+                       strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN);
+                       mode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+               }
+
+               connector_funcs = (struct drm_connector_helper_funcs *)
+                                  connector->helper_private;
+
+               if (connector_funcs->mode_valid) {
+                       resp = connector_funcs->mode_valid(connector, mode);
+                       arg->data = (void *)resp;
+               }
+
+               /*do some clean up work*/
+               if (mode)
+                       drm_mode_destroy(dev, mode);
+mode_op_out:
+               mutex_unlock(&dev->mode_config.mutex);
+               return ret;
+
+       default:
+               dev_dbg(dev->dev, "Unsupported psb mode operation\n");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
+                                  struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct drm_psb_stolen_memory_arg *arg = data;
+
+       arg->base = dev_priv->stolen_base;
+       arg->size = dev_priv->vram_stolen_size;
+
+       return 0;
+}
+
+/* FIXME: needs Medfield changes */
+static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
+                                struct drm_file *file_priv)
+{
+       struct drm_psb_private *dev_priv = psb_priv(dev);
+       struct drm_psb_register_rw_arg *arg = data;
+       bool usage = arg->b_force_hw_on ? true : false;
+
+       if (arg->display_write_mask != 0) {
+               if (gma_power_begin(dev, usage)) {
+                       if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
+                               PSB_WVDC32(arg->display.pfit_controls,
+                                          PFIT_CONTROL);
+                       if (arg->display_write_mask &
+                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+                               PSB_WVDC32(arg->display.pfit_autoscale_ratios,
+                                          PFIT_AUTO_RATIOS);
+                       if (arg->display_write_mask &
+                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+                               PSB_WVDC32(
+                                  arg->display.pfit_programmed_scale_ratios,
+                                  PFIT_PGM_RATIOS);
+                       if (arg->display_write_mask & REGRWBITS_PIPEASRC)
+                               PSB_WVDC32(arg->display.pipeasrc,
+                                          PIPEASRC);
+                       if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
+                               PSB_WVDC32(arg->display.pipebsrc,
+                                          PIPEBSRC);
+                       if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
+                               PSB_WVDC32(arg->display.vtotal_a,
+                                          VTOTAL_A);
+                       if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
+                               PSB_WVDC32(arg->display.vtotal_b,
+                                          VTOTAL_B);
+                       gma_power_end(dev);
+               } else {
+                       if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
+                               dev_priv->savePFIT_CONTROL =
+                                               arg->display.pfit_controls;
+                       if (arg->display_write_mask &
+                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+                               dev_priv->savePFIT_AUTO_RATIOS =
+                                       arg->display.pfit_autoscale_ratios;
+                       if (arg->display_write_mask &
+                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+                               dev_priv->savePFIT_PGM_RATIOS =
+                                  arg->display.pfit_programmed_scale_ratios;
+                       if (arg->display_write_mask & REGRWBITS_PIPEASRC)
+                               dev_priv->savePIPEASRC = arg->display.pipeasrc;
+                       if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
+                               dev_priv->savePIPEBSRC = arg->display.pipebsrc;
+                       if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
+                               dev_priv->saveVTOTAL_A = arg->display.vtotal_a;
+                       if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
+                               dev_priv->saveVTOTAL_B = arg->display.vtotal_b;
+               }
+       }
+
+       if (arg->display_read_mask != 0) {
+               if (gma_power_begin(dev, usage)) {
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_CONTROLS)
+                               arg->display.pfit_controls =
+                                               PSB_RVDC32(PFIT_CONTROL);
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+                               arg->display.pfit_autoscale_ratios =
+                                               PSB_RVDC32(PFIT_AUTO_RATIOS);
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+                               arg->display.pfit_programmed_scale_ratios =
+                                               PSB_RVDC32(PFIT_PGM_RATIOS);
+                       if (arg->display_read_mask & REGRWBITS_PIPEASRC)
+                               arg->display.pipeasrc = PSB_RVDC32(PIPEASRC);
+                       if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
+                               arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC);
+                       if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
+                               arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A);
+                       if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
+                               arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B);
+                       gma_power_end(dev);
+               } else {
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_CONTROLS)
+                               arg->display.pfit_controls =
+                                               dev_priv->savePFIT_CONTROL;
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+                               arg->display.pfit_autoscale_ratios =
+                                               dev_priv->savePFIT_AUTO_RATIOS;
+                       if (arg->display_read_mask &
+                           REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+                               arg->display.pfit_programmed_scale_ratios =
+                                               dev_priv->savePFIT_PGM_RATIOS;
+                       if (arg->display_read_mask & REGRWBITS_PIPEASRC)
+                               arg->display.pipeasrc = dev_priv->savePIPEASRC;
+                       if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
+                               arg->display.pipebsrc = dev_priv->savePIPEBSRC;
+                       if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
+                               arg->display.vtotal_a = dev_priv->saveVTOTAL_A;
+                       if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
+                               arg->display.vtotal_b = dev_priv->saveVTOTAL_B;
+               }
+       }
+
+       if (arg->overlay_write_mask != 0) {
+               if (gma_power_begin(dev, usage)) {
+                       if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
+                               PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5);
+                               PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4);
+                               PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3);
+                               PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2);
+                               PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1);
+                               PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0);
+                       }
+                       if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
+                               PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5);
+                               PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4);
+                               PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3);
+                               PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2);
+                               PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1);
+                               PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0);
+                       }
+
+                       if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) {
+                               PSB_WVDC32(arg->overlay.OVADD, OV_OVADD);
+
+                               if (arg->overlay.b_wait_vblank) {
+                                       /* Wait for 20ms.*/
+                                       unsigned long vblank_timeout = jiffies
+                                                               + HZ/50;
+                                       uint32_t temp;
+                                       while (time_before_eq(jiffies,
+                                                       vblank_timeout)) {
+                                               temp = PSB_RVDC32(OV_DOVASTA);
+                                               if ((temp & (0x1 << 31)) != 0)
+                                                       break;
+                                               cpu_relax();
+                                       }
+                               }
+                       }
+                       if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) {
+                               PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD);
+                               if (arg->overlay.b_wait_vblank) {
+                                       /* Wait for 20ms.*/
+                                       unsigned long vblank_timeout =
+                                                       jiffies + HZ/50;
+                                       uint32_t temp;
+                                       while (time_before_eq(jiffies,
+                                                       vblank_timeout)) {
+                                               temp = PSB_RVDC32(OVC_DOVCSTA);
+                                               if ((temp & (0x1 << 31)) != 0)
+                                                       break;
+                                               cpu_relax();
+                                       }
+                               }
+                       }
+                       gma_power_end(dev);
+               } else {
+                       if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
+                               dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5;
+                               dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4;
+                               dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3;
+                               dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2;
+                               dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1;
+                               dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0;
+                       }
+                       if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
+                               dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5;
+                               dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4;
+                               dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3;
+                               dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2;
+                               dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1;
+                               dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0;
+                       }
+                       if (arg->overlay_write_mask & OV_REGRWBITS_OVADD)
+                               dev_priv->saveOV_OVADD = arg->overlay.OVADD;
+                       if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD)
+                               dev_priv->saveOVC_OVADD = arg->overlay.OVADD;
+               }
+       }
+
+       if (arg->overlay_read_mask != 0) {
+               if (gma_power_begin(dev, usage)) {
+                       if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
+                               arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+                               arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+                               arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+                               arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+                               arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+                               arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+                       }
+                       if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
+                               arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5);
+                               arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4);
+                               arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3);
+                               arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2);
+                               arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1);
+                               arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0);
+                       }
+                       if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
+                               arg->overlay.OVADD = PSB_RVDC32(OV_OVADD);
+                       if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
+                               arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD);
+                       gma_power_end(dev);
+               } else {
+                       if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
+                               arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5;
+                               arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4;
+                               arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3;
+                               arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2;
+                               arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1;
+                               arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0;
+                       }
+                       if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
+                               arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5;
+                               arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4;
+                               arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3;
+                               arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2;
+                               arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1;
+                               arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0;
+                       }
+                       if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
+                               arg->overlay.OVADD = dev_priv->saveOV_OVADD;
+                       if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
+                               arg->overlay.OVADD = dev_priv->saveOVC_OVADD;
+               }
+       }
+
+       if (arg->sprite_enable_mask != 0) {
+               if (gma_power_begin(dev, usage)) {
+                       PSB_WVDC32(0x1F3E, DSPARB);
+                       PSB_WVDC32(arg->sprite.dspa_control
+                                       | PSB_RVDC32(DSPACNTR), DSPACNTR);
+                       PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL);
+                       PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK);
+                       PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF);
+                       PSB_RVDC32(DSPASURF);
+                       PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR);
+                       PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE);
+                       PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS);
+                       PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF);
+                       PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE);
+                       PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
+                       PSB_RVDC32(DSPCSURF);
+                       gma_power_end(dev);
+               }
+       }
+
+       if (arg->sprite_disable_mask != 0) {
+               if (gma_power_begin(dev, usage)) {
+                       PSB_WVDC32(0x3F3E, DSPARB);
+                       PSB_WVDC32(0x0, DSPCCNTR);
+                       PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
+                       PSB_RVDC32(DSPCSURF);
+                       gma_power_end(dev);
+               }
+       }
+
+       if (arg->subpicture_enable_mask != 0) {
+               if (gma_power_begin(dev, usage)) {
+                       uint32_t temp;
+                       if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) {
+                               temp =  PSB_RVDC32(DSPACNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp &= ~DISPPLANE_BOTTOM;
+                               temp |= DISPPLANE_32BPP;
+                               PSB_WVDC32(temp, DSPACNTR);
+
+                               temp =  PSB_RVDC32(DSPABASE);
+                               PSB_WVDC32(temp, DSPABASE);
+                               PSB_RVDC32(DSPABASE);
+                               temp =  PSB_RVDC32(DSPASURF);
+                               PSB_WVDC32(temp, DSPASURF);
+                               PSB_RVDC32(DSPASURF);
+                       }
+                       if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) {
+                               temp =  PSB_RVDC32(DSPBCNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp &= ~DISPPLANE_BOTTOM;
+                               temp |= DISPPLANE_32BPP;
+                               PSB_WVDC32(temp, DSPBCNTR);
+
+                               temp =  PSB_RVDC32(DSPBBASE);
+                               PSB_WVDC32(temp, DSPBBASE);
+                               PSB_RVDC32(DSPBBASE);
+                               temp =  PSB_RVDC32(DSPBSURF);
+                               PSB_WVDC32(temp, DSPBSURF);
+                               PSB_RVDC32(DSPBSURF);
+                       }
+                       if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) {
+                               temp =  PSB_RVDC32(DSPCCNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp &= ~DISPPLANE_BOTTOM;
+                               temp |= DISPPLANE_32BPP;
+                               PSB_WVDC32(temp, DSPCCNTR);
+
+                               temp =  PSB_RVDC32(DSPCBASE);
+                               PSB_WVDC32(temp, DSPCBASE);
+                               PSB_RVDC32(DSPCBASE);
+                               temp =  PSB_RVDC32(DSPCSURF);
+                               PSB_WVDC32(temp, DSPCSURF);
+                               PSB_RVDC32(DSPCSURF);
+                       }
+                       gma_power_end(dev);
+               }
+       }
+
+       if (arg->subpicture_disable_mask != 0) {
+               if (gma_power_begin(dev, usage)) {
+                       uint32_t temp;
+                       if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) {
+                               temp =  PSB_RVDC32(DSPACNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp |= DISPPLANE_32BPP_NO_ALPHA;
+                               PSB_WVDC32(temp, DSPACNTR);
+
+                               temp =  PSB_RVDC32(DSPABASE);
+                               PSB_WVDC32(temp, DSPABASE);
+                               PSB_RVDC32(DSPABASE);
+                               temp =  PSB_RVDC32(DSPASURF);
+                               PSB_WVDC32(temp, DSPASURF);
+                               PSB_RVDC32(DSPASURF);
+                       }
+                       if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) {
+                               temp =  PSB_RVDC32(DSPBCNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp |= DISPPLANE_32BPP_NO_ALPHA;
+                               PSB_WVDC32(temp, DSPBCNTR);
+
+                               temp =  PSB_RVDC32(DSPBBASE);
+                               PSB_WVDC32(temp, DSPBBASE);
+                               PSB_RVDC32(DSPBBASE);
+                               temp =  PSB_RVDC32(DSPBSURF);
+                               PSB_WVDC32(temp, DSPBSURF);
+                               PSB_RVDC32(DSPBSURF);
+                       }
+                       if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) {
+                               temp =  PSB_RVDC32(DSPCCNTR);
+                               temp &= ~DISPPLANE_PIXFORMAT_MASK;
+                               temp |= DISPPLANE_32BPP_NO_ALPHA;
+                               PSB_WVDC32(temp, DSPCCNTR);
+
+                               temp =  PSB_RVDC32(DSPCBASE);
+                               PSB_WVDC32(temp, DSPCBASE);
+                               PSB_RVDC32(DSPCBASE);
+                               temp =  PSB_RVDC32(DSPCSURF);
+                               PSB_WVDC32(temp, DSPCSURF);
+                               PSB_RVDC32(DSPCSURF);
+                       }
+                       gma_power_end(dev);
+               }
+       }
+
+       return 0;
+}
+
+static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
+{
+       return 0;
+}
+
+static void psb_driver_close(struct drm_device *dev, struct drm_file *priv)
+{
+}
+
+static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
+                              unsigned long arg)
+{
+       struct drm_file *file_priv = filp->private_data;
+       struct drm_device *dev = file_priv->minor->dev;
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       static unsigned int runtime_allowed;
+
+       if (runtime_allowed == 1 && dev_priv->is_lvds_on) {
+               runtime_allowed++;
+               pm_runtime_allow(&dev->pdev->dev);
+               dev_priv->rpm_enabled = 1;
+       }
+       return drm_ioctl(filp, cmd, arg);
+       /* FIXME: do we need to wrap the other side of this */
+}
+
+
+/* When a client dies:
+ *    - Check for and clean up flipped page state
+ */
+void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
+{
+}
+
+static void psb_remove(struct pci_dev *pdev)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       drm_put_dev(dev);
+}
+
+static const struct dev_pm_ops psb_pm_ops = {
+       .resume = gma_power_resume,
+       .suspend = gma_power_suspend,
+       .runtime_suspend = psb_runtime_suspend,
+       .runtime_resume = psb_runtime_resume,
+       .runtime_idle = psb_runtime_idle,
+};
+
+static struct vm_operations_struct psb_gem_vm_ops = {
+       .fault = psb_gem_fault,
+       .open = drm_gem_vm_open,
+       .close = drm_gem_vm_close,
+};
+
+static struct drm_driver driver = {
+       .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
+                          DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM ,
+       .load = psb_driver_load,
+       .unload = psb_driver_unload,
+
+       .ioctls = psb_ioctls,
+       .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls),
+       .device_is_agp = psb_driver_device_is_agp,
+       .irq_preinstall = psb_irq_preinstall,
+       .irq_postinstall = psb_irq_postinstall,
+       .irq_uninstall = psb_irq_uninstall,
+       .irq_handler = psb_irq_handler,
+       .enable_vblank = psb_enable_vblank,
+       .disable_vblank = psb_disable_vblank,
+       .get_vblank_counter = psb_get_vblank_counter,
+       .lastclose = psb_lastclose,
+       .open = psb_driver_open,
+       .preclose = psb_driver_preclose,
+       .postclose = psb_driver_close,
+       .reclaim_buffers = drm_core_reclaim_buffers,
+
+       .gem_init_object = psb_gem_init_object,
+       .gem_free_object = psb_gem_free_object,
+       .gem_vm_ops = &psb_gem_vm_ops,
+       .dumb_create = psb_gem_dumb_create,
+       .dumb_map_offset = psb_gem_dumb_map_gtt,
+       .dumb_destroy = psb_gem_dumb_destroy,
+
+       .fops = {
+                .owner = THIS_MODULE,
+                .open = drm_open,
+                .release = drm_release,
+                .unlocked_ioctl = psb_unlocked_ioctl,
+                .mmap = drm_gem_mmap,
+                .poll = drm_poll,
+                .fasync = drm_fasync,
+                .read = drm_read,
+        },
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = PSB_DRM_DRIVER_DATE,
+       .major = PSB_DRM_DRIVER_MAJOR,
+       .minor = PSB_DRM_DRIVER_MINOR,
+       .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL
+};
+
+static struct pci_driver psb_pci_driver = {
+       .name = DRIVER_NAME,
+       .id_table = pciidlist,
+       .probe = psb_probe,
+       .remove = psb_remove,
+       .driver.pm = &psb_pm_ops,
+};
+
+static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       /* MLD Added this from Inaky's patch */
+       if (pci_enable_msi(pdev))
+               dev_warn(&pdev->dev, "Enable MSI failed!\n");
+       return drm_get_pci_dev(pdev, ent, &driver);
+}
+
+static int __init psb_init(void)
+{
+       return drm_pci_init(&driver, &psb_pci_driver);
+}
+
+static void __exit psb_exit(void)
+{
+       drm_pci_exit(&driver, &psb_pci_driver);
+}
+
+late_initcall(psb_init);
+module_exit(psb_exit);
+
+MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
new file mode 100644 (file)
index 0000000..a5ae9b1
--- /dev/null
@@ -0,0 +1,924 @@
+/**************************************************************************
+ * Copyright (c) 2007-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.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_DRV_H_
+#define _PSB_DRV_H_
+
+#include <linux/kref.h>
+
+#include <drm/drmP.h>
+#include "drm_global.h"
+#include "gem_glue.h"
+#include "psb_drm.h"
+#include "psb_reg.h"
+#include "psb_intel_drv.h"
+#include "gtt.h"
+#include "power.h"
+#include "oaktrail.h"
+
+/* Append new drm mode definition here, align with libdrm definition */
+#define DRM_MODE_SCALE_NO_SCALE        2
+
+enum {
+       CHIP_PSB_8108 = 0,              /* Poulsbo */
+       CHIP_PSB_8109 = 1,              /* Poulsbo */
+       CHIP_MRST_4100 = 2,             /* Moorestown/Oaktrail */
+       CHIP_MFLD_0130 = 3,             /* Medfield */
+};
+
+#define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100)
+#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130)
+
+/*
+ * Driver definitions
+ */
+
+#define DRIVER_NAME "gma500"
+#define DRIVER_DESC "DRM driver for the Intel GMA500"
+
+#define PSB_DRM_DRIVER_DATE "2011-06-06"
+#define PSB_DRM_DRIVER_MAJOR 1
+#define PSB_DRM_DRIVER_MINOR 0
+#define PSB_DRM_DRIVER_PATCHLEVEL 0
+
+/*
+ *     Hardware offsets
+ */
+#define PSB_VDC_OFFSET          0x00000000
+#define PSB_VDC_SIZE            0x000080000
+#define MRST_MMIO_SIZE          0x0000C0000
+#define MDFLD_MMIO_SIZE          0x000100000
+#define PSB_SGX_SIZE            0x8000
+#define PSB_SGX_OFFSET          0x00040000
+#define MRST_SGX_OFFSET                 0x00080000
+/*
+ *     PCI resource identifiers
+ */
+#define PSB_MMIO_RESOURCE       0
+#define PSB_GATT_RESOURCE       2
+#define PSB_GTT_RESOURCE        3
+/*
+ *     PCI configuration
+ */
+#define PSB_GMCH_CTRL           0x52
+#define PSB_BSM                         0x5C
+#define _PSB_GMCH_ENABLED       0x4
+#define PSB_PGETBL_CTL          0x2020
+#define _PSB_PGETBL_ENABLED     0x00000001
+#define PSB_SGX_2D_SLAVE_PORT   0x4000
+
+/* To get rid of */
+#define PSB_TT_PRIV0_LIMIT      (256*1024*1024)
+#define PSB_TT_PRIV0_PLIMIT     (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
+
+/*
+ *     SGX side MMU definitions (these can probably go)
+ */
+
+/*
+ *     Flags for external memory type field.
+ */
+#define PSB_MMU_CACHED_MEMORY    0x0001        /* Bind to MMU only */
+#define PSB_MMU_RO_MEMORY        0x0002        /* MMU RO memory */
+#define PSB_MMU_WO_MEMORY        0x0004        /* MMU WO memory */
+/*
+ *     PTE's and PDE's
+ */
+#define PSB_PDE_MASK             0x003FFFFF
+#define PSB_PDE_SHIFT            22
+#define PSB_PTE_SHIFT            12
+/*
+ *     Cache control
+ */
+#define PSB_PTE_VALID            0x0001        /* PTE / PDE valid */
+#define PSB_PTE_WO               0x0002        /* Write only */
+#define PSB_PTE_RO               0x0004        /* Read only */
+#define PSB_PTE_CACHED           0x0008        /* CPU cache coherent */
+
+/*
+ *     VDC registers and bits
+ */
+#define PSB_MSVDX_CLOCKGATING    0x2064
+#define PSB_TOPAZ_CLOCKGATING    0x2068
+#define PSB_HWSTAM               0x2098
+#define PSB_INSTPM               0x20C0
+#define PSB_INT_IDENTITY_R        0x20A4
+#define _MDFLD_PIPEC_EVENT_FLAG   (1<<2)
+#define _MDFLD_PIPEC_VBLANK_FLAG  (1<<3)
+#define _PSB_DPST_PIPEB_FLAG      (1<<4)
+#define _MDFLD_PIPEB_EVENT_FLAG   (1<<4)
+#define _PSB_VSYNC_PIPEB_FLAG    (1<<5)
+#define _PSB_DPST_PIPEA_FLAG      (1<<6)
+#define _PSB_PIPEA_EVENT_FLAG     (1<<6)
+#define _PSB_VSYNC_PIPEA_FLAG    (1<<7)
+#define _MDFLD_MIPIA_FLAG        (1<<16)
+#define _MDFLD_MIPIC_FLAG        (1<<17)
+#define _PSB_IRQ_SGX_FLAG        (1<<18)
+#define _PSB_IRQ_MSVDX_FLAG      (1<<19)
+#define _LNC_IRQ_TOPAZ_FLAG      (1<<20)
+
+/* This flag includes all the display IRQ bits excepts the vblank irqs. */
+#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \
+                                 _MDFLD_PIPEB_EVENT_FLAG | \
+                                 _PSB_PIPEA_EVENT_FLAG | \
+                                 _PSB_VSYNC_PIPEA_FLAG | \
+                                 _MDFLD_MIPIA_FLAG | \
+                                 _MDFLD_MIPIC_FLAG)
+#define PSB_INT_IDENTITY_R       0x20A4
+#define PSB_INT_MASK_R           0x20A8
+#define PSB_INT_ENABLE_R         0x20A0
+
+#define _PSB_MMU_ER_MASK      0x0001FF00
+#define _PSB_MMU_ER_HOST      (1 << 16)
+#define GPIOA                  0x5010
+#define GPIOB                  0x5014
+#define GPIOC                  0x5018
+#define GPIOD                  0x501c
+#define GPIOE                  0x5020
+#define GPIOF                  0x5024
+#define GPIOG                  0x5028
+#define GPIOH                  0x502c
+#define GPIO_CLOCK_DIR_MASK            (1 << 0)
+#define GPIO_CLOCK_DIR_IN              (0 << 1)
+#define GPIO_CLOCK_DIR_OUT             (1 << 1)
+#define GPIO_CLOCK_VAL_MASK            (1 << 2)
+#define GPIO_CLOCK_VAL_OUT             (1 << 3)
+#define GPIO_CLOCK_VAL_IN              (1 << 4)
+#define GPIO_CLOCK_PULLUP_DISABLE      (1 << 5)
+#define GPIO_DATA_DIR_MASK             (1 << 8)
+#define GPIO_DATA_DIR_IN               (0 << 9)
+#define GPIO_DATA_DIR_OUT              (1 << 9)
+#define GPIO_DATA_VAL_MASK             (1 << 10)
+#define GPIO_DATA_VAL_OUT              (1 << 11)
+#define GPIO_DATA_VAL_IN               (1 << 12)
+#define GPIO_DATA_PULLUP_DISABLE       (1 << 13)
+
+#define VCLK_DIVISOR_VGA0   0x6000
+#define VCLK_DIVISOR_VGA1   0x6004
+#define VCLK_POST_DIV      0x6010
+
+#define PSB_COMM_2D (PSB_ENGINE_2D << 4)
+#define PSB_COMM_3D (PSB_ENGINE_3D << 4)
+#define PSB_COMM_TA (PSB_ENGINE_TA << 4)
+#define PSB_COMM_HP (PSB_ENGINE_HP << 4)
+#define PSB_COMM_USER_IRQ (1024 >> 2)
+#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1)
+#define PSB_COMM_FW (2048 >> 2)
+
+#define PSB_UIRQ_VISTEST              1
+#define PSB_UIRQ_OOM_REPLY            2
+#define PSB_UIRQ_FIRE_TA_REPLY        3
+#define PSB_UIRQ_FIRE_RASTER_REPLY     4
+
+#define PSB_2D_SIZE (256*1024*1024)
+#define PSB_MAX_RELOC_PAGES 1024
+
+#define PSB_LOW_REG_OFFS 0x0204
+#define PSB_HIGH_REG_OFFS 0x0600
+
+#define PSB_NUM_VBLANKS 2
+
+
+#define PSB_2D_SIZE (256*1024*1024)
+#define PSB_MAX_RELOC_PAGES 1024
+
+#define PSB_LOW_REG_OFFS 0x0204
+#define PSB_HIGH_REG_OFFS 0x0600
+
+#define PSB_NUM_VBLANKS 2
+#define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
+#define PSB_LID_DELAY (DRM_HZ / 10)
+
+#define MDFLD_PNW_B0 0x04
+#define MDFLD_PNW_C0 0x08
+
+#define MDFLD_DSR_2D_3D_0      (1 << 0)
+#define MDFLD_DSR_2D_3D_2      (1 << 1)
+#define MDFLD_DSR_CURSOR_0     (1 << 2)
+#define MDFLD_DSR_CURSOR_2     (1 << 3)
+#define MDFLD_DSR_OVERLAY_0    (1 << 4)
+#define MDFLD_DSR_OVERLAY_2    (1 << 5)
+#define MDFLD_DSR_MIPI_CONTROL (1 << 6)
+#define MDFLD_DSR_DAMAGE_MASK_0        ((1 << 0) | (1 << 2) | (1 << 4))
+#define MDFLD_DSR_DAMAGE_MASK_2        ((1 << 1) | (1 << 3) | (1 << 5))
+#define MDFLD_DSR_2D_3D        (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2)
+
+#define MDFLD_DSR_RR           45
+#define MDFLD_DPU_ENABLE       (1 << 31)
+#define MDFLD_DSR_FULLSCREEN   (1 << 30)
+#define MDFLD_DSR_DELAY                (DRM_HZ / MDFLD_DSR_RR)
+
+#define PSB_PWR_STATE_ON               1
+#define PSB_PWR_STATE_OFF              2
+
+#define PSB_PMPOLICY_NOPM              0
+#define PSB_PMPOLICY_CLOCKGATING       1
+#define PSB_PMPOLICY_POWERDOWN         2
+
+#define PSB_PMSTATE_POWERUP            0
+#define PSB_PMSTATE_CLOCKGATED         1
+#define PSB_PMSTATE_POWERDOWN          2
+#define PSB_PCIx_MSI_ADDR_LOC          0x94
+#define PSB_PCIx_MSI_DATA_LOC          0x98
+
+/* Medfield crystal settings */
+#define KSEL_CRYSTAL_19 1
+#define KSEL_BYPASS_19 5
+#define KSEL_BYPASS_25 6
+#define KSEL_BYPASS_83_100 7
+
+struct opregion_header;
+struct opregion_acpi;
+struct opregion_swsci;
+struct opregion_asle;
+
+struct psb_intel_opregion {
+       struct opregion_header *header;
+       struct opregion_acpi *acpi;
+       struct opregion_swsci *swsci;
+       struct opregion_asle *asle;
+       int enabled;
+};
+
+struct psb_ops;
+
+struct drm_psb_private {
+       struct drm_device *dev;
+       const struct psb_ops *ops;
+
+       struct psb_gtt gtt;
+
+       /* GTT Memory manager */
+       struct psb_gtt_mm *gtt_mm;
+       struct page *scratch_page;
+       u32 *gtt_map;
+       uint32_t stolen_base;
+       void *vram_addr;
+       unsigned long vram_stolen_size;
+       int gtt_initialized;
+       u16 gmch_ctrl;          /* Saved GTT setup */
+       u32 pge_ctl;
+
+       struct mutex gtt_mutex;
+       struct resource *gtt_mem;       /* Our PCI resource */
+
+       struct psb_mmu_driver *mmu;
+       struct psb_mmu_pd *pf_pd;
+
+       /*
+        * Register base
+        */
+
+       uint8_t *sgx_reg;
+       uint8_t *vdc_reg;
+       uint32_t gatt_free_offset;
+
+       /*
+        * Fencing / irq.
+        */
+
+       uint32_t vdc_irq_mask;
+       uint32_t pipestat[PSB_NUM_PIPE];
+
+       spinlock_t irqmask_lock;
+
+       /*
+        * Power
+        */
+
+       bool suspended;
+       bool display_power;
+       int display_count;
+
+       /*
+        * Modesetting
+        */
+       struct psb_intel_mode_device mode_dev;
+
+       struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE];
+       struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE];
+       uint32_t num_pipe;
+
+       /*
+        * OSPM info (Power management base) (can go ?)
+        */
+       uint32_t ospm_base;
+
+       /*
+        * Sizes info
+        */
+
+       struct drm_psb_sizes_arg sizes;
+
+       u32 fuse_reg_value;
+       u32 video_device_fuse;
+
+       /* PCI revision ID for B0:D2:F0 */
+       uint8_t platform_rev_id;
+
+       /*
+        * LVDS info
+        */
+       int backlight_duty_cycle;       /* restore backlight to this value */
+       bool panel_wants_dither;
+       struct drm_display_mode *panel_fixed_mode;
+       struct drm_display_mode *lfp_lvds_vbt_mode;
+       struct drm_display_mode *sdvo_lvds_vbt_mode;
+
+       struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */
+       struct psb_intel_i2c_chan *lvds_i2c_bus;
+
+       /* Feature bits from the VBIOS */
+       unsigned int int_tv_support:1;
+       unsigned int lvds_dither:1;
+       unsigned int lvds_vbt:1;
+       unsigned int int_crt_support:1;
+       unsigned int lvds_use_ssc:1;
+       int lvds_ssc_freq;
+       bool is_lvds_on;
+       bool is_mipi_on;
+       u32 mipi_ctrl_display;
+
+       unsigned int core_freq;
+       uint32_t iLVDS_enable;
+
+       /* Runtime PM state */
+       int rpm_enabled;
+
+       /* MID specific */
+       struct oaktrail_vbt vbt_data;
+       struct oaktrail_gct_data gct_data;
+
+       /* MIPI Panel type etc */
+       int panel_id;
+       bool dual_mipi;         /* dual display - DPI & DBI */
+       bool dpi_panel_on;      /* The DPI panel power is on */
+       bool dpi_panel_on2;     /* The DPI panel power is on */
+       bool dbi_panel_on;      /* The DBI panel power is on */
+       bool dbi_panel_on2;     /* The DBI panel power is on */
+       u32 dsr_fb_update;      /* DSR FB update counter */
+
+       /* Moorestown HDMI state */
+       struct oaktrail_hdmi_dev *hdmi_priv;
+
+       /* Moorestown pipe config register value cache */
+       uint32_t pipeconf;
+       uint32_t pipeconf1;
+       uint32_t pipeconf2;
+
+       /* Moorestown plane control register value cache */
+       uint32_t dspcntr;
+       uint32_t dspcntr1;
+       uint32_t dspcntr2;
+
+       /* Moorestown MM backlight cache */
+       uint8_t saveBKLTCNT;
+       uint8_t saveBKLTREQ;
+       uint8_t saveBKLTBRTL;
+
+       /*
+        * Register state
+        */
+       uint32_t saveDSPACNTR;
+       uint32_t saveDSPBCNTR;
+       uint32_t savePIPEACONF;
+       uint32_t savePIPEBCONF;
+       uint32_t savePIPEASRC;
+       uint32_t savePIPEBSRC;
+       uint32_t saveFPA0;
+       uint32_t saveFPA1;
+       uint32_t saveDPLL_A;
+       uint32_t saveDPLL_A_MD;
+       uint32_t saveHTOTAL_A;
+       uint32_t saveHBLANK_A;
+       uint32_t saveHSYNC_A;
+       uint32_t saveVTOTAL_A;
+       uint32_t saveVBLANK_A;
+       uint32_t saveVSYNC_A;
+       uint32_t saveDSPASTRIDE;
+       uint32_t saveDSPASIZE;
+       uint32_t saveDSPAPOS;
+       uint32_t saveDSPABASE;
+       uint32_t saveDSPASURF;
+       uint32_t saveDSPASTATUS;
+       uint32_t saveFPB0;
+       uint32_t saveFPB1;
+       uint32_t saveDPLL_B;
+       uint32_t saveDPLL_B_MD;
+       uint32_t saveHTOTAL_B;
+       uint32_t saveHBLANK_B;
+       uint32_t saveHSYNC_B;
+       uint32_t saveVTOTAL_B;
+       uint32_t saveVBLANK_B;
+       uint32_t saveVSYNC_B;
+       uint32_t saveDSPBSTRIDE;
+       uint32_t saveDSPBSIZE;
+       uint32_t saveDSPBPOS;
+       uint32_t saveDSPBBASE;
+       uint32_t saveDSPBSURF;
+       uint32_t saveDSPBSTATUS;
+       uint32_t saveVCLK_DIVISOR_VGA0;
+       uint32_t saveVCLK_DIVISOR_VGA1;
+       uint32_t saveVCLK_POST_DIV;
+       uint32_t saveVGACNTRL;
+       uint32_t saveADPA;
+       uint32_t saveLVDS;
+       uint32_t saveDVOA;
+       uint32_t saveDVOB;
+       uint32_t saveDVOC;
+       uint32_t savePP_ON;
+       uint32_t savePP_OFF;
+       uint32_t savePP_CONTROL;
+       uint32_t savePP_CYCLE;
+       uint32_t savePFIT_CONTROL;
+       uint32_t savePaletteA[256];
+       uint32_t savePaletteB[256];
+       uint32_t saveBLC_PWM_CTL2;
+       uint32_t saveBLC_PWM_CTL;
+       uint32_t saveCLOCKGATING;
+       uint32_t saveDSPARB;
+       uint32_t saveDSPATILEOFF;
+       uint32_t saveDSPBTILEOFF;
+       uint32_t saveDSPAADDR;
+       uint32_t saveDSPBADDR;
+       uint32_t savePFIT_AUTO_RATIOS;
+       uint32_t savePFIT_PGM_RATIOS;
+       uint32_t savePP_ON_DELAYS;
+       uint32_t savePP_OFF_DELAYS;
+       uint32_t savePP_DIVISOR;
+       uint32_t saveBSM;
+       uint32_t saveVBT;
+       uint32_t saveBCLRPAT_A;
+       uint32_t saveBCLRPAT_B;
+       uint32_t saveDSPALINOFF;
+       uint32_t saveDSPBLINOFF;
+       uint32_t savePERF_MODE;
+       uint32_t saveDSPFW1;
+       uint32_t saveDSPFW2;
+       uint32_t saveDSPFW3;
+       uint32_t saveDSPFW4;
+       uint32_t saveDSPFW5;
+       uint32_t saveDSPFW6;
+       uint32_t saveCHICKENBIT;
+       uint32_t saveDSPACURSOR_CTRL;
+       uint32_t saveDSPBCURSOR_CTRL;
+       uint32_t saveDSPACURSOR_BASE;
+       uint32_t saveDSPBCURSOR_BASE;
+       uint32_t saveDSPACURSOR_POS;
+       uint32_t saveDSPBCURSOR_POS;
+       uint32_t save_palette_a[256];
+       uint32_t save_palette_b[256];
+       uint32_t saveOV_OVADD;
+       uint32_t saveOV_OGAMC0;
+       uint32_t saveOV_OGAMC1;
+       uint32_t saveOV_OGAMC2;
+       uint32_t saveOV_OGAMC3;
+       uint32_t saveOV_OGAMC4;
+       uint32_t saveOV_OGAMC5;
+       uint32_t saveOVC_OVADD;
+       uint32_t saveOVC_OGAMC0;
+       uint32_t saveOVC_OGAMC1;
+       uint32_t saveOVC_OGAMC2;
+       uint32_t saveOVC_OGAMC3;
+       uint32_t saveOVC_OGAMC4;
+       uint32_t saveOVC_OGAMC5;
+
+       /* MSI reg save */
+       uint32_t msi_addr;
+       uint32_t msi_data;
+
+       /* Medfield specific register save state */
+       uint32_t saveHDMIPHYMISCCTL;
+       uint32_t saveHDMIB_CONTROL;
+       uint32_t saveDSPCCNTR;
+       uint32_t savePIPECCONF;
+       uint32_t savePIPECSRC;
+       uint32_t saveHTOTAL_C;
+       uint32_t saveHBLANK_C;
+       uint32_t saveHSYNC_C;
+       uint32_t saveVTOTAL_C;
+       uint32_t saveVBLANK_C;
+       uint32_t saveVSYNC_C;
+       uint32_t saveDSPCSTRIDE;
+       uint32_t saveDSPCSIZE;
+       uint32_t saveDSPCPOS;
+       uint32_t saveDSPCSURF;
+       uint32_t saveDSPCSTATUS;
+       uint32_t saveDSPCLINOFF;
+       uint32_t saveDSPCTILEOFF;
+       uint32_t saveDSPCCURSOR_CTRL;
+       uint32_t saveDSPCCURSOR_BASE;
+       uint32_t saveDSPCCURSOR_POS;
+       uint32_t save_palette_c[256];
+       uint32_t saveOV_OVADD_C;
+       uint32_t saveOV_OGAMC0_C;
+       uint32_t saveOV_OGAMC1_C;
+       uint32_t saveOV_OGAMC2_C;
+       uint32_t saveOV_OGAMC3_C;
+       uint32_t saveOV_OGAMC4_C;
+       uint32_t saveOV_OGAMC5_C;
+
+       /* DSI register save */
+       uint32_t saveDEVICE_READY_REG;
+       uint32_t saveINTR_EN_REG;
+       uint32_t saveDSI_FUNC_PRG_REG;
+       uint32_t saveHS_TX_TIMEOUT_REG;
+       uint32_t saveLP_RX_TIMEOUT_REG;
+       uint32_t saveTURN_AROUND_TIMEOUT_REG;
+       uint32_t saveDEVICE_RESET_REG;
+       uint32_t saveDPI_RESOLUTION_REG;
+       uint32_t saveHORIZ_SYNC_PAD_COUNT_REG;
+       uint32_t saveHORIZ_BACK_PORCH_COUNT_REG;
+       uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG;
+       uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG;
+       uint32_t saveVERT_SYNC_PAD_COUNT_REG;
+       uint32_t saveVERT_BACK_PORCH_COUNT_REG;
+       uint32_t saveVERT_FRONT_PORCH_COUNT_REG;
+       uint32_t saveHIGH_LOW_SWITCH_COUNT_REG;
+       uint32_t saveINIT_COUNT_REG;
+       uint32_t saveMAX_RET_PAK_REG;
+       uint32_t saveVIDEO_FMT_REG;
+       uint32_t saveEOT_DISABLE_REG;
+       uint32_t saveLP_BYTECLK_REG;
+       uint32_t saveHS_LS_DBI_ENABLE_REG;
+       uint32_t saveTXCLKESC_REG;
+       uint32_t saveDPHY_PARAM_REG;
+       uint32_t saveMIPI_CONTROL_REG;
+       uint32_t saveMIPI;
+       uint32_t saveMIPI_C;
+
+       /* DPST register save */
+       uint32_t saveHISTOGRAM_INT_CONTROL_REG;
+       uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG;
+       uint32_t savePWM_CONTROL_LOGIC;
+
+       /*
+        * DSI info. 
+        */
+       void * dbi_dsr_info;    
+       void * dbi_dpu_info;
+       void * dsi_configs[2];
+       /*
+        * LID-Switch
+        */
+       spinlock_t lid_lock;
+       struct timer_list lid_timer;
+       struct psb_intel_opregion opregion;
+       u32 *lid_state;
+       u32 lid_last_state;
+
+       /*
+        * Watchdog
+        */
+
+       uint32_t apm_reg;
+       uint16_t apm_base;
+
+       /*
+        * Used for modifying backlight from
+        * xrandr -- consider removing and using HAL instead
+        */
+       struct backlight_device *backlight_device;
+       struct drm_property *backlight_property;
+       uint32_t blc_adj1;
+       uint32_t blc_adj2;
+
+       void *fbdev;
+
+       /* 2D acceleration */
+       struct mutex mutex_2d;
+};
+
+
+/*
+ *     Operations for each board type
+ */
+struct psb_ops {
+       const char *name;
+       unsigned int accel_2d:1;
+       int pipes;              /* Number of output pipes */
+       int crtcs;              /* Number of CRTCs */
+       int sgx_offset;         /* Base offset of SGX device */
+
+       /* Sub functions */
+       struct drm_crtc_helper_funcs const *crtc_helper;
+       struct drm_crtc_funcs const *crtc_funcs;
+
+       /* Setup hooks */
+       int (*chip_setup)(struct drm_device *dev);
+       void (*chip_teardown)(struct drm_device *dev);
+
+       /* 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);
+
+       void (*lvds_bl_power)(struct drm_device *dev, bool on);
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+       /* Backlight */
+       int (*backlight_init)(struct drm_device *dev);
+#endif
+       int i2c_bus;            /* I2C bus identifier for Moorestown */
+};
+
+
+
+struct psb_mmu_driver;
+
+extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
+extern int drm_pick_crtcs(struct drm_device *dev);
+
+static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
+{
+       return (struct drm_psb_private *) dev->dev_private;
+}
+
+/*
+ * MMU stuff.
+ */
+
+extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
+                                       int trap_pagefaults,
+                                       int invalid_type,
+                                       struct drm_psb_private *dev_priv);
+extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
+extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
+                                                *driver);
+extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset,
+                              uint32_t gtt_start, uint32_t gtt_pages);
+extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+                                          int trap_pagefaults,
+                                          int invalid_type);
+extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
+extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot);
+extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+                                       unsigned long address,
+                                       uint32_t num_pages);
+extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
+                                      uint32_t start_pfn,
+                                      unsigned long address,
+                                      uint32_t num_pages, int type);
+extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
+                                 unsigned long *pfn);
+
+/*
+ * Enable / disable MMU for different requestors.
+ */
+
+
+extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
+extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
+                               unsigned long address, uint32_t num_pages,
+                               uint32_t desired_tile_stride,
+                               uint32_t hw_tile_stride, int type);
+extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
+                                unsigned long address, uint32_t num_pages,
+                                uint32_t desired_tile_stride,
+                                uint32_t hw_tile_stride);
+/*
+ *psb_irq.c
+ */
+
+extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
+extern int psb_irq_enable_dpst(struct drm_device *dev);
+extern int psb_irq_disable_dpst(struct drm_device *dev);
+extern void psb_irq_preinstall(struct drm_device *dev);
+extern int psb_irq_postinstall(struct drm_device *dev);
+extern void psb_irq_uninstall(struct drm_device *dev);
+extern void psb_irq_turn_on_dpst(struct drm_device *dev);
+extern void psb_irq_turn_off_dpst(struct drm_device *dev);
+
+extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
+extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
+extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence);
+extern int psb_enable_vblank(struct drm_device *dev, int crtc);
+extern void psb_disable_vblank(struct drm_device *dev, int crtc);
+void
+psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
+
+void
+psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
+
+extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
+
+/*
+ * intel_opregion.c
+ */
+extern int gma_intel_opregion_init(struct drm_device *dev);
+extern int gma_intel_opregion_exit(struct drm_device *dev);
+
+/*
+ * framebuffer.c
+ */
+extern int psbfb_probed(struct drm_device *dev);
+extern int psbfb_remove(struct drm_device *dev,
+                       struct drm_framebuffer *fb);
+/*
+ * accel_2d.c
+ */
+extern void psbfb_copyarea(struct fb_info *info,
+                                       const struct fb_copyarea *region);
+extern int psbfb_sync(struct fb_info *info);
+extern void psb_spank(struct drm_psb_private *dev_priv);
+
+/*
+ * psb_reset.c
+ */
+
+extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
+extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
+extern void psb_print_pagefault(struct drm_psb_private *dev_priv);
+
+/* modesetting */
+extern void psb_modeset_init(struct drm_device *dev);
+extern void psb_modeset_cleanup(struct drm_device *dev);
+extern int psb_fbdev_init(struct drm_device *dev);
+
+/* backlight.c */
+int gma_backlight_init(struct drm_device *dev);
+void gma_backlight_exit(struct drm_device *dev);
+
+/* oaktrail_crtc.c */
+extern const struct drm_crtc_helper_funcs oaktrail_helper_funcs;
+
+/* oaktrail_lvds.c */
+extern void oaktrail_lvds_init(struct drm_device *dev,
+                   struct psb_intel_mode_device *mode_dev);
+
+/* psb_intel_display.c */
+extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs;
+extern const struct drm_crtc_funcs psb_intel_crtc_funcs;
+
+/* psb_intel_lvds.c */
+extern const struct drm_connector_helper_funcs
+                                       psb_intel_lvds_connector_helper_funcs;
+extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs;
+
+/* gem.c */
+extern int psb_gem_init_object(struct drm_gem_object *obj);
+extern void psb_gem_free_object(struct drm_gem_object *obj);
+extern int psb_gem_get_aperture(struct drm_device *dev, void *data,
+                       struct drm_file *file);
+extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+                       struct drm_mode_create_dumb *args);
+extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
+                       uint32_t handle);
+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);
+extern int psb_gem_create_ioctl(struct drm_device *dev, void *data,
+                       struct drm_file *file);
+extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
+                                       struct drm_file *file);
+
+/* psb_device.c */
+extern const struct psb_ops psb_chip_ops;
+
+/* oaktrail_device.c */
+extern const struct psb_ops oaktrail_chip_ops;
+
+/* cdv_device.c */
+extern const struct psb_ops cdv_chip_ops;
+
+/*
+ * Debug print bits setting
+ */
+#define PSB_D_GENERAL (1 << 0)
+#define PSB_D_INIT    (1 << 1)
+#define PSB_D_IRQ     (1 << 2)
+#define PSB_D_ENTRY   (1 << 3)
+/* debug the get H/V BP/FP count */
+#define PSB_D_HV      (1 << 4)
+#define PSB_D_DBI_BF  (1 << 5)
+#define PSB_D_PM      (1 << 6)
+#define PSB_D_RENDER  (1 << 7)
+#define PSB_D_REG     (1 << 8)
+#define PSB_D_MSVDX   (1 << 9)
+#define PSB_D_TOPAZ   (1 << 10)
+
+extern int drm_psb_no_fb;
+extern int drm_idle_check_interval;
+
+/*
+ *     Utilities
+ */
+
+static inline u32 MRST_MSG_READ32(uint port, uint offset)
+{
+       int mcr = (0xD0<<24) | (port << 16) | (offset << 8);
+       uint32_t ret_val = 0;
+       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+       pci_write_config_dword(pci_root, 0xD0, mcr);
+       pci_read_config_dword(pci_root, 0xD4, &ret_val);
+       pci_dev_put(pci_root);
+       return ret_val;
+}
+static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value)
+{
+       int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0;
+       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+       pci_write_config_dword(pci_root, 0xD4, value);
+       pci_write_config_dword(pci_root, 0xD0, mcr);
+       pci_dev_put(pci_root);
+}
+static inline u32 MDFLD_MSG_READ32(uint port, uint offset)
+{
+       int mcr = (0x10<<24) | (port << 16) | (offset << 8);
+       uint32_t ret_val = 0;
+       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+       pci_write_config_dword(pci_root, 0xD0, mcr);
+       pci_read_config_dword(pci_root, 0xD4, &ret_val);
+       pci_dev_put(pci_root);
+       return ret_val;
+}
+static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
+{
+       int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
+       struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+       pci_write_config_dword(pci_root, 0xD4, value);
+       pci_write_config_dword(pci_root, 0xD0, mcr);
+       pci_dev_put(pci_root);
+}
+
+static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       return ioread32(dev_priv->vdc_reg + reg);
+}
+
+#define REG_READ(reg)         REGISTER_READ(dev, (reg))
+
+static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg,
+                                     uint32_t val)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       iowrite32((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE(reg, val)    REGISTER_WRITE(dev, (reg), (val))
+
+static inline void REGISTER_WRITE16(struct drm_device *dev,
+                                       uint32_t reg, uint32_t val)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       iowrite16((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE16(reg, val)    REGISTER_WRITE16(dev, (reg), (val))
+
+static inline void REGISTER_WRITE8(struct drm_device *dev,
+                                      uint32_t reg, uint32_t val)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       iowrite8((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE8(reg, val)           REGISTER_WRITE8(dev, (reg), (val))
+
+#define PSB_WVDC32(_val, _offs)                iowrite32(_val, dev_priv->vdc_reg + (_offs))
+#define PSB_RVDC32(_offs)              ioread32(dev_priv->vdc_reg + (_offs))
+
+/* #define TRAP_SGX_PM_FAULT 1 */
+#ifdef TRAP_SGX_PM_FAULT
+#define PSB_RSGX32(_offs)                                              \
+({                                                                     \
+       if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) {              \
+               printk(KERN_ERR                                         \
+                       "access sgx when it's off!! (READ) %s, %d\n",   \
+              __FILE__, __LINE__);                                     \
+               melay(1000);                                            \
+       }                                                               \
+       ioread32(dev_priv->sgx_reg + (_offs));                          \
+})
+#else
+#define PSB_RSGX32(_offs)              ioread32(dev_priv->sgx_reg + (_offs))
+#endif
+#define PSB_WSGX32(_val, _offs)                iowrite32(_val, dev_priv->sgx_reg + (_offs))
+
+#define MSVDX_REG_DUMP 0
+
+#define PSB_WMSVDX32(_val, _offs)      iowrite32(_val, dev_priv->msvdx_reg + (_offs))
+#define PSB_RMSVDX32(_offs)            ioread32(dev_priv->msvdx_reg + (_offs))
+
+#endif
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c
new file mode 100644 (file)
index 0000000..2d95458
--- /dev/null
@@ -0,0 +1,553 @@
+/**************************************************************************
+ * Copyright (c) 2007, 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.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ **************************************************************************/
+/*
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "power.h"
+
+/*
+ * inline functions
+ */
+
+static inline u32
+psb_pipestat(int pipe)
+{
+       if (pipe == 0)
+               return PIPEASTAT;
+       if (pipe == 1)
+               return PIPEBSTAT;
+       if (pipe == 2)
+               return PIPECSTAT;
+       BUG();
+}
+
+static inline u32
+mid_pipe_event(int pipe)
+{
+       if (pipe == 0)
+               return _PSB_PIPEA_EVENT_FLAG;
+       if (pipe == 1)
+               return _MDFLD_PIPEB_EVENT_FLAG;
+       if (pipe == 2)
+               return _MDFLD_PIPEC_EVENT_FLAG;
+       BUG();
+}
+
+static inline u32
+mid_pipe_vsync(int pipe)
+{
+       if (pipe == 0)
+               return _PSB_VSYNC_PIPEA_FLAG;
+       if (pipe == 1)
+               return _PSB_VSYNC_PIPEB_FLAG;
+       if (pipe == 2)
+               return _MDFLD_PIPEC_VBLANK_FLAG;
+       BUG();
+}
+
+static inline u32
+mid_pipeconf(int pipe)
+{
+       if (pipe == 0)
+               return PIPEACONF;
+       if (pipe == 1)
+               return PIPEBCONF;
+       if (pipe == 2)
+               return PIPECCONF;
+       BUG();
+}
+
+void
+psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
+{
+       if ((dev_priv->pipestat[pipe] & mask) != mask) {
+               u32 reg = psb_pipestat(pipe);
+               dev_priv->pipestat[pipe] |= mask;
+               /* Enable the interrupt, clear any pending status */
+               if (gma_power_begin(dev_priv->dev, false)) {
+                       u32 writeVal = PSB_RVDC32(reg);
+                       writeVal |= (mask | (mask >> 16));
+                       PSB_WVDC32(writeVal, reg);
+                       (void) PSB_RVDC32(reg);
+                       gma_power_end(dev_priv->dev);
+               }
+       }
+}
+
+void
+psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
+{
+       if ((dev_priv->pipestat[pipe] & mask) != 0) {
+               u32 reg = psb_pipestat(pipe);
+               dev_priv->pipestat[pipe] &= ~mask;
+               if (gma_power_begin(dev_priv->dev, false)) {
+                       u32 writeVal = PSB_RVDC32(reg);
+                       writeVal &= ~mask;
+                       PSB_WVDC32(writeVal, reg);
+                       (void) PSB_RVDC32(reg);
+                       gma_power_end(dev_priv->dev);
+               }
+       }
+}
+
+void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
+{
+       if (gma_power_begin(dev_priv->dev, false)) {
+               u32 pipe_event = mid_pipe_event(pipe);
+               dev_priv->vdc_irq_mask |= pipe_event;
+               PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+               PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+               gma_power_end(dev_priv->dev);
+       }
+}
+
+void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
+{
+       if (dev_priv->pipestat[pipe] == 0) {
+               if (gma_power_begin(dev_priv->dev, false)) {
+                       u32 pipe_event = mid_pipe_event(pipe);
+                       dev_priv->vdc_irq_mask &= ~pipe_event;
+                       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+                       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+                       gma_power_end(dev_priv->dev);
+               }
+       }
+}
+
+/**
+ * Display controller interrupt handler for vsync/vblank.
+ *
+ */
+static void mid_vblank_handler(struct drm_device *dev, uint32_t pipe)
+{
+       drm_handle_vblank(dev, pipe);
+}
+
+
+/**
+ * Display controller interrupt handler for pipe event.
+ *
+ */
+#define WAIT_STATUS_CLEAR_LOOP_COUNT 0xffff
+static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
+{
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) dev->dev_private;
+
+       uint32_t pipe_stat_val = 0;
+       uint32_t pipe_stat_reg = psb_pipestat(pipe);
+       uint32_t pipe_enable = dev_priv->pipestat[pipe];
+       uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
+       uint32_t i = 0;
+
+       spin_lock(&dev_priv->irqmask_lock);
+
+       pipe_stat_val = PSB_RVDC32(pipe_stat_reg);
+       pipe_stat_val &= pipe_enable | pipe_status;
+       pipe_stat_val &= pipe_stat_val >> 16;
+
+       spin_unlock(&dev_priv->irqmask_lock);
+
+       /* clear the 2nd level interrupt status bits */
+       /**
+       * FIXME: shouldn't use while loop here. However, the interrupt
+       * status 'sticky' bits cannot be cleared by setting '1' to that
+       * bit once...
+       */
+       for (i = 0; i < WAIT_STATUS_CLEAR_LOOP_COUNT; i++) {
+               PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
+               (void) PSB_RVDC32(pipe_stat_reg);
+
+               if ((PSB_RVDC32(pipe_stat_reg) & pipe_status) == 0)
+                       break;
+       }
+
+       if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)
+               dev_err(dev->dev,
+       "%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x.\n",
+                       __func__, PSB_RVDC32(pipe_stat_reg));
+
+       if (pipe_stat_val & PIPE_VBLANK_STATUS)
+               mid_vblank_handler(dev, pipe);
+
+       if (pipe_stat_val & PIPE_TE_STATUS)
+               drm_handle_vblank(dev, pipe);
+}
+
+/*
+ * Display controller interrupt handler.
+ */
+static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
+{
+       if (vdc_stat & _PSB_PIPEA_EVENT_FLAG)
+               mid_pipe_event_handler(dev, 0);
+}
+
+irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) dev->dev_private;
+
+       uint32_t vdc_stat, dsp_int = 0, sgx_int = 0;
+       int handled = 0;
+
+       spin_lock(&dev_priv->irqmask_lock);
+
+       vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
+
+       if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG)
+               dsp_int = 1;
+
+       if (vdc_stat & _PSB_IRQ_SGX_FLAG)
+               sgx_int = 1;
+
+       vdc_stat &= dev_priv->vdc_irq_mask;
+       spin_unlock(&dev_priv->irqmask_lock);
+
+       if (dsp_int && gma_power_is_on(dev)) {
+               psb_vdc_interrupt(dev, vdc_stat);
+               handled = 1;
+       }
+
+       if (sgx_int) {
+               /* Not expected - we have it masked, shut it up */
+               u32 s, s2;
+               s = PSB_RSGX32(PSB_CR_EVENT_STATUS);
+               s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
+               PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR);
+               PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2);
+               /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but
+                  we may as well poll even if we add that ! */
+               handled = 1;
+       }
+
+       PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
+       (void) PSB_RVDC32(PSB_INT_IDENTITY_R);
+       DRM_READMEMORYBARRIER();
+
+       if (!handled)
+               return IRQ_NONE;
+
+       return IRQ_HANDLED;
+}
+
+void psb_irq_preinstall(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       if (gma_power_is_on(dev))
+               PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
+       if (dev->vblank_enabled[0])
+               dev_priv->vdc_irq_mask |= _PSB_PIPEA_EVENT_FLAG;
+       if (dev->vblank_enabled[1])
+               dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG;
+       if (dev->vblank_enabled[2])
+               dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
+
+       /*This register is safe even if display island is off*/
+       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+int psb_irq_postinstall(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       /* This register is safe even if display island is off */
+       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+       PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
+
+       if (dev->vblank_enabled[0])
+               psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
+       else
+               psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+       if (dev->vblank_enabled[1])
+               psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
+       else
+               psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+       if (dev->vblank_enabled[2])
+               psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
+       else
+               psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+       return 0;
+}
+
+void psb_irq_uninstall(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
+
+       if (dev->vblank_enabled[0])
+               psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+       if (dev->vblank_enabled[1])
+               psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+       if (dev->vblank_enabled[2])
+               psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+       dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
+                                 _PSB_IRQ_MSVDX_FLAG |
+                                 _LNC_IRQ_TOPAZ_FLAG;
+
+       /* These two registers are safe even if display island is off */
+       PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+       PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+
+       wmb();
+
+       /* This register is safe even if display island is off */
+       PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+void psb_irq_turn_on_dpst(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       u32 hist_reg;
+       u32 pwm_reg;
+
+       if (gma_power_begin(dev, false)) {
+               PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL);
+               hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+               PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL);
+               hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+               PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC);
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+               PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE
+                                               | PWM_PHASEIN_INT_ENABLE,
+                                                          PWM_CONTROL_LOGIC);
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+
+               psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
+
+               hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+               PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR,
+                                                       HISTOGRAM_INT_CONTROL);
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+               PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
+                                                       PWM_CONTROL_LOGIC);
+
+               gma_power_end(dev);
+       }
+}
+
+int psb_irq_enable_dpst(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+               (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       /* enable DPST */
+       mid_enable_pipe_event(dev_priv, 0);
+       psb_irq_turn_on_dpst(dev);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+       return 0;
+}
+
+void psb_irq_turn_off_dpst(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) dev->dev_private;
+       u32 hist_reg;
+       u32 pwm_reg;
+
+       if (gma_power_begin(dev, false)) {
+               PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL);
+               hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+               psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
+
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+               PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE),
+                                                       PWM_CONTROL_LOGIC);
+               pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+
+               gma_power_end(dev);
+       }
+}
+
+int psb_irq_disable_dpst(struct drm_device *dev)
+{
+       struct drm_psb_private *dev_priv =
+           (struct drm_psb_private *) dev->dev_private;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       mid_disable_pipe_event(dev_priv, 0);
+       psb_irq_turn_off_dpst(dev);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+       return 0;
+}
+
+#ifdef PSB_FIXME
+static int psb_vblank_do_wait(struct drm_device *dev,
+                             unsigned int *sequence, atomic_t *counter)
+{
+       unsigned int cur_vblank;
+       int ret = 0;
+       DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+                   (((cur_vblank = atomic_read(counter))
+                     - *sequence) <= (1 << 23)));
+       *sequence = cur_vblank;
+
+       return ret;
+}
+#endif
+
+/*
+ * It is used to enable VBLANK interrupt
+ */
+int psb_enable_vblank(struct drm_device *dev, int pipe)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       unsigned long irqflags;
+       uint32_t reg_val = 0;
+       uint32_t pipeconf_reg = mid_pipeconf(pipe);
+
+       if (gma_power_begin(dev, false)) {
+               reg_val = REG_READ(pipeconf_reg);
+               gma_power_end(dev);
+       }
+
+       if (!(reg_val & PIPEACONF_ENABLE))
+               return -EINVAL;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       mid_enable_pipe_event(dev_priv, pipe);
+       psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+       return 0;
+}
+
+/*
+ * It is used to disable VBLANK interrupt
+ */
+void psb_disable_vblank(struct drm_device *dev, int pipe)
+{
+       struct drm_psb_private *dev_priv = dev->dev_private;
+       unsigned long irqflags;
+
+       spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+       mid_disable_pipe_event(dev_priv, pipe);
+       psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+       spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+/* Called from drm generic code, passed a 'crtc', which
+ * we use as a pipe index
+ */
+u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
+{
+       uint32_t high_frame = PIPEAFRAMEHIGH;
+       uint32_t low_frame = PIPEAFRAMEPIXEL;
+       uint32_t pipeconf_reg = PIPEACONF;
+       uint32_t reg_val = 0;
+       uint32_t high1 = 0, high2 = 0, low = 0, count = 0;
+
+       switch (pipe) {
+       case 0:
+               break;
+       case 1:
+               high_frame = PIPEBFRAMEHIGH;
+               low_frame = PIPEBFRAMEPIXEL;
+               pipeconf_reg = PIPEBCONF;
+               break;
+       case 2:
+               high_frame = PIPECFRAMEHIGH;
+               low_frame = PIPECFRAMEPIXEL;
+               pipeconf_reg = PIPECCONF;
+               break;
+       default:
+               dev_err(dev->dev, "%s, invalid pipe.\n", __func__);
+               return 0;
+       }
+
+       if (!gma_power_begin(dev, false))
+               return 0;
+
+       reg_val = REG_READ(pipeconf_reg);
+
+       if (!(reg_val & PIPEACONF_ENABLE)) {
+               dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n",
+                                                               pipe);
+               goto psb_get_vblank_counter_exit;
+       }
+
+       /*
+        * High & low register fields aren't synchronized, so make sure
+        * we get a low value that's stable across two reads of the high
+        * register.
+        */
+       do {
+               high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+                        PIPE_FRAME_HIGH_SHIFT);
+               low =  ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
+                       PIPE_FRAME_LOW_SHIFT);
+               high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+                        PIPE_FRAME_HIGH_SHIFT);
+       } while (high1 != high2);
+
+       count = (high1 << 8) | low;
+
+psb_get_vblank_counter_exit:
+
+       gma_power_end(dev);
+
+       return count;
+}
+
diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h
new file mode 100644 (file)
index 0000000..216fda3
--- /dev/null
@@ -0,0 +1,45 @@
+/**************************************************************************
+ * Copyright (c) 2009-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.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ **************************************************************************/
+
+#ifndef _SYSIRQ_H_
+#define _SYSIRQ_H_
+
+#include <drm/drmP.h>
+
+bool sysirq_init(struct drm_device *dev);
+void sysirq_uninit(struct drm_device *dev);
+
+void psb_irq_preinstall(struct drm_device *dev);
+int  psb_irq_postinstall(struct drm_device *dev);
+void psb_irq_uninstall(struct drm_device *dev);
+irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
+
+int psb_irq_enable_dpst(struct drm_device *dev);
+int psb_irq_disable_dpst(struct drm_device *dev);
+void psb_irq_turn_on_dpst(struct drm_device *dev);
+void psb_irq_turn_off_dpst(struct drm_device *dev);
+int  psb_enable_vblank(struct drm_device *dev, int pipe);
+void psb_disable_vblank(struct drm_device *dev, int pipe);
+u32  psb_get_vblank_counter(struct drm_device *dev, int pipe);
+
+#endif /* _SYSIRQ_H_ */
diff --git a/drivers/gpu/drm/gma500/psb_reg.h b/drivers/gpu/drm/gma500/psb_reg.h
new file mode 100644 (file)
index 0000000..b81c7c1
--- /dev/null
@@ -0,0 +1,582 @@
+/**************************************************************************
+ *
+ * Copyright (c) (2005-2007) Imagination Technologies Limited.
+ * Copyright (c) 2007, 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..
+ *
+ **************************************************************************/
+
+#ifndef _PSB_REG_H_
+#define _PSB_REG_H_
+
+#define PSB_CR_CLKGATECTL              0x0000
+#define _PSB_C_CLKGATECTL_AUTO_MAN_REG         (1 << 24)
+#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT       (20)
+#define _PSB_C_CLKGATECTL_USE_CLKG_MASK                (0x3 << 20)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT       (16)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK                (0x3 << 16)
+#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT                (12)
+#define _PSB_C_CLKGATECTL_TA_CLKG_MASK         (0x3 << 12)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT       (8)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK                (0x3 << 8)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT       (4)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK                (0x3 << 4)
+#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT                (0)
+#define _PSB_C_CLKGATECTL_2D_CLKG_MASK         (0x3 << 0)
+#define _PSB_C_CLKGATECTL_CLKG_ENABLED         (0)
+#define _PSB_C_CLKGATECTL_CLKG_DISABLED                (1)
+#define _PSB_C_CLKGATECTL_CLKG_AUTO            (2)
+
+#define PSB_CR_CORE_ID                 0x0010
+#define _PSB_CC_ID_ID_SHIFT                    (16)
+#define _PSB_CC_ID_ID_MASK                     (0xFFFF << 16)
+#define _PSB_CC_ID_CONFIG_SHIFT                        (0)
+#define _PSB_CC_ID_CONFIG_MASK                 (0xFFFF << 0)
+
+#define PSB_CR_CORE_REVISION           0x0014
+#define _PSB_CC_REVISION_DESIGNER_SHIFT                (24)
+#define _PSB_CC_REVISION_DESIGNER_MASK         (0xFF << 24)
+#define _PSB_CC_REVISION_MAJOR_SHIFT           (16)
+#define _PSB_CC_REVISION_MAJOR_MASK            (0xFF << 16)
+#define _PSB_CC_REVISION_MINOR_SHIFT           (8)
+#define _PSB_CC_REVISION_MINOR_MASK            (0xFF << 8)
+#define _PSB_CC_REVISION_MAINTENANCE_SHIFT     (0)
+#define _PSB_CC_REVISION_MAINTENANCE_MASK      (0xFF << 0)
+
+#define PSB_CR_DESIGNER_REV_FIELD1     0x0018
+
+#define PSB_CR_SOFT_RESET              0x0080
+#define _PSB_CS_RESET_TSP_RESET                (1 << 6)
+#define _PSB_CS_RESET_ISP_RESET                (1 << 5)
+#define _PSB_CS_RESET_USE_RESET                (1 << 4)
+#define _PSB_CS_RESET_TA_RESET         (1 << 3)
+#define _PSB_CS_RESET_DPM_RESET                (1 << 2)
+#define _PSB_CS_RESET_TWOD_RESET       (1 << 1)
+#define _PSB_CS_RESET_BIF_RESET                        (1 << 0)
+
+#define PSB_CR_DESIGNER_REV_FIELD2     0x001C
+
+#define PSB_CR_EVENT_HOST_ENABLE2      0x0110
+
+#define PSB_CR_EVENT_STATUS2           0x0118
+
+#define PSB_CR_EVENT_HOST_CLEAR2       0x0114
+#define _PSB_CE2_BIF_REQUESTER_FAULT           (1 << 4)
+
+#define PSB_CR_EVENT_STATUS            0x012C
+
+#define PSB_CR_EVENT_HOST_ENABLE       0x0130
+
+#define PSB_CR_EVENT_HOST_CLEAR                0x0134
+#define _PSB_CE_MASTER_INTERRUPT               (1 << 31)
+#define _PSB_CE_TA_DPM_FAULT                   (1 << 28)
+#define _PSB_CE_TWOD_COMPLETE                  (1 << 27)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS          (1 << 25)
+#define _PSB_CE_DPM_TA_MEM_FREE                        (1 << 24)
+#define _PSB_CE_PIXELBE_END_RENDER             (1 << 18)
+#define _PSB_CE_SW_EVENT                       (1 << 14)
+#define _PSB_CE_TA_FINISHED                    (1 << 13)
+#define _PSB_CE_TA_TERMINATE                   (1 << 12)
+#define _PSB_CE_DPM_REACHED_MEM_THRESH         (1 << 3)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL          (1 << 2)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_MT           (1 << 1)
+#define _PSB_CE_DPM_3D_MEM_FREE                        (1 << 0)
+
+
+#define PSB_USE_OFFSET_MASK            0x0007FFFF
+#define PSB_USE_OFFSET_SIZE            (PSB_USE_OFFSET_MASK + 1)
+#define PSB_CR_USE_CODE_BASE0          0x0A0C
+#define PSB_CR_USE_CODE_BASE1          0x0A10
+#define PSB_CR_USE_CODE_BASE2          0x0A14
+#define PSB_CR_USE_CODE_BASE3          0x0A18
+#define PSB_CR_USE_CODE_BASE4          0x0A1C
+#define PSB_CR_USE_CODE_BASE5          0x0A20
+#define PSB_CR_USE_CODE_BASE6          0x0A24
+#define PSB_CR_USE_CODE_BASE7          0x0A28
+#define PSB_CR_USE_CODE_BASE8          0x0A2C
+#define PSB_CR_USE_CODE_BASE9          0x0A30
+#define PSB_CR_USE_CODE_BASE10         0x0A34
+#define PSB_CR_USE_CODE_BASE11         0x0A38
+#define PSB_CR_USE_CODE_BASE12         0x0A3C
+#define PSB_CR_USE_CODE_BASE13         0x0A40
+#define PSB_CR_USE_CODE_BASE14         0x0A44
+#define PSB_CR_USE_CODE_BASE15         0x0A48
+#define PSB_CR_USE_CODE_BASE(_i)       (0x0A0C + ((_i) << 2))
+#define _PSB_CUC_BASE_DM_SHIFT                 (25)
+#define _PSB_CUC_BASE_DM_MASK                  (0x3 << 25)
+#define _PSB_CUC_BASE_ADDR_SHIFT               (0)     /* 1024-bit aligned address? */
+#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT          (7)
+#define _PSB_CUC_BASE_ADDR_MASK                        (0x1FFFFFF << 0)
+#define _PSB_CUC_DM_VERTEX                     (0)
+#define _PSB_CUC_DM_PIXEL                      (1)
+#define _PSB_CUC_DM_RESERVED                   (2)
+#define _PSB_CUC_DM_EDM                                (3)
+
+#define PSB_CR_PDS_EXEC_BASE           0x0AB8
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT       (20)    /* 1MB aligned address */
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT  (20)
+
+#define PSB_CR_EVENT_KICKER            0x0AC4
+#define _PSB_CE_KICKER_ADDRESS_SHIFT           (4)     /* 128-bit aligned address */
+
+#define PSB_CR_EVENT_KICK              0x0AC8
+#define _PSB_CE_KICK_NOW                       (1 << 0)
+
+#define PSB_CR_BIF_DIR_LIST_BASE1      0x0C38
+
+#define PSB_CR_BIF_CTRL                        0x0C00
+#define _PSB_CB_CTRL_CLEAR_FAULT               (1 << 4)
+#define _PSB_CB_CTRL_INVALDC                   (1 << 3)
+#define _PSB_CB_CTRL_FLUSH                     (1 << 2)
+
+#define PSB_CR_BIF_INT_STAT            0x0C04
+
+#define PSB_CR_BIF_FAULT               0x0C08
+#define _PSB_CBI_STAT_PF_N_RW                  (1 << 14)
+#define _PSB_CBI_STAT_FAULT_SHIFT              (0)
+#define _PSB_CBI_STAT_FAULT_MASK               (0x3FFF << 0)
+#define _PSB_CBI_STAT_FAULT_CACHE              (1 << 1)
+#define _PSB_CBI_STAT_FAULT_TA                 (1 << 2)
+#define _PSB_CBI_STAT_FAULT_VDM                        (1 << 3)
+#define _PSB_CBI_STAT_FAULT_2D                 (1 << 4)
+#define _PSB_CBI_STAT_FAULT_PBE                        (1 << 5)
+#define _PSB_CBI_STAT_FAULT_TSP                        (1 << 6)
+#define _PSB_CBI_STAT_FAULT_ISP                        (1 << 7)
+#define _PSB_CBI_STAT_FAULT_USSEPDS            (1 << 8)
+#define _PSB_CBI_STAT_FAULT_HOST               (1 << 9)
+
+#define PSB_CR_BIF_BANK0               0x0C78
+#define PSB_CR_BIF_BANK1               0x0C7C
+#define PSB_CR_BIF_DIR_LIST_BASE0      0x0C84
+#define PSB_CR_BIF_TWOD_REQ_BASE       0x0C88
+#define PSB_CR_BIF_3D_REQ_BASE         0x0CAC
+
+#define PSB_CR_2D_SOCIF                        0x0E18
+#define _PSB_C2_SOCIF_FREESPACE_SHIFT          (0)
+#define _PSB_C2_SOCIF_FREESPACE_MASK           (0xFF << 0)
+#define _PSB_C2_SOCIF_EMPTY                    (0x80 << 0)
+
+#define PSB_CR_2D_BLIT_STATUS          0x0E04
+#define _PSB_C2B_STATUS_BUSY                   (1 << 24)
+#define _PSB_C2B_STATUS_COMPLETE_SHIFT         (0)
+#define _PSB_C2B_STATUS_COMPLETE_MASK          (0xFFFFFF << 0)
+
+/*
+ * 2D defs.
+ */
+
+/*
+ * 2D Slave Port Data : Block Header's Object Type
+ */
+
+#define        PSB_2D_CLIP_BH                  (0x00000000)
+#define        PSB_2D_PAT_BH                   (0x10000000)
+#define        PSB_2D_CTRL_BH                  (0x20000000)
+#define        PSB_2D_SRC_OFF_BH               (0x30000000)
+#define        PSB_2D_MASK_OFF_BH              (0x40000000)
+#define        PSB_2D_RESERVED1_BH             (0x50000000)
+#define        PSB_2D_RESERVED2_BH             (0x60000000)
+#define        PSB_2D_FENCE_BH                 (0x70000000)
+#define        PSB_2D_BLIT_BH                  (0x80000000)
+#define        PSB_2D_SRC_SURF_BH              (0x90000000)
+#define        PSB_2D_DST_SURF_BH              (0xA0000000)
+#define        PSB_2D_PAT_SURF_BH              (0xB0000000)
+#define        PSB_2D_SRC_PAL_BH               (0xC0000000)
+#define        PSB_2D_PAT_PAL_BH               (0xD0000000)
+#define        PSB_2D_MASK_SURF_BH             (0xE0000000)
+#define        PSB_2D_FLUSH_BH                 (0xF0000000)
+
+/*
+ * Clip Definition block (PSB_2D_CLIP_BH)
+ */
+#define PSB_2D_CLIPCOUNT_MAX           (1)
+#define PSB_2D_CLIPCOUNT_MASK          (0x00000000)
+#define PSB_2D_CLIPCOUNT_CLRMASK       (0xFFFFFFFF)
+#define PSB_2D_CLIPCOUNT_SHIFT         (0)
+/* clip rectangle min & max */
+#define PSB_2D_CLIP_XMAX_MASK          (0x00FFF000)
+#define PSB_2D_CLIP_XMAX_CLRMASK       (0xFF000FFF)
+#define PSB_2D_CLIP_XMAX_SHIFT         (12)
+#define PSB_2D_CLIP_XMIN_MASK          (0x00000FFF)
+#define PSB_2D_CLIP_XMIN_CLRMASK       (0x00FFF000)
+#define PSB_2D_CLIP_XMIN_SHIFT         (0)
+/* clip rectangle offset */
+#define PSB_2D_CLIP_YMAX_MASK          (0x00FFF000)
+#define PSB_2D_CLIP_YMAX_CLRMASK       (0xFF000FFF)
+#define PSB_2D_CLIP_YMAX_SHIFT         (12)
+#define PSB_2D_CLIP_YMIN_MASK          (0x00000FFF)
+#define PSB_2D_CLIP_YMIN_CLRMASK       (0x00FFF000)
+#define PSB_2D_CLIP_YMIN_SHIFT         (0)
+
+/*
+ * Pattern Control (PSB_2D_PAT_BH)
+ */
+#define PSB_2D_PAT_HEIGHT_MASK         (0x0000001F)
+#define PSB_2D_PAT_HEIGHT_SHIFT                (0)
+#define PSB_2D_PAT_WIDTH_MASK          (0x000003E0)
+#define PSB_2D_PAT_WIDTH_SHIFT         (5)
+#define PSB_2D_PAT_YSTART_MASK         (0x00007C00)
+#define PSB_2D_PAT_YSTART_SHIFT                (10)
+#define PSB_2D_PAT_XSTART_MASK         (0x000F8000)
+#define PSB_2D_PAT_XSTART_SHIFT                (15)
+
+/*
+ * 2D Control block (PSB_2D_CTRL_BH)
+ */
+/* Present Flags */
+#define PSB_2D_SRCCK_CTRL              (0x00000001)
+#define PSB_2D_DSTCK_CTRL              (0x00000002)
+#define PSB_2D_ALPHA_CTRL              (0x00000004)
+/* Colour Key Colour (SRC/DST)*/
+#define PSB_2D_CK_COL_MASK             (0xFFFFFFFF)
+#define PSB_2D_CK_COL_CLRMASK          (0x00000000)
+#define PSB_2D_CK_COL_SHIFT            (0)
+/* Colour Key Mask (SRC/DST)*/
+#define PSB_2D_CK_MASK_MASK            (0xFFFFFFFF)
+#define PSB_2D_CK_MASK_CLRMASK         (0x00000000)
+#define PSB_2D_CK_MASK_SHIFT           (0)
+/* Alpha Control (Alpha/RGB)*/
+#define PSB_2D_GBLALPHA_MASK           (0x000FF000)
+#define PSB_2D_GBLALPHA_CLRMASK                (0xFFF00FFF)
+#define PSB_2D_GBLALPHA_SHIFT          (12)
+#define PSB_2D_SRCALPHA_OP_MASK                (0x00700000)
+#define PSB_2D_SRCALPHA_OP_CLRMASK     (0xFF8FFFFF)
+#define PSB_2D_SRCALPHA_OP_SHIFT       (20)
+#define PSB_2D_SRCALPHA_OP_ONE         (0x00000000)
+#define PSB_2D_SRCALPHA_OP_SRC         (0x00100000)
+#define PSB_2D_SRCALPHA_OP_DST         (0x00200000)
+#define PSB_2D_SRCALPHA_OP_SG          (0x00300000)
+#define PSB_2D_SRCALPHA_OP_DG          (0x00400000)
+#define PSB_2D_SRCALPHA_OP_GBL         (0x00500000)
+#define PSB_2D_SRCALPHA_OP_ZERO                (0x00600000)
+#define PSB_2D_SRCALPHA_INVERT         (0x00800000)
+#define PSB_2D_SRCALPHA_INVERT_CLR     (0xFF7FFFFF)
+#define PSB_2D_DSTALPHA_OP_MASK                (0x07000000)
+#define PSB_2D_DSTALPHA_OP_CLRMASK     (0xF8FFFFFF)
+#define PSB_2D_DSTALPHA_OP_SHIFT       (24)
+#define PSB_2D_DSTALPHA_OP_ONE         (0x00000000)
+#define PSB_2D_DSTALPHA_OP_SRC         (0x01000000)
+#define PSB_2D_DSTALPHA_OP_DST         (0x02000000)
+#define PSB_2D_DSTALPHA_OP_SG          (0x03000000)
+#define PSB_2D_DSTALPHA_OP_DG          (0x04000000)
+#define PSB_2D_DSTALPHA_OP_GBL         (0x05000000)
+#define PSB_2D_DSTALPHA_OP_ZERO                (0x06000000)
+#define PSB_2D_DSTALPHA_INVERT         (0x08000000)
+#define PSB_2D_DSTALPHA_INVERT_CLR     (0xF7FFFFFF)
+
+#define PSB_2D_PRE_MULTIPLICATION_ENABLE       (0x10000000)
+#define PSB_2D_PRE_MULTIPLICATION_CLRMASK      (0xEFFFFFFF)
+#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE                (0x20000000)
+#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK       (0xDFFFFFFF)
+
+/*
+ *Source Offset (PSB_2D_SRC_OFF_BH)
+ */
+#define PSB_2D_SRCOFF_XSTART_MASK      ((0x00000FFF) << 12)
+#define PSB_2D_SRCOFF_XSTART_SHIFT     (12)
+#define PSB_2D_SRCOFF_YSTART_MASK      (0x00000FFF)
+#define PSB_2D_SRCOFF_YSTART_SHIFT     (0)
+
+/*
+ * Mask Offset (PSB_2D_MASK_OFF_BH)
+ */
+#define PSB_2D_MASKOFF_XSTART_MASK     ((0x00000FFF) << 12)
+#define PSB_2D_MASKOFF_XSTART_SHIFT    (12)
+#define PSB_2D_MASKOFF_YSTART_MASK     (0x00000FFF)
+#define PSB_2D_MASKOFF_YSTART_SHIFT    (0)
+
+/*
+ * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored
+ */
+
+/*
+ *Blit Rectangle (PSB_2D_BLIT_BH)
+ */
+
+#define PSB_2D_ROT_MASK                        (3 << 25)
+#define PSB_2D_ROT_CLRMASK             (~PSB_2D_ROT_MASK)
+#define PSB_2D_ROT_NONE                        (0 << 25)
+#define PSB_2D_ROT_90DEGS              (1 << 25)
+#define PSB_2D_ROT_180DEGS             (2 << 25)
+#define PSB_2D_ROT_270DEGS             (3 << 25)
+
+#define PSB_2D_COPYORDER_MASK          (3 << 23)
+#define PSB_2D_COPYORDER_CLRMASK       (~PSB_2D_COPYORDER_MASK)
+#define PSB_2D_COPYORDER_TL2BR         (0 << 23)
+#define PSB_2D_COPYORDER_BR2TL         (1 << 23)
+#define PSB_2D_COPYORDER_TR2BL         (2 << 23)
+#define PSB_2D_COPYORDER_BL2TR         (3 << 23)
+
+#define PSB_2D_DSTCK_CLRMASK           (0xFF9FFFFF)
+#define PSB_2D_DSTCK_DISABLE           (0x00000000)
+#define PSB_2D_DSTCK_PASS              (0x00200000)
+#define PSB_2D_DSTCK_REJECT            (0x00400000)
+
+#define PSB_2D_SRCCK_CLRMASK           (0xFFE7FFFF)
+#define PSB_2D_SRCCK_DISABLE           (0x00000000)
+#define PSB_2D_SRCCK_PASS              (0x00080000)
+#define PSB_2D_SRCCK_REJECT            (0x00100000)
+
+#define PSB_2D_CLIP_ENABLE             (0x00040000)
+
+#define PSB_2D_ALPHA_ENABLE            (0x00020000)
+
+#define PSB_2D_PAT_CLRMASK             (0xFFFEFFFF)
+#define PSB_2D_PAT_MASK                        (0x00010000)
+#define PSB_2D_USE_PAT                 (0x00010000)
+#define PSB_2D_USE_FILL                        (0x00000000)
+/*
+ * Tungsten Graphics note on rop codes: If rop A and rop B are
+ * identical, the mask surface will not be read and need not be
+ * set up.
+ */
+
+#define PSB_2D_ROP3B_MASK              (0x0000FF00)
+#define PSB_2D_ROP3B_CLRMASK           (0xFFFF00FF)
+#define PSB_2D_ROP3B_SHIFT             (8)
+/* rop code A */
+#define PSB_2D_ROP3A_MASK              (0x000000FF)
+#define PSB_2D_ROP3A_CLRMASK           (0xFFFFFF00)
+#define PSB_2D_ROP3A_SHIFT             (0)
+
+#define PSB_2D_ROP4_MASK               (0x0000FFFF)
+/*
+ *     DWORD0: (Only pass if Pattern control == Use Fill Colour)
+ *     Fill Colour RGBA8888
+ */
+#define PSB_2D_FILLCOLOUR_MASK         (0xFFFFFFFF)
+#define PSB_2D_FILLCOLOUR_SHIFT                (0)
+/*
+ *     DWORD1: (Always Present)
+ *     X Start (Dest)
+ *     Y Start (Dest)
+ */
+#define PSB_2D_DST_XSTART_MASK         (0x00FFF000)
+#define PSB_2D_DST_XSTART_CLRMASK      (0xFF000FFF)
+#define PSB_2D_DST_XSTART_SHIFT                (12)
+#define PSB_2D_DST_YSTART_MASK         (0x00000FFF)
+#define PSB_2D_DST_YSTART_CLRMASK      (0xFFFFF000)
+#define PSB_2D_DST_YSTART_SHIFT                (0)
+/*
+ *     DWORD2: (Always Present)
+ *     X Size (Dest)
+ *     Y Size (Dest)
+ */
+#define PSB_2D_DST_XSIZE_MASK          (0x00FFF000)
+#define PSB_2D_DST_XSIZE_CLRMASK       (0xFF000FFF)
+#define PSB_2D_DST_XSIZE_SHIFT         (12)
+#define PSB_2D_DST_YSIZE_MASK          (0x00000FFF)
+#define PSB_2D_DST_YSIZE_CLRMASK       (0xFFFFF000)
+#define PSB_2D_DST_YSIZE_SHIFT         (0)
+
+/*
+ * Source Surface (PSB_2D_SRC_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+
+#define PSB_2D_SRC_FORMAT_MASK         (0x00078000)
+#define PSB_2D_SRC_1_PAL               (0x00000000)
+#define PSB_2D_SRC_2_PAL               (0x00008000)
+#define PSB_2D_SRC_4_PAL               (0x00010000)
+#define PSB_2D_SRC_8_PAL               (0x00018000)
+#define PSB_2D_SRC_8_ALPHA             (0x00020000)
+#define PSB_2D_SRC_4_ALPHA             (0x00028000)
+#define PSB_2D_SRC_332RGB              (0x00030000)
+#define PSB_2D_SRC_4444ARGB            (0x00038000)
+#define PSB_2D_SRC_555RGB              (0x00040000)
+#define PSB_2D_SRC_1555ARGB            (0x00048000)
+#define PSB_2D_SRC_565RGB              (0x00050000)
+#define PSB_2D_SRC_0888ARGB            (0x00058000)
+#define PSB_2D_SRC_8888ARGB            (0x00060000)
+#define PSB_2D_SRC_8888UYVY            (0x00068000)
+#define PSB_2D_SRC_RESERVED            (0x00070000)
+#define PSB_2D_SRC_1555ARGB_LOOKUP     (0x00078000)
+
+
+#define PSB_2D_SRC_STRIDE_MASK         (0x00007FFF)
+#define PSB_2D_SRC_STRIDE_CLRMASK      (0xFFFF8000)
+#define PSB_2D_SRC_STRIDE_SHIFT                (0)
+/*
+ *  WORD 1 - Base Address
+ */
+#define PSB_2D_SRC_ADDR_MASK           (0x0FFFFFFC)
+#define PSB_2D_SRC_ADDR_CLRMASK                (0x00000003)
+#define PSB_2D_SRC_ADDR_SHIFT          (2)
+#define PSB_2D_SRC_ADDR_ALIGNSHIFT     (2)
+
+/*
+ * Pattern Surface (PSB_2D_PAT_SURF_BH)
+ */
+/*
+ *  WORD 0
+ */
+
+#define PSB_2D_PAT_FORMAT_MASK         (0x00078000)
+#define PSB_2D_PAT_1_PAL               (0x00000000)
+#define PSB_2D_PAT_2_PAL               (0x00008000)
+#define PSB_2D_PAT_4_PAL               (0x00010000)
+#define PSB_2D_PAT_8_PAL               (0x00018000)
+#define PSB_2D_PAT_8_ALPHA             (0x00020000)
+#define PSB_2D_PAT_4_ALPHA             (0x00028000)
+#define PSB_2D_PAT_332RGB              (0x00030000)
+#define PSB_2D_PAT_4444ARGB            (0x00038000)
+#define PSB_2D_PAT_555RGB              (0x00040000)
+#define PSB_2D_PAT_1555ARGB            (0x00048000)
+#define PSB_2D_PAT_565RGB              (0x00050000)
+#define PSB_2D_PAT_0888ARGB            (0x00058000)
+#define PSB_2D_PAT_8888ARGB            (0x00060000)
+
+#define PSB_2D_PAT_STRIDE_MASK         (0x00007FFF)
+#define PSB_2D_PAT_STRIDE_CLRMASK      (0xFFFF8000)
+#define PSB_2D_PAT_STRIDE_SHIFT                (0)
+/*
+ *  WORD 1 - Base Address
+ */
+#define PSB_2D_PAT_ADDR_MASK           (0x0FFFFFFC)
+#define PSB_2D_PAT_ADDR_CLRMASK                (0x00000003)
+#define PSB_2D_PAT_ADDR_SHIFT          (2)
+#define PSB_2D_PAT_ADDR_ALIGNSHIFT     (2)
+
+/*
+ * Destination Surface (PSB_2D_DST_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+
+#define PSB_2D_DST_FORMAT_MASK         (0x00078000)
+#define PSB_2D_DST_332RGB              (0x00030000)
+#define PSB_2D_DST_4444ARGB            (0x00038000)
+#define PSB_2D_DST_555RGB              (0x00040000)
+#define PSB_2D_DST_1555ARGB            (0x00048000)
+#define PSB_2D_DST_565RGB              (0x00050000)
+#define PSB_2D_DST_0888ARGB            (0x00058000)
+#define PSB_2D_DST_8888ARGB            (0x00060000)
+#define PSB_2D_DST_8888AYUV            (0x00070000)
+
+#define PSB_2D_DST_STRIDE_MASK         (0x00007FFF)
+#define PSB_2D_DST_STRIDE_CLRMASK      (0xFFFF8000)
+#define PSB_2D_DST_STRIDE_SHIFT                (0)
+/*
+ * WORD 1 - Base Address
+ */
+#define PSB_2D_DST_ADDR_MASK           (0x0FFFFFFC)
+#define PSB_2D_DST_ADDR_CLRMASK                (0x00000003)
+#define PSB_2D_DST_ADDR_SHIFT          (2)
+#define PSB_2D_DST_ADDR_ALIGNSHIFT     (2)
+
+/*
+ * Mask Surface (PSB_2D_MASK_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+#define PSB_2D_MASK_STRIDE_MASK                (0x00007FFF)
+#define PSB_2D_MASK_STRIDE_CLRMASK     (0xFFFF8000)
+#define PSB_2D_MASK_STRIDE_SHIFT       (0)
+/*
+ *  WORD 1 - Base Address
+ */
+#define PSB_2D_MASK_ADDR_MASK          (0x0FFFFFFC)
+#define PSB_2D_MASK_ADDR_CLRMASK       (0x00000003)
+#define PSB_2D_MASK_ADDR_SHIFT         (2)
+#define PSB_2D_MASK_ADDR_ALIGNSHIFT    (2)
+
+/*
+ * Source Palette (PSB_2D_SRC_PAL_BH)
+ */
+
+#define PSB_2D_SRCPAL_ADDR_SHIFT       (0)
+#define PSB_2D_SRCPAL_ADDR_CLRMASK     (0xF0000007)
+#define PSB_2D_SRCPAL_ADDR_MASK                (0x0FFFFFF8)
+#define PSB_2D_SRCPAL_BYTEALIGN                (1024)
+
+/*
+ * Pattern Palette (PSB_2D_PAT_PAL_BH)
+ */
+
+#define PSB_2D_PATPAL_ADDR_SHIFT       (0)
+#define PSB_2D_PATPAL_ADDR_CLRMASK     (0xF0000007)
+#define PSB_2D_PATPAL_ADDR_MASK                (0x0FFFFFF8)
+#define PSB_2D_PATPAL_BYTEALIGN                (1024)
+
+/*
+ * Rop3 Codes (2 LS bytes)
+ */
+
+#define PSB_2D_ROP3_SRCCOPY            (0xCCCC)
+#define PSB_2D_ROP3_PATCOPY            (0xF0F0)
+#define PSB_2D_ROP3_WHITENESS          (0xFFFF)
+#define PSB_2D_ROP3_BLACKNESS          (0x0000)
+#define PSB_2D_ROP3_SRC                        (0xCC)
+#define PSB_2D_ROP3_PAT                        (0xF0)
+#define PSB_2D_ROP3_DST                        (0xAA)
+
+/*
+ * Sizes.
+ */
+
+#define PSB_SCENE_HW_COOKIE_SIZE       16
+#define PSB_TA_MEM_HW_COOKIE_SIZE      16
+
+/*
+ * Scene stuff.
+ */
+
+#define PSB_NUM_HW_SCENES              2
+
+/*
+ * Scheduler completion actions.
+ */
+
+#define PSB_RASTER_BLOCK               0
+#define PSB_RASTER                     1
+#define PSB_RETURN                     2
+#define PSB_TA                         3
+
+/* Power management */
+#define PSB_PUNIT_PORT                 0x04
+#define PSB_OSPMBA                     0x78
+#define PSB_APMBA                      0x7a
+#define PSB_APM_CMD                    0x0
+#define PSB_APM_STS                    0x04
+#define PSB_PWRGT_VID_ENC_MASK         0x30
+#define PSB_PWRGT_VID_DEC_MASK         0xc
+#define PSB_PWRGT_GL3_MASK             0xc0
+
+#define PSB_PM_SSC                     0x20
+#define PSB_PM_SSS                     0x30
+#define PSB_PWRGT_DISPLAY_MASK         0xc /*on a different BA than video/gfx*/
+#define MDFLD_PWRGT_DISPLAY_A_CNTR     0x0000000c
+#define MDFLD_PWRGT_DISPLAY_B_CNTR     0x0000c000
+#define MDFLD_PWRGT_DISPLAY_C_CNTR     0x00030000
+#define MDFLD_PWRGT_DISP_MIPI_CNTR     0x000c0000
+#define MDFLD_PWRGT_DISPLAY_CNTR    (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR) /* 0x000fc00c */
+/* Display SSS register bits are different in A0 vs. B0 */
+#define PSB_PWRGT_GFX_MASK             0x3
+#define MDFLD_PWRGT_DISPLAY_A_STS      0x000000c0
+#define MDFLD_PWRGT_DISPLAY_B_STS      0x00000300
+#define MDFLD_PWRGT_DISPLAY_C_STS      0x00000c00
+#define PSB_PWRGT_GFX_MASK_B0          0xc3
+#define MDFLD_PWRGT_DISPLAY_A_STS_B0   0x0000000c
+#define MDFLD_PWRGT_DISPLAY_B_STS_B0   0x0000c000
+#define MDFLD_PWRGT_DISPLAY_C_STS_B0   0x00030000
+#define MDFLD_PWRGT_DISP_MIPI_STS      0x000c0000
+#define MDFLD_PWRGT_DISPLAY_STS_A0    (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */
+#define MDFLD_PWRGT_DISPLAY_STS_B0    (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */
+#endif