All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/49] GMA50 series update
@ 2011-07-05 14:33 Alan Cox
  2011-07-05 14:34 ` [PATCH 01/49] gma500: Ensure the frame buffer has a linear virtual mapping Alan Cox
                   ` (49 more replies)
  0 siblings, 50 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:33 UTC (permalink / raw)
  To: greg, linux-kernel

(Rebased versus the patches Greg took earlier)

The main things here are modularisation and support for Cedarview (this is
unaccelerated as it has no 2D acceleration). I have some crazy ideas about using
the GTT to do 2D console acceleration however but not much can be done for X.

At this point I think the Poulsbo (GMA500) and Cedarview code are probably ready
to move out of staging - hence the modularisation work. The MID platforms need
more cleaning up.

HDMI support at this point is pretty basic with no HDMI audio support. I'm hoping
that will be something that can be addressed in future and now the basic bits
are there I need to take a look at Oaktrail (Atom Z760/GMA600) and see if the
same code can be used to bring up HDMI on that device too.

Alan



---

Alan Cox (48):
      gma500: power can be touched in IRQ state
      gma500: Fix missing memory check
      gma500: Workaround for Medfield/Cedarview cursor bug
      gma500: Fix backlight crash
      gma500: Add the HDMI bits
      gma500: begin adding CDV specific code
      gma500: move the power header
      gma500: move the BIOS header
      gma500: tidying up the power stuff a spot
      gma500: move the i2c code
      gma500: the MMU code is also generic
      gma500: move opregion files
      gma500: tidy up the opregion and lid code
      gma500: Rename the psb_intel_bios code
      gma500: begin the config based split
      gma500: the GEM and GTT code is device independant
      gma500: The 2D code is now also device independent
      gma500: move framebuffer file
      gma500: tidy the framebuffer fixme and oddments
      gma500: the 'mrst' BIOS is actually MID generic
      gma500: Add the beginnings of Cedarview support
      gma500: move configuration bits into the psb_ops structure
      gma500: remove an un-needed check
      gma500: add more ops
      gma500: enable Medfield CRTC support
      gma500: Read the GCT panel type information for Medfield
      gma500: Fix early Medfield crash
      gma500: continue abstracting platform specific code
      gma500: being abstracting out devices a bit more
      gma500: Only fiddle with clock gating on PSB
      gma500: Update the GEM todo
      gma500: psb_fb tidy/cleanup pass
      gma500: Extract BIOSisy stuff from psb_drv
      gma500: Move our other GEM helper into the bits want to push into GEM
      gma500: Medfield support
      gma500: 2D polish
      gma500: CodingStyle pass
      gma500: Use the GEM tweaks to provide a GEM frame buffer
      gma500: GEM glue
      gma500: Kill spare kref
      gma500: nuke the PSB debug stuff
      gma500: nuke the last bits of TTM code
      gma500: 2D acceleration tidying
      gma500: polish for completion of this phase
      gma500: trim some of the debug
      gma500: Do sane FB cleanup
      gma500: revamp frame buffer creation and handling
      gma500: Ensure the frame buffer has a linear virtual mapping

Jani Nikula (1):
      commit ee12661199b82934552c7636b10217a9aa42958a


 drivers/staging/gma500/Kconfig                |   27 
 drivers/staging/gma500/Makefile               |   43 +
 drivers/staging/gma500/accel_2d.c             |  358 ++++++
 drivers/staging/gma500/backlight.c            |   47 +
 drivers/staging/gma500/cdv_device.c           |  350 ++++++
 drivers/staging/gma500/cdv_intel_display.c    | 1513 +++++++++++++++++++++++++
 drivers/staging/gma500/cdv_intel_lvds.c       |  718 ++++++++++++
 drivers/staging/gma500/displays/hdmi.h        |   33 +
 drivers/staging/gma500/displays/pyr_cmd.h     |   34 +
 drivers/staging/gma500/displays/pyr_vid.h     |   34 +
 drivers/staging/gma500/displays/tmd_cmd.h     |   34 +
 drivers/staging/gma500/displays/tmd_vid.h     |   34 +
 drivers/staging/gma500/displays/tpo_cmd.h     |   35 +
 drivers/staging/gma500/displays/tpo_vid.h     |   33 +
 drivers/staging/gma500/framebuffer.c          |  810 +++++++++++++
 drivers/staging/gma500/framebuffer.h          |   49 +
 drivers/staging/gma500/gem.c                  |  252 ++++
 drivers/staging/gma500/gem_glue.c             |  110 ++
 drivers/staging/gma500/gem_glue.h             |    4 
 drivers/staging/gma500/gtt.c                  |  510 ++++++++
 drivers/staging/gma500/gtt.h                  |   62 +
 drivers/staging/gma500/intel_bios.c           |  303 +++++
 drivers/staging/gma500/intel_bios.h           |  430 +++++++
 drivers/staging/gma500/intel_i2c.c            |  169 +++
 drivers/staging/gma500/intel_opregion.c       |   80 +
 drivers/staging/gma500/mdfld_device.c         |  713 ++++++++++++
 drivers/staging/gma500/mdfld_dsi_dbi.c        |  872 ++++++++++++++
 drivers/staging/gma500/mdfld_dsi_dbi.h        |  188 +++
 drivers/staging/gma500/mdfld_dsi_dbi_dpu.h    |  157 +++
 drivers/staging/gma500/mdfld_dsi_dpi.c        |  991 ++++++++++++++++
 drivers/staging/gma500/mdfld_dsi_dpi.h        |   80 +
 drivers/staging/gma500/mdfld_dsi_output.c     |  980 ++++++++++++++++
 drivers/staging/gma500/mdfld_dsi_output.h     |  328 +++++
 drivers/staging/gma500/mdfld_dsi_pkg_sender.c | 1097 ++++++++++++++++++
 drivers/staging/gma500/mdfld_dsi_pkg_sender.h |  158 +++
 drivers/staging/gma500/mdfld_intel_display.c  | 1415 +++++++++++++++++++++++
 drivers/staging/gma500/mdfld_msic.h           |   31 +
 drivers/staging/gma500/mdfld_output.c         |  144 ++
 drivers/staging/gma500/mdfld_output.h         |   80 +
 drivers/staging/gma500/mdfld_pyr_cmd.c        |  575 ++++++++++
 drivers/staging/gma500/mdfld_tmd_vid.c        |  144 ++
 drivers/staging/gma500/mdfld_tpo_cmd.c        |  495 ++++++++
 drivers/staging/gma500/mdfld_tpo_vid.c        |  140 ++
 drivers/staging/gma500/mid_bios.c             |  271 ++++
 drivers/staging/gma500/mid_bios.h             |   21 
 drivers/staging/gma500/mmu.c                  |  858 ++++++++++++++
 drivers/staging/gma500/mrst.h                 |   38 -
 drivers/staging/gma500/mrst_crtc.c            |   31 -
 drivers/staging/gma500/mrst_device.c          |  377 ++++++
 drivers/staging/gma500/mrst_lvds.c            |   26 
 drivers/staging/gma500/power.c                |  315 +++++
 drivers/staging/gma500/power.h                |   67 +
 drivers/staging/gma500/psb_2d.c               |  410 -------
 drivers/staging/gma500/psb_bl.c               |  227 ----
 drivers/staging/gma500/psb_device.c           |  352 ++++++
 drivers/staging/gma500/psb_drm.h              |  109 --
 drivers/staging/gma500/psb_drv.c              |  419 +------
 drivers/staging/gma500/psb_drv.h              |  460 +++++---
 drivers/staging/gma500/psb_fb.c               |  834 --------------
 drivers/staging/gma500/psb_fb.h               |   49 -
 drivers/staging/gma500/psb_gem.c              |  308 -----
 drivers/staging/gma500/psb_gtt.c              |  539 ---------
 drivers/staging/gma500/psb_gtt.h              |   61 -
 drivers/staging/gma500/psb_intel_bios.c       |  306 -----
 drivers/staging/gma500/psb_intel_bios.h       |  430 -------
 drivers/staging/gma500/psb_intel_display.c    |  164 +--
 drivers/staging/gma500/psb_intel_display.h    |    3 
 drivers/staging/gma500/psb_intel_drv.h        |   24 
 drivers/staging/gma500/psb_intel_i2c.c        |  169 ---
 drivers/staging/gma500/psb_intel_lvds.c       |   91 --
 drivers/staging/gma500/psb_intel_opregion.c   |   78 -
 drivers/staging/gma500/psb_intel_reg.h        | 1144 ++++++++++---------
 drivers/staging/gma500/psb_intel_sdvo.c       |   35 -
 drivers/staging/gma500/psb_intel_sdvo_regs.h  |   14 
 drivers/staging/gma500/psb_irq.c              |   99 +-
 drivers/staging/gma500/psb_irq.h              |    8 
 drivers/staging/gma500/psb_lid.c              |    6 
 drivers/staging/gma500/psb_mmu.c              |  858 --------------
 drivers/staging/gma500/psb_powermgmt.c        |  489 --------
 drivers/staging/gma500/psb_powermgmt.h        |   67 -
 drivers/staging/gma500/psb_reg.h              |  842 +++++++-------
 81 files changed, 18550 insertions(+), 6709 deletions(-)
 create mode 100644 drivers/staging/gma500/accel_2d.c
 create mode 100644 drivers/staging/gma500/backlight.c
 create mode 100644 drivers/staging/gma500/cdv_device.c
 create mode 100644 drivers/staging/gma500/cdv_intel_display.c
 create mode 100644 drivers/staging/gma500/cdv_intel_lvds.c
 create mode 100644 drivers/staging/gma500/displays/hdmi.h
 create mode 100644 drivers/staging/gma500/displays/pyr_cmd.h
 create mode 100644 drivers/staging/gma500/displays/pyr_vid.h
 create mode 100644 drivers/staging/gma500/displays/tmd_cmd.h
 create mode 100644 drivers/staging/gma500/displays/tmd_vid.h
 create mode 100644 drivers/staging/gma500/displays/tpo_cmd.h
 create mode 100644 drivers/staging/gma500/displays/tpo_vid.h
 create mode 100644 drivers/staging/gma500/framebuffer.c
 create mode 100644 drivers/staging/gma500/framebuffer.h
 create mode 100644 drivers/staging/gma500/gem.c
 create mode 100644 drivers/staging/gma500/gem_glue.c
 create mode 100644 drivers/staging/gma500/gem_glue.h
 create mode 100644 drivers/staging/gma500/gtt.c
 create mode 100644 drivers/staging/gma500/gtt.h
 create mode 100644 drivers/staging/gma500/intel_bios.c
 create mode 100644 drivers/staging/gma500/intel_bios.h
 create mode 100644 drivers/staging/gma500/intel_i2c.c
 create mode 100644 drivers/staging/gma500/intel_opregion.c
 create mode 100644 drivers/staging/gma500/mdfld_device.c
 create mode 100644 drivers/staging/gma500/mdfld_dsi_dbi.c
 create mode 100644 drivers/staging/gma500/mdfld_dsi_dbi.h
 create mode 100644 drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
 create mode 100644 drivers/staging/gma500/mdfld_dsi_dpi.c
 create mode 100644 drivers/staging/gma500/mdfld_dsi_dpi.h
 create mode 100644 drivers/staging/gma500/mdfld_dsi_output.c
 create mode 100644 drivers/staging/gma500/mdfld_dsi_output.h
 create mode 100644 drivers/staging/gma500/mdfld_dsi_pkg_sender.c
 create mode 100644 drivers/staging/gma500/mdfld_dsi_pkg_sender.h
 create mode 100644 drivers/staging/gma500/mdfld_intel_display.c
 create mode 100644 drivers/staging/gma500/mdfld_msic.h
 create mode 100644 drivers/staging/gma500/mdfld_output.c
 create mode 100644 drivers/staging/gma500/mdfld_output.h
 create mode 100644 drivers/staging/gma500/mdfld_pyr_cmd.c
 create mode 100644 drivers/staging/gma500/mdfld_tmd_vid.c
 create mode 100644 drivers/staging/gma500/mdfld_tpo_cmd.c
 create mode 100644 drivers/staging/gma500/mdfld_tpo_vid.c
 create mode 100644 drivers/staging/gma500/mid_bios.c
 create mode 100644 drivers/staging/gma500/mid_bios.h
 create mode 100644 drivers/staging/gma500/mmu.c
 create mode 100644 drivers/staging/gma500/mrst_device.c
 create mode 100644 drivers/staging/gma500/power.c
 create mode 100644 drivers/staging/gma500/power.h
 delete mode 100644 drivers/staging/gma500/psb_2d.c
 delete mode 100644 drivers/staging/gma500/psb_bl.c
 create mode 100644 drivers/staging/gma500/psb_device.c
 delete mode 100644 drivers/staging/gma500/psb_fb.c
 delete mode 100644 drivers/staging/gma500/psb_fb.h
 delete mode 100644 drivers/staging/gma500/psb_gem.c
 delete mode 100644 drivers/staging/gma500/psb_gtt.c
 delete mode 100644 drivers/staging/gma500/psb_gtt.h
 delete mode 100644 drivers/staging/gma500/psb_intel_bios.c
 delete mode 100644 drivers/staging/gma500/psb_intel_bios.h
 delete mode 100644 drivers/staging/gma500/psb_intel_i2c.c
 delete mode 100644 drivers/staging/gma500/psb_intel_opregion.c
 delete mode 100644 drivers/staging/gma500/psb_mmu.c
 delete mode 100644 drivers/staging/gma500/psb_powermgmt.c
 delete mode 100644 drivers/staging/gma500/psb_powermgmt.h

-- 
Signature

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [PATCH 01/49] gma500: Ensure the frame buffer has a linear virtual mapping
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
@ 2011-07-05 14:34 ` Alan Cox
  2011-07-05 14:34 ` [PATCH 02/49] gma500: revamp frame buffer creation and handling Alan Cox
                   ` (48 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:34 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We need this for the framebuffer in order to ensure that the kernel
framebuffer layer can handle it when using KMS. Except for the base
framebuffer this isn't a concern.

Add an npage field to the gtt as too many copies of the page calculation
are getting spread around the code.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_fb.c  |   47 ++++++++++++++++++++++++--------------
 drivers/staging/gma500/psb_fb.h  |    1 +
 drivers/staging/gma500/psb_gtt.c |   18 ++++++---------
 drivers/staging/gma500/psb_gtt.h |    5 ++--
 4 files changed, 42 insertions(+), 29 deletions(-)

diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index b276fe9..4b05cdc 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -254,17 +254,13 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 				vma->vm_pgoff, fb_screen_base,
                                 dev_priv->vram_addr);
 
-        /* FIXME: ultimately this needs to become 'if entirely stolen memory' */
-	if (1 || fb_screen_base == dev_priv->vram_addr) {
-		vma->vm_ops = &psbfb_vm_ops;
-		vma->vm_private_data = (void *)psbfb;
-		vma->vm_flags |= VM_RESERVED | VM_IO |
-						VM_MIXEDMAP | VM_DONTEXPAND;
-	} else {
-	        /* GTT memory backed by kernel/user pages, needs a different
-	           approach ? - GEM ? */
-	}
-
+        /* If this is a GEM object then info->screen_base is the virtual
+           kernel remapping of the object. FIXME: Review if this is
+           suitable for our mmap work */
+	vma->vm_ops = &psbfb_vm_ops;
+	vma->vm_private_data = (void *)psbfb;
+	vma->vm_flags |= VM_RESERVED | VM_IO |
+					VM_MIXEDMAP | VM_DONTEXPAND;
 	return 0;
 }
 
@@ -349,8 +345,6 @@ err:
  *
  *	FIXME: console speed up - allocate twice the space if room and use
  *	hardware scrolling for acceleration.
- *	FIXME: we need to vm_map_ram  a linear mapping if the object has to
- *	be GEM host mapped, otherwise the cfb layer's brain will fall out.
  */
 static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
 {
@@ -439,10 +433,22 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	info->fix.smem_start = dev->mode_config.fb_base;
 	info->fix.smem_len = size;
 
-	/* Accessed via stolen memory directly, This only works for stolem
-	   memory however. Need to address this once we start using gtt
-	   pages we allocate. FIXME: vm_map_ram for that case */
-	info->screen_base = (char *)dev_priv->vram_addr + backing->offset;
+	if (backing->stolen) {
+		/* Accessed stolen memory directly */
+		info->screen_base = (char *)dev_priv->vram_addr +
+							backing->offset;
+	} else {
+		/* Pin the pages into the GTT and create a mapping to them */
+		psb_gtt_pin(backing);
+		info->screen_base = vm_map_ram(backing->pages, backing->npage,
+				-1, PAGE_KERNEL);
+		if (info->screen_base == NULL) {
+			psb_gtt_unpin(backing);
+			ret = -ENOMEM;
+			goto out_err0;
+		}
+		psbfb->vm_map = 1;
+	}
 	info->screen_size = size;
 	memset(info->screen_base, 0, size);
 
@@ -570,6 +576,13 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
 
 	if (fbdev->psb_fb_helper.fbdev) {
 		info = fbdev->psb_fb_helper.fbdev;
+
+		/* If this is our base framebuffer then kill any virtual map
+		   for the framebuffer layer and unpin it */
+		if (psbfb->vm_map) {
+			vm_unmap_ram(info->screen_base, psbfb->gtt->npage);
+			psb_gtt_unpin(psbfb->gtt);
+		}
 		/* FIXME: this is a bit more inside knowledge than I'd like
 		   but I don't see how to make a fake GEM object of the
 		   stolen space nicely */
diff --git a/drivers/staging/gma500/psb_fb.h b/drivers/staging/gma500/psb_fb.h
index c8ec0d6..2153c74 100644
--- a/drivers/staging/gma500/psb_fb.h
+++ b/drivers/staging/gma500/psb_fb.h
@@ -33,6 +33,7 @@ struct psb_framebuffer {
 	struct address_space *addr_space;
 	struct fb_info *fbdev;
 	struct gtt_range *gtt;
+	bool vm_map;		/* True if we must undo a vm_map_ram */
 };
 
 struct psb_fbdev {
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index 15a51f1..5a296e1 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -79,7 +79,6 @@ u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
 static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
 {
 	u32 *gtt_slot, pte;
-	int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT;
 	struct page **pages;
 	int i;
 
@@ -94,10 +93,10 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
 	pages = r->pages;
 
 	/* Make sure changes are visible to the GPU */
-	set_pages_array_uc(pages, numpages);
+	set_pages_array_uc(pages, r->npage);
 
 	/* Write our page entries into the GTT itself */
-	for (i = 0; i < numpages; i++) {
+	for (i = 0; i < r->npage; i++) {
 		pte = psb_gtt_mask_pte(page_to_pfn(*pages++), 0/*type*/);
 		iowrite32(pte, gtt_slot++);
 	}
@@ -120,7 +119,6 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	u32 *gtt_slot, pte;
-	int numpages = (r->resource.end + 1 - r->resource.start) >> PAGE_SHIFT;
 	int i;
 
 	WARN_ON(r->stolen);
@@ -128,10 +126,10 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
 	gtt_slot = psb_gtt_entry(dev, r);
 	pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
 
-	for (i = 0; i < numpages; i++)
+	for (i = 0; i < r->npage; i++)
 		iowrite32(pte, gtt_slot++);
 	ioread32(gtt_slot - 1);
-	set_pages_array_wb(r->pages, numpages);
+	set_pages_array_wb(r->pages, r->npage);
 }
 
 /**
@@ -149,7 +147,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt)
 	struct address_space *mapping;
 	int i;
 	struct page *p;
-	int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT;
+	int pages = gt->gem.size / PAGE_SIZE;
 
 	WARN_ON(gt->pages);
 
@@ -160,6 +158,8 @@ static int psb_gtt_attach_pages(struct gtt_range *gt)
 	gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
 	if (gt->pages == NULL)
 		return -ENOMEM;
+	gt->npage = pages;
+
 	for (i = 0; i < pages; i++) {
 		/* FIXME: review flags later */
 		p = read_cache_page_gfp(mapping, i,
@@ -191,9 +191,7 @@ err:
 static void psb_gtt_detach_pages(struct gtt_range *gt)
 {
 	int i;
-	int pages = (gt->resource.end + 1 - gt->resource.start) >> PAGE_SHIFT;
-
-	for (i = 0; i < pages; i++) {
+	for (i = 0; i < gt->npage; i++) {
 		/* FIXME: do we need to force dirty */
 		set_page_dirty(gt->pages[i]);
 		/* Undo the reference we took when populating the table */
diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h
index 535ae00..37287eb 100644
--- a/drivers/staging/gma500/psb_gtt.h
+++ b/drivers/staging/gma500/psb_gtt.h
@@ -46,9 +46,10 @@ struct gtt_range {
 	struct kref kref;
 	struct drm_gem_object gem;	/* GEM high level stuff */
 	int in_gart;			/* Currently in the GART (ref ct) */
-        bool stolen;			/* Backed from stolen RAM */
-        bool mmapping;			/* Is mmappable */
+	bool stolen;			/* Backed from stolen RAM */
+	bool mmapping;			/* Is mmappable */
 	struct page **pages;		/* Backing pages if present */
+	int npage;			/* Number of backing pages */
 };
 
 extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 02/49] gma500: revamp frame buffer creation and handling
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
  2011-07-05 14:34 ` [PATCH 01/49] gma500: Ensure the frame buffer has a linear virtual mapping Alan Cox
@ 2011-07-05 14:34 ` Alan Cox
  2011-07-05 14:34 ` [PATCH 03/49] gma500: Do sane FB cleanup Alan Cox
                   ` (47 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:34 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Restructure this to work the same way as the i915 frame buffer does. That
cleans up various chunks of code.

We can now set a mode in modetest but mode restore is a bit iffy

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_2d.c  |   13 +--
 drivers/staging/gma500/psb_fb.c  |  195 +++++++++++++++++++++-----------------
 drivers/staging/gma500/psb_fb.h  |    2 
 drivers/staging/gma500/psb_gem.c |   18 +++-
 drivers/staging/gma500/psb_gtt.c |    2 
 5 files changed, 133 insertions(+), 97 deletions(-)

diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c
index 0bd834c..060eeaf 100644
--- a/drivers/staging/gma500/psb_2d.c
+++ b/drivers/staging/gma500/psb_2d.c
@@ -148,7 +148,7 @@ static void psbfb_fillrect_accel(struct fb_info *info,
 				 const struct fb_fillrect *r)
 {
 	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
 	struct drm_device *dev = psbfb->base.dev;
 	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
 	struct drm_psb_private *dev_priv = dev->dev_private;
@@ -291,7 +291,7 @@ static void psbfb_copyarea_accel(struct fb_info *info,
 				 const struct fb_copyarea *a)
 {
 	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
 	struct drm_device *dev = psbfb->base.dev;
 	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
 	struct drm_psb_private *dev_priv = dev->dev_private;
@@ -360,19 +360,12 @@ void psbfb_imageblit(struct fb_info *info, const struct fb_image *image)
 int psbfb_sync(struct fb_info *info)
 {
 	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
 	struct drm_device *dev = psbfb->base.dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	unsigned long _end = jiffies + DRM_HZ;
 	int busy = 0;
 
-#if 0
-        /* Just a way to quickly test if cmd issue explodes */
-	u32 test[2] = {
-	        PSB_2D_FENCE_BH,
-        };
-	psbfb_2d_submit(dev_priv, test, 1);
-#endif	
 	/*
 	 * First idle the 2D engine.
 	 */
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 4b05cdc..5977add 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -235,7 +235,7 @@ static struct vm_operations_struct psbfb_vm_ops = {
 static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
 	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
 	char *fb_screen_base = NULL;
 	struct drm_device *dev = psbfb->base.dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
@@ -267,7 +267,7 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 {
 	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
 	struct drm_device *dev = psbfb->base.dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	u32 __user *p = (u32 __user *)arg;
@@ -304,8 +304,58 @@ static struct fb_ops psbfb_ops = {
 	.fb_ioctl = psbfb_ioctl,
 };
 
+/**
+ *	psb_framebuffer_init	-	initialize a framebuffer
+ *	@dev: our DRM device
+ *	@fb: framebuffer to set up
+ *	@mode_cmd: mode description
+ *	@gt: backing object
+ *
+ *	Configure and fill in the boilerplate for our frame buffer. Return
+ *	0 on success or an error code if we fail.
+ */
+static int psb_framebuffer_init(struct drm_device *dev,
+                                struct psb_framebuffer *fb,
+                                struct drm_mode_fb_cmd *mode_cmd,
+                                struct gtt_range *gt)
+{
+        int ret;
+
+        if (mode_cmd->pitch & 63)
+                return -EINVAL;
+        switch (mode_cmd->bpp) {
+        case 8:
+        case 16:
+        case 24:
+        case 32:
+                break;
+        default:
+                return -EINVAL;
+        }
+        ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
+        if (ret) {
+                dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
+                return ret;
+        }
+        drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
+        fb->gtt = gt;
+        return 0;
+}
+                
+/**
+ *	psb_framebuffer_create	-	create a framebuffer backed by gt
+ *	@dev: our DRM device
+ *	@mode_cmd: the description of the requested mode
+ *	@gt: the backing object
+ *
+ *	Create a framebuffer object backed by the gt, and fill in the
+ *	boilerplate required
+ *
+ *	TODO: review object references
+ */
 static struct drm_framebuffer *psb_framebuffer_create
-			(struct drm_device *dev, struct drm_mode_fb_cmd *r,
+			(struct drm_device *dev,
+			 struct drm_mode_fb_cmd *mode_cmd,
 			 struct gtt_range *gt)
 {
 	struct psb_framebuffer *fb;
@@ -313,22 +363,14 @@ static struct drm_framebuffer *psb_framebuffer_create
 
 	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
 	if (!fb)
-		return NULL;
-
-	ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
-
-	if (ret)
-		goto err;
-
-	drm_helper_mode_fill_fb_struct(&fb->base, r);
-
-	fb->gtt = gt;
-
-	return &fb->base;
+		return ERR_PTR(-ENOMEM);
 
-err:
-	kfree(fb);
-	return NULL;
+	ret = psb_framebuffer_init(dev, fb, mode_cmd, gt);
+	if (ret) {
+	        kfree(fb);
+	        return ERR_PTR(ret);
+        }
+        return &fb->base;
 }
 
 /**
@@ -380,56 +422,63 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	struct fb_info *info;
 	struct drm_framebuffer *fb;
-	struct psb_framebuffer *psbfb;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
 	struct drm_mode_fb_cmd mode_cmd;
 	struct device *device = &dev->pdev->dev;
-	int size, aligned_size;
+	int size;
 	int ret;
 	struct gtt_range *backing;
 
 	mode_cmd.width = sizes->surface_width;
 	mode_cmd.height = sizes->surface_height;
+	mode_cmd.bpp = sizes->surface_bpp;
+
+	/* No 24bit packed */
+	if (mode_cmd.bpp == 24)
+        	mode_cmd.bpp = 32;
 
-	mode_cmd.bpp = 32;
 	/* HW requires pitch to be 64 byte aligned */
-	mode_cmd.pitch =  ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64);
-	mode_cmd.depth = 24;
+	mode_cmd.pitch =  ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
+	mode_cmd.depth = sizes->surface_depth;
 
 	size = mode_cmd.pitch * mode_cmd.height;
-	aligned_size = ALIGN(size, PAGE_SIZE);
+	size = ALIGN(size, PAGE_SIZE);
 
 	/* Allocate the framebuffer in the GTT with stolen page backing */
-	backing = psbfb_alloc(dev, aligned_size);
+	backing = psbfb_alloc(dev, size);
 	if (backing == NULL)
 	        return -ENOMEM;
 
 	mutex_lock(&dev->struct_mutex);
-	fb = psb_framebuffer_create(dev, &mode_cmd, backing);
-	if (!fb) {
-		DRM_ERROR("failed to allocate fb.\n");
-		ret = -ENOMEM;
-		goto out_err1;
-	}
-	psbfb = to_psb_fb(fb);
 
-	info = framebuffer_alloc(sizeof(struct psb_fbdev), device);
+	info = framebuffer_alloc(0, device);
 	if (!info) {
 		ret = -ENOMEM;
-		goto out_err0;
+		goto out_err1;
 	}
-
 	info->par = fbdev;
 
+	ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
+	if (ret)
+		goto out_unref;
+
+        fb = &psbfb->base;
 	psbfb->fbdev = info;
 
 	fbdev->psb_fb_helper.fb = fb;
 	fbdev->psb_fb_helper.fbdev = info;
-	fbdev->pfb = psbfb;
 
 	strcpy(info->fix.id, "psbfb");
 
 	info->flags = FBINFO_DEFAULT;
 	info->fbops = &psbfb_ops;
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret) {
+		ret = -ENOMEM;
+		goto out_unref;
+	}
+
 	info->fix.smem_start = dev->mode_config.fb_base;
 	info->fix.smem_len = size;
 
@@ -445,18 +494,18 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 		if (info->screen_base == NULL) {
 			psb_gtt_unpin(backing);
 			ret = -ENOMEM;
-			goto out_err0;
+			goto out_unref;
 		}
 		psbfb->vm_map = 1;
 	}
 	info->screen_size = size;
-	memset(info->screen_base, 0, size);
+/*	memset(info->screen_base, 0, size); */
 
 	if (dev_priv->pg->stolen_size) {
 		info->apertures = alloc_apertures(1);
 		if (!info->apertures) {
 			ret = -ENOMEM;
-			goto out_err0;
+			goto out_unref;
 		}
 		info->apertures->ranges[0].base = dev->mode_config.fb_base;
 		info->apertures->ranges[0].size = dev_priv->pg->stolen_size;
@@ -484,8 +533,14 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
-out_err0:
-	fb->funcs->destroy(fb);
+out_unref:
+        if (backing->stolen)
+                psb_gtt_free_range(dev, backing);
+        else {
+                if (psbfb->vm_map)
+                        vm_unmap_ram(info->screen_base, backing->npage);
+                drm_gem_object_unreference(&backing->gem);
+        }
 out_err1:
 	mutex_unlock(&dev->struct_mutex);
 	psb_gtt_free_range(dev, backing);
@@ -506,7 +561,6 @@ static struct drm_framebuffer *psb_user_framebuffer_create
 {
         struct gtt_range *r;
         struct drm_gem_object *obj;
-        struct psb_framebuffer *psbfb;
 
         /* Find the GEM object and thus the gtt range object that is
            to back this space */
@@ -514,23 +568,9 @@ static struct drm_framebuffer *psb_user_framebuffer_create
 	if (obj == NULL)
 	        return ERR_PTR(-ENOENT);
 
-        /* Allocate a framebuffer */
-        psbfb = kzalloc(sizeof(*psbfb), GFP_KERNEL);
-        if (psbfb == NULL) {
-                drm_gem_object_unreference_unlocked(obj);
-                return ERR_PTR(-ENOMEM);
-        }
-        
         /* Let the core code do all the work */
         r = container_of(obj, struct gtt_range, gem);
-	if (psb_framebuffer_create(dev, cmd, r) == NULL) {
-                drm_gem_object_unreference_unlocked(obj);
-                kfree(psbfb);
-                return ERR_PTR(-EINVAL);
-        }
-        /* Return the drm_framebuffer contained within the psb fbdev which
-           has been initialized by the framebuffer creation */
-        return &psbfb->base;
+	return psb_framebuffer_create(dev, cmd, r);
 }
 
 static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
@@ -572,7 +612,7 @@ struct drm_fb_helper_funcs psb_fb_helper_funcs = {
 int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
 {
 	struct fb_info *info;
-	struct psb_framebuffer *psbfb = fbdev->pfb;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
 
 	if (fbdev->psb_fb_helper.fbdev) {
 		info = fbdev->psb_fb_helper.fbdev;
@@ -583,6 +623,15 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
 			vm_unmap_ram(info->screen_base, psbfb->gtt->npage);
 			psb_gtt_unpin(psbfb->gtt);
 		}
+		unregister_framebuffer(info);
+		if (info->cmap.len)
+		        fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	drm_fb_helper_fini(&fbdev->psb_fb_helper);
+	drm_framebuffer_cleanup(&psbfb->base);
+	
+	if (psbfb->gtt) {
 		/* FIXME: this is a bit more inside knowledge than I'd like
 		   but I don't see how to make a fake GEM object of the
 		   stolen space nicely */
@@ -590,13 +639,7 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
 			psb_gtt_free_range(dev, psbfb->gtt);
 		else
 			drm_gem_object_unreference(&psbfb->gtt->gem);
-		unregister_framebuffer(info);
-		iounmap(info->screen_base);
-		framebuffer_release(info);
-	}
-
-	drm_fb_helper_fini(&fbdev->psb_fb_helper);
-	drm_framebuffer_cleanup(&psbfb->base);
+        }
 	return 0;
 }
 
@@ -644,22 +687,6 @@ static void psbfb_output_poll_changed(struct drm_device *dev)
 	drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
 }
 
-int psbfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
-{
-	struct fb_info *info;
-	struct psb_framebuffer *psbfb = to_psb_fb(fb);
-
-	if (drm_psb_no_fb)
-		return 0;
-
-	info = psbfb->fbdev;
-
-	if (info)
-		framebuffer_release(info);
-	return 0;
-}
-/*EXPORT_SYMBOL(psbfb_remove); */
-
 /**
  *	psb_user_framebuffer_create_handle - add hamdle to a framebuffer
  *	@fb: framebuffer
@@ -690,15 +717,13 @@ static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
  */
 static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
-	struct drm_device *dev = fb->dev;
 	struct psb_framebuffer *psbfb = to_psb_fb(fb);
 	struct gtt_range *r = psbfb->gtt;
 
+	/* Should never get stolen memory for a user fb */
+	WARN_ON(r->stolen);
 	pr_err("user framebuffer destroy %p, fbdev %p\n",
 						psbfb, psbfb->fbdev);
-	if (psbfb->fbdev)
-		psbfb_remove(dev, fb);
-
         /* Let DRM do its clean up */
 	drm_framebuffer_cleanup(fb);
 	/*  We are no longer using the resource in GEM */
diff --git a/drivers/staging/gma500/psb_fb.h b/drivers/staging/gma500/psb_fb.h
index 2153c74..fd7e51a 100644
--- a/drivers/staging/gma500/psb_fb.h
+++ b/drivers/staging/gma500/psb_fb.h
@@ -38,7 +38,7 @@ struct psb_framebuffer {
 
 struct psb_fbdev {
 	struct drm_fb_helper psb_fb_helper;
-	struct psb_framebuffer *pfb;
+	struct psb_framebuffer pfb;
 };
 
 
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
index 98d8ab3..b24b964 100644
--- a/drivers/staging/gma500/psb_gem.c
+++ b/drivers/staging/gma500/psb_gem.c
@@ -51,6 +51,7 @@ void psb_gem_free_object(struct drm_gem_object *obj)
 	}
 	drm_gem_object_release(obj);
 	/* This must occur last as it frees up the memory of the GEM object */
+	pr_err("GEM destroyed %p, %p\n", gtt, obj);
 	psb_gtt_free_range(obj->dev, gtt);
 }
 
@@ -176,21 +177,28 @@ static int psb_gem_create(struct drm_file *file,
 
 	size = roundup(size, PAGE_SIZE);
 
+	dev_err(dev->dev, "GEM creating %lld\n", size);
+
 	/* Allocate our object - for now a direct gtt range which is not 
 	   stolen memory backed */
 	r = psb_gtt_alloc_range(dev, size, "gem", 0);
-	if (r == NULL)
+	if (r == NULL) {
+		dev_err(dev->dev, "no memory for %lld byte GEM object\n", size);
 		return -ENOSPC;
+	}
 	/* Initialize the extra goodies GEM needs to do all the hard work */
 	if (drm_gem_object_init(dev, &r->gem, size) != 0) {
 		psb_gtt_free_range(dev, r);
 		/* GEM doesn't give an error code and we don't have an
 		   EGEMSUCKS so make something up for now - FIXME */
+		dev_err(dev->dev, "GEM init failed for %lld\n", size);
 		return -ENOMEM;
 	}
 	/* Give the object a handle so we can carry it more easily */
 	ret = drm_gem_handle_create(file, &r->gem, &handle);
 	if (ret) {
+		dev_err(dev->dev, "GEM handle failed for %p, %lld\n",
+							&r->gem, size);
 		drm_gem_object_release(&r->gem);
 		psb_gtt_free_range(dev, r);
 		return ret;
@@ -198,6 +206,8 @@ static int psb_gem_create(struct drm_file *file,
 	/* We have the initial and handle reference but need only one now */
 	drm_gem_object_unreference(&r->gem);
 	*handlep = handle;
+	dev_err(dev->dev, "GEM handle %x for %p OK\n",
+				handle, &r->gem);
 	return 0;
 }
 
@@ -273,9 +283,12 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	   something from beneath our feet */
 	mutex_lock(&dev->struct_mutex);
 
+	dev_err(dev->dev, "Fault on GTT %p\n", r);
+
 	/* For now the mmap pins the object and it stays pinned. As things
 	   stand that will do us no harm */
 	if (r->mmapping == 0) {
+		dev_err(dev->dev, "Need to pin %p\n", r);
 		ret = psb_gtt_pin(r);
 		if (ret < 0) {
 		        DRM_ERROR("gma500: pin failed: %d\n", ret);
@@ -289,10 +302,13 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
 				>> PAGE_SHIFT;
 
+	dev_err(dev->dev, "Page offset %p %d\n", r, (int)page_offset);
         /* CPU view of the page, don't go via the GART for CPU writes */
 	pfn = page_to_phys(r->pages[page_offset]) >> PAGE_SHIFT;
 	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
 
+	dev_err(dev->dev, "PFN %ld for VA %p = %d\n", pfn, vmf->virtual_address, ret);
+
 fail:
         mutex_unlock(&dev->struct_mutex);
 	switch (ret) {
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index 5a296e1..c6a7492 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -314,6 +314,7 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
 				len, start, end, PAGE_SIZE, NULL, NULL);
 	if (ret == 0) {
 		gt->offset = gt->resource.start - r->start;
+		dev_err(dev->dev, "GTT new %p, %d\n", gt, gt->stolen);
 		return gt;
 	}
 	kfree(gt);
@@ -340,6 +341,7 @@ static void psb_gtt_destroy(struct kref *kref)
 	}
 	WARN_ON(gt->in_gart && !gt->stolen);
 	release_resource(&gt->resource);
+	pr_err("GTT destroyed %p, %d\n", gt, gt->stolen);
 	kfree(gt);
 }
 


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 03/49] gma500: Do sane FB cleanup
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
  2011-07-05 14:34 ` [PATCH 01/49] gma500: Ensure the frame buffer has a linear virtual mapping Alan Cox
  2011-07-05 14:34 ` [PATCH 02/49] gma500: revamp frame buffer creation and handling Alan Cox
@ 2011-07-05 14:34 ` Alan Cox
  2011-07-05 14:34 ` [PATCH 04/49] gma500: trim some of the debug Alan Cox
                   ` (46 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:34 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

If we get a user frame buffer destroyed which is being displayed then clean
up the mess nicely. We can now run a slightly modified modetest including setting
modes, and handling crashes.

Modetest still blows up but this is because libdrm 2.4.25 is busted.


Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_fb.c            |   24 +++++++++++++++++++++++-
 drivers/staging/gma500/psb_intel_display.c |   22 +++++++++++++---------
 2 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 5977add..d005025 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -719,16 +719,38 @@ static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
 	struct psb_framebuffer *psbfb = to_psb_fb(fb);
 	struct gtt_range *r = psbfb->gtt;
+	struct drm_device *dev = fb->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_fbdev *fbdev = dev_priv->fbdev;
+	struct drm_crtc *crtc;
+	int reset = 0;
 
 	/* Should never get stolen memory for a user fb */
 	WARN_ON(r->stolen);
 	pr_err("user framebuffer destroy %p, fbdev %p\n",
 						psbfb, psbfb->fbdev);
+	/* Check if we are erroneously live */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		if (crtc->fb == fb)
+			reset = 1;
+
+	if (reset)
+		pr_err("DRM: gma500, forcing reset\n");
+
+	if (reset)
+		/* 
+		 * Now force a sane response before we permit the DRM crc layer to
+		 * do stupid things like blank the display. Instead we reset this
+		 * framebuffer as if the user had forced a reset. We must do this
+		 * before the cleanup so that the DRM layer doesn't get a chance
+		 * to stick its oar in where it isn't wanted.
+		 */
+		drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
+
         /* Let DRM do its clean up */
 	drm_framebuffer_cleanup(fb);
 	/*  We are no longer using the resource in GEM */
 	drm_gem_object_unreference_unlocked(&r->gem);
-
 	kfree(fb);
 }
 
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index a358987..540304c 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -352,15 +352,15 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 
 	PSB_DEBUG_ENTRY("\n");
 
+	if (!gma_power_begin(dev, true))
+		return 0;
+
 	/* no fb bound */
 	if (!crtc->fb) {
 		DRM_DEBUG("No FB bound\n");
-		return 0;
+		goto psb_intel_pipe_cleaner;
 	}
 
-	if (!gma_power_begin(dev, true))
-		return 0;
-
 	/* We are displaying this buffer, make sure it is actually loaded
 	   into the GTT */
 	ret = psb_gtt_pin(psbfb->gtt);
@@ -409,6 +409,7 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 		REG_READ(dspbase);
 	}
 
+psb_intel_pipe_cleaner:
 	/* If there was a previous display we can now unpin it */
 	if (old_fb)
 		psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
@@ -588,6 +589,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 	int pipe = psb_intel_crtc->pipe;
 	int fp_reg = (pipe == 0) ? FPA0 : FPB0;
 	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
@@ -610,6 +612,12 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	struct drm_connector *connector;
 
+	/* No scan out no play */
+	if (crtc->fb == NULL) {
+	        crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+                return 0;
+        }
+
 	list_for_each_entry(connector, &mode_config->connector_list, head) {
 		struct psb_intel_output *psb_intel_output =
 		    to_psb_intel_output(connector);
@@ -786,11 +794,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 	REG_WRITE(dspcntr_reg, dspcntr);
 
 	/* Flush the plane changes */
-	{
-		struct drm_crtc_helper_funcs *crtc_funcs =
-		    crtc->helper_private;
-		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
-	}
+	crtc_funcs->mode_set_base(crtc, x, y, old_fb);
 
 	psb_intel_wait_for_vblank(dev);
 


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 04/49] gma500: trim some of the debug
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (2 preceding siblings ...)
  2011-07-05 14:34 ` [PATCH 03/49] gma500: Do sane FB cleanup Alan Cox
@ 2011-07-05 14:34 ` Alan Cox
  2011-07-05 14:34 ` [PATCH 05/49] gma500: polish for completion of this phase Alan Cox
                   ` (45 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:34 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_fb.c  |    6 +-----
 drivers/staging/gma500/psb_gem.c |   11 -----------
 drivers/staging/gma500/psb_gtt.c |    2 --
 3 files changed, 1 insertions(+), 18 deletions(-)

diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index d005025..156f8ad 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -727,17 +727,13 @@ static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
 
 	/* Should never get stolen memory for a user fb */
 	WARN_ON(r->stolen);
-	pr_err("user framebuffer destroy %p, fbdev %p\n",
-						psbfb, psbfb->fbdev);
+
 	/* Check if we are erroneously live */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 		if (crtc->fb == fb)
 			reset = 1;
 
 	if (reset)
-		pr_err("DRM: gma500, forcing reset\n");
-
-	if (reset)
 		/* 
 		 * Now force a sane response before we permit the DRM crc layer to
 		 * do stupid things like blank the display. Instead we reset this
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
index b24b964..125ea6b 100644
--- a/drivers/staging/gma500/psb_gem.c
+++ b/drivers/staging/gma500/psb_gem.c
@@ -51,7 +51,6 @@ void psb_gem_free_object(struct drm_gem_object *obj)
 	}
 	drm_gem_object_release(obj);
 	/* This must occur last as it frees up the memory of the GEM object */
-	pr_err("GEM destroyed %p, %p\n", gtt, obj);
 	psb_gtt_free_range(obj->dev, gtt);
 }
 
@@ -177,8 +176,6 @@ static int psb_gem_create(struct drm_file *file,
 
 	size = roundup(size, PAGE_SIZE);
 
-	dev_err(dev->dev, "GEM creating %lld\n", size);
-
 	/* Allocate our object - for now a direct gtt range which is not 
 	   stolen memory backed */
 	r = psb_gtt_alloc_range(dev, size, "gem", 0);
@@ -206,8 +203,6 @@ static int psb_gem_create(struct drm_file *file,
 	/* We have the initial and handle reference but need only one now */
 	drm_gem_object_unreference(&r->gem);
 	*handlep = handle;
-	dev_err(dev->dev, "GEM handle %x for %p OK\n",
-				handle, &r->gem);
 	return 0;
 }
 
@@ -283,12 +278,9 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	   something from beneath our feet */
 	mutex_lock(&dev->struct_mutex);
 
-	dev_err(dev->dev, "Fault on GTT %p\n", r);
-
 	/* For now the mmap pins the object and it stays pinned. As things
 	   stand that will do us no harm */
 	if (r->mmapping == 0) {
-		dev_err(dev->dev, "Need to pin %p\n", r);
 		ret = psb_gtt_pin(r);
 		if (ret < 0) {
 		        DRM_ERROR("gma500: pin failed: %d\n", ret);
@@ -302,13 +294,10 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
 				>> PAGE_SHIFT;
 
-	dev_err(dev->dev, "Page offset %p %d\n", r, (int)page_offset);
         /* CPU view of the page, don't go via the GART for CPU writes */
 	pfn = page_to_phys(r->pages[page_offset]) >> PAGE_SHIFT;
 	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
 
-	dev_err(dev->dev, "PFN %ld for VA %p = %d\n", pfn, vmf->virtual_address, ret);
-
 fail:
         mutex_unlock(&dev->struct_mutex);
 	switch (ret) {
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index c6a7492..5a296e1 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -314,7 +314,6 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
 				len, start, end, PAGE_SIZE, NULL, NULL);
 	if (ret == 0) {
 		gt->offset = gt->resource.start - r->start;
-		dev_err(dev->dev, "GTT new %p, %d\n", gt, gt->stolen);
 		return gt;
 	}
 	kfree(gt);
@@ -341,7 +340,6 @@ static void psb_gtt_destroy(struct kref *kref)
 	}
 	WARN_ON(gt->in_gart && !gt->stolen);
 	release_resource(&gt->resource);
-	pr_err("GTT destroyed %p, %d\n", gt, gt->stolen);
 	kfree(gt);
 }
 


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 05/49] gma500: polish for completion of this phase
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (3 preceding siblings ...)
  2011-07-05 14:34 ` [PATCH 04/49] gma500: trim some of the debug Alan Cox
@ 2011-07-05 14:34 ` Alan Cox
  2011-07-05 14:35 ` [PATCH 06/49] gma500: 2D acceleration tidying Alan Cox
                   ` (44 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:34 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Give the driver its own proper DRM name, clean up copyright headers and so
forth

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/mrst_crtc.c     |    4 +
 drivers/staging/gma500/mrst_lvds.c     |    2 -
 drivers/staging/gma500/psb_2d.c        |    7 --
 drivers/staging/gma500/psb_bl.c        |    4 +
 drivers/staging/gma500/psb_drm.h       |   90 +-------------------------------
 drivers/staging/gma500/psb_drv.c       |    4 +
 drivers/staging/gma500/psb_drv.h       |   85 +++++++++++++++---------------
 drivers/staging/gma500/psb_fb.c        |    3 -
 drivers/staging/gma500/psb_fb.h        |    3 -
 drivers/staging/gma500/psb_gtt.h       |    7 +-
 drivers/staging/gma500/psb_intel_drv.h |   19 +------
 drivers/staging/gma500/psb_irq.h       |    8 +--
 drivers/staging/gma500/psb_powermgmt.c |    4 +
 drivers/staging/gma500/psb_powermgmt.h |    2 -
 drivers/staging/gma500/psb_reg.h       |    2 -
 15 files changed, 67 insertions(+), 177 deletions(-)

diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c
index e4a0c03..fd97c80 100644
--- a/drivers/staging/gma500/mrst_crtc.c
+++ b/drivers/staging/gma500/mrst_crtc.c
@@ -86,7 +86,7 @@ static const struct mrst_limit_t *mrst_limit(struct drm_crtc *crtc)
 {
 	const struct mrst_limit_t *limit = NULL;
 	struct drm_device *dev = crtc->dev;
-	DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 
 	if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)
 	    || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) {
@@ -296,7 +296,7 @@ static int mrst_crtc_mode_set(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
-	DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 	int pipe = psb_intel_crtc->pipe;
 	int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0;
 	int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B;
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
index 4a08b74..22ea00e 100644
--- a/drivers/staging/gma500/mrst_lvds.c
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -46,7 +46,7 @@ static void mrst_lvds_set_power(struct drm_device *dev,
 				struct psb_intel_output *output, bool on)
 {
 	u32 pp_status;
-	DRM_DRIVER_PRIVATE_T *dev_priv = dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 	PSB_DEBUG_ENTRY("\n");
 
 	if (!gma_power_begin(dev, true))
diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c
index 060eeaf..c3d7085 100644
--- a/drivers/staging/gma500/psb_2d.c
+++ b/drivers/staging/gma500/psb_2d.c
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
+ * Copyright (c) 2007-2011, Intel Corporation.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -396,8 +396,3 @@ int psbfb_sync(struct fb_info *info)
 out:
 	return (busy) ? -EBUSY : 0;
 }
-
-/*
-	info->fix.accel = FB_ACCEL_I830;
-	info->flags = FBINFO_DEFAULT;
-*/
diff --git a/drivers/staging/gma500/psb_bl.c b/drivers/staging/gma500/psb_bl.c
index 5dffc71..2f9674d 100644
--- a/drivers/staging/gma500/psb_bl.c
+++ b/drivers/staging/gma500/psb_bl.c
@@ -1,7 +1,7 @@
 /*
- *  psb backlight interface
+ * GMA500 Backlight Interface
  *
- * Copyright (c) 2009, Intel Corporation.
+ * Copyright (c) 2009-2011, Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
index 49ffdd5..b005293 100644
--- a/drivers/staging/gma500/psb_drm.h
+++ b/drivers/staging/gma500/psb_drm.h
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
+ * Copyright (c) 2007-2011, Intel Corporation.
  * All Rights Reserved.
  * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA.
  * All Rights Reserved.
@@ -22,84 +22,8 @@
 #ifndef _PSB_DRM_H_
 #define _PSB_DRM_H_
 
-#if defined(__linux__) && !defined(__KERNEL__)
-#include<stdint.h>
-#include <linux/types.h>
-#include "drm_mode.h"
-#endif
-
-#define DRM_PSB_SAREA_MAJOR 0
-#define DRM_PSB_SAREA_MINOR 2
-#define PSB_FIXED_SHIFT 16
-
 #define PSB_NUM_PIPE 3
 
-/*
- * Public memory types.
- */
-
-typedef s32 psb_fixed;
-typedef u32 psb_ufixed;
-
-static inline s32 psb_int_to_fixed(int a)
-{
-	return a * (1 << PSB_FIXED_SHIFT);
-}
-
-static inline u32 psb_unsigned_to_ufixed(unsigned int a)
-{
-	return a << PSB_FIXED_SHIFT;
-}
-
-/*Status of the command sent to the gfx device.*/
-typedef enum {
-	DRM_CMD_SUCCESS,
-	DRM_CMD_FAILED,
-	DRM_CMD_HANG
-} drm_cmd_status_t;
-
-struct drm_psb_scanout {
-	u32 buffer_id;	/* DRM buffer object ID */
-	u32 rotation;	/* Rotation as in RR_rotation definitions */
-	u32 stride;	/* Buffer stride in bytes */
-	u32 depth;		/* Buffer depth in bits (NOT) bpp */
-	u32 width;		/* Buffer width in pixels */
-	u32 height;	/* Buffer height in lines */
-	s32 transform[3][3];	/* Buffer composite transform */
-	/* (scaling, rot, reflect) */
-};
-
-#define DRM_PSB_SAREA_OWNERS 16
-#define DRM_PSB_SAREA_OWNER_2D 0
-#define DRM_PSB_SAREA_OWNER_3D 1
-
-#define DRM_PSB_SAREA_SCANOUTS 3
-
-struct drm_psb_sarea {
-	/* Track changes of this data structure */
-
-	u32 major;
-	u32 minor;
-
-	/* Last context to touch part of hw */
-	u32 ctx_owners[DRM_PSB_SAREA_OWNERS];
-
-	/* Definition of front- and rotated buffers */
-	u32 num_scanouts;
-	struct drm_psb_scanout scanouts[DRM_PSB_SAREA_SCANOUTS];
-
-	int planeA_x;
-	int planeA_y;
-	int planeA_w;
-	int planeA_h;
-	int planeB_x;
-	int planeB_y;
-	int planeB_w;
-	int planeB_h;
-	/* Number of active scanouts */
-	u32 num_active_scanouts;
-};
-
 #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)
@@ -223,20 +147,14 @@ struct drm_psb_register_rw_arg {
 
 #define DRM_PSB_KMS_OFF		0x00
 #define DRM_PSB_KMS_ON		0x01
-#define DRM_PSB_VT_LEAVE        0x02
-#define DRM_PSB_VT_ENTER        0x03
-#define DRM_PSB_EXTENSION       0x06
 #define DRM_PSB_SIZES           0x07
 #define DRM_PSB_FUSE_REG	0x08
-#define DRM_PSB_VBT		0x09
 #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
-#define DRM_PSB_GTT_MAP         0x0F
-#define DRM_PSB_GTT_UNMAP       0x10
-#define DRM_PSB_GETPAGEADDRS	0x11
+
 /**
  * NOTE: Add new commands here, but increment
  * the values below and increment their
@@ -249,10 +167,6 @@ struct drm_psb_register_rw_arg {
 #define DRM_PVR_RESERVED4	0x15
 #define DRM_PVR_RESERVED5	0x16
 
-#define DRM_PSB_HIST_ENABLE	0x17
-#define DRM_PSB_HIST_STATUS	0x18
-#define DRM_PSB_UPDATE_GUARD	0x19
-#define DRM_PSB_INIT_COMM	0x1A
 #define DRM_PSB_DPST		0x1B
 #define DRM_PSB_GAMMA		0x1C
 #define DRM_PSB_DPST_BL		0x1D
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index aa87b1b..9bd0a5d 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
+ * Copyright (c) 2007-2011, Intel Corporation.
  * All Rights Reserved.
  * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA.
  * All Rights Reserved.
@@ -1462,6 +1462,6 @@ static void __exit psb_exit(void)
 late_initcall(psb_init);
 module_exit(psb_exit);
 
-MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others");
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index e19a454..c0468ee 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2007-2008, Intel Corporation.
+ * Copyright (c) 2007-2011, Intel Corporation.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -32,40 +32,32 @@
 #include "psb_powermgmt.h"
 #include "mrst.h"
 
-/*Append new drm mode definition here, align with libdrm definition*/
+/* Append new drm mode definition here, align with libdrm definition */
 #define DRM_MODE_SCALE_NO_SCALE   2
 
 enum {
-	CHIP_PSB_8108 = 0,
-	CHIP_PSB_8109 = 1,
-	CHIP_MRST_4100 = 2,
+	CHIP_PSB_8108 = 0,		/* Poulsbo */
+	CHIP_PSB_8109 = 1,		/* Poulsbo */
+	CHIP_MRST_4100 = 2,		/* Moorestown/Oaktrail */
 };
 
 #define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100)
 
 /*
- *Hardware bugfixes
+ * Driver definitions
  */
 
-#define DRIVER_NAME "pvrsrvkm"
-#define DRIVER_DESC "drm driver for the Intel GMA500"
-#define DRIVER_AUTHOR "Intel Corporation"
+#define DRIVER_NAME "gma500"
+#define DRIVER_DESC "DRM driver for the Intel GMA500"
 
-#define PSB_DRM_DRIVER_DATE "2009-03-10"
-#define PSB_DRM_DRIVER_MAJOR 8
-#define PSB_DRM_DRIVER_MINOR 1
+#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
 
 /*
- *TTM driver private offsets.
+ *	Hardware offsets
  */
-
-#define DRM_PSB_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
-#define PSB_OBJECT_HASH_ORDER 13
-#define PSB_FILE_OBJECT_HASH_ORDER 12
-#define PSB_BO_HASH_ORDER 12
-
 #define PSB_VDC_OFFSET		 0x00000000
 #define PSB_VDC_SIZE		 0x000080000
 #define MRST_MMIO_SIZE		 0x0000C0000
@@ -73,42 +65,52 @@ enum {
 #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)
-#define PSB_NUM_VALIDATE_BUFFERS 2048
 
 /*
- *Flags for external memory type field.
+ *	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
+ *	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
+ *	VDC registers and bits
  */
 #define PSB_MSVDX_CLOCKGATING	  0x2064
 #define PSB_TOPAZ_CLOCKGATING	  0x2068
@@ -278,7 +280,7 @@ struct drm_psb_private {
 	int display_count;
 
 	/*
-	 *Modesetting
+	 * Modesetting
 	 */
 	struct psb_intel_mode_device mode_dev;
 
@@ -287,12 +289,8 @@ struct drm_psb_private {
 	uint32_t num_pipe;
 
 	/*
-	 *Memory managers
+	 * OSPM info (Power management base) (can go ?)
 	 */
-
-	/*
-	*OSPM info
-	*/
 	uint32_t ospm_base;
 
 	/*
@@ -304,11 +302,11 @@ struct drm_psb_private {
 	u32 fuse_reg_value;
 	u32 video_device_fuse;
 
-	/* pci revision id for B0:D2:F0 */
+	/* PCI revision ID for B0:D2:F0 */
 	uint8_t platform_rev_id;
 
 	/*
-	 *LVDS info
+	 * LVDS info
 	 */
 	int backlight_duty_cycle;	/* restore backlight to this value */
 	bool panel_wants_dither;
@@ -316,10 +314,10 @@ struct drm_psb_private {
 	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 bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */
 	struct psb_intel_i2c_chan *lvds_i2c_bus;
 
-	/* Feature bits from the VBIOS*/
+	/* Feature bits from the VBIOS */
 	unsigned int int_tv_support:1;
 	unsigned int lvds_dither:1;
 	unsigned int lvds_vbt:1;
@@ -332,7 +330,7 @@ struct drm_psb_private {
 	unsigned int core_freq;
 	uint32_t iLVDS_enable;
 
-	/*runtime PM state*/
+	/* Runtime PM state */
 	int rpm_enabled;
 
 	/* Moorestown specific */
@@ -350,7 +348,7 @@ struct drm_psb_private {
 	uint32_t dspcntr2;
 
 	/*
-	 *Register state
+	 * Register state
 	 */
 	uint32_t saveDSPACNTR;
 	uint32_t saveDSPBCNTR;
@@ -468,7 +466,7 @@ struct drm_psb_private {
 	u32 lid_last_state;
 
 	/*
-	 *Watchdog
+	 * Watchdog
 	 */
 
 	uint32_t apm_reg;
@@ -497,7 +495,7 @@ static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
 }
 
 /*
- *MMU stuff.
+ * MMU stuff.
  */
 
 extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
@@ -525,7 +523,7 @@ extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
 				  unsigned long *pfn);
 
 /*
- *Enable / disable MMU for different requestors.
+ * Enable / disable MMU for different requestors.
  */
 
 
@@ -598,7 +596,7 @@ extern int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
 	 	  	   unsigned size);
 
 /*
- *psb_reset.c
+ * psb_reset.c
  */
 
 extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
@@ -710,7 +708,6 @@ extern int drm_idle_check_interval;
 /*
  *Utilities
  */
-#define DRM_DRIVER_PRIVATE_T struct drm_psb_private
 
 static inline u32 MRST_MSG_READ32(uint port, uint offset)
 {
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 156f8ad..0a77abf 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
+ * Copyright (c) 2007-2011, Intel Corporation.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -56,7 +56,6 @@ void *psbfb_vdc_reg(struct drm_device *dev)
 	dev_priv = (struct drm_psb_private *) dev->dev_private;
 	return dev_priv->vdc_reg;
 }
-/*EXPORT_SYMBOL(psbfb_vdc_reg); */
 
 static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 			   unsigned blue, unsigned transp,
diff --git a/drivers/staging/gma500/psb_fb.h b/drivers/staging/gma500/psb_fb.h
index fd7e51a..ed6e856 100644
--- a/drivers/staging/gma500/psb_fb.h
+++ b/drivers/staging/gma500/psb_fb.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Intel Corporation
+ * Copyright (c) 2008-2011, Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -41,7 +41,6 @@ struct psb_fbdev {
 	struct psb_framebuffer pfb;
 };
 
-
 #define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
 
 extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h
index 37287eb..7e1f21e 100644
--- a/drivers/staging/gma500/psb_gtt.h
+++ b/drivers/staging/gma500/psb_gtt.h
@@ -22,6 +22,7 @@
 
 #include <drm/drmP.h>
 
+/* This wants cleaning up with respect to the psb_dev and un-needed stuff */
 struct psb_gtt {
 	struct drm_device *dev;
 	uint32_t gatt_start;
@@ -41,9 +42,9 @@ extern void psb_gtt_takedown(struct drm_device *dev);
 
 /* Each gtt_range describes an allocation in the GTT area */
 struct gtt_range {
-	struct resource resource;
-	u32 offset;
-	struct kref kref;
+	struct resource resource;	/* Resource for our allocation */
+	u32 offset;			/* GTT offset of our object */
+	struct kref kref;		/* Can probably go FIXME - GEM kref will do */
 	struct drm_gem_object gem;	/* GEM high level stuff */
 	int in_gart;			/* Currently in the GART (ref ct) */
 	bool stolen;			/* Backed from stolen RAM */
diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h
index 6006ddd..75a95f7 100644
--- a/drivers/staging/gma500/psb_intel_drv.h
+++ b/drivers/staging/gma500/psb_intel_drv.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Intel Corporation.
+ * Copyright (c) 2009-2011, Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -26,11 +26,6 @@
 #include <linux/gpio.h>
 
 /*
- * MOORESTOWN defines
- */
-#define DELAY_TIME1 2000 /* 1000 = 1ms */
-
-/*
  * Display related stuff
  */
 
@@ -61,16 +56,10 @@
 #define INTEL_DVO_CHIP_TMDS 2
 #define INTEL_DVO_CHIP_TVOUT 4
 
-enum mipi_panel_type {
-	NSC_800X480 = 1,
-	LGE_480X1024 = 2,
-	TPO_864X480 = 3
-};
-
-/**
+/*
  * Hold information useally put on the device driver privates here,
  * since it needs to be shared across multiple of devices drivers privates.
-*/
+ */
 struct psb_intel_mode_device {
 
 	/*
@@ -79,7 +68,7 @@ struct psb_intel_mode_device {
 	 size_t(*bo_offset) (struct drm_device *dev, void *bo);
 
 	/*
-	 * Cursor
+	 * Cursor (Can go ?)
 	 */
 	int cursor_needs_physical;
 
diff --git a/drivers/staging/gma500/psb_irq.h b/drivers/staging/gma500/psb_irq.h
index 3e56f33..216fda3 100644
--- a/drivers/staging/gma500/psb_irq.h
+++ b/drivers/staging/gma500/psb_irq.h
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2009, Intel Corporation.
+ * Copyright (c) 2009-2011, Intel Corporation.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -34,10 +34,6 @@ int  psb_irq_postinstall(struct drm_device *dev);
 void psb_irq_uninstall(struct drm_device *dev);
 irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
 
-void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands);
-int  psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands);
-void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
-
 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);
@@ -46,4 +42,4 @@ 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_
+#endif /* _SYSIRQ_H_ */
diff --git a/drivers/staging/gma500/psb_powermgmt.c b/drivers/staging/gma500/psb_powermgmt.c
index 1495415..50f2234 100644
--- a/drivers/staging/gma500/psb_powermgmt.c
+++ b/drivers/staging/gma500/psb_powermgmt.c
@@ -1,7 +1,7 @@
 /**************************************************************************
- * Copyright (c) 2009, Intel Corporation.
+ * Copyright (c) 2009-2011, Intel Corporation.
  * All Rights Reserved.
-
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * to deal in the Software without restriction, including without limitation
diff --git a/drivers/staging/gma500/psb_powermgmt.h b/drivers/staging/gma500/psb_powermgmt.h
index e005229..333b28d 100644
--- a/drivers/staging/gma500/psb_powermgmt.h
+++ b/drivers/staging/gma500/psb_powermgmt.h
@@ -1,5 +1,5 @@
 /**************************************************************************
- * Copyright (c) 2009, Intel Corporation.
+ * Copyright (c) 2009-2011, Intel Corporation.
  * All Rights Reserved.
 
  * Permission is hereby granted, free of charge, to any person obtaining a
diff --git a/drivers/staging/gma500/psb_reg.h b/drivers/staging/gma500/psb_reg.h
index 9ad4989..529fda8 100644
--- a/drivers/staging/gma500/psb_reg.h
+++ b/drivers/staging/gma500/psb_reg.h
@@ -573,7 +573,7 @@
 #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
+/* 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


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 06/49] gma500: 2D acceleration tidying
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (4 preceding siblings ...)
  2011-07-05 14:34 ` [PATCH 05/49] gma500: polish for completion of this phase Alan Cox
@ 2011-07-05 14:35 ` Alan Cox
  2011-07-05 14:35 ` [PATCH 07/49] gma500: nuke the last bits of TTM code Alan Cox
                   ` (43 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:35 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We have a FIXME to do the power management for which the framework now
exists, and we also need to deal with an erratum. Some operations exactly 8
pixels wide or high fail. The work around is to do two smaller ones (see
the Intel released X driver bits) but for console quite frankly if it's
8bits wide and/or high its not worth it so fall back.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_2d.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c
index c3d7085..494bad5 100644
--- a/drivers/staging/gma500/psb_2d.c
+++ b/drivers/staging/gma500/psb_2d.c
@@ -183,10 +183,14 @@ static void psbfb_fillrect_accel(struct fb_info *info,
 		cfb_fillrect(info, r);
 		return;
 	}
-
+	if (!gma_power_begin(dev, false)) {
+		cfb_fillrect(info, r);
+		return;
+	}
 	psb_accel_2d_fillrect(dev_priv,
 			      offset, stride, format,
 			      r->dx, r->dy, r->width, r->height, r->color);
+	gma_power_end(dev);
 }
 
 void psbfb_fillrect(struct fb_info *info,
@@ -198,9 +202,7 @@ void psbfb_fillrect(struct fb_info *info,
 	if (1 || (info->flags & FBINFO_HWACCEL_DISABLED))
 		return cfb_fillrect(info, rect);
 
-	/*psb_check_power_state(dev, PSB_DEVICE_SGX); */
 	psbfb_fillrect_accel(info, rect);
-	/* Drop power again here on MRST FIXMEAC */
 }
 
 static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
@@ -331,10 +333,15 @@ static void psbfb_copyarea_accel(struct fb_info *info,
 		return;
 	}
 
+	if (!gma_power_begin(dev, false)) {
+		cfb_copyarea(info, a);
+		return;
+	}
 	psb_accel_2d_copy(dev_priv,
 			  offset, stride, src_format,
 			  offset, stride, dst_format,
 			  a->sx, a->sy, a->dx, a->dy, a->width, a->height);
+	gma_power_end(dev);
 }
 
 void psbfb_copyarea(struct fb_info *info,
@@ -343,12 +350,12 @@ void psbfb_copyarea(struct fb_info *info,
 	if (unlikely(info->state != FBINFO_STATE_RUNNING))
 		return;
 
-	if (info->flags & FBINFO_HWACCEL_DISABLED)
+        /* Avoid the 8 pixel erratum */
+	if (region->width == 8 || region->height == 8 ||
+	        (info->flags & FBINFO_HWACCEL_DISABLED))
 		return cfb_copyarea(info, region);
 
-	/* psb_check_power_state(dev, PSB_DEVICE_SGX); */
 	psbfb_copyarea_accel(info, region);
-	/* Need to power back off here for MRST FIXMEAC */
 }
 
 void psbfb_imageblit(struct fb_info *info, const struct fb_image *image)


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 07/49] gma500: nuke the last bits of TTM code
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (5 preceding siblings ...)
  2011-07-05 14:35 ` [PATCH 06/49] gma500: 2D acceleration tidying Alan Cox
@ 2011-07-05 14:35 ` Alan Cox
  2011-07-05 14:35 ` [PATCH 08/49] gma500: nuke the PSB debug stuff Alan Cox
                   ` (42 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:35 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We don't seem to need this for our task.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_drv.c |    6 ----
 drivers/staging/gma500/psb_gtt.c |   62 ++++++++++++--------------------------
 2 files changed, 19 insertions(+), 49 deletions(-)

diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 9bd0a5d..ab1da30 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -409,8 +409,6 @@ static int psb_do_init(struct drm_device *dev)
 	struct psb_gtt *pg = dev_priv->pg;
 
 	uint32_t stolen_gtt;
-	uint32_t tt_start;
-	uint32_t tt_pages;
 
 	int ret = -ENOMEM;
 
@@ -449,10 +447,6 @@ static int psb_do_init(struct drm_device *dev)
 
 	spin_lock_init(&dev_priv->irqmask_lock);
 
-	tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
-	    pg->gatt_pages : PSB_TT_PRIV0_PLIMIT;
-	tt_start = dev_priv->gatt_free_offset - pg->mmu_gatt_start;
-	tt_pages -= tt_start >> PAGE_SHIFT;
 	/* FIXME: can we kill ta_mem_size ? */
 	dev_priv->sizes.ta_mem_size = 0;
 
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index 5a296e1..8fcb833 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -138,8 +138,6 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
  *
  *	Pin and build an in kernel list of the pages that back our GEM object.
  *	While we hold this the pages cannot be swapped out
- *
- *	FIXME: Do we need to cache flush when we update the GTT
  */
 static int psb_gtt_attach_pages(struct gtt_range *gt)
 {
@@ -185,8 +183,6 @@ err:
  *	Undo the effect of psb_gtt_attach_pages. At this point the pages
  *	must have been removed from the GTT as they could now be paged out
  *	and move bus address.
- *
- *	FIXME: Do we need to cache flush when we update the GTT
  */
 static void psb_gtt_detach_pages(struct gtt_range *gt)
 {
@@ -194,7 +190,6 @@ static void psb_gtt_detach_pages(struct gtt_range *gt)
 	for (i = 0; i < gt->npage; i++) {
 		/* FIXME: do we need to force dirty */
 		set_page_dirty(gt->pages[i]);
-		/* Undo the reference we took when populating the table */
 		page_cache_release(gt->pages[i]);
 	}
 	kfree(gt->pages);
@@ -384,7 +379,6 @@ void psb_gtt_takedown(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
 
-	/* FIXME: iounmap dev_priv->vram_addr etc */
 	if (dev_priv->gtt_map) {
 		iounmap(dev_priv->gtt_map);
 		dev_priv->gtt_map = NULL;
@@ -395,6 +389,8 @@ void psb_gtt_takedown(struct drm_device *dev)
 		PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
 		(void) PSB_RVDC32(PSB_PGETBL_CTL);
 	}
+	if (dev_priv->vram_addr)
+		iounmap(dev_priv->gtt_map);
 	kfree(dev_priv->pg);
 	dev_priv->pg = NULL;
 }
@@ -407,8 +403,6 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	unsigned i, num_pages;
 	unsigned pfn_base;
 	uint32_t vram_pages;
-	uint32_t tt_pages;
-	uint32_t *ttm_gtt_map;
 	uint32_t dvmt_mode = 0;
 	struct psb_gtt *pg;
 
@@ -421,6 +415,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	if (pg == NULL)
 		return -ENOMEM;
 
+        /* Enable the GTT */
 	pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
 	pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
 			      dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
@@ -431,30 +426,26 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 
 	/* The root resource we allocate address space from */
 	dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
-
 	dev_priv->gtt_initialized = 1;
 
 	pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
 
 	pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
-	/* fix me: video mmu has hw bug to access 0x0D0000000,
-	 * then make gatt start at 0x0e000,0000 */
+	/* 
+	 *	FIXME: video mmu has hw bug to access 0x0D0000000,
+	 *	then make gatt start at 0x0e000,0000
+	 */
 	pg->mmu_gatt_start = 0xE0000000;
+
 	pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
-	gtt_pages =
-	    pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
-	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
-	    >> PAGE_SHIFT;
+	gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
+	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT;
 
 	pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
 	vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE;
 
 	stolen_size = vram_stolen_size;
 
-	printk(KERN_INFO"GMMADR(region 0) start: 0x%08x (%dM).\n",
-		pg->gatt_start, pg->gatt_pages/256);
-	printk(KERN_INFO"GTTADR(region 3) start: 0x%08x (can map %dM RAM), and actual RAM base 0x%08x.\n",
-		pg->gtt_start, gtt_pages * 4, pg->gtt_phys_start);
 	printk(KERN_INFO "Stolen memory information\n");
 	printk(KERN_INFO "       base in RAM: 0x%x\n", dev_priv->stolen_base);
 	printk(KERN_INFO "       size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
@@ -473,8 +464,11 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	pg->gtt_pages = gtt_pages;
 	pg->stolen_size = stolen_size;
 	dev_priv->vram_stolen_size = vram_stolen_size;
-	dev_priv->gtt_map =
-	    ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT);
+
+	/*
+	 *	Map the GTT and the stolen memory area
+	 */
+	dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT);
 	if (!dev_priv->gtt_map) {
 		DRM_ERROR("Failure to map gtt.\n");
 		ret = -ENOMEM;
@@ -488,15 +482,8 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 		goto out_err;
 	}
 
-	DRM_DEBUG("gma500: vram kernel virtual address %p\n", dev_priv->vram_addr);
-
-	tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
-		(pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
-
-	ttm_gtt_map = dev_priv->gtt_map + tt_pages / 2;
-
 	/*
-	 * insert vram stolen pages.
+	 * Insert vram stolen pages into the GTT
 	 */
 
 	pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
@@ -509,26 +496,15 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	}
 
 	/*
-	 * Init rest of gtt managed by IMG.
-	 */
-	pfn_base = page_to_pfn(dev_priv->scratch_page);
-	pte = psb_gtt_mask_pte(pfn_base, 0);
-	for (; i < tt_pages / 2 - 1; ++i)
-		iowrite32(pte, dev_priv->gtt_map + i);
-
-	/*
-	 * Init rest of gtt managed by TTM.
+	 * Init rest of GTT to the scratch page to avoid accidents or scribbles
 	 */
 
 	pfn_base = page_to_pfn(dev_priv->scratch_page);
 	pte = psb_gtt_mask_pte(pfn_base, 0);
-	PSB_DEBUG_INIT("Initializing the rest of a total "
-		       "of %d gtt pages.\n", pg->gatt_pages);
+	for (; i < gtt_pages; ++i)
+		iowrite32(pte, dev_priv->gtt_map + i);
 
-	for (; i < pg->gatt_pages - tt_pages / 2; ++i)
-		iowrite32(pte, ttm_gtt_map + i);
 	(void) ioread32(dev_priv->gtt_map + i - 1);
-
 	return 0;
 
 out_err:


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 08/49] gma500: nuke the PSB debug stuff
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (6 preceding siblings ...)
  2011-07-05 14:35 ` [PATCH 07/49] gma500: nuke the last bits of TTM code Alan Cox
@ 2011-07-05 14:35 ` Alan Cox
  2011-07-05 14:35 ` [PATCH 09/49] gma500: Kill spare kref Alan Cox
                   ` (41 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:35 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Lose all the PSB debug gunge. We can replace it with dev_dbg() like normal
drivers if and when we need debug on stuff.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/mrst_crtc.c          |   23 ++----
 drivers/staging/gma500/mrst_lvds.c          |   12 +--
 drivers/staging/gma500/psb_bl.c             |    8 --
 drivers/staging/gma500/psb_drv.c            |   33 +++------
 drivers/staging/gma500/psb_drv.h            |   96 +++-----------------------
 drivers/staging/gma500/psb_fb.c             |   34 +--------
 drivers/staging/gma500/psb_gem.c            |    6 +-
 drivers/staging/gma500/psb_gtt.c            |    6 +-
 drivers/staging/gma500/psb_intel_bios.c     |   17 +----
 drivers/staging/gma500/psb_intel_display.c  |   99 +++------------------------
 drivers/staging/gma500/psb_intel_lvds.c     |   53 ++------------
 drivers/staging/gma500/psb_intel_opregion.c |    7 --
 drivers/staging/gma500/psb_intel_sdvo.c     |   34 ++++-----
 drivers/staging/gma500/psb_irq.c            |   33 ++-------
 14 files changed, 87 insertions(+), 374 deletions(-)

diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c
index fd97c80..fb9f2a2 100644
--- a/drivers/staging/gma500/mrst_crtc.c
+++ b/drivers/staging/gma500/mrst_crtc.c
@@ -103,7 +103,7 @@ static const struct mrst_limit_t *mrst_limit(struct drm_crtc *crtc)
 		}
 	} else {
 		limit = NULL;
-		PSB_DEBUG_ENTRY("mrst_limit Wrong display type.\n");
+		dev_err(dev->dev, "mrst_limit Wrong display type.\n");
 	}
 
 	return limit;
@@ -117,7 +117,7 @@ static void mrst_clock(int refclk, struct mrst_clock_t *clock)
 
 void mrstPrintPll(char *prefix, struct mrst_clock_t *clock)
 {
-	PSB_DEBUG_ENTRY("%s: dotclock = %d,  m = %d, p1 = %d.\n",
+	pr_debug("%s: dotclock = %d,  m = %d, p1 = %d.\n",
 	     prefix, clock->dot, clock->m, clock->p1);
 }
 
@@ -149,8 +149,7 @@ mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
 			}
 		}
 	}
-	DRM_DEBUG("mrstFindBestPLL err = %d.\n", err);
-
+	dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err);
 	return err != target;
 }
 
@@ -172,8 +171,6 @@ static void mrst_crtc_dpms(struct drm_crtc *crtc, int mode)
 	u32 temp;
 	bool enabled;
 
-	PSB_DEBUG_ENTRY("mode = %d, pipe = %d\n", mode, pipe);
-
 	if (!gma_power_begin(dev, true))
 		return;
 
@@ -320,8 +317,6 @@ static int mrst_crtc_mode_set(struct drm_crtc *crtc,
 	uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
 	struct drm_encoder *encoder;
 
-	PSB_DEBUG_ENTRY("pipe = 0x%x\n", pipe);
-
 	if (!gma_power_begin(dev, true))
 		return 0;
 
@@ -446,10 +441,9 @@ static int mrst_crtc_mode_set(struct drm_crtc *crtc,
 	ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock);
 
 	if (!ok) {
-		PSB_DEBUG_ENTRY(
-			"mrstFindBestPLL fail in mrst_crtc_mode_set.\n");
+		dev_dbg(dev->dev, "mrstFindBestPLL fail in mrst_crtc_mode_set.\n");
 	} else {
-		PSB_DEBUG_ENTRY("mrst_crtc_mode_set pixel clock = %d,"
+		dev_dbg(dev->dev, "mrst_crtc_mode_set pixel clock = %d,"
 			 "m = %x, p1 = %x.\n", clock.dot, clock.m,
 			 clock.p1);
 	}
@@ -540,11 +534,9 @@ int mrst_pipe_set_base(struct drm_crtc *crtc,
 	u32 dspcntr;
 	int ret = 0;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	/* no fb bound */
 	if (!crtc->fb) {
-		DRM_DEBUG("No FB bound\n");
+		dev_dbg(dev->dev, "No FB bound\n");
 		return 0;
 	}
 
@@ -574,13 +566,12 @@ int mrst_pipe_set_base(struct drm_crtc *crtc,
 		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 		break;
 	default:
-		DRM_ERROR("Unknown color depth\n");
+		dev_err(dev->dev, "Unknown color depth\n");
 		ret = -EINVAL;
 		goto pipe_set_base_exit;
 	}
 	REG_WRITE(dspcntr_reg, dspcntr);
 
-	DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
 	if (0 /* FIXMEAC - check what PSB needs */) {
 		REG_WRITE(dspbase, offset);
 		REG_READ(dspbase);
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
index 22ea00e..aac80cc 100644
--- a/drivers/staging/gma500/mrst_lvds.c
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -47,7 +47,6 @@ static void mrst_lvds_set_power(struct drm_device *dev,
 {
 	u32 pp_status;
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	PSB_DEBUG_ENTRY("\n");
 
 	if (!gma_power_begin(dev, true))
 		return;
@@ -77,8 +76,6 @@ static void mrst_lvds_dpms(struct drm_encoder *encoder, int mode)
 	struct drm_device *dev = encoder->dev;
 	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (mode == DRM_MODE_DPMS_ON)
 		mrst_lvds_set_power(dev, output, true);
 	else
@@ -97,8 +94,6 @@ static void mrst_lvds_mode_set(struct drm_encoder *encoder,
 	u32 lvds_port;
 	uint64_t v = DRM_MODE_SCALE_FULLSCREEN;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (!gma_power_begin(dev, true))
 		return;
 
@@ -252,8 +247,6 @@ void mrst_lvds_init(struct drm_device *dev,
 	struct i2c_adapter *i2c_adap;
 	struct drm_display_mode *scan;	/* *modes, *bios_mode; */
 
-	PSB_DEBUG_ENTRY("\n");
-
 	psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
 	if (!psb_intel_output)
 		return;
@@ -348,8 +341,7 @@ void mrst_lvds_init(struct drm_device *dev,
 
 	/* If we still don't have a mode after all that, give up. */
 	if (!mode_dev->panel_fixed_mode) {
-		DRM_DEBUG
-		    ("Found no modes on the lvds, ignoring the LVDS\n");
+		dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
 		goto failed_find;
 	}
 
@@ -358,7 +350,7 @@ out:
 	return;
 
 failed_find:
-	DRM_DEBUG("No LVDS modes found, disabling.\n");
+	dev_dbg(dev->dev, "No LVDS modes found, disabling.\n");
 	if (psb_intel_output->ddc_bus)
 		psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
 
diff --git a/drivers/staging/gma500/psb_bl.c b/drivers/staging/gma500/psb_bl.c
index 2f9674d..4a00047 100644
--- a/drivers/staging/gma500/psb_bl.c
+++ b/drivers/staging/gma500/psb_bl.c
@@ -56,8 +56,6 @@ int psb_set_brightness(struct backlight_device *bd)
 	struct drm_device *dev = bl_get_data(psb_backlight_device);
 	int level = bd->props.brightness;
 
-	DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
-
 	/* Percentage 1-100% being valid */
 	if (level < 1)
 		level = 1;
@@ -75,8 +73,6 @@ int mrst_set_brightness(struct backlight_device *bd)
 	u32 blc_pwm_ctl;
 	u32 max_pwm_blc;
 
-	DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
-
 	/* Percentage 1-100% being valid */
 	if (level < 1)
 		level = 1;
@@ -111,8 +107,6 @@ int mrst_set_brightness(struct backlight_device *bd)
 
 int psb_get_brightness(struct backlight_device *bd)
 {
-	DRM_DEBUG_DRIVER("brightness = 0x%x\n", psb_brightness);
-
 	/* return locally cached var instead of HW read (due to DPST etc.) */
 	/* FIXME: ideally return actual value in case firmware fiddled with
 	   it */
@@ -144,7 +138,7 @@ static int device_backlight_init(struct drm_device *dev)
 	} else {
 		/* get bl_max_freq and pol from dev_priv*/
 		if (!dev_priv->lvds_bl) {
-			DRM_ERROR("Has no valid LVDS backlight info\n");
+			dev_err(dev->dev, "Has no valid LVDS backlight info\n");
 			return 1;
 		}
 		bl_max_freq = dev_priv->lvds_bl->freq;
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index ab1da30..6ea06dd 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -35,17 +35,14 @@
 #include <linux/pm_runtime.h>
 #include <acpi/video.h>
 
-int drm_psb_debug;
 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(debug, "Enable debug output");
 MODULE_PARM_DESC(no_fb, "Disable FBdev");
 MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
-module_param_named(debug, drm_psb_debug, int, 0600);
 module_param_named(no_fb, drm_psb_no_fb, int, 0600);
 module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
 
@@ -215,7 +212,8 @@ void mrst_get_fuse_settings(struct drm_device *dev)
 		dev_priv->core_freq = 166;
 		break;
 	default:
-		DRM_ERROR("Invalid SKU values, SKU value = 0x%08x\n", fuse_value_tmp);
+		dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n",
+								fuse_value_tmp);
 		dev_priv->core_freq = 0;
 	}
 	DRM_INFO("LNC core clk is %dMHz.\n", dev_priv->core_freq);
@@ -231,7 +229,8 @@ void mid_get_pci_revID (struct drm_psb_private *dev_priv)
 	pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
 	dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
 	pci_dev_put(pci_gfx_root);
-	PSB_DEBUG_ENTRY("platform_rev_id is %x\n",	dev_priv->platform_rev_id);
+	dev_info(dev_priv->dev->dev, "platform_rev_id is %x\n",
+							dev_priv->platform_rev_id);
 }
 
 void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
@@ -413,7 +412,7 @@ static int psb_do_init(struct drm_device *dev)
 	int ret = -ENOMEM;
 
 	if (pg->mmu_gatt_start & 0x0FFFFFFF) {
-		DRM_ERROR("Gatt must be 256M aligned. This is a bug.\n");
+		dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n");
 		ret = -EINVAL;
 		goto out_err;
 	}
@@ -447,9 +446,6 @@ static int psb_do_init(struct drm_device *dev)
 
 	spin_lock_init(&dev_priv->irqmask_lock);
 
-	/* FIXME: can we kill ta_mem_size ? */
-	dev_priv->sizes.ta_mem_size = 0;
-
 	PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
 	PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
 	PSB_RSGX32(PSB_CR_BIF_BANK1);
@@ -553,7 +549,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	dev->dev_private = (void *) dev_priv;
 	dev_priv->chipset = chipset;
 
-	PSB_DEBUG_INIT("Mapping MMIO\n");
 	resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
 
 	dev_priv->vdc_reg =
@@ -679,7 +674,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	pm_runtime_set_active(&dev->pdev->dev);
 #endif
 	/*Intel drm driver load is done, continue doing pvr load*/
-	DRM_DEBUG("Pvr driver load\n");
 	return 0;
 out_err:
 	psb_driver_unload(dev);
@@ -721,7 +715,7 @@ static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
 		obj = drm_mode_object_find(dev, obj_id,
 				DRM_MODE_OBJECT_CRTC);
 		if (!obj) {
-			DRM_DEBUG("Invalid CRTC object.\n");
+			dev_dbg(dev->dev, "Invalid CRTC object.\n");
 			return -EINVAL;
 		}
 
@@ -741,7 +735,7 @@ static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
 		obj = drm_mode_object_find(dev, obj_id,
 				DRM_MODE_OBJECT_CONNECTOR);
 		if (!obj) {
-			DRM_DEBUG("Invalid connector id.\n");
+			dev_dbg(dev->dev, "Invalid connector id.\n");
 			return -EINVAL;
 		}
 
@@ -753,8 +747,6 @@ static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
 
 		return 0;
 	}
-
-	DRM_DEBUG("Bad flags 0x%x\n", flags);
 	return -EINVAL;
 }
 
@@ -832,7 +824,7 @@ static int psb_gamma_ioctl(struct drm_device *dev, void *data,
 	obj_id = lut_arg->output_id;
 	obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
 	if (!obj) {
-		DRM_DEBUG("Invalid Connector object.\n");
+		dev_dbg(dev->dev, "Invalid Connector object.\n");
 		return -EINVAL;
 	}
 
@@ -873,7 +865,7 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
 	case PSB_MODE_OPERATION_SET_DC_BASE:
 		obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB);
 		if (!obj) {
-			DRM_ERROR("Invalid FB id %d\n", obj_id);
+			dev_dbg(dev->dev, "Invalid FB id %d\n", obj_id);
 			return -EINVAL;
 		}
 
@@ -945,7 +937,7 @@ mode_op_out:
 		return ret;
 
 	default:
-		DRM_DEBUG("Unsupported psb mode operation");
+		dev_dbg(dev->dev, "Unsupported psb mode operation\n");
 		return -EOPNOTSUPP;
 	}
 
@@ -1336,9 +1328,6 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
 	struct drm_device *dev = file_priv->minor->dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	static unsigned int runtime_allowed;
-	unsigned int nr = DRM_IOCTL_NR(cmd);
-
-	DRM_DEBUG("cmd = %x, nr = %x\n", cmd, nr);
 
 	if (runtime_allowed == 1 && dev_priv->is_lvds_on) {
 		runtime_allowed++;
@@ -1439,7 +1428,7 @@ 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))
-		DRM_ERROR("Enable MSI failed!\n");
+                dev_warn(&pdev->dev, "Enable MSI failed!\n");
 	return drm_get_pci_dev(pdev, ent, &driver);
 }
 
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index c0468ee..45752aa 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -659,54 +659,12 @@ extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 #define PSB_D_MSVDX   (1 << 9)
 #define PSB_D_TOPAZ   (1 << 10)
 
-#ifndef DRM_DEBUG_CODE
-/* To enable debug printout, set drm_psb_debug in psb_drv.c
- * to any combination of above print flags.
- */
-/* #define DRM_DEBUG_CODE 2 */
-#endif
-
-extern int drm_psb_debug;
 extern int drm_psb_no_fb;
 extern int drm_idle_check_interval;
 
-#define PSB_DEBUG_GENERAL(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_GENERAL, _fmt, ##_arg)
-#define PSB_DEBUG_INIT(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_INIT, _fmt, ##_arg)
-#define PSB_DEBUG_IRQ(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_IRQ, _fmt, ##_arg)
-#define PSB_DEBUG_ENTRY(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_ENTRY, _fmt, ##_arg)
-#define PSB_DEBUG_HV(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_HV, _fmt, ##_arg)
-#define PSB_DEBUG_DBI_BF(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_DBI_BF, _fmt, ##_arg)
-#define PSB_DEBUG_PM(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_PM, _fmt, ##_arg)
-#define PSB_DEBUG_RENDER(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_RENDER, _fmt, ##_arg)
-#define PSB_DEBUG_REG(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_REG, _fmt, ##_arg)
-#define PSB_DEBUG_MSVDX(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_MSVDX, _fmt, ##_arg)
-#define PSB_DEBUG_TOPAZ(_fmt, _arg...) \
-	PSB_DEBUG(PSB_D_TOPAZ, _fmt, ##_arg)
-
-#if DRM_DEBUG_CODE
-#define PSB_DEBUG(_flag, _fmt, _arg...)					\
-	do {								\
-		if (unlikely((_flag) & drm_psb_debug))			\
-			printk(KERN_DEBUG				\
-			       "[psb:0x%02x:%s] " _fmt , _flag,		\
-			       __func__ , ##_arg);			\
-	} while (0)
-#else
-#define PSB_DEBUG(_fmt, _arg...)     do { } while (0)
-#endif
 
 /*
- *Utilities
+ *	Utilities
  */
 
 static inline u32 MRST_MSG_READ32(uint port, uint offset)
@@ -749,19 +707,15 @@ static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
 static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	int reg_val = ioread32(dev_priv->vdc_reg + (reg));
-	PSB_DEBUG_REG("reg = 0x%x. reg_val = 0x%x. \n", reg, reg_val);
-	return reg_val;
+	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;
-	if ((reg < 0x70084 || reg >0x70088) && (reg < 0xa000 || reg >0xa3ff))
-		PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
-
 	iowrite32((val), dev_priv->vdc_reg + (reg));
 }
 
@@ -771,9 +725,6 @@ static inline void REGISTER_WRITE16(struct drm_device *dev,
 					uint32_t reg, uint32_t val)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
-
 	iowrite16((val), dev_priv->vdc_reg + (reg));
 }
 
@@ -783,20 +734,13 @@ static inline void REGISTER_WRITE8(struct drm_device *dev,
 				       uint32_t reg, uint32_t val)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
-
 	iowrite8((val), dev_priv->vdc_reg + (reg));
 }
 
-#define REG_WRITE8(reg, val)	 REGISTER_WRITE8(dev, (reg), (val))
+#define REG_WRITE8(reg, val)		REGISTER_WRITE8(dev, (reg), (val))
 
-#define PSB_ALIGN_TO(_val, _align) \
-  (((_val) + ((_align) - 1)) & ~((_align) - 1))
-#define PSB_WVDC32(_val, _offs) \
-  iowrite32(_val, dev_priv->vdc_reg + (_offs))
-#define PSB_RVDC32(_offs) \
-  ioread32(dev_priv->vdc_reg + (_offs))
+#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
@@ -810,33 +754,13 @@ static inline void REGISTER_WRITE8(struct drm_device *dev,
     ioread32(dev_priv->sgx_reg + (_offs));			\
 })
 #else
-#define PSB_RSGX32(_offs)					\
-  ioread32(dev_priv->sgx_reg + (_offs))
+#define PSB_RSGX32(_offs)		ioread32(dev_priv->sgx_reg + (_offs))
 #endif
-#define PSB_WSGX32(_val, _offs) \
-  iowrite32(_val, dev_priv->sgx_reg + (_offs))
+#define PSB_WSGX32(_val, _offs)		iowrite32(_val, dev_priv->sgx_reg + (_offs))
 
 #define MSVDX_REG_DUMP 0
-#if MSVDX_REG_DUMP
-
-#define PSB_WMSVDX32(_val, _offs) \
-  printk("MSVDX: write %08x to reg 0x%08x\n", (unsigned int)(_val), (unsigned int)(_offs));\
-  iowrite32(_val, dev_priv->msvdx_reg + (_offs))
-#define PSB_RMSVDX32(_offs) \
-  ioread32(dev_priv->msvdx_reg + (_offs))
-
-#else
-
-#define PSB_WMSVDX32(_val, _offs) \
-  iowrite32(_val, dev_priv->msvdx_reg + (_offs))
-#define PSB_RMSVDX32(_offs) \
-  ioread32(dev_priv->msvdx_reg + (_offs))
-
-#endif
 
-#define PSB_ALPL(_val, _base)			\
-  (((_val) >> (_base ## _ALIGNSHIFT)) << (_base ## _SHIFT))
-#define PSB_ALPLM(_val, _base)			\
-  ((((_val) >> (_base ## _ALIGNSHIFT)) << (_base ## _SHIFT)) & (_base ## _MASK))
+#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/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 0a77abf..988f4db 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -100,7 +100,6 @@ static int psbfb_kms_off(struct drm_device *dev, int suspend)
 {
 	struct drm_framebuffer *fb = 0;
 	struct psb_framebuffer *psbfb = to_psb_fb(fb);
-	DRM_DEBUG("psbfb_kms_off_ioctl\n");
 
 	mutex_lock(&dev->mode_config.mutex);
 	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
@@ -134,8 +133,6 @@ static int psbfb_kms_on(struct drm_device *dev, int resume)
 	struct drm_framebuffer *fb = 0;
 	struct psb_framebuffer *psbfb = to_psb_fb(fb);
 
-	DRM_DEBUG("psbfb_kms_on_ioctl\n");
-
 	mutex_lock(&dev->mode_config.mutex);
 	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
 		struct fb_info *info = psbfb->fbdev;
@@ -217,12 +214,10 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 static void psbfb_vm_open(struct vm_area_struct *vma)
 {
-	DRM_DEBUG("vm_open\n");
 }
 
 static void psbfb_vm_close(struct vm_area_struct *vma)
 {
-	DRM_DEBUG("vm_close\n");
 }
 
 static struct vm_operations_struct psbfb_vm_ops = {
@@ -237,7 +232,6 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 	struct psb_framebuffer *psbfb = &fbdev->pfb;
 	char *fb_screen_base = NULL;
 	struct drm_device *dev = psbfb->base.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
 
 	if (vma->vm_pgoff != 0)
 		return -EINVAL;
@@ -249,10 +243,6 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 
 	fb_screen_base = (char *)info->screen_base;
 
-	DRM_DEBUG("vm_pgoff 0x%lx, screen base %p vram_addr %p\n",
-				vma->vm_pgoff, fb_screen_base,
-                                dev_priv->vram_addr);
-
         /* If this is a GEM object then info->screen_base is the virtual
            kernel remapping of the object. FIXME: Review if this is
            suitable for our mmap work */
@@ -523,14 +513,10 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
 	info->pixmap.scan_align = 1;
 
-	DRM_DEBUG("fb depth is %d\n", fb->depth);
-	DRM_DEBUG("   pitch is %d\n", fb->pitch);
-
-	printk(KERN_INFO"allocated %dx%d fb\n",
-				psbfb->base.width, psbfb->base.height);
+	dev_info(dev->dev, "allocated %dx%d fb\n",
+					psbfb->base.width, psbfb->base.height);
 
 	mutex_unlock(&dev->struct_mutex);
-
 	return 0;
 out_unref:
         if (backing->stolen)
@@ -575,13 +561,11 @@ static struct drm_framebuffer *psb_user_framebuffer_create
 static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
 							u16 blue, int regno)
 {
-	DRM_DEBUG("%s\n", __func__);
 }
 
 static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
 					u16 *green, u16 *blue, int regno)
 {
-	DRM_DEBUG("%s\n", __func__);
 }
 
 static int psbfb_probe(struct drm_fb_helper *helper,
@@ -591,8 +575,6 @@ static int psbfb_probe(struct drm_fb_helper *helper,
 	int new_fb = 0;
 	int ret;
 
-	DRM_DEBUG("%s\n", __func__);
-
 	if (!helper->fb) {
 		ret = psbfb_create(psb_fbdev, sizes);
 		if (ret)
@@ -650,7 +632,7 @@ int psb_fbdev_init(struct drm_device *dev)
 
 	fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
 	if (!fbdev) {
-		DRM_ERROR("no memory\n");
+		dev_err(dev->dev, "no memory\n");
 		return -ENOMEM;
 	}
 
@@ -781,8 +763,6 @@ static void psb_setup_outputs(struct drm_device *dev)
 	    (struct drm_psb_private *) dev->dev_private;
 	struct drm_connector *connector;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	drm_mode_create_scaling_mode_property(dev);
 
 	psb_create_backlight_property(dev);
@@ -791,7 +771,7 @@ static void psb_setup_outputs(struct drm_device *dev)
 		if (dev_priv->iLVDS_enable)
 			mrst_lvds_init(dev, &dev_priv->mode_dev);
 		else
-			DRM_ERROR("DSI is not supported\n");
+			dev_err(dev->dev, "DSI is not supported\n");
 	} else {
 		psb_intel_lvds_init(dev, &dev_priv->mode_dev);
 		psb_intel_sdvo_init(dev, SDVOB);
@@ -811,7 +791,6 @@ static void psb_setup_outputs(struct drm_device *dev)
 			clone_mask = (1 << INTEL_OUTPUT_SDVO);
 			break;
 		case INTEL_OUTPUT_LVDS:
-			PSB_DEBUG_ENTRY("LVDS.\n");
 			if (IS_MRST(dev))
 				crtc_mask = (1 << 0);
 			else
@@ -819,17 +798,14 @@ static void psb_setup_outputs(struct drm_device *dev)
 			clone_mask = (1 << INTEL_OUTPUT_LVDS);
 			break;
 		case INTEL_OUTPUT_MIPI:
-			PSB_DEBUG_ENTRY("MIPI.\n");
 			crtc_mask = (1 << 0);
 			clone_mask = (1 << INTEL_OUTPUT_MIPI);
 			break;
 		case INTEL_OUTPUT_MIPI2:
-			PSB_DEBUG_ENTRY("MIPI2.\n");
 			crtc_mask = (1 << 2);
 			clone_mask = (1 << INTEL_OUTPUT_MIPI2);
 			break;
 		case INTEL_OUTPUT_HDMI:
-			PSB_DEBUG_ENTRY("HDMI.\n");
 			crtc_mask = (1 << 1);
 			clone_mask = (1 << INTEL_OUTPUT_HDMI);
 			break;
@@ -849,8 +825,6 @@ void psb_modeset_init(struct drm_device *dev)
 	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
 	int i;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	drm_mode_config_init(dev);
 
 	dev->mode_config.min_width = 0;
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
index 125ea6b..7f6f479 100644
--- a/drivers/staging/gma500/psb_gem.c
+++ b/drivers/staging/gma500/psb_gem.c
@@ -87,7 +87,7 @@ static int psb_gem_create_mmap_offset(struct drm_gem_object *obj)
 	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
 					obj->size / PAGE_SIZE, 0, 0);
 	if (!list->file_offset_node) {
-		DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
+		dev_err(dev->dev, "failed to allocate offset for bo %d\n", obj->name);
 		ret = -ENOSPC;
 		goto free_it;
 	}
@@ -100,7 +100,7 @@ static int psb_gem_create_mmap_offset(struct drm_gem_object *obj)
 	list->hash.key = list->file_offset_node->start;
 	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
 	if (ret) {
-		DRM_ERROR("failed to add to map hash\n");
+		dev_err(dev->dev, "failed to add to map hash\n");
 		goto free_mm;
 	}
 	return 0;
@@ -283,7 +283,7 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	if (r->mmapping == 0) {
 		ret = psb_gtt_pin(r);
 		if (ret < 0) {
-		        DRM_ERROR("gma500: pin failed: %d\n", ret);
+		        dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
 		        goto fail;
                 }
 		r->mmapping = 1;
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index 8fcb833..54a9308 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -456,7 +456,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 
 	if (resume && (gtt_pages != pg->gtt_pages) &&
 	    (stolen_size != pg->stolen_size)) {
-		DRM_ERROR("GTT resume error.\n");
+		dev_err(dev->dev, "GTT resume error.\n");
 		ret = -EINVAL;
 		goto out_err;
 	}
@@ -470,14 +470,14 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	 */
 	dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT);
 	if (!dev_priv->gtt_map) {
-		DRM_ERROR("Failure to map gtt.\n");
+		dev_err(dev->dev, "Failure to map gtt.\n");
 		ret = -ENOMEM;
 		goto out_err;
 	}
 
 	dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
 	if (!dev_priv->vram_addr) {
-		DRM_ERROR("Failure to map stolen base.\n");
+		dev_err(dev->dev, "Failure to map stolen base.\n");
 		ret = -ENOMEM;
 		goto out_err;
 	}
diff --git a/drivers/staging/gma500/psb_intel_bios.c b/drivers/staging/gma500/psb_intel_bios.c
index 417965d..5b3e88c 100644
--- a/drivers/staging/gma500/psb_intel_bios.c
+++ b/drivers/staging/gma500/psb_intel_bios.c
@@ -96,25 +96,20 @@ static void parse_backlight_data(struct drm_psb_private *dev_priv,
 
 	dev_priv->lvds_bl = NULL;
 
-	if (lvds_opts) {
-		DRM_DEBUG("lvds_options found at %p\n", lvds_opts);
+	if (lvds_opts)
 		p_type = lvds_opts->panel_type;
-	} else {
-		DRM_DEBUG("no lvds_options\n");
+	else
 		return;
-	}
 
 	bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT);
 	vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type;
 
 	lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL);
 	if (!lvds_bl) {
-		DRM_DEBUG("No memory\n");
+		dev_err(dev_priv->dev->dev, "out of memory for backlight data\n");
 		return;
 	}
-
 	memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl));
-
 	dev_priv->lvds_bl = lvds_bl;
 }
 
@@ -156,14 +151,12 @@ static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
 
 	if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) {
 		dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
-		DRM_DEBUG("Found panel mode in BIOS VBT tables:\n");
 		drm_mode_debug_printmodeline(panel_fixed_mode);
 	} else {
-		DRM_DEBUG("Ignoring bogus LVDS VBT mode.\n");
+		dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n");
 		dev_priv->lvds_vbt = 0;
 		kfree(panel_fixed_mode);
 	}
-
 	return;
 }
 
@@ -257,7 +250,7 @@ bool psb_intel_init_bios(struct drm_device *dev)
 	}
 
 	if (!vbt) {
-		DRM_ERROR("VBT signature missing\n");
+		dev_err(dev->dev, "VBT signature missing\n");
 		pci_unmap_rom(pdev, bios);
 		return -1;
 	}
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 540304c..6039a31 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -350,14 +350,12 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 	u32 dspcntr;
 	int ret = 0;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (!gma_power_begin(dev, true))
 		return 0;
 
 	/* no fb bound */
 	if (!crtc->fb) {
-		DRM_DEBUG("No FB bound\n");
+		dev_dbg(dev->dev, "No FB bound\n");
 		goto psb_intel_pipe_cleaner;
 	}
 
@@ -390,7 +388,7 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 		break;
 	default:
-		DRM_ERROR("Unknown color depth\n");
+                dev_err(dev->dev, "Unknown color depth\n");
 		ret = -EINVAL;
 		psb_gtt_unpin(psbfb->gtt);
 		goto psb_intel_pipe_set_base_exit;
@@ -398,7 +396,6 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 	REG_WRITE(dspcntr_reg, dspcntr);
 
 
-	DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
 	if (0 /* FIXMEAC - check what PSB needs */) {
 		REG_WRITE(dspbase, offset);
 		REG_READ(dspbase);
@@ -650,7 +647,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 	ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
 				 &clock);
 	if (!ok) {
-		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
 		return 0;
 	}
 
@@ -714,7 +711,6 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 	if (psb_intel_panel_fitter_pipe(dev) == pipe)
 		REG_WRITE(PFIT_CONTROL, 0);
 
-	DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 	drm_mode_debug_printmodeline(mode);
 
 	if (dpll & DPLL_VCO_ENABLE) {
@@ -825,7 +821,7 @@ void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
 		palreg = PALETTE_C;
 		break;
 	default:
-		DRM_ERROR("Illegal Pipe Number.\n");
+		dev_err(dev->dev, "Illegal Pipe Number.\n");
 		return;
 	}
 
@@ -868,10 +864,8 @@ static void psb_intel_crtc_save(struct drm_crtc *crtc)
 	uint32_t paletteReg;
 	int i;
 
-	DRM_DEBUG("\n");
-
 	if (!crtc_state) {
-		DRM_DEBUG("No CRTC state found\n");
+		dev_err(dev->dev, "No CRTC state found\n");
 		return;
 	}
 
@@ -895,25 +889,6 @@ static void psb_intel_crtc_save(struct drm_crtc *crtc)
 
 	crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
 
-	DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
-			crtc_state->saveDSPCNTR,
-			crtc_state->savePIPECONF,
-			crtc_state->savePIPESRC,
-			crtc_state->saveFP0,
-			crtc_state->saveFP1,
-			crtc_state->saveDPLL,
-			crtc_state->saveHTOTAL,
-			crtc_state->saveHBLANK,
-			crtc_state->saveHSYNC,
-			crtc_state->saveVTOTAL,
-			crtc_state->saveVBLANK,
-			crtc_state->saveVSYNC,
-			crtc_state->saveDSPSTRIDE,
-			crtc_state->saveDSPSIZE,
-			crtc_state->saveDSPPOS,
-			crtc_state->saveDSPBASE
-		);
-
 	paletteReg = pipeA ? PALETTE_A : PALETTE_B;
 	for (i = 0; i < 256; ++i)
 		crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
@@ -934,60 +909,15 @@ static void psb_intel_crtc_restore(struct drm_crtc *crtc)
 	uint32_t paletteReg;
 	int i;
 
-	DRM_DEBUG("\n");
-
 	if (!crtc_state) {
-		DRM_DEBUG("No crtc state\n");
+		dev_err(dev->dev, "No crtc state\n");
 		return;
 	}
 
-	DRM_DEBUG(
-		"current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
-		REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
-		REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
-		REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
-		REG_READ(pipeA ? FPA0 : FPB0),
-		REG_READ(pipeA ? FPA1 : FPB1),
-		REG_READ(pipeA ? DPLL_A : DPLL_B),
-		REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
-		REG_READ(pipeA ? HBLANK_A : HBLANK_B),
-		REG_READ(pipeA ? HSYNC_A : HSYNC_B),
-		REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
-		REG_READ(pipeA ? VBLANK_A : VBLANK_B),
-		REG_READ(pipeA ? VSYNC_A : VSYNC_B),
-		REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
-		REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
-		REG_READ(pipeA ? DSPAPOS : DSPBPOS),
-		REG_READ(pipeA ? DSPABASE : DSPBBASE)
-		);
-
-	DRM_DEBUG(
-		"saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
-		crtc_state->saveDSPCNTR,
-		crtc_state->savePIPECONF,
-		crtc_state->savePIPESRC,
-		crtc_state->saveFP0,
-		crtc_state->saveFP1,
-		crtc_state->saveDPLL,
-		crtc_state->saveHTOTAL,
-		crtc_state->saveHBLANK,
-		crtc_state->saveHSYNC,
-		crtc_state->saveVTOTAL,
-		crtc_state->saveVBLANK,
-		crtc_state->saveVSYNC,
-		crtc_state->saveDSPSTRIDE,
-		crtc_state->saveDSPSIZE,
-		crtc_state->saveDSPPOS,
-		crtc_state->saveDSPBASE
-		);
-
-
 	if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
 		REG_WRITE(pipeA ? DPLL_A : DPLL_B,
 			crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
 		REG_READ(pipeA ? DPLL_A : DPLL_B);
-		DRM_DEBUG("write dpll: %x\n",
-				REG_READ(pipeA ? DPLL_A : DPLL_B));
 		udelay(150);
 	}
 
@@ -1044,11 +974,8 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 	struct drm_gem_object *obj;
 	int ret;
 
-	DRM_DEBUG("\n");
-
 	/* if we want to turn of the cursor ignore width and height */
 	if (!handle) {
-		DRM_DEBUG("cursor off\n");
 		/* turn off the cursor */
 		temp = CURSOR_MODE_DISABLE;
 
@@ -1072,7 +999,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 
 	/* Currently we only support 64x64 cursors */
 	if (width != 64 || height != 64) {
-		DRM_ERROR("we currently only support 64x64 cursors\n");
+		dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
 		return -EINVAL;
 	}
 
@@ -1081,7 +1008,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 		return -ENOENT;
 
 	if (obj->size < width * height * 4) {
-		DRM_ERROR("buffer is to small\n");
+		dev_dbg(dev->dev, "buffer is to small\n");
 		return -ENOMEM;
 	}
 
@@ -1090,7 +1017,7 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 	/* Pin the memory into the GTT */
 	ret = psb_gtt_pin(gt);
 	if (ret) {
-		DRM_ERROR("Can not pin down handle 0x%x\n", handle);
+		dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
 		return ret;
 	}
 
@@ -1359,8 +1286,6 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 	int i;
 	uint16_t *r_base, *g_base, *b_base;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	/* We allocate a extra array of drm_connector pointers
 	 * for fbdev after the crtc */
 	psb_intel_crtc =
@@ -1373,7 +1298,7 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 	psb_intel_crtc->crtc_state =
 		kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL);
 	if (!psb_intel_crtc->crtc_state) {
-		DRM_INFO("Crtc state error: No memory\n");
+		dev_err(dev->dev, "Crtc state error: No memory\n");
 		kfree(psb_intel_crtc);
 		return;
 	}
@@ -1430,7 +1355,7 @@ int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
 	struct psb_intel_crtc *crtc;
 
 	if (!dev_priv) {
-		DRM_ERROR("called with no initialization\n");
+		dev_err(dev->dev, "called with no initialization\n");
 		return -EINVAL;
 	}
 
@@ -1438,7 +1363,7 @@ int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
 			DRM_MODE_OBJECT_CRTC);
 
 	if (!drmmode_obj) {
-		DRM_ERROR("no such CRTC id\n");
+		dev_err(dev->dev, "no such CRTC id\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index b0a225b..1cbc9bc 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -126,13 +126,13 @@ static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
 	out_buf[1] = (u8)blc_i2c_brightness;
 
 	if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) {
-		DRM_DEBUG("I2C set brightness.(command, value) (%d, %d)\n",
+		dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n",
 			dev_priv->lvds_bl->brightnesscmd,
 			blc_i2c_brightness);
 		return 0;
 	}
 
-	DRM_ERROR("I2C transfer error\n");
+	dev_err(dev->dev, "I2C transfer error\n");
 	return -1;
 }
 
@@ -172,10 +172,10 @@ void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
 	struct drm_psb_private *dev_priv =
 			(struct drm_psb_private *)dev->dev_private;
 
-	DRM_DEBUG("backlight level is %d\n", level);
+	dev_dbg(dev->dev, "backlight level is %d\n", level);
 
 	if (!dev_priv->lvds_bl) {
-		DRM_ERROR("NO LVDS Backlight Info\n");
+		dev_err(dev->dev, "NO LVDS Backlight Info\n");
 		return;
 	}
 
@@ -289,7 +289,7 @@ static void psb_intel_lvds_save(struct drm_connector *connector)
 		dev_priv->backlight_duty_cycle =
 		psb_intel_lvds_get_max_backlight(dev);
 
-	DRM_DEBUG("(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+	dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
 			lvds_priv->savePP_ON,
 			lvds_priv->savePP_OFF,
 			lvds_priv->saveLVDS,
@@ -310,7 +310,7 @@ static void psb_intel_lvds_restore(struct drm_connector *connector)
 	struct psb_intel_lvds_priv *lvds_priv =
 		(struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
 
-	DRM_DEBUG("(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+	dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
 			lvds_priv->savePP_ON,
 			lvds_priv->savePP_OFF,
 			lvds_priv->saveLVDS,
@@ -351,8 +351,6 @@ int psb_intel_lvds_mode_valid(struct drm_connector *connector,
 	struct drm_display_mode *fixed_mode =
 	    psb_intel_output->mode_dev->panel_fixed_mode;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
 		fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2;
 
@@ -387,9 +385,6 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
 	struct psb_intel_output *psb_intel_output =
 					enc_to_psb_intel_output(encoder);
 
-	PSB_DEBUG_ENTRY("type = 0x%x, pipe = %d.\n",
-			psb_intel_output->type, psb_intel_crtc->pipe);
-
 	if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
 		panel_fixed_mode = mode_dev->panel_fixed_mode2;
 
@@ -448,8 +443,6 @@ void psb_intel_lvds_prepare(struct drm_encoder *encoder)
 	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
 	struct psb_intel_mode_device *mode_dev = output->mode_dev;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (!gma_power_begin(dev, true))
 		return;
 
@@ -468,8 +461,6 @@ void psb_intel_lvds_commit(struct drm_encoder *encoder)
 	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
 	struct psb_intel_mode_device *mode_dev = output->mode_dev;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (mode_dev->backlight_duty_cycle == 0)
 		mode_dev->backlight_duty_cycle =
 		    psb_intel_lvds_get_max_backlight(dev);
@@ -585,15 +576,11 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
 {
 	struct drm_encoder *pEncoder = connector->encoder;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (!strcmp(property->name, "scaling mode") && pEncoder) {
 		struct psb_intel_crtc *pPsbCrtc =
 					to_psb_intel_crtc(pEncoder->crtc);
 		uint64_t curValue;
 
-		PSB_DEBUG_ENTRY("scaling mode\n");
-
 		if (!pPsbCrtc)
 			goto set_prop_error;
 
@@ -631,8 +618,6 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
 				goto set_prop_error;
 		}
 	} else if (!strcmp(property->name, "backlight") && pEncoder) {
-		PSB_DEBUG_ENTRY("backlight\n");
-
 		if (drm_connector_property_set_value(connector,
 							property,
 							value))
@@ -647,7 +632,6 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
 	} else if (!strcmp(property->name, "DPMS") && pEncoder) {
 		struct drm_encoder_helper_funcs *pEncHFuncs
 						= pEncoder->helper_private;
-		PSB_DEBUG_ENTRY("DPMS\n");
 		pEncHFuncs->dpms(pEncoder, value);
 	}
 
@@ -722,7 +706,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
 	lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL);
 	if (!lvds_priv) {
 		kfree(psb_intel_output);
-		DRM_DEBUG("LVDS private allocation error\n");
+		dev_err(dev->dev, "LVDS private allocation error\n");
 		return;
 	}
 
@@ -838,8 +822,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
 
 	/* If we still don't have a mode after all that, give up. */
 	if (!mode_dev->panel_fixed_mode) {
-		DRM_DEBUG
-			("Found no modes on the lvds, ignoring the LVDS\n");
+		dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
 		goto failed_find;
 	}
 
@@ -849,26 +832,6 @@ void psb_intel_lvds_init(struct drm_device *dev,
 	 */
 out:
 	drm_sysfs_connector_add(connector);
-
-	PSB_DEBUG_ENTRY("hdisplay = %d\n",
-		 mode_dev->panel_fixed_mode->hdisplay);
-	PSB_DEBUG_ENTRY(" vdisplay = %d\n",
-		 mode_dev->panel_fixed_mode->vdisplay);
-	PSB_DEBUG_ENTRY(" hsync_start = %d\n",
-		 mode_dev->panel_fixed_mode->hsync_start);
-	PSB_DEBUG_ENTRY(" hsync_end = %d\n",
-		 mode_dev->panel_fixed_mode->hsync_end);
-	PSB_DEBUG_ENTRY(" htotal = %d\n",
-		 mode_dev->panel_fixed_mode->htotal);
-	PSB_DEBUG_ENTRY(" vsync_start = %d\n",
-		 mode_dev->panel_fixed_mode->vsync_start);
-	PSB_DEBUG_ENTRY(" vsync_end = %d\n",
-		 mode_dev->panel_fixed_mode->vsync_end);
-	PSB_DEBUG_ENTRY(" vtotal = %d\n",
-		 mode_dev->panel_fixed_mode->vtotal);
-	PSB_DEBUG_ENTRY(" clock = %d\n",
-		 mode_dev->panel_fixed_mode->clock);
-
 	return;
 
 failed_find:
diff --git a/drivers/staging/gma500/psb_intel_opregion.c b/drivers/staging/gma500/psb_intel_opregion.c
index 65e3e9b..51cf1d6 100644
--- a/drivers/staging/gma500/psb_intel_opregion.c
+++ b/drivers/staging/gma500/psb_intel_opregion.c
@@ -58,11 +58,8 @@ int psb_intel_opregion_init(struct drm_device *dev)
 	dev_priv->lid_state = NULL;
 
 	pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy);
-	if (opregion_phy == 0) {
-		DRM_DEBUG("Opregion not supported, won't support lid-switch\n");
+	if (opregion_phy == 0)
 		return -ENOTSUPP;
-	}
-	DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy);
 
 	base = ioremap(opregion_phy, 8*1024);
 	if (!base)
@@ -70,8 +67,6 @@ int psb_intel_opregion_init(struct drm_device *dev)
 
 	lid_state = base + 0x01ac;
 
-	DRM_DEBUG("Lid switch state 0x%08x\n", *lid_state);
-
 	dev_priv->lid_state = lid_state;
 	dev_priv->lid_last_state = *lid_state;
 	return 0;
diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c
index df1c006..e313ce2 100644
--- a/drivers/staging/gma500/psb_intel_sdvo.c
+++ b/drivers/staging/gma500/psb_intel_sdvo.c
@@ -107,14 +107,10 @@ static bool psb_intel_sdvo_read_byte(
 
 	ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2);
 	if (ret == 2) {
-		/* DRM_DEBUG("got back from addr %02X = %02x\n",
-		 * out_buf[0], buf[0]);
-		 */
 		*ch = buf[0];
 		return true;
 	}
 
-	DRM_DEBUG("i2c transfer returned %d\n", ret);
 	return false;
 }
 
@@ -205,24 +201,24 @@ static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output,
 	int i;
 
 	if (0) {
-		DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
+		printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
 		for (i = 0; i < args_len; i++)
-			printk(KERN_INFO"%02X ", ((u8 *) args)[i]);
+			printk(KERN_CONT "%02X ", ((u8 *) args)[i]);
 		for (; i < 8; i++)
-			printk("   ");
+			printk(KERN_CONT "   ");
 		for (i = 0;
 		     i <
 		     sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]);
 		     i++) {
 			if (cmd == sdvo_cmd_names[i].cmd) {
-				printk("(%s)", sdvo_cmd_names[i].name);
+				printk(KERN_CONT "(%s)", sdvo_cmd_names[i].name);
 				break;
 			}
 		}
 		if (i ==
 		    sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]))
-			printk("(%02X)", cmd);
-		printk("\n");
+			printk(KERN_CONT "(%02X)", cmd);
+		printk(KERN_CONT "\n");
 	}
 
 	for (i = 0; i < args_len; i++) {
@@ -267,17 +263,17 @@ static u8 psb_intel_sdvo_read_response(
 					 &status);
 
 		if (0) {
-			DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv));
+			pr_debug("%s: R: ", SDVO_NAME(sdvo_priv));
 			for (i = 0; i < response_len; i++)
-				printk(KERN_INFO"%02X ", ((u8 *) response)[i]);
+				printk(KERN_CONT "%02X ", ((u8 *) response)[i]);
 			for (; i < 8; i++)
 				printk("   ");
 			if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
-				printk(KERN_INFO"(%s)",
+				printk(KERN_CONT "(%s)",
 					 cmd_status_names[status]);
 			else
-				printk(KERN_INFO"(??? %d)", status);
-			printk("\n");
+				printk(KERN_CONT "(??? %d)", status);
+			printk(KERN_CONT "\n");
 		}
 
 		if (status != SDVO_CMD_STATUS_PENDING)
@@ -997,7 +993,6 @@ int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector)
 	u8 response[2];
 	u8 status;
 	struct psb_intel_output *psb_intel_output;
-	DRM_DEBUG("\n");
 
 	if (!connector)
 		return 0;
@@ -1198,7 +1193,7 @@ void psb_intel_sdvo_init(struct drm_device *dev, int output_device)
 	/* Read the regs to test if we can talk to the device */
 	for (i = 0; i < 0x40; i++) {
 		if (!psb_intel_sdvo_read_byte(psb_intel_output, i, &ch[i])) {
-			DRM_DEBUG("No SDVO device found on SDVO%c\n",
+			dev_dbg(dev->dev, "No SDVO device found on SDVO%c\n",
 				  output_device == SDVOB ? 'B' : 'C');
 			goto err_i2c;
 		}
@@ -1242,8 +1237,7 @@ void psb_intel_sdvo_init(struct drm_device *dev, int output_device)
 		unsigned char bytes[2];
 
 		memcpy(bytes, &sdvo_priv->caps.output_flags, 2);
-		DRM_DEBUG
-		    ("%s: No active RGB or TMDS outputs (0x%02x%02x)\n",
+		dev_dbg(dev->dev, "%s: No active RGB or TMDS outputs (0x%02x%02x)\n",
 		     SDVO_NAME(sdvo_priv), bytes[0], bytes[1]);
 		goto err_i2c;
 	}
@@ -1267,7 +1261,7 @@ void psb_intel_sdvo_init(struct drm_device *dev, int output_device)
 					       pixel_clock_max);
 
 
-	DRM_DEBUG("%s device VID/DID: %02X:%02X.%02X, "
+	dev_dbg(dev->dev, "%s device VID/DID: %02X:%02X.%02X, "
 		  "clock range %dMHz - %dMHz, "
 		  "input 1: %c, input 2: %c, "
 		  "output 1: %c, output 2: %c\n",
diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c
index 9ea37e5..1cbfeb6 100644
--- a/drivers/staging/gma500/psb_irq.c
+++ b/drivers/staging/gma500/psb_irq.c
@@ -187,7 +187,8 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
 	}
 
 	if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)
-		DRM_ERROR("%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x.\n",
+		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)
@@ -219,21 +220,11 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
 
 	vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
 
-	if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) {
-		PSB_DEBUG_IRQ("Got DISP interrupt\n");
+	if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG)
 		dsp_int = 1;
-	}
 
-	if (vdc_stat & _PSB_IRQ_SGX_FLAG) {
-		PSB_DEBUG_IRQ("Got SGX interrupt\n");
+	if (vdc_stat & _PSB_IRQ_SGX_FLAG)
 		sgx_int = 1;
-	}
-	if (vdc_stat & _PSB_IRQ_MSVDX_FLAG)
-		PSB_DEBUG_IRQ("Got MSVDX interrupt\n");
-
-	if (vdc_stat & _LNC_IRQ_TOPAZ_FLAG)
-		PSB_DEBUG_IRQ("Got TOPAZ interrupt\n");
-
 
 	vdc_stat &= dev_priv->vdc_irq_mask;
 	spin_unlock(&dev_priv->irqmask_lock);
@@ -293,8 +284,6 @@ int psb_irq_postinstall(struct drm_device *dev)
 	    (struct drm_psb_private *) dev->dev_private;
 	unsigned long irqflags;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	/* This register is safe even if display island is off */
@@ -326,8 +315,6 @@ void psb_irq_uninstall(struct drm_device *dev)
 	    (struct drm_psb_private *) dev->dev_private;
 	unsigned long irqflags;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
@@ -395,8 +382,6 @@ int psb_irq_enable_dpst(struct drm_device *dev)
 		(struct drm_psb_private *) dev->dev_private;
 	unsigned long irqflags;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	/* enable DPST */
@@ -435,8 +420,6 @@ int psb_irq_disable_dpst(struct drm_device *dev)
 	    (struct drm_psb_private *) dev->dev_private;
 	unsigned long irqflags;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	mid_disable_pipe_event(dev_priv, 0);
@@ -472,8 +455,6 @@ int psb_enable_vblank(struct drm_device *dev, int pipe)
 	uint32_t reg_val = 0;
 	uint32_t pipeconf_reg = mid_pipeconf(pipe);
 
-	PSB_DEBUG_ENTRY("\n");
-
 	if (gma_power_begin(dev, false)) {
 		reg_val = REG_READ(pipeconf_reg);
 		gma_power_end(dev);
@@ -500,8 +481,6 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	unsigned long irqflags;
 
-	PSB_DEBUG_ENTRY("\n");
-
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	mid_disable_pipe_event(dev_priv, pipe);
@@ -535,7 +514,7 @@ u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
 		pipeconf_reg = PIPECCONF;
 		break;
 	default:
-		DRM_ERROR("%s, invalded pipe.\n", __func__);
+		dev_err(dev->dev, "%s, invalid pipe.\n", __func__);
 		return 0;
 	}
 
@@ -545,7 +524,7 @@ u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
 	reg_val = REG_READ(pipeconf_reg);
 
 	if (!(reg_val & PIPEACONF_ENABLE)) {
-		DRM_ERROR("trying to get vblank count for disabled pipe %d\n",
+		dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n",
 								pipe);
 		goto psb_get_vblank_counter_exit;
 	}


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 09/49] gma500: Kill spare kref
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (7 preceding siblings ...)
  2011-07-05 14:35 ` [PATCH 08/49] gma500: nuke the PSB debug stuff Alan Cox
@ 2011-07-05 14:35 ` Alan Cox
  2011-07-05 14:35 ` [PATCH 10/49] gma500: GEM glue Alan Cox
                   ` (40 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:35 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We are using the underlying kref in the GEM object so we don't need our own

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_fb.c  |    1 -
 drivers/staging/gma500/psb_gtt.c |   41 ++++++--------------------------------
 drivers/staging/gma500/psb_gtt.h |    1 -
 3 files changed, 6 insertions(+), 37 deletions(-)

diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 988f4db..fb75aba 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -231,7 +231,6 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 	struct psb_fbdev *fbdev = info->par;
 	struct psb_framebuffer *psbfb = &fbdev->pfb;
 	char *fb_screen_base = NULL;
-	struct drm_device *dev = psbfb->base.dev;
 
 	if (vma->vm_pgoff != 0)
 		return -EINVAL;
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index 54a9308..9da1375 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -303,8 +303,6 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
 	gt->in_gart = backed;
 	/* Ensure this is set for non GEM objects */
 	gt->gem.dev = dev;
-	kref_init(&gt->kref);
-
 	ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
 				len, start, end, PAGE_SIZE, NULL, NULL);
 	if (ret == 0) {
@@ -316,18 +314,15 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
 }
 
 /**
- *	psb_gtt_destroy		-	final free up of a gtt
- *	@kref: the kref of the gtt
- *
- *	Called from the kernel kref put when the final reference to our
- *	GTT object is dropped. At that point we can free up the resources.
+ *	psb_gtt_free_range	-	release GTT address space
+ *	@dev: our DRM device
+ *	@gt: a mapping created with psb_gtt_alloc_range
  *
- *	For now we handle mmap clean up here to work around limits in GEM
+ *	Release a resource that was allocated with psb_gtt_alloc_range. If the object
+ *	has been pinned by mmap users we clean this up here currently.
  */
-static void psb_gtt_destroy(struct kref *kref)
+void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
 {
-	struct gtt_range *gt = container_of(kref, struct gtt_range, kref);
-
 	/* Undo the mmap pin if we are destroying the object */
 	if (gt->mmapping) {
 		psb_gtt_unpin(gt);
@@ -338,30 +333,6 @@ static void psb_gtt_destroy(struct kref *kref)
 	kfree(gt);
 }
 
-/**
- *	psb_gtt_kref_put	-	drop reference to a GTT object
- *	@gt: the GT being dropped
- *
- *	Drop a reference to a psb gtt
- */
-void psb_gtt_kref_put(struct gtt_range *gt)
-{
-	kref_put(&gt->kref, psb_gtt_destroy);
-}
-
-/**
- *	psb_gtt_free_range	-	release GTT address space
- *	@dev: our DRM device
- *	@gt: a mapping created with psb_gtt_alloc_range
- *
- *	Release a resource that was allocated with psb_gtt_alloc_range
- */
-void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
-{
-	psb_gtt_kref_put(gt);
-}
-
-
 struct psb_gtt *psb_gtt_alloc(struct drm_device *dev)
 {
 	struct psb_gtt *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h
index 7e1f21e..4d6dc5f 100644
--- a/drivers/staging/gma500/psb_gtt.h
+++ b/drivers/staging/gma500/psb_gtt.h
@@ -44,7 +44,6 @@ extern void psb_gtt_takedown(struct drm_device *dev);
 struct gtt_range {
 	struct resource resource;	/* Resource for our allocation */
 	u32 offset;			/* GTT offset of our object */
-	struct kref kref;		/* Can probably go FIXME - GEM kref will do */
 	struct drm_gem_object gem;	/* GEM high level stuff */
 	int in_gart;			/* Currently in the GART (ref ct) */
 	bool stolen;			/* Backed from stolen RAM */


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 10/49] gma500: GEM glue
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (8 preceding siblings ...)
  2011-07-05 14:35 ` [PATCH 09/49] gma500: Kill spare kref Alan Cox
@ 2011-07-05 14:35 ` Alan Cox
  2011-07-05 14:36 ` [PATCH 11/49] gma500: Use the GEM tweaks to provide a GEM frame buffer Alan Cox
                   ` (39 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:35 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Add this temporarily so we can keep making progress and also bundle all the
GEM bits we need together in our staging driver while we get them into GEM
itself.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile   |    3 ++
 drivers/staging/gma500/gem_glue.c |   47 +++++++++++++++++++++++++++++++++++++
 drivers/staging/gma500/gem_glue.h |    4 +++
 3 files changed, 53 insertions(+), 1 deletions(-)
 create mode 100644 drivers/staging/gma500/gem_glue.c
 create mode 100644 drivers/staging/gma500/gem_glue.h

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index db73ec6..01aaa28 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -3,7 +3,8 @@
 #
 ccflags-y += -Iinclude/drm
 
-psb_gfx-y += psb_bl.o \
+psb_gfx-y += gem_glue.o \
+	  psb_bl.o \
 	  psb_drv.o \
 	  psb_gem.o \
 	  psb_fb.o \
diff --git a/drivers/staging/gma500/gem_glue.c b/drivers/staging/gma500/gem_glue.c
new file mode 100644
index 0000000..0817497
--- /dev/null
+++ b/drivers/staging/gma500/gem_glue.c
@@ -0,0 +1,47 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+
+/**
+ * Initialize an already allocated GEM object of the specified size with
+ * no GEM provided backing store. Instead the caller is responsible for
+ * backing the object and handling it.
+ */
+int drm_gem_private_object_init(struct drm_device *dev,
+			struct drm_gem_object *obj, size_t size)
+{
+	BUG_ON((size & (PAGE_SIZE - 1)) != 0);
+
+	obj->dev = dev;
+	obj->filp = NULL;
+
+	kref_init(&obj->refcount);
+	atomic_set(&obj->handle_count, 0);
+	obj->size = size;
+
+	return 0;
+}
+
+void drm_gem_object_release_wrap(struct drm_gem_object *obj)
+{
+	if (obj->filp)
+		drm_gem_object_release(obj);
+}
diff --git a/drivers/staging/gma500/gem_glue.h b/drivers/staging/gma500/gem_glue.h
new file mode 100644
index 0000000..c38285b
--- /dev/null
+++ b/drivers/staging/gma500/gem_glue.h
@@ -0,0 +1,4 @@
+extern void drm_gem_object_release_wrap(struct drm_gem_object *obj);
+extern int drm_gem_private_object_init(struct drm_device *dev,
+			struct drm_gem_object *obj, size_t size);
+


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 11/49] gma500: Use the GEM tweaks to provide a GEM frame buffer
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (9 preceding siblings ...)
  2011-07-05 14:35 ` [PATCH 10/49] gma500: GEM glue Alan Cox
@ 2011-07-05 14:36 ` Alan Cox
  2011-07-05 14:36 ` [PATCH 12/49] gma500: CodingStyle pass Alan Cox
                   ` (38 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:36 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We can now make our system frame buffer a GEM object.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_fb.c  |   11 +++++++----
 drivers/staging/gma500/psb_gem.c |   11 ++++++++---
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index fb75aba..400dbee 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -186,6 +186,8 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	struct psb_framebuffer *psbfb = vma->vm_private_data;
 	struct drm_device *dev = psbfb->base.dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/* FIXME: assumes fb at stolen base which may not be true */
 	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
 
 	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
@@ -381,8 +383,11 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
 	struct gtt_range *backing;
 	/* Begin by trying to use stolen memory backing */
 	backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
-	if (backing)
-		return backing;
+	if (backing) {
+	        if (drm_gem_private_object_init(dev, &backing->gem, aligned_size) == 0)
+        		return backing;
+                psb_gtt_free_range(dev, backing);
+        }
 	/* Next try using GEM host memory */
 	backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
 	if (backing == NULL)
@@ -683,8 +688,6 @@ static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
 {
         struct psb_framebuffer *psbfb = to_psb_fb(fb);
         struct gtt_range *r = psbfb->gtt;
-        if (r->stolen)
-                return -EOPNOTSUPP;
         return drm_gem_handle_create(file_priv, &r->gem, handle);
 }
 
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
index 7f6f479..4aec38c 100644
--- a/drivers/staging/gma500/psb_gem.c
+++ b/drivers/staging/gma500/psb_gem.c
@@ -49,7 +49,7 @@ void psb_gem_free_object(struct drm_gem_object *obj)
 		kfree(list->map);
 		list->map = NULL;
 	}
-	drm_gem_object_release(obj);
+	drm_gem_object_release_wrap(obj);
 	/* This must occur last as it frees up the memory of the GEM object */
 	psb_gtt_free_range(obj->dev, gtt);
 }
@@ -268,9 +268,11 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	unsigned long pfn;
 	pgoff_t page_offset;
 	struct drm_device *dev;
+	struct drm_psb_private *dev_priv;
 
 	obj = vma->vm_private_data;	/* GEM object */
 	dev = obj->dev;
+	dev_priv = dev->dev_private;
 
 	r = container_of(obj, struct gtt_range, gem);	/* Get the gtt range */
 
@@ -294,8 +296,11 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
 				>> PAGE_SHIFT;
 
-        /* CPU view of the page, don't go via the GART for CPU writes */
-	pfn = page_to_phys(r->pages[page_offset]) >> PAGE_SHIFT;
+	/* CPU view of the page, don't go via the GART for CPU writes */
+	if (r->stolen)
+		pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT;
+	else
+		pfn = page_to_pfn(r->pages[page_offset]);
 	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
 
 fail:


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 12/49] gma500: CodingStyle pass
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (10 preceding siblings ...)
  2011-07-05 14:36 ` [PATCH 11/49] gma500: Use the GEM tweaks to provide a GEM frame buffer Alan Cox
@ 2011-07-05 14:36 ` Alan Cox
  2011-07-05 14:36 ` [PATCH 13/49] gma500: 2D polish Alan Cox
                   ` (37 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:36 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Start the style cleanup

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/mrst.h                |   38 -
 drivers/staging/gma500/mrst_lvds.c           |    8 
 drivers/staging/gma500/psb_2d.c              |   23 -
 drivers/staging/gma500/psb_drm.h             |    8 
 drivers/staging/gma500/psb_drv.c             |   25 -
 drivers/staging/gma500/psb_drv.h             |   63 +-
 drivers/staging/gma500/psb_fb.c              |  145 ++--
 drivers/staging/gma500/psb_gem.c             |   19 
 drivers/staging/gma500/psb_gtt.c             |   35 -
 drivers/staging/gma500/psb_intel_display.c   |   12 
 drivers/staging/gma500/psb_intel_opregion.c  |    8 
 drivers/staging/gma500/psb_intel_reg.h       | 1055 +++++++++++++-------------
 drivers/staging/gma500/psb_intel_sdvo.c      |    3 
 drivers/staging/gma500/psb_intel_sdvo_regs.h |   14 
 drivers/staging/gma500/psb_reg.h             |  840 ++++++++++-----------
 15 files changed, 1156 insertions(+), 1140 deletions(-)

diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h
index 5e4aaeb..7bacb9a 100644
--- a/drivers/staging/gma500/mrst.h
+++ b/drivers/staging/gma500/mrst.h
@@ -25,7 +25,7 @@ struct mrst_vbt {
 	u8 size;
 	u8 checksum;
 	void *mrst_gct;
-} __attribute__ ((packed));
+} __packed;
 
 struct mrst_timing_info {
 	u16 pixel_clock;
@@ -58,7 +58,7 @@ struct mrst_timing_info {
 	u8 stereo:1;
 	u8 unknown6:1;
 	u8 interlaced:1;
-} __attribute__((packed));
+} __packed;
 
 struct gct_r10_timing_info {
 	u16 pixel_clock;
@@ -82,7 +82,7 @@ struct gct_r10_timing_info {
 	u16 vsync_pulse_width_hi:2;
 	u16 vsync_positive:1;
 	u16 rsvd_2:3;
-} __attribute__((packed));
+} __packed;
 
 struct mrst_panel_descriptor_v1 {
 	u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
@@ -111,7 +111,7 @@ struct mrst_panel_descriptor_v1 {
 			/* Bit 6, Reserved, 2 bits, 00b */
 			/* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
 			/* Bit 14, Reserved, 2 bits, 00b */
-} __attribute__ ((packed));
+} __packed;
 
 struct mrst_panel_descriptor_v2 {
 	u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */
@@ -141,10 +141,10 @@ struct mrst_panel_descriptor_v2 {
 			/* Bit 6, Reserved, 2 bits, 00b */
 			/* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */
 			/* Bit 14, Reserved, 2 bits, 00b */
-} __attribute__ ((packed));
+} __packed;
 
 union mrst_panel_rx {
-	struct{
+	struct {
 		u16 NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/
 			/* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */
 		u16 MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */
@@ -159,10 +159,10 @@ union mrst_panel_rx {
 		u16 Rsvd:5;/*5 bits,00000b */
 	} panelrx;
 	u16 panel_receiver;
-} __attribute__ ((packed));
+} __packed;
 
 struct mrst_gct_v1 {
-	union{ /*8 bits,Defined as follows: */
+	union { /*8 bits,Defined as follows: */
 		struct {
 			u8 PanelType:4; /*4 bits, Bit field for panels*/
 					/* 0 - 3: 0 = LVDS, 1 = MIPI*/
@@ -176,10 +176,10 @@ struct mrst_gct_v1 {
 	};
 	struct mrst_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/
 	union mrst_panel_rx panelrx[4]; /* panel receivers*/
-} __attribute__ ((packed));
+} __packed;
 
 struct mrst_gct_v2 {
-	union{ /*8 bits,Defined as follows: */
+	union { /*8 bits,Defined as follows: */
 		struct {
 			u8 PanelType:4; /*4 bits, Bit field for panels*/
 					/* 0 - 3: 0 = LVDS, 1 = MIPI*/
@@ -193,7 +193,7 @@ struct mrst_gct_v2 {
 	};
 	struct mrst_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/
 	union mrst_panel_rx panelrx[4]; /* panel receivers*/
-} __attribute__ ((packed));
+} __packed;
 
 struct mrst_gct_data {
 	u8 bpi; /* boot panel index, number of panel used during boot */
@@ -205,13 +205,13 @@ struct mrst_gct_data {
 	u32 PP_Cycle_Delay;
 	u16 Panel_Backlight_Inverter_Descriptor;
 	u16 Panel_MIPI_Display_Descriptor;
-} __attribute__ ((packed));
+} __packed;
 
-#define MODE_SETTING_IN_CRTC 	0x1
-#define MODE_SETTING_IN_ENCODER 0x2
-#define MODE_SETTING_ON_GOING 	0x3
-#define MODE_SETTING_IN_DSR 	0x4
-#define MODE_SETTING_ENCODER_DONE 0x8
-#define GCT_R10_HEADER_SIZE	16
-#define GCT_R10_DISPLAY_DESC_SIZE	28
+#define MODE_SETTING_IN_CRTC		0x1
+#define MODE_SETTING_IN_ENCODER		0x2
+#define MODE_SETTING_ON_GOING		0x3
+#define MODE_SETTING_IN_DSR		0x4
+#define MODE_SETTING_ENCODER_DONE	0x8
 
+#define GCT_R10_HEADER_SIZE		16
+#define GCT_R10_DISPLAY_DESC_SIZE	28
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
index aac80cc..a746571 100644
--- a/drivers/staging/gma500/mrst_lvds.c
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -298,10 +298,10 @@ void mrst_lvds_init(struct drm_device *dev,
 	 /* This ifdef can go once the cpu ident stuff is cleaned up in arch */
 #if defined(CONFIG_X86_MRST)
 	if (mrst_identify_cpu())
-        	i2c_adap = i2c_get_adapter(2);
-        else	/* Oaktrail uses I2C 1 */
-#endif        
-        	i2c_adap = i2c_get_adapter(1);
+		i2c_adap = i2c_get_adapter(2);
+	else	/* Oaktrail uses I2C 1 */
+#endif
+		i2c_adap = i2c_get_adapter(1);
 
 	if (i2c_adap == NULL)
 		printk(KERN_ALERT "No ddc adapter available!\n");
diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c
index 494bad5..dea4bc1 100644
--- a/drivers/staging/gma500/psb_2d.c
+++ b/drivers/staging/gma500/psb_2d.c
@@ -43,11 +43,11 @@
 
 void psb_spank(struct drm_psb_private *dev_priv)
 {
-        PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
+	PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
 		_PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET |
 		_PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET |
 		_PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET);
-	(void) PSB_RSGX32(PSB_CR_SOFT_RESET);
+	PSB_RSGX32(PSB_CR_SOFT_RESET);
 
 	msleep(1);
 
@@ -71,7 +71,7 @@ static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
 	uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
 	unsigned long t = jiffies + HZ;
 
-	while(avail < size) {
+	while (avail < size) {
 		avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
 		if (time_after(jiffies, t)) {
 			psb_spank(dev_priv);
@@ -85,7 +85,7 @@ static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
    it with console use */
 
 int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
-	 	  	   unsigned size)
+								unsigned size)
 {
 	int ret = 0;
 	int i;
@@ -99,9 +99,10 @@ int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
 			return ret;
 
 		submit_size <<= 2;
-		for (i = 0; i < submit_size; i += 4) {
+
+		for (i = 0; i < submit_size; i += 4)
 			PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
-		}
+
 		(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
 	}
 	return 0;
@@ -209,10 +210,10 @@ static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
 {
 	if (xdir < 0)
 		return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
-                			PSB_2D_COPYORDER_TR2BL;
+						PSB_2D_COPYORDER_TR2BL;
 	else
 		return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
-                			PSB_2D_COPYORDER_TL2BR;
+						PSB_2D_COPYORDER_TL2BR;
 }
 
 /*
@@ -350,9 +351,9 @@ void psbfb_copyarea(struct fb_info *info,
 	if (unlikely(info->state != FBINFO_STATE_RUNNING))
 		return;
 
-        /* Avoid the 8 pixel erratum */
+	/* Avoid the 8 pixel erratum */
 	if (region->width == 8 || region->height == 8 ||
-	        (info->flags & FBINFO_HWACCEL_DISABLED))
+		(info->flags & FBINFO_HWACCEL_DISABLED))
 		return cfb_copyarea(info, region);
 
 	psbfb_copyarea_accel(info, region);
@@ -360,7 +361,7 @@ void psbfb_copyarea(struct fb_info *info,
 
 void psbfb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
-        /* For now */
+	/* For now */
 	cfb_imageblit(info, image);
 }
 
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
index b005293..8c259b8 100644
--- a/drivers/staging/gma500/psb_drm.h
+++ b/drivers/staging/gma500/psb_drm.h
@@ -118,10 +118,10 @@ struct drm_psb_register_rw_arg {
 		u32 OGAMC3;
 		u32 OGAMC4;
 		u32 OGAMC5;
-        	u32 IEP_ENABLED;
-        	u32 IEP_BLE_MINMAX;
-        	u32 IEP_BSSCC_CONTROL;
-                u32 b_wait_vblank;
+		u32 IEP_ENABLED;
+		u32 IEP_BLE_MINMAX;
+		u32 IEP_BSSCC_CONTROL;
+		u32 b_wait_vblank;
 	} overlay;
 
 	u32 sprite_enable_mask;
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 6ea06dd..3c2363a 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -47,7 +47,7 @@ module_param_named(no_fb, drm_psb_no_fb, int, 0600);
 module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
 
 
-static struct pci_device_id pciidlist[] = {
+static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
 	{ 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8108 },
 	{ 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8109 },
 	{ 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
@@ -185,8 +185,7 @@ void mrst_get_fuse_settings(struct drm_device *dev)
 	 if (dev_priv->iLVDS_enable) {
 		dev_priv->is_lvds_on = true;
 		dev_priv->is_mipi_on = false;
-	}
-	else {
+	} else {
 		dev_priv->is_mipi_on = true;
 		dev_priv->is_lvds_on = false;
 	}
@@ -196,7 +195,7 @@ void mrst_get_fuse_settings(struct drm_device *dev)
 	pci_write_config_dword(pci_root, 0xD0, FB_REG09);
 	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
 
-	DRM_INFO("SKU values is 0x%x. \n", fuse_value);
+	DRM_INFO("SKU values is 0x%x.\n", fuse_value);
 	fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
 
 	dev_priv->fuse_reg_value = fuse_value;
@@ -220,7 +219,7 @@ void mrst_get_fuse_settings(struct drm_device *dev)
 	pci_dev_put(pci_root);
 }
 
-void mid_get_pci_revID (struct drm_psb_private *dev_priv)
+void mid_get_pci_revID(struct drm_psb_private *dev_priv)
 {
 	uint32_t platform_rev_id = 0;
 	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
@@ -230,7 +229,7 @@ void mid_get_pci_revID (struct drm_psb_private *dev_priv)
 	dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
 	pci_dev_put(pci_gfx_root);
 	dev_info(dev_priv->dev->dev, "platform_rev_id is %x\n",
-							dev_priv->platform_rev_id);
+					dev_priv->platform_rev_id);
 }
 
 void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
@@ -285,7 +284,7 @@ void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
 		dev_priv->gct_data.Panel_Port_Control =
 		  ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
 		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-		  ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+			((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
 		break;
 	case 1:
 		vbt->mrst_gct = NULL;
@@ -303,7 +302,7 @@ void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
 		dev_priv->gct_data.Panel_Port_Control =
 		  ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
 		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-		  ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+			((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
 		break;
 	case 0x10:
 		/*header definition changed from rev 01 (v2) to rev 10h. */
@@ -449,13 +448,12 @@ static int psb_do_init(struct drm_device *dev)
 	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_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);
-
+	PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
 	return 0;
 out_err:
 	psb_do_takedown(dev);
@@ -1335,7 +1333,6 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
 		dev_priv->rpm_enabled = 1;
 	}
 	return drm_ioctl(filp, cmd, arg);
-	
 	/* FIXME: do we need to wrap the other side of this */
 }
 
@@ -1367,7 +1364,7 @@ static struct vm_operations_struct psb_gem_vm_ops = {
 
 static struct drm_driver driver = {
 	.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
-			   DRIVER_IRQ_VBL | DRIVER_MODESET| DRIVER_GEM ,
+			   DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM ,
 	.load = psb_driver_load,
 	.unload = psb_driver_unload,
 
@@ -1428,7 +1425,7 @@ 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");
+		dev_warn(&pdev->dev, "Enable MSI failed!\n");
 	return drm_get_pci_dev(pdev, ent, &driver);
 }
 
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 45752aa..1114021 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -25,6 +25,7 @@
 
 #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"
@@ -132,8 +133,12 @@ enum {
 #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 _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
@@ -273,7 +278,7 @@ struct drm_psb_private {
 
 	/*
 	 * Power
-         */
+	 */
 
 	bool suspended;
 	bool display_power;
@@ -480,7 +485,7 @@ struct drm_psb_private {
 	uint32_t blc_adj1;
 	uint32_t blc_adj2;
 
-	void * fbdev;
+	void *fbdev;
 };
 
 
@@ -550,7 +555,7 @@ 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_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);
@@ -593,7 +598,7 @@ extern int psbfb_sync(struct fb_info *info);
 extern void psb_spank(struct drm_psb_private *dev_priv);
 
 extern int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
-	 	  	   unsigned size);
+					unsigned size);
 
 /*
  * psb_reset.c
@@ -606,14 +611,14 @@ 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);
+extern int psb_fbdev_init(struct drm_device *dev);
 
 /* psb_bl.c */
 int psb_backlight_init(struct drm_device *dev);
 void psb_backlight_exit(void);
 int psb_set_brightness(struct backlight_device *bd);
 int psb_get_brightness(struct backlight_device *bd);
-struct backlight_device * psb_get_backlight_device(void);
+struct backlight_device *psb_get_backlight_device(void);
 
 /* mrst_crtc.c */
 extern const struct drm_crtc_helper_funcs mrst_helper_funcs;
@@ -662,7 +667,6 @@ extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 extern int drm_psb_no_fb;
 extern int drm_idle_check_interval;
 
-
 /*
  *	Utilities
  */
@@ -671,36 +675,36 @@ 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);
+	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);
+	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);
+	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);
+	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);
 }
 
@@ -744,14 +748,15 @@ static inline void REGISTER_WRITE8(struct drm_device *dev,
 
 /* #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__);				\
-	mdelay(1000);						\
-    }								\
-    ioread32(dev_priv->sgx_reg + (_offs));			\
+#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))
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 400dbee..f1a7e8d 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -244,9 +244,11 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 
 	fb_screen_base = (char *)info->screen_base;
 
-        /* If this is a GEM object then info->screen_base is the virtual
-           kernel remapping of the object. FIXME: Review if this is
-           suitable for our mmap work */
+	/*
+	 * If this is a GEM object then info->screen_base is the virtual
+	 * kernel remapping of the object. FIXME: Review if this is
+	 * suitable for our mmap work
+	 */
 	vma->vm_ops = &psbfb_vm_ops;
 	vma->vm_private_data = (void *)psbfb;
 	vma->vm_flags |= VM_RESERVED | VM_IO |
@@ -254,7 +256,8 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 	return 0;
 }
 
-static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
+						unsigned long arg)
 {
 	struct psb_fbdev *fbdev = info->par;
 	struct psb_framebuffer *psbfb = &fbdev->pfb;
@@ -305,33 +308,33 @@ static struct fb_ops psbfb_ops = {
  *	0 on success or an error code if we fail.
  */
 static int psb_framebuffer_init(struct drm_device *dev,
-                                struct psb_framebuffer *fb,
-                                struct drm_mode_fb_cmd *mode_cmd,
-                                struct gtt_range *gt)
+					struct psb_framebuffer *fb,
+					struct drm_mode_fb_cmd *mode_cmd,
+					struct gtt_range *gt)
 {
-        int ret;
-
-        if (mode_cmd->pitch & 63)
-                return -EINVAL;
-        switch (mode_cmd->bpp) {
-        case 8:
-        case 16:
-        case 24:
-        case 32:
-                break;
-        default:
-                return -EINVAL;
-        }
-        ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
-        if (ret) {
-                dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
-                return ret;
-        }
-        drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
-        fb->gtt = gt;
-        return 0;
+	int ret;
+
+	if (mode_cmd->pitch & 63)
+		return -EINVAL;
+	switch (mode_cmd->bpp) {
+	case 8:
+	case 16:
+	case 24:
+	case 32:
+		break;
+	default:
+		return -EINVAL;
+	}
+	ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
+	if (ret) {
+		dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
+		return ret;
+	}
+	drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
+	fb->gtt = gt;
+	return 0;
 }
-                
+
 /**
  *	psb_framebuffer_create	-	create a framebuffer backed by gt
  *	@dev: our DRM device
@@ -357,10 +360,10 @@ static struct drm_framebuffer *psb_framebuffer_create
 
 	ret = psb_framebuffer_init(dev, fb, mode_cmd, gt);
 	if (ret) {
-	        kfree(fb);
-	        return ERR_PTR(ret);
-        }
-        return &fb->base;
+		kfree(fb);
+		return ERR_PTR(ret);
+	}
+	return &fb->base;
 }
 
 /**
@@ -373,7 +376,7 @@ static struct drm_framebuffer *psb_framebuffer_create
  *	stolen memory or the system has no stolen memory we allocate a range
  *	and back it with a GEM object.
  *
- *	In this case the GEM object has no handle. 
+ *	In this case the GEM object has no handle.
  *
  *	FIXME: console speed up - allocate twice the space if room and use
  *	hardware scrolling for acceleration.
@@ -384,10 +387,11 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
 	/* Begin by trying to use stolen memory backing */
 	backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
 	if (backing) {
-	        if (drm_gem_private_object_init(dev, &backing->gem, aligned_size) == 0)
-        		return backing;
-                psb_gtt_free_range(dev, backing);
-        }
+		if (drm_gem_private_object_init(dev,
+					&backing->gem, aligned_size) == 0)
+			return backing;
+		psb_gtt_free_range(dev, backing);
+	}
 	/* Next try using GEM host memory */
 	backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
 	if (backing == NULL)
@@ -400,7 +404,7 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
 	}
 	return backing;
 }
-	
+
 /**
  *	psbfb_create		-	create a framebuffer
  *	@fbdev: the framebuffer device
@@ -428,7 +432,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 
 	/* No 24bit packed */
 	if (mode_cmd.bpp == 24)
-        	mode_cmd.bpp = 32;
+		mode_cmd.bpp = 32;
 
 	/* HW requires pitch to be 64 byte aligned */
 	mode_cmd.pitch =  ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
@@ -440,7 +444,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	/* Allocate the framebuffer in the GTT with stolen page backing */
 	backing = psbfb_alloc(dev, size);
 	if (backing == NULL)
-	        return -ENOMEM;
+		return -ENOMEM;
 
 	mutex_lock(&dev->struct_mutex);
 
@@ -455,7 +459,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	if (ret)
 		goto out_unref;
 
-        fb = &psbfb->base;
+	fb = &psbfb->base;
 	psbfb->fbdev = info;
 
 	fbdev->psb_fb_helper.fb = fb;
@@ -523,13 +527,13 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	mutex_unlock(&dev->struct_mutex);
 	return 0;
 out_unref:
-        if (backing->stolen)
-                psb_gtt_free_range(dev, backing);
-        else {
-                if (psbfb->vm_map)
-                        vm_unmap_ram(info->screen_base, backing->npage);
-                drm_gem_object_unreference(&backing->gem);
-        }
+	if (backing->stolen)
+		psb_gtt_free_range(dev, backing);
+	else {
+		if (psbfb->vm_map)
+			vm_unmap_ram(info->screen_base, backing->npage);
+		drm_gem_object_unreference(&backing->gem);
+	}
 out_err1:
 	mutex_unlock(&dev->struct_mutex);
 	psb_gtt_free_range(dev, backing);
@@ -548,17 +552,19 @@ static struct drm_framebuffer *psb_user_framebuffer_create
 			(struct drm_device *dev, struct drm_file *filp,
 			 struct drm_mode_fb_cmd *cmd)
 {
-        struct gtt_range *r;
-        struct drm_gem_object *obj;
+	struct gtt_range *r;
+	struct drm_gem_object *obj;
 
-        /* Find the GEM object and thus the gtt range object that is
-           to back this space */
+	/*
+	 *	Find the GEM object and thus the gtt range object that is
+	 *	to back this space
+	 */
 	obj = drm_gem_object_lookup(dev, filp, cmd->handle);
 	if (obj == NULL)
-	        return ERR_PTR(-ENOENT);
+		return ERR_PTR(-ENOENT);
 
-        /* Let the core code do all the work */
-        r = container_of(obj, struct gtt_range, gem);
+	/* Let the core code do all the work */
+	r = container_of(obj, struct gtt_range, gem);
 	return psb_framebuffer_create(dev, cmd, r);
 }
 
@@ -610,12 +616,12 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
 		}
 		unregister_framebuffer(info);
 		if (info->cmap.len)
-		        fb_dealloc_cmap(&info->cmap);
+			fb_dealloc_cmap(&info->cmap);
 		framebuffer_release(info);
 	}
 	drm_fb_helper_fini(&fbdev->psb_fb_helper);
 	drm_framebuffer_cleanup(&psbfb->base);
-	
+
 	if (psbfb->gtt) {
 		/* FIXME: this is a bit more inside knowledge than I'd like
 		   but I don't see how to make a fake GEM object of the
@@ -624,7 +630,7 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
 			psb_gtt_free_range(dev, psbfb->gtt);
 		else
 			drm_gem_object_unreference(&psbfb->gtt->gem);
-        }
+	}
 	return 0;
 }
 
@@ -686,9 +692,9 @@ static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
 					      struct drm_file *file_priv,
 					      unsigned int *handle)
 {
-        struct psb_framebuffer *psbfb = to_psb_fb(fb);
-        struct gtt_range *r = psbfb->gtt;
-        return drm_gem_handle_create(file_priv, &r->gem, handle);
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+	struct gtt_range *r = psbfb->gtt;
+	return drm_gem_handle_create(file_priv, &r->gem, handle);
 }
 
 /**
@@ -717,16 +723,17 @@ static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
 			reset = 1;
 
 	if (reset)
-		/* 
-		 * Now force a sane response before we permit the DRM crc layer to
-		 * do stupid things like blank the display. Instead we reset this
-		 * framebuffer as if the user had forced a reset. We must do this
-		 * before the cleanup so that the DRM layer doesn't get a chance
-		 * to stick its oar in where it isn't wanted.
+		/*
+		 * Now force a sane response before we permit the DRM CRTC
+		 * layer to do stupid things like blank the display. Instead
+		 * we reset this framebuffer as if the user had forced a reset.
+		 * We must do this before the cleanup so that the DRM layer
+		 * doesn't get a chance to stick its oar in where it isn't
+		 * wanted.
 		 */
 		drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
 
-        /* Let DRM do its clean up */
+	/* Let DRM do its clean up */
 	drm_framebuffer_cleanup(fb);
 	/*  We are no longer using the resource in GEM */
 	drm_gem_object_unreference_unlocked(&r->gem);
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
index 4aec38c..3f658e4 100644
--- a/drivers/staging/gma500/psb_gem.c
+++ b/drivers/staging/gma500/psb_gem.c
@@ -82,12 +82,13 @@ static int psb_gem_create_mmap_offset(struct drm_gem_object *obj)
 	map = list->map;
 	map->type = _DRM_GEM;
 	map->size = obj->size;
-	map->handle =obj;
+	map->handle = obj;
 
 	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
 					obj->size / PAGE_SIZE, 0, 0);
 	if (!list->file_offset_node) {
-		dev_err(dev->dev, "failed to allocate offset for bo %d\n", obj->name);
+		dev_err(dev->dev, "failed to allocate offset for bo %d\n",
+								obj->name);
 		ret = -ENOSPC;
 		goto free_it;
 	}
@@ -130,7 +131,7 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
 
 	if (!(dev->driver->driver_features & DRIVER_GEM))
 		return -ENODEV;
-		
+
 	mutex_lock(&dev->struct_mutex);
 
 	/* GEM does all our handle to object mapping */
@@ -140,7 +141,7 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
 		goto unlock;
 	}
 	/* What validation is needed here ? */
-	
+
 	/* Make it mmapable */
 	if (!obj->map_list.map) {
 		ret = psb_gem_create_mmap_offset(obj);
@@ -176,7 +177,7 @@ static int psb_gem_create(struct drm_file *file,
 
 	size = roundup(size, PAGE_SIZE);
 
-	/* Allocate our object - for now a direct gtt range which is not 
+	/* Allocate our object - for now a direct gtt range which is not
 	   stolen memory backed */
 	r = psb_gtt_alloc_range(dev, size, "gem", 0);
 	if (r == NULL) {
@@ -285,9 +286,9 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	if (r->mmapping == 0) {
 		ret = psb_gtt_pin(r);
 		if (ret < 0) {
-		        dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
-		        goto fail;
-                }
+			dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
+			goto fail;
+		}
 		r->mmapping = 1;
 	}
 
@@ -304,7 +305,7 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
 
 fail:
-        mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->struct_mutex);
 	switch (ret) {
 	case 0:
 	case -ERESTARTSYS:
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
index 9da1375..6cfa59b 100644
--- a/drivers/staging/gma500/psb_gtt.c
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -52,7 +52,7 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
  *	psb_gtt_entry		-	find the GTT entries for a gtt_range
  *	@dev: our DRM device
  *	@r: our GTT range
- * 
+ *
  *	Given a gtt_range object return the GTT offset of the page table
  *	entries for this gtt_range
  */
@@ -102,7 +102,6 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
 	}
 	/* Make sure all the entries are set before we return */
 	ioread32(gtt_slot - 1);
-	
 	return 0;
 }
 
@@ -257,7 +256,7 @@ void psb_gtt_unpin(struct gtt_range *gt)
 	}
 	mutex_unlock(&dev_priv->gtt_mutex);
 }
-	
+
 /*
  *	GTT resource allocator - allocate and manage GTT address space
  */
@@ -289,11 +288,11 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
 		/* The start of the GTT is the stolen pages */
 		start = r->start;
 		end = r->start + dev_priv->pg->stolen_size - 1;
-        } else {
-        	/* The rest we will use for GEM backed objects */
-        	start = r->start + dev_priv->pg->stolen_size;
-        	end = r->end;
-        }
+	} else {
+		/* The rest we will use for GEM backed objects */
+		start = r->start + dev_priv->pg->stolen_size;
+		end = r->end;
+	}
 
 	gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
 	if (gt == NULL)
@@ -318,8 +317,8 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
  *	@dev: our DRM device
  *	@gt: a mapping created with psb_gtt_alloc_range
  *
- *	Release a resource that was allocated with psb_gtt_alloc_range. If the object
- *	has been pinned by mmap users we clean this up here currently.
+ *	Release a resource that was allocated with psb_gtt_alloc_range. If the
+ *	object has been pinned by mmap users we clean this up here currently.
  */
 void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
 {
@@ -386,7 +385,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	if (pg == NULL)
 		return -ENOMEM;
 
-        /* Enable the GTT */
+	/* Enable the GTT */
 	pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
 	pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
 			      dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
@@ -402,18 +401,21 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
 
 	pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
-	/* 
+	/*
 	 *	FIXME: video mmu has hw bug to access 0x0D0000000,
 	 *	then make gatt start at 0x0e000,0000
 	 */
 	pg->mmu_gatt_start = 0xE0000000;
 
 	pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
-	gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
-	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT;
+	gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
+								>> PAGE_SHIFT;
+	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
+								>> PAGE_SHIFT;
 
 	pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
-	vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE;
+	vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base
+								- PAGE_SIZE;
 
 	stolen_size = vram_stolen_size;
 
@@ -439,7 +441,8 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	/*
 	 *	Map the GTT and the stolen memory area
 	 */
-	dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT);
+	dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
+						gtt_pages << PAGE_SHIFT);
 	if (!dev_priv->gtt_map) {
 		dev_err(dev->dev, "Failure to map gtt.\n");
 		ret = -ENOMEM;
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 6039a31..f28f5d6 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -388,7 +388,7 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
 		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
 		break;
 	default:
-                dev_err(dev->dev, "Unknown color depth\n");
+		dev_err(dev->dev, "Unknown color depth\n");
 		ret = -EINVAL;
 		psb_gtt_unpin(psbfb->gtt);
 		goto psb_intel_pipe_set_base_exit;
@@ -611,9 +611,9 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 
 	/* No scan out no play */
 	if (crtc->fb == NULL) {
-	        crtc_funcs->mode_set_base(crtc, x, y, old_fb);
-                return 0;
-        }
+		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+		return 0;
+	}
 
 	list_for_each_entry(connector, &mode_config->connector_list, head) {
 		struct psb_intel_output *psb_intel_output =
@@ -728,8 +728,8 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
 		u32 lvds = REG_READ(LVDS);
 
 		lvds &= ~LVDS_PIPEB_SELECT;
-                if (pipe == 1)
-                        lvds |= LVDS_PIPEB_SELECT;
+		if (pipe == 1)
+			lvds |= LVDS_PIPEB_SELECT;
 
 		lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
 		/* Set the B0-B3 data pairs corresponding to
diff --git a/drivers/staging/gma500/psb_intel_opregion.c b/drivers/staging/gma500/psb_intel_opregion.c
index 51cf1d6..97a8b00 100644
--- a/drivers/staging/gma500/psb_intel_opregion.c
+++ b/drivers/staging/gma500/psb_intel_opregion.c
@@ -33,19 +33,19 @@ struct opregion_header {
 	u8 driver_ver[16];
 	u32 mboxes;
 	u8 reserved[164];
-} __attribute__((packed));
+} __packed;
 
 struct opregion_apci {
 	/*FIXME: add it later*/
-} __attribute__((packed));
+} __packed;
 
 struct opregion_swsci {
 	/*FIXME: add it later*/
-} __attribute__((packed));
+} __packed;
 
 struct opregion_acpi {
 	/*FIXME: add it later*/
-} __attribute__((packed));
+} __packed;
 
 int psb_intel_opregion_init(struct drm_device *dev)
 {
diff --git a/drivers/staging/gma500/psb_intel_reg.h b/drivers/staging/gma500/psb_intel_reg.h
index 1c28314..c9630a2 100644
--- a/drivers/staging/gma500/psb_intel_reg.h
+++ b/drivers/staging/gma500/psb_intel_reg.h
@@ -28,8 +28,8 @@
  *
  * The actual value is this field multiplied by two.
  */
-#define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
-#define BLM_LEGACY_MODE				(1 << 16)
+#define BACKLIGHT_MODULATION_FREQ_MASK	(0x7fff << 17)
+#define BLM_LEGACY_MODE			(1 << 16)
 /*
  * This is the number of cycles out of the backlight modulation cycle for which
  * the backlight is on.
@@ -37,55 +37,55 @@
  * This field must be no greater than the number of cycles in the complete
  * backlight modulation cycle.
  */
-#define BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
-#define BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
+#define BACKLIGHT_DUTY_CYCLE_SHIFT	(0)
+#define BACKLIGHT_DUTY_CYCLE_MASK	(0xffff)
 
 #define I915_GCFGC			0xf0
-#define I915_LOW_FREQUENCY_ENABLE		(1 << 7)
-#define I915_DISPLAY_CLOCK_190_200_MHZ		(0 << 4)
-#define I915_DISPLAY_CLOCK_333_MHZ		(4 << 4)
-#define I915_DISPLAY_CLOCK_MASK			(7 << 4)
+#define I915_LOW_FREQUENCY_ENABLE	(1 << 7)
+#define I915_DISPLAY_CLOCK_190_200_MHZ	(0 << 4)
+#define I915_DISPLAY_CLOCK_333_MHZ	(4 << 4)
+#define I915_DISPLAY_CLOCK_MASK		(7 << 4)
 
 #define I855_HPLLCC			0xc0
-#define I855_CLOCK_CONTROL_MASK			(3 << 0)
-#define I855_CLOCK_133_200			(0 << 0)
-#define I855_CLOCK_100_200			(1 << 0)
-#define I855_CLOCK_100_133			(2 << 0)
-#define I855_CLOCK_166_250			(3 << 0)
+#define I855_CLOCK_CONTROL_MASK		(3 << 0)
+#define I855_CLOCK_133_200		(0 << 0)
+#define I855_CLOCK_100_200		(1 << 0)
+#define I855_CLOCK_100_133		(2 << 0)
+#define I855_CLOCK_166_250		(3 << 0)
 
 /* I830 CRTC registers */
-#define HTOTAL_A	0x60000
-#define HBLANK_A	0x60004
-#define HSYNC_A 	0x60008
-#define VTOTAL_A	0x6000c
-#define VBLANK_A	0x60010
-#define VSYNC_A 	0x60014
-#define PIPEASRC	0x6001c
-#define BCLRPAT_A	0x60020
-#define VSYNCSHIFT_A	0x60028
-
-#define HTOTAL_B	0x61000
-#define HBLANK_B	0x61004
-#define HSYNC_B 	0x61008
-#define VTOTAL_B	0x6100c
-#define VBLANK_B	0x61010
-#define VSYNC_B 	0x61014
-#define PIPEBSRC	0x6101c
-#define BCLRPAT_B	0x61020
-#define VSYNCSHIFT_B	0x61028
-
-#define HTOTAL_C	0x62000
-#define HBLANK_C	0x62004
-#define HSYNC_C 	0x62008
-#define VTOTAL_C	0x6200c
-#define VBLANK_C	0x62010
-#define VSYNC_C 	0x62014
-#define PIPECSRC	0x6201c
-#define BCLRPAT_C	0x62020
-#define VSYNCSHIFT_C	0x62028
-
-#define PP_STATUS	0x61200
-# define PP_ON					(1 << 31)
+#define HTOTAL_A		0x60000
+#define HBLANK_A		0x60004
+#define HSYNC_A			0x60008
+#define VTOTAL_A		0x6000c
+#define VBLANK_A		0x60010
+#define VSYNC_A			0x60014
+#define PIPEASRC		0x6001c
+#define BCLRPAT_A		0x60020
+#define VSYNCSHIFT_A		0x60028
+
+#define HTOTAL_B		0x61000
+#define HBLANK_B		0x61004
+#define HSYNC_B			0x61008
+#define VTOTAL_B		0x6100c
+#define VBLANK_B		0x61010
+#define VSYNC_B			0x61014
+#define PIPEBSRC		0x6101c
+#define BCLRPAT_B		0x61020
+#define VSYNCSHIFT_B		0x61028
+
+#define HTOTAL_C		0x62000
+#define HBLANK_C		0x62004
+#define HSYNC_C			0x62008
+#define VTOTAL_C		0x6200c
+#define VBLANK_C		0x62010
+#define VSYNC_C			0x62014
+#define PIPECSRC		0x6201c
+#define BCLRPAT_C		0x62020
+#define VSYNCSHIFT_C		0x62028
+
+#define PP_STATUS		0x61200
+# define PP_ON				(1 << 31)
 /*
  * Indicates that all dependencies of the panel are on:
  *
@@ -93,56 +93,55 @@
  * - pipe enabled
  * - LVDS/DVOB/DVOC on
  */
-# define PP_READY				(1 << 30)
-# define PP_SEQUENCE_NONE			(0 << 28)
-# define PP_SEQUENCE_ON				(1 << 28)
-# define PP_SEQUENCE_OFF			(2 << 28)
-# define PP_SEQUENCE_MASK			0x30000000
-#define PP_CONTROL	0x61204
-# define POWER_TARGET_ON			(1 << 0)
-
-#define LVDSPP_ON       0x61208
-#define LVDSPP_OFF      0x6120c
-#define PP_CYCLE        0x61210
-
-#define PFIT_CONTROL	0x61230
-# define PFIT_ENABLE				(1 << 31)
-# define PFIT_PIPE_MASK				(3 << 29)
-# define PFIT_PIPE_SHIFT			29
-# define PFIT_SCALING_MODE_PILLARBOX            (1 << 27)
-# define PFIT_SCALING_MODE_LETTERBOX            (3 << 26)
-# define VERT_INTERP_DISABLE			(0 << 10)
-# define VERT_INTERP_BILINEAR			(1 << 10)
-# define VERT_INTERP_MASK			(3 << 10)
-# define VERT_AUTO_SCALE			(1 << 9)
-# define HORIZ_INTERP_DISABLE			(0 << 6)
-# define HORIZ_INTERP_BILINEAR			(1 << 6)
-# define HORIZ_INTERP_MASK			(3 << 6)
-# define HORIZ_AUTO_SCALE			(1 << 5)
-# define PANEL_8TO6_DITHER_ENABLE		(1 << 3)
-
-#define PFIT_PGM_RATIOS	0x61234
-# define PFIT_VERT_SCALE_MASK			0xfff00000
-# define PFIT_HORIZ_SCALE_MASK			0x0000fff0
+#define PP_READY			(1 << 30)
+#define PP_SEQUENCE_NONE		(0 << 28)
+#define PP_SEQUENCE_ON			(1 << 28)
+#define PP_SEQUENCE_OFF			(2 << 28)
+#define PP_SEQUENCE_MASK		0x30000000
+#define PP_CONTROL		0x61204
+#define POWER_TARGET_ON			(1 << 0)
+
+#define LVDSPP_ON		0x61208
+#define LVDSPP_OFF		0x6120c
+#define PP_CYCLE		0x61210
+
+#define PFIT_CONTROL		0x61230
+#define PFIT_ENABLE			(1 << 31)
+#define PFIT_PIPE_MASK			(3 << 29)
+#define PFIT_PIPE_SHIFT			29
+#define PFIT_SCALING_MODE_PILLARBOX	(1 << 27)
+#define PFIT_SCALING_MODE_LETTERBOX	(3 << 26)
+#define VERT_INTERP_DISABLE		(0 << 10)
+#define VERT_INTERP_BILINEAR		(1 << 10)
+#define VERT_INTERP_MASK		(3 << 10)
+#define VERT_AUTO_SCALE			(1 << 9)
+#define HORIZ_INTERP_DISABLE		(0 << 6)
+#define HORIZ_INTERP_BILINEAR		(1 << 6)
+#define HORIZ_INTERP_MASK		(3 << 6)
+#define HORIZ_AUTO_SCALE		(1 << 5)
+#define PANEL_8TO6_DITHER_ENABLE	(1 << 3)
+
+#define PFIT_PGM_RATIOS		0x61234
+#define PFIT_VERT_SCALE_MASK			0xfff00000
+#define PFIT_HORIZ_SCALE_MASK			0x0000fff0
 
 #define PFIT_AUTO_RATIOS	0x61238
 
-
-#define DPLL_A		0x06014
-#define DPLL_B		0x06018
-# define DPLL_VCO_ENABLE			(1 << 31)
-# define DPLL_DVO_HIGH_SPEED			(1 << 30)
-# define DPLL_SYNCLOCK_ENABLE			(1 << 29)
-# define DPLL_VGA_MODE_DIS			(1 << 28)
-# define DPLLB_MODE_DAC_SERIAL			(1 << 26)	/* i915 */
-# define DPLLB_MODE_LVDS			(2 << 26)	/* i915 */
-# define DPLL_MODE_MASK				(3 << 26)
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24)	/* i915 */
-# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5		(1 << 24)	/* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_14		(0 << 24)	/* i915 */
-# define DPLLB_LVDS_P2_CLOCK_DIV_7		(1 << 24)	/* i915 */
-# define DPLL_P2_CLOCK_DIV_MASK			0x03000000	/* i915 */
-# define DPLL_FPA01_P1_POST_DIV_MASK		0x00ff0000	/* i915 */
+#define DPLL_A			0x06014
+#define DPLL_B			0x06018
+#define DPLL_VCO_ENABLE			(1 << 31)
+#define DPLL_DVO_HIGH_SPEED		(1 << 30)
+#define DPLL_SYNCLOCK_ENABLE		(1 << 29)
+#define DPLL_VGA_MODE_DIS		(1 << 28)
+#define DPLLB_MODE_DAC_SERIAL		(1 << 26)	/* i915 */
+#define DPLLB_MODE_LVDS			(2 << 26)	/* i915 */
+#define DPLL_MODE_MASK			(3 << 26)
+#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24)	/* i915 */
+#define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5	(1 << 24)	/* i915 */
+#define DPLLB_LVDS_P2_CLOCK_DIV_14	(0 << 24)	/* i915 */
+#define DPLLB_LVDS_P2_CLOCK_DIV_7	(1 << 24)	/* i915 */
+#define DPLL_P2_CLOCK_DIV_MASK		0x03000000	/* i915 */
+#define DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000	/* i915 */
 /*
  *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
  * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
@@ -152,35 +151,35 @@
  * The i830 generation, in LVDS mode, defines P1 as the bit number set within
  * this field (only one bit may be set).
  */
-# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
-# define DPLL_FPA01_P1_POST_DIV_SHIFT		16
-# define PLL_P2_DIVIDE_BY_4		(1 << 23)	/* i830, required
+#define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
+#define DPLL_FPA01_P1_POST_DIV_SHIFT	16
+#define PLL_P2_DIVIDE_BY_4		(1 << 23)	/* i830, required
 							 * in DVO non-gang */
-# define PLL_P1_DIVIDE_BY_TWO			(1 << 21)	/* i830 */
-# define PLL_REF_INPUT_DREFCLK			(0 << 13)
-# define PLL_REF_INPUT_TVCLKINA			(1 << 13)	/* i830 */
-# define PLL_REF_INPUT_TVCLKINBC		(2 << 13)	/* SDVO
+# define PLL_P1_DIVIDE_BY_TWO		(1 << 21)	/* i830 */
+#define PLL_REF_INPUT_DREFCLK		(0 << 13)
+#define PLL_REF_INPUT_TVCLKINA		(1 << 13)	/* i830 */
+#define PLL_REF_INPUT_TVCLKINBC		(2 << 13)	/* SDVO
 								 * TVCLKIN */
-# define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
-# define PLL_REF_INPUT_MASK			(3 << 13)
-# define PLL_LOAD_PULSE_PHASE_SHIFT		9
+#define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
+#define PLL_REF_INPUT_MASK		(3 << 13)
+#define PLL_LOAD_PULSE_PHASE_SHIFT	9
 /*
  * Parallel to Serial Load Pulse phase selection.
  * Selects the phase for the 10X DPLL clock for the PCIe
  * digital display port. The range is 4 to 13; 10 or more
  * is just a flip delay. The default is 6
  */
-# define PLL_LOAD_PULSE_PHASE_MASK	(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
-# define DISPLAY_RATE_SELECT_FPA1	(1 << 8)
+#define PLL_LOAD_PULSE_PHASE_MASK	(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+#define DISPLAY_RATE_SELECT_FPA1	(1 << 8)
 
 /*
  * SDVO multiplier for 945G/GM. Not used on 965.
  *
  * DPLL_MD_UDI_MULTIPLIER_MASK
  */
-# define SDVO_MULTIPLIER_MASK			0x000000ff
-# define SDVO_MULTIPLIER_SHIFT_HIRES		4
-# define SDVO_MULTIPLIER_SHIFT_VGA		0
+#define SDVO_MULTIPLIER_MASK		0x000000ff
+#define SDVO_MULTIPLIER_SHIFT_HIRES	4
+#define SDVO_MULTIPLIER_SHIFT_VGA	0
 
 /*
  * PLL_MD
@@ -194,11 +193,11 @@
  *
  * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
  */
-# define DPLL_MD_UDI_DIVIDER_MASK		0x3f000000
-# define DPLL_MD_UDI_DIVIDER_SHIFT		24
+#define DPLL_MD_UDI_DIVIDER_MASK	0x3f000000
+#define DPLL_MD_UDI_DIVIDER_SHIFT	24
 /* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
-# define DPLL_MD_VGA_UDI_DIVIDER_MASK		0x003f0000
-# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT		16
+#define DPLL_MD_VGA_UDI_DIVIDER_MASK	0x003f0000
+#define DPLL_MD_VGA_UDI_DIVIDER_SHIFT	16
 /*
  * SDVO/UDI pixel multiplier.
  *
@@ -216,80 +215,80 @@
  * This register field has values of multiplication factor minus 1, with
  * a maximum multiplier of 5 for SDVO.
  */
-# define DPLL_MD_UDI_MULTIPLIER_MASK		0x00003f00
-# define DPLL_MD_UDI_MULTIPLIER_SHIFT		8
+#define DPLL_MD_UDI_MULTIPLIER_MASK	0x00003f00
+#define DPLL_MD_UDI_MULTIPLIER_SHIFT	8
 /*
  * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
  * This best be set to the default value (3) or the CRT won't work. No,
  * I don't entirely understand what this does...
  */
-# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
-# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
+#define DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
+#define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
 
 #define DPLL_TEST		0x606c
-# define DPLLB_TEST_SDVO_DIV_1			(0 << 22)
-# define DPLLB_TEST_SDVO_DIV_2			(1 << 22)
-# define DPLLB_TEST_SDVO_DIV_4			(2 << 22)
-# define DPLLB_TEST_SDVO_DIV_MASK		(3 << 22)
-# define DPLLB_TEST_N_BYPASS			(1 << 19)
-# define DPLLB_TEST_M_BYPASS			(1 << 18)
-# define DPLLB_INPUT_BUFFER_ENABLE		(1 << 16)
-# define DPLLA_TEST_N_BYPASS			(1 << 3)
-# define DPLLA_TEST_M_BYPASS			(1 << 2)
-# define DPLLA_INPUT_BUFFER_ENABLE		(1 << 0)
+#define DPLLB_TEST_SDVO_DIV_1		(0 << 22)
+#define DPLLB_TEST_SDVO_DIV_2		(1 << 22)
+#define DPLLB_TEST_SDVO_DIV_4		(2 << 22)
+#define DPLLB_TEST_SDVO_DIV_MASK	(3 << 22)
+#define DPLLB_TEST_N_BYPASS		(1 << 19)
+#define DPLLB_TEST_M_BYPASS		(1 << 18)
+#define DPLLB_INPUT_BUFFER_ENABLE	(1 << 16)
+#define DPLLA_TEST_N_BYPASS		(1 << 3)
+#define DPLLA_TEST_M_BYPASS		(1 << 2)
+#define DPLLA_INPUT_BUFFER_ENABLE	(1 << 0)
 
 #define ADPA			0x61100
-#define ADPA_DAC_ENABLE 	(1<<31)
-#define ADPA_DAC_DISABLE	0
-#define ADPA_PIPE_SELECT_MASK	(1<<30)
-#define ADPA_PIPE_A_SELECT	0
-#define ADPA_PIPE_B_SELECT	(1<<30)
-#define ADPA_USE_VGA_HVPOLARITY (1<<15)
-#define ADPA_SETS_HVPOLARITY	0
-#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
-#define ADPA_VSYNC_CNTL_ENABLE	0
-#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
-#define ADPA_HSYNC_CNTL_ENABLE	0
-#define ADPA_VSYNC_ACTIVE_HIGH	(1<<4)
-#define ADPA_VSYNC_ACTIVE_LOW	0
-#define ADPA_HSYNC_ACTIVE_HIGH	(1<<3)
-#define ADPA_HSYNC_ACTIVE_LOW	0
-
-#define FPA0		0x06040
-#define FPA1		0x06044
-#define FPB0		0x06048
-#define FPB1		0x0604c
-# define FP_N_DIV_MASK				0x003f0000
-# define FP_N_DIV_SHIFT				16
-# define FP_M1_DIV_MASK				0x00003f00
-# define FP_M1_DIV_SHIFT			8
-# define FP_M2_DIV_MASK				0x0000003f
-# define FP_M2_DIV_SHIFT			0
-
+#define ADPA_DAC_ENABLE			(1 << 31)
+#define ADPA_DAC_DISABLE		0
+#define ADPA_PIPE_SELECT_MASK		(1 << 30)
+#define ADPA_PIPE_A_SELECT		0
+#define ADPA_PIPE_B_SELECT		(1 << 30)
+#define ADPA_USE_VGA_HVPOLARITY		(1 << 15)
+#define ADPA_SETS_HVPOLARITY		0
+#define ADPA_VSYNC_CNTL_DISABLE		(1 << 11)
+#define ADPA_VSYNC_CNTL_ENABLE		0
+#define ADPA_HSYNC_CNTL_DISABLE		(1 << 10)
+#define ADPA_HSYNC_CNTL_ENABLE		0
+#define ADPA_VSYNC_ACTIVE_HIGH		(1 << 4)
+#define ADPA_VSYNC_ACTIVE_LOW		0
+#define ADPA_HSYNC_ACTIVE_HIGH		(1 << 3)
+#define ADPA_HSYNC_ACTIVE_LOW		0
+
+#define FPA0			0x06040
+#define FPA1			0x06044
+#define FPB0			0x06048
+#define FPB1			0x0604c
+#define FP_N_DIV_MASK			0x003f0000
+#define FP_N_DIV_SHIFT			16
+#define FP_M1_DIV_MASK			0x00003f00
+#define FP_M1_DIV_SHIFT			8
+#define FP_M2_DIV_MASK			0x0000003f
+#define FP_M2_DIV_SHIFT			0
 
 #define PORT_HOTPLUG_EN		0x61110
-# define SDVOB_HOTPLUG_INT_EN			(1 << 26)
-# define SDVOC_HOTPLUG_INT_EN			(1 << 25)
-# define TV_HOTPLUG_INT_EN			(1 << 18)
-# define CRT_HOTPLUG_INT_EN			(1 << 9)
-# define CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
+#define SDVOB_HOTPLUG_INT_EN		(1 << 26)
+#define SDVOC_HOTPLUG_INT_EN		(1 << 25)
+#define TV_HOTPLUG_INT_EN		(1 << 18)
+#define CRT_HOTPLUG_INT_EN		(1 << 9)
+#define CRT_HOTPLUG_FORCE_DETECT	(1 << 3)
 
 #define PORT_HOTPLUG_STAT	0x61114
-# define CRT_HOTPLUG_INT_STATUS			(1 << 11)
-# define TV_HOTPLUG_INT_STATUS			(1 << 10)
-# define CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
-# define CRT_HOTPLUG_MONITOR_COLOR		(3 << 8)
-# define CRT_HOTPLUG_MONITOR_MONO		(2 << 8)
-# define CRT_HOTPLUG_MONITOR_NONE		(0 << 8)
-# define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
-# define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
+#define CRT_HOTPLUG_INT_STATUS		(1 << 11)
+#define TV_HOTPLUG_INT_STATUS		(1 << 10)
+#define CRT_HOTPLUG_MONITOR_MASK	(3 << 8)
+#define CRT_HOTPLUG_MONITOR_COLOR	(3 << 8)
+#define CRT_HOTPLUG_MONITOR_MONO	(2 << 8)
+#define CRT_HOTPLUG_MONITOR_NONE	(0 << 8)
+#define SDVOC_HOTPLUG_INT_STATUS	(1 << 7)
+#define SDVOB_HOTPLUG_INT_STATUS	(1 << 6)
 
 #define SDVOB			0x61140
 #define SDVOC			0x61160
-#define SDVO_ENABLE				(1 << 31)
-#define SDVO_PIPE_B_SELECT			(1 << 30)
-#define SDVO_STALL_SELECT			(1 << 29)
-#define SDVO_INTERRUPT_ENABLE			(1 << 26)
+#define SDVO_ENABLE			(1 << 31)
+#define SDVO_PIPE_B_SELECT		(1 << 30)
+#define SDVO_STALL_SELECT		(1 << 29)
+#define SDVO_INTERRUPT_ENABLE		(1 << 26)
+
 /**
  * 915G/GM SDVO pixel multiplier.
  *
@@ -297,18 +296,18 @@
  *
  * DPLL_MD_UDI_MULTIPLIER_MASK
  */
-#define SDVO_PORT_MULTIPLY_MASK			(7 << 23)
-#define SDVO_PORT_MULTIPLY_SHIFT		23
-#define SDVO_PHASE_SELECT_MASK			(15 << 19)
-#define SDVO_PHASE_SELECT_DEFAULT		(6 << 19)
-#define SDVO_CLOCK_OUTPUT_INVERT		(1 << 18)
-#define SDVOC_GANG_MODE				(1 << 16)
-#define SDVO_BORDER_ENABLE			(1 << 7)
-#define SDVOB_PCIE_CONCURRENCY			(1 << 3)
-#define SDVO_DETECTED				(1 << 2)
+#define SDVO_PORT_MULTIPLY_MASK		(7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT	23
+#define SDVO_PHASE_SELECT_MASK		(15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT	(6 << 19)
+#define SDVO_CLOCK_OUTPUT_INVERT	(1 << 18)
+#define SDVOC_GANG_MODE			(1 << 16)
+#define SDVO_BORDER_ENABLE		(1 << 7)
+#define SDVOB_PCIE_CONCURRENCY		(1 << 3)
+#define SDVO_DETECTED			(1 << 2)
 /* Bits to be preserved when writing */
 #define SDVOB_PRESERVE_MASK		((1 << 17) | (1 << 16) | (1 << 14))
-#define SDVOC_PRESERVE_MASK			(1 << 17)
+#define SDVOC_PRESERVE_MASK		(1 << 17)
 
 /*
  * This register controls the LVDS output enable, pipe selection, and data
@@ -321,116 +320,116 @@
  * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
  * the DPLL semantics change when the LVDS is assigned to that pipe.
  */
-# define LVDS_PORT_EN			(1 << 31)
+#define LVDS_PORT_EN			(1 << 31)
 /* Selects pipe B for LVDS data.  Must be set on pre-965. */
-# define LVDS_PIPEB_SELECT		(1 << 30)
+#define LVDS_PIPEB_SELECT		(1 << 30)
 
 /* Turns on border drawing to allow centered display. */
-# define LVDS_BORDER_EN                 (1 << 15)
+#define LVDS_BORDER_EN			(1 << 15)
 
 /*
  * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
  * pixel.
  */
-# define LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
-# define LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
-# define LVDS_A0A2_CLKA_POWER_UP	(3 << 8)
+#define LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
+#define LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
+#define LVDS_A0A2_CLKA_POWER_UP		(3 << 8)
 /*
  * Controls the A3 data pair, which contains the additional LSBs for 24 bit
  * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
  * on.
  */
-# define LVDS_A3_POWER_MASK		(3 << 6)
-# define LVDS_A3_POWER_DOWN		(0 << 6)
-# define LVDS_A3_POWER_UP		(3 << 6)
+#define LVDS_A3_POWER_MASK		(3 << 6)
+#define LVDS_A3_POWER_DOWN		(0 << 6)
+#define LVDS_A3_POWER_UP		(3 << 6)
 /*
  * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
  * is set.
  */
-# define LVDS_CLKB_POWER_MASK		(3 << 4)
-# define LVDS_CLKB_POWER_DOWN		(0 << 4)
-# define LVDS_CLKB_POWER_UP		(3 << 4)
+#define LVDS_CLKB_POWER_MASK		(3 << 4)
+#define LVDS_CLKB_POWER_DOWN		(0 << 4)
+#define LVDS_CLKB_POWER_UP		(3 << 4)
 /*
  * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
  * setting for whether we are in dual-channel mode.  The B3 pair will
  * additionally only be powered up when LVDS_A3_POWER_UP is set.
  */
-# define LVDS_B0B3_POWER_MASK		(3 << 2)
-# define LVDS_B0B3_POWER_DOWN		(0 << 2)
-# define LVDS_B0B3_POWER_UP		(3 << 2)
-
-#define PIPEACONF 0x70008
-#define PIPEACONF_ENABLE	(1<<31)
-#define PIPEACONF_DISABLE	0
-#define PIPEACONF_DOUBLE_WIDE	(1<<30)
-#define PIPECONF_ACTIVE		(1<<30)
-#define I965_PIPECONF_ACTIVE	(1<<30)
-#define PIPECONF_DSIPLL_LOCK	(1<<29)
-#define PIPEACONF_SINGLE_WIDE	0
-#define PIPEACONF_PIPE_UNLOCKED 0
-#define PIPEACONF_DSR		(1<<26)
-#define PIPEACONF_PIPE_LOCKED	(1<<25)
-#define PIPEACONF_PALETTE	0
-#define PIPECONF_FORCE_BORDER	(1<<25)
-#define PIPEACONF_GAMMA 	(1<<24)
-#define PIPECONF_PROGRESSIVE	(0 << 21)
+#define LVDS_B0B3_POWER_MASK		(3 << 2)
+#define LVDS_B0B3_POWER_DOWN		(0 << 2)
+#define LVDS_B0B3_POWER_UP		(3 << 2)
+
+#define PIPEACONF		0x70008
+#define PIPEACONF_ENABLE		(1 << 31)
+#define PIPEACONF_DISABLE		0
+#define PIPEACONF_DOUBLE_WIDE		(1 << 30)
+#define PIPECONF_ACTIVE			(1 << 30)
+#define I965_PIPECONF_ACTIVE		(1 << 30)
+#define PIPECONF_DSIPLL_LOCK		(1 << 29)
+#define PIPEACONF_SINGLE_WIDE		0
+#define PIPEACONF_PIPE_UNLOCKED		0
+#define PIPEACONF_DSR			(1 << 26)
+#define PIPEACONF_PIPE_LOCKED		(1 << 25)
+#define PIPEACONF_PALETTE		0
+#define PIPECONF_FORCE_BORDER		(1 << 25)
+#define PIPEACONF_GAMMA			(1 << 24)
+#define PIPECONF_PROGRESSIVE		(0 << 21)
 #define PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
 #define PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
-#define PIPECONF_PLANE_OFF 	(1<<19)
-#define PIPECONF_CURSOR_OFF 	(1<<18)
+#define PIPECONF_PLANE_OFF		(1 << 19)
+#define PIPECONF_CURSOR_OFF		(1 << 18)
 
+#define PIPEBCONF		0x71008
+#define PIPEBCONF_ENABLE		(1 << 31)
+#define PIPEBCONF_DISABLE		0
+#define PIPEBCONF_DOUBLE_WIDE		(1 << 30)
+#define PIPEBCONF_DISABLE		0
+#define PIPEBCONF_GAMMA			(1 << 24)
+#define PIPEBCONF_PALETTE		0
 
-#define PIPEBCONF 0x71008
-#define PIPEBCONF_ENABLE	(1<<31)
-#define PIPEBCONF_DISABLE	0
-#define PIPEBCONF_DOUBLE_WIDE	(1<<30)
-#define PIPEBCONF_DISABLE	0
-#define PIPEBCONF_GAMMA 	(1<<24)
-#define PIPEBCONF_PALETTE	0
-
-#define PIPECCONF 0x72008
+#define PIPECCONF		0x72008
 
 #define PIPEBGCMAXRED		0x71010
 #define PIPEBGCMAXGREEN		0x71014
 #define PIPEBGCMAXBLUE		0x71018
 
-#define PIPEASTAT               0x70024
+#define PIPEASTAT		0x70024
 #define PIPEBSTAT		0x71024
 #define PIPECSTAT		0x72024
-#define PIPE_VBLANK_INTERRUPT_STATUS         (1UL<<1)
-#define PIPE_START_VBLANK_INTERRUPT_STATUS   (1UL<<2)
-#define PIPE_VBLANK_CLEAR                    (1 << 1)
-#define PIPE_VBLANK_STATUS                   (1 << 1)
-#define PIPE_TE_STATUS		             (1UL<<6)
-#define PIPE_DPST_EVENT_STATUS		     (1UL<<7)
-#define PIPE_VSYNC_CLEAR                     (1UL<<9)
-#define PIPE_VSYNC_STATUS                    (1UL<<9)
-#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS      (1UL<<10)
-#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS   (1UL<<11)
-#define PIPE_VBLANK_INTERRUPT_ENABLE         (1UL<<17)
-#define PIPE_START_VBLANK_INTERRUPT_ENABLE   (1UL<<18)
-#define PIPE_TE_ENABLE		             (1UL<<22)
-#define PIPE_DPST_EVENT_ENABLE               (1UL<<23)
-#define PIPE_VSYNC_ENABL                     (1UL<<25)
-#define PIPE_HDMI_AUDIO_UNDERRUN             (1UL<<26)
-#define PIPE_HDMI_AUDIO_BUFFER_DONE          (1UL<<27)
-#define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | PIPE_HDMI_AUDIO_BUFFER_DONE)
+#define PIPE_VBLANK_INTERRUPT_STATUS		(1UL << 1)
+#define PIPE_START_VBLANK_INTERRUPT_STATUS	(1UL << 2)
+#define PIPE_VBLANK_CLEAR			(1 << 1)
+#define PIPE_VBLANK_STATUS			(1 << 1)
+#define PIPE_TE_STATUS				(1UL << 6)
+#define PIPE_DPST_EVENT_STATUS			(1UL << 7)
+#define PIPE_VSYNC_CLEAR			(1UL << 9)
+#define PIPE_VSYNC_STATUS			(1UL << 9)
+#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS		(1UL << 10)
+#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS	(1UL << 11)
+#define PIPE_VBLANK_INTERRUPT_ENABLE		(1UL << 17)
+#define PIPE_START_VBLANK_INTERRUPT_ENABLE	(1UL << 18)
+#define PIPE_TE_ENABLE				(1UL << 22)
+#define PIPE_DPST_EVENT_ENABLE			(1UL << 23)
+#define PIPE_VSYNC_ENABL			(1UL << 25)
+#define PIPE_HDMI_AUDIO_UNDERRUN		(1UL << 26)
+#define PIPE_HDMI_AUDIO_BUFFER_DONE		(1UL << 27)
+#define PIPE_HDMI_AUDIO_INT_MASK		(PIPE_HDMI_AUDIO_UNDERRUN | \
+						PIPE_HDMI_AUDIO_BUFFER_DONE)
 #define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16))
 #define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17))
 #define HISTOGRAM_INT_CONTROL		0x61268
 #define HISTOGRAM_BIN_DATA		0X61264
 #define HISTOGRAM_LOGIC_CONTROL		0x61260
 #define PWM_CONTROL_LOGIC		0x61250
-#define PIPE_HOTPLUG_INTERRUPT_STATUS	(1UL<<10)
-#define HISTOGRAM_INTERRUPT_ENABLE	(1UL<<31)
-#define HISTOGRAM_LOGIC_ENABLE		(1UL<<31)
-#define PWM_LOGIC_ENABLE		(1UL<<31)
-#define PWM_PHASEIN_ENABLE		(1UL<<25)
-#define PWM_PHASEIN_INT_ENABLE		(1UL<<24)
-#define PWM_PHASEIN_VB_COUNT		0x00001f00
-#define PWM_PHASEIN_INC			0x0000001f
-#define HISTOGRAM_INT_CTRL_CLEAR	(1UL<<30)
-#define DPST_YUV_LUMA_MODE		0
+#define PIPE_HOTPLUG_INTERRUPT_STATUS		(1UL << 10)
+#define HISTOGRAM_INTERRUPT_ENABLE		(1UL << 31)
+#define HISTOGRAM_LOGIC_ENABLE			(1UL << 31)
+#define PWM_LOGIC_ENABLE			(1UL << 31)
+#define PWM_PHASEIN_ENABLE			(1UL << 25)
+#define PWM_PHASEIN_INT_ENABLE			(1UL << 24)
+#define PWM_PHASEIN_VB_COUNT			0x00001f00
+#define PWM_PHASEIN_INC				0x0000001f
+#define HISTOGRAM_INT_CTRL_CLEAR		(1UL << 30)
+#define DPST_YUV_LUMA_MODE			0
 
 struct dpst_ie_histogram_control {
 	union {
@@ -470,12 +469,12 @@ struct dpst_guardband {
 #define PIPEBFRAMEPIXEL		0x71044
 #define PIPECFRAMEHIGH		0x72040
 #define PIPECFRAMEPIXEL		0x72044
-#define PIPE_FRAME_HIGH_MASK    0x0000ffff
-#define PIPE_FRAME_HIGH_SHIFT   0
-#define PIPE_FRAME_LOW_MASK     0xff000000
-#define PIPE_FRAME_LOW_SHIFT    24
-#define PIPE_PIXEL_MASK         0x00ffffff
-#define PIPE_PIXEL_SHIFT        0
+#define PIPE_FRAME_HIGH_MASK	0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT	0
+#define PIPE_FRAME_LOW_MASK	0xff000000
+#define PIPE_FRAME_LOW_SHIFT	24
+#define PIPE_PIXEL_MASK		0x00ffffff
+#define PIPE_PIXEL_SHIFT	0
 
 #define DSPARB			0x70030
 #define DSPFW1			0x70034
@@ -488,30 +487,30 @@ struct dpst_guardband {
 #define DSPACNTR		0x70180
 #define DSPBCNTR		0x71180
 #define DSPCCNTR		0x72180
-#define DISPLAY_PLANE_ENABLE 			(1<<31)
+#define DISPLAY_PLANE_ENABLE			(1 << 31)
 #define DISPLAY_PLANE_DISABLE			0
-#define DISPPLANE_GAMMA_ENABLE			(1<<30)
+#define DISPPLANE_GAMMA_ENABLE			(1 << 30)
 #define DISPPLANE_GAMMA_DISABLE			0
-#define DISPPLANE_PIXFORMAT_MASK		(0xf<<26)
-#define DISPPLANE_8BPP				(0x2<<26)
-#define DISPPLANE_15_16BPP			(0x4<<26)
-#define DISPPLANE_16BPP				(0x5<<26)
-#define DISPPLANE_32BPP_NO_ALPHA 		(0x6<<26)
-#define DISPPLANE_32BPP				(0x7<<26)
-#define DISPPLANE_STEREO_ENABLE			(1<<25)
+#define DISPPLANE_PIXFORMAT_MASK		(0xf << 26)
+#define DISPPLANE_8BPP				(0x2 << 26)
+#define DISPPLANE_15_16BPP			(0x4 << 26)
+#define DISPPLANE_16BPP				(0x5 << 26)
+#define DISPPLANE_32BPP_NO_ALPHA		(0x6 << 26)
+#define DISPPLANE_32BPP				(0x7 << 26)
+#define DISPPLANE_STEREO_ENABLE			(1 << 25)
 #define DISPPLANE_STEREO_DISABLE		0
-#define DISPPLANE_SEL_PIPE_MASK			(1<<24)
+#define DISPPLANE_SEL_PIPE_MASK			(1 << 24)
 #define DISPPLANE_SEL_PIPE_POS			24
 #define DISPPLANE_SEL_PIPE_A			0
-#define DISPPLANE_SEL_PIPE_B			(1<<24)
-#define DISPPLANE_SRC_KEY_ENABLE		(1<<22)
+#define DISPPLANE_SEL_PIPE_B			(1 << 24)
+#define DISPPLANE_SRC_KEY_ENABLE		(1 << 22)
 #define DISPPLANE_SRC_KEY_DISABLE		0
-#define DISPPLANE_LINE_DOUBLE			(1<<20)
+#define DISPPLANE_LINE_DOUBLE			(1 << 20)
 #define DISPPLANE_NO_LINE_DOUBLE		0
 #define DISPPLANE_STEREO_POLARITY_FIRST		0
-#define DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
+#define DISPPLANE_STEREO_POLARITY_SECOND	(1 << 18)
 /* plane B only */
-#define DISPPLANE_ALPHA_TRANS_ENABLE		(1<<15)
+#define DISPPLANE_ALPHA_TRANS_ENABLE		(1 << 15)
 #define DISPPLANE_ALPHA_TRANS_DISABLE		0
 #define DISPPLANE_SPRITE_ABOVE_DISPLAYA		0
 #define DISPPLANE_SPRITE_ABOVE_OVERLAY		(1)
@@ -548,25 +547,25 @@ struct dpst_guardband {
 
 #define DSPCSURF		0x7219C
 #define DSPCTILEOFF		0x721A4
-#define DSPCKEYMAXVAL 		0x721A0
-#define DSPCKEYMINVAL 		0x72194
-#define DSPCKEYMSK 		0x72198
+#define DSPCKEYMAXVAL		0x721A0
+#define DSPCKEYMINVAL		0x72194
+#define DSPCKEYMSK		0x72198
 
 #define VGACNTRL		0x71400
-# define VGA_DISP_DISABLE			(1 << 31)
-# define VGA_2X_MODE				(1 << 30)
-# define VGA_PIPE_B_SELECT			(1 << 29)
+#define VGA_DISP_DISABLE		(1 << 31)
+#define VGA_2X_MODE			(1 << 30)
+#define VGA_PIPE_B_SELECT		(1 << 29)
 
 /*
  * Overlay registers
  */
 #define OV_C_OFFSET		0x08000
 #define OV_OVADD		0x30000
-#define OV_DOVASTA              0x30008
-# define OV_PIPE_SELECT				((1 << 6)|(1 << 7))
-# define OV_PIPE_SELECT_POS			6
-# define OV_PIPE_A				0
-# define OV_PIPE_C				1
+#define OV_DOVASTA		0x30008
+# define OV_PIPE_SELECT			((1 << 6)|(1 << 7))
+# define OV_PIPE_SELECT_POS		6
+# define OV_PIPE_A			0
+# define OV_PIPE_C			1
 #define OV_OGAMC5		0x30010
 #define OV_OGAMC4		0x30014
 #define OV_OGAMC3		0x30018
@@ -574,7 +573,7 @@ struct dpst_guardband {
 #define OV_OGAMC1		0x30020
 #define OV_OGAMC0		0x30024
 #define OVC_OVADD		0x38000
-#define OVC_DOVCSTA             0x38008
+#define OVC_DOVCSTA		0x38008
 #define OVC_OGAMC5		0x38010
 #define OVC_OGAMC4		0x38014
 #define OVC_OGAMC3		0x38018
@@ -627,16 +626,16 @@ struct dpst_guardband {
 
 /* Cursor A & B regs */
 #define CURACNTR		0x70080
-#define   CURSOR_MODE_DISABLE   0x00
-#define   CURSOR_MODE_64_32B_AX 0x07
-#define   CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
-#define   MCURSOR_GAMMA_ENABLE  (1 << 26)
+#define CURSOR_MODE_DISABLE		0x00
+#define CURSOR_MODE_64_32B_AX		0x07
+#define CURSOR_MODE_64_ARGB_AX		((1 << 5) | CURSOR_MODE_64_32B_AX)
+#define MCURSOR_GAMMA_ENABLE		(1 << 26)
 #define CURABASE		0x70084
 #define CURAPOS			0x70088
-#define   CURSOR_POS_MASK       0x007FF
-#define   CURSOR_POS_SIGN       0x8000
-#define   CURSOR_X_SHIFT        0
-#define   CURSOR_Y_SHIFT        16
+#define CURSOR_POS_MASK			0x007FF
+#define CURSOR_POS_SIGN			0x8000
+#define CURSOR_X_SHIFT			0
+#define CURSOR_Y_SHIFT			16
 #define CURBCNTR		0x700c0
 #define CURBBASE		0x700c4
 #define CURBPOS			0x700c8
@@ -647,22 +646,22 @@ struct dpst_guardband {
 /*
  * Interrupt Registers
  */
-#define IER 0x020a0
-#define IIR 0x020a4
-#define IMR 0x020a8
-#define ISR 0x020ac
+#define IER			0x020a0
+#define IIR			0x020a4
+#define IMR			0x020a8
+#define ISR			0x020ac
 
 /*
  * MOORESTOWN delta registers
  */
 #define MRST_DPLL_A		0x0f014
 #define MDFLD_DPLL_B		0x0f018
-#define MDFLD_INPUT_REF_SEL	(1 << 14)
-#define MDFLD_VCO_SEL		(1 << 16)
-#define DPLLA_MODE_LVDS		(2 << 26)	/* mrst */
-#define MDFLD_PLL_LATCHEN	(1 << 28)
-#define MDFLD_PWR_GATE_EN	(1 << 30)
-#define MDFLD_P1_MASK		(0x1FF << 17)
+#define MDFLD_INPUT_REF_SEL		(1 << 14)
+#define MDFLD_VCO_SEL			(1 << 16)
+#define DPLLA_MODE_LVDS			(2 << 26)	/* mrst */
+#define MDFLD_PLL_LATCHEN		(1 << 28)
+#define MDFLD_PWR_GATE_EN		(1 << 30)
+#define MDFLD_P1_MASK			(0x1FF << 17)
 #define MRST_FPA0		0x0f040
 #define MRST_FPA1		0x0f044
 #define MDFLD_DPLL_DIV0		0x0f048
@@ -672,45 +671,45 @@ struct dpst_guardband {
 /*
  * MEDFIELD HDMI registers
  */
-#define HDMIPHYMISCCTL   	0x61134
-# define HDMI_PHY_POWER_DOWN	0x7f
-#define HDMIB_CONTROL   	0x61140
-# define HDMIB_PORT_EN			(1 << 31)
-# define HDMIB_PIPE_B_SELECT		(1 << 30)
-# define HDMIB_NULL_PACKET		(1 << 9)
-#define HDMIB_HDCP_PORT (1 << 5)
+#define HDMIPHYMISCCTL		0x61134
+#define HDMI_PHY_POWER_DOWN		0x7f
+#define HDMIB_CONTROL		0x61140
+#define HDMIB_PORT_EN			(1 << 31)
+#define HDMIB_PIPE_B_SELECT		(1 << 30)
+#define HDMIB_NULL_PACKET		(1 << 9)
+#define HDMIB_HDCP_PORT			(1 << 5)
 
 /* #define LVDS			0x61180 */
-# define MRST_PANEL_8TO6_DITHER_ENABLE		(1 << 25)
-# define MRST_PANEL_24_DOT_1_FORMAT		(1 << 24)
-# define LVDS_A3_POWER_UP_0_OUTPUT		(1 << 6)
+#define MRST_PANEL_8TO6_DITHER_ENABLE	(1 << 25)
+#define MRST_PANEL_24_DOT_1_FORMAT	(1 << 24)
+#define LVDS_A3_POWER_UP_0_OUTPUT	(1 << 6)
 
 #define MIPI			0x61190
 #define MIPI_C			0x62190
-# define MIPI_PORT_EN			(1 << 31)
+#define MIPI_PORT_EN			(1 << 31)
 /* Turns on border drawing to allow centered display. */
-# define SEL_FLOPPED_HSTX		(1 << 23)
-# define PASS_FROM_SPHY_TO_AFE 		(1 << 16)
-# define MIPI_BORDER_EN			(1 << 15)
-# define MIPIA_3LANE_MIPIC_1LANE	0x1
-# define MIPIA_2LANE_MIPIC_2LANE	0x2
-# define TE_TRIGGER_DSI_PROTOCOL	(1 << 2)
-# define TE_TRIGGER_GPIO_PIN		(1 << 3)
-#define MIPI_TE_COUNT			0x61194
+#define SEL_FLOPPED_HSTX		(1 << 23)
+#define PASS_FROM_SPHY_TO_AFE		(1 << 16)
+#define MIPI_BORDER_EN			(1 << 15)
+#define MIPIA_3LANE_MIPIC_1LANE		0x1
+#define MIPIA_2LANE_MIPIC_2LANE		0x2
+#define TE_TRIGGER_DSI_PROTOCOL		(1 << 2)
+#define TE_TRIGGER_GPIO_PIN		(1 << 3)
+#define MIPI_TE_COUNT		0x61194
 
 /* #define PP_CONTROL	0x61204 */
-# define POWER_DOWN_ON_RESET		(1 << 1)
+#define POWER_DOWN_ON_RESET		(1 << 1)
 
 /* #define PFIT_CONTROL	0x61230 */
-# define PFIT_PIPE_SELECT				(3 << 29)
-# define PFIT_PIPE_SELECT_SHIFT			(29)
+#define PFIT_PIPE_SELECT		(3 << 29)
+#define PFIT_PIPE_SELECT_SHIFT		(29)
 
 /* #define BLC_PWM_CTL		0x61254 */
-#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT		(16)
-#define MRST_BACKLIGHT_MODULATION_FREQ_MASK		(0xffff << 16)
+#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT	(16)
+#define MRST_BACKLIGHT_MODULATION_FREQ_MASK	(0xffff << 16)
 
 /* #define PIPEACONF 0x70008 */
-#define PIPEACONF_PIPE_STATE	(1<<30)
+#define PIPEACONF_PIPE_STATE		(1 << 30)
 /* #define DSPACNTR		0x70180 */
 
 #define MRST_DSPABASE		0x7019c
@@ -724,281 +723,286 @@ struct dpst_guardband {
 /*
  *	MIPI IP registers
  */
-#define MIPIC_REG_OFFSET             0x800
-#define DEVICE_READY_REG             0xb000
-#define LP_OUTPUT_HOLD               (1 << 16)
-#define EXIT_ULPS_DEV_READY          0x3
-#define LP_OUTPUT_HOLD_RELEASE       0x810000
-# define ENTERING_ULPS		(2 << 1)
-# define EXITING_ULPS		(1 << 1)
-# define ULPS_MASK		(3 << 1)
-# define BUS_POSSESSION		(1 << 3)
-#define INTR_STAT_REG                0xb004
-#define RX_SOT_ERROR (1 << 0)
-#define RX_SOT_SYNC_ERROR (1 << 1)
-#define RX_ESCAPE_MODE_ENTRY_ERROR (1 << 3)
-#define RX_LP_TX_SYNC_ERROR (1 << 4)
-#define RX_HS_RECEIVE_TIMEOUT_ERROR (1 << 5)
-#define RX_FALSE_CONTROL_ERROR (1 << 6)
-#define RX_ECC_SINGLE_BIT_ERROR (1 << 7)
-#define RX_ECC_MULTI_BIT_ERROR (1 << 8)
-#define RX_CHECKSUM_ERROR (1 << 9)
-#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 10)
-#define RX_DSI_VC_ID_INVALID (1 << 11)
-#define TX_FALSE_CONTROL_ERROR (1 << 12)
-#define TX_ECC_SINGLE_BIT_ERROR (1 << 13)
-#define TX_ECC_MULTI_BIT_ERROR (1 << 14)
-#define TX_CHECKSUM_ERROR (1 << 15)
-#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 16)
-#define TX_DSI_VC_ID_INVALID (1 << 17)
-#define HIGH_CONTENTION (1 << 18)
-#define LOW_CONTENTION (1 << 19)
-#define DPI_FIFO_UNDER_RUN (1 << 20)
-#define HS_TX_TIMEOUT (1 << 21)
-#define LP_RX_TIMEOUT (1 << 22)
-#define TURN_AROUND_ACK_TIMEOUT (1 << 23)
-#define ACK_WITH_NO_ERROR (1 << 24)
-#define HS_GENERIC_WR_FIFO_FULL (1 << 27)
-#define LP_GENERIC_WR_FIFO_FULL (1 << 28)
-#define SPL_PKT_SENT			(1 << 30)
-#define INTR_EN_REG                  0xb008
-#define DSI_FUNC_PRG_REG             0xb00c
-#define DPI_CHANNEL_NUMBER_POS   0x03
-#define DBI_CHANNEL_NUMBER_POS   0x05
-#define FMT_DPI_POS              0x07
-#define FMT_DBI_POS              0x0A
-#define DBI_DATA_WIDTH_POS       0x0D
+#define MIPIC_REG_OFFSET		0x800
+
+#define DEVICE_READY_REG		0xb000
+#define LP_OUTPUT_HOLD				(1 << 16)
+#define EXIT_ULPS_DEV_READY			0x3
+#define LP_OUTPUT_HOLD_RELEASE			0x810000
+# define ENTERING_ULPS				(2 << 1)
+# define EXITING_ULPS				(1 << 1)
+# define ULPS_MASK				(3 << 1)
+# define BUS_POSSESSION				(1 << 3)
+#define INTR_STAT_REG			0xb004
+#define RX_SOT_ERROR				(1 << 0)
+#define RX_SOT_SYNC_ERROR			(1 << 1)
+#define RX_ESCAPE_MODE_ENTRY_ERROR		(1 << 3)
+#define RX_LP_TX_SYNC_ERROR			(1 << 4)
+#define RX_HS_RECEIVE_TIMEOUT_ERROR		(1 << 5)
+#define RX_FALSE_CONTROL_ERROR			(1 << 6)
+#define RX_ECC_SINGLE_BIT_ERROR			(1 << 7)
+#define RX_ECC_MULTI_BIT_ERROR			(1 << 8)
+#define RX_CHECKSUM_ERROR			(1 << 9)
+#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED		(1 << 10)
+#define RX_DSI_VC_ID_INVALID			(1 << 11)
+#define TX_FALSE_CONTROL_ERROR			(1 << 12)
+#define TX_ECC_SINGLE_BIT_ERROR			(1 << 13)
+#define TX_ECC_MULTI_BIT_ERROR			(1 << 14)
+#define TX_CHECKSUM_ERROR			(1 << 15)
+#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED		(1 << 16)
+#define TX_DSI_VC_ID_INVALID			(1 << 17)
+#define HIGH_CONTENTION				(1 << 18)
+#define LOW_CONTENTION				(1 << 19)
+#define DPI_FIFO_UNDER_RUN			(1 << 20)
+#define HS_TX_TIMEOUT				(1 << 21)
+#define LP_RX_TIMEOUT				(1 << 22)
+#define TURN_AROUND_ACK_TIMEOUT			(1 << 23)
+#define ACK_WITH_NO_ERROR			(1 << 24)
+#define HS_GENERIC_WR_FIFO_FULL			(1 << 27)
+#define LP_GENERIC_WR_FIFO_FULL			(1 << 28)
+#define SPL_PKT_SENT				(1 << 30)
+#define INTR_EN_REG			0xb008
+#define DSI_FUNC_PRG_REG		0xb00c
+#define DPI_CHANNEL_NUMBER_POS			0x03
+#define DBI_CHANNEL_NUMBER_POS			0x05
+#define FMT_DPI_POS				0x07
+#define FMT_DBI_POS				0x0A
+#define DBI_DATA_WIDTH_POS			0x0D
+
 /* DPI PIXEL FORMATS */
-#define RGB_565_FMT		     0x01	/* RGB 565 FORMAT */
-#define RGB_666_FMT		     0x02	/* RGB 666 FORMAT */
-#define LRGB_666_FMT		     0x03	/* RGB LOOSELY PACKED
-						 * 666 FORMAT
-						 */
-#define RGB_888_FMT		     0x04	/* RGB 888 FORMAT */
-#define VIRTUAL_CHANNEL_NUMBER_0	0x00	/* Virtual channel 0 */
-#define VIRTUAL_CHANNEL_NUMBER_1	0x01	/* Virtual channel 1 */
-#define VIRTUAL_CHANNEL_NUMBER_2	0x02	/* Virtual channel 2 */
-#define VIRTUAL_CHANNEL_NUMBER_3	0x03	/* Virtual channel 3 */
-#define DBI_NOT_SUPPORTED		0x00	/* command mode
-						 * is not supported
-						 */
-#define DBI_DATA_WIDTH_16BIT		0x01	/* 16 bit data */
+#define RGB_565_FMT				0x01	/* RGB 565 FORMAT */
+#define RGB_666_FMT				0x02	/* RGB 666 FORMAT */
+#define LRGB_666_FMT				0x03	/* RGB LOOSELY PACKED
+							 * 666 FORMAT
+							 */
+#define RGB_888_FMT				0x04	/* RGB 888 FORMAT */
+#define VIRTUAL_CHANNEL_NUMBER_0		0x00	/* Virtual channel 0 */
+#define VIRTUAL_CHANNEL_NUMBER_1		0x01	/* Virtual channel 1 */
+#define VIRTUAL_CHANNEL_NUMBER_2		0x02	/* Virtual channel 2 */
+#define VIRTUAL_CHANNEL_NUMBER_3		0x03	/* Virtual channel 3 */
+
+#define DBI_NOT_SUPPORTED			0x00	/* command mode
+							 * is not supported
+							 */
+#define DBI_DATA_WIDTH_16BIT			0x01	/* 16 bit data */
 #define DBI_DATA_WIDTH_9BIT			0x02	/* 9 bit data */
 #define DBI_DATA_WIDTH_8BIT			0x03	/* 8 bit data */
-#define DBI_DATA_WIDTH_OPT1		0x04	/* option 1 */
-#define DBI_DATA_WIDTH_OPT2		0x05	/* option 2 */
-#define HS_TX_TIMEOUT_REG            0xb010
-#define LP_RX_TIMEOUT_REG            0xb014
-#define TURN_AROUND_TIMEOUT_REG      0xb018
-#define DEVICE_RESET_REG             0xb01C
-#define DPI_RESOLUTION_REG           0xb020
-#define RES_V_POS                0x10
-#define DBI_RESOLUTION_REG           0xb024 /* Reserved for MDFLD */
-#define HORIZ_SYNC_PAD_COUNT_REG     0xb028
-#define HORIZ_BACK_PORCH_COUNT_REG   0xb02C
-#define HORIZ_FRONT_PORCH_COUNT_REG  0xb030
-#define HORIZ_ACTIVE_AREA_COUNT_REG  0xb034
-#define VERT_SYNC_PAD_COUNT_REG      0xb038
-#define VERT_BACK_PORCH_COUNT_REG    0xb03c
-#define VERT_FRONT_PORCH_COUNT_REG   0xb040
-#define HIGH_LOW_SWITCH_COUNT_REG    0xb044
-#define DPI_CONTROL_REG              0xb048
-#define DPI_SHUT_DOWN            (1 << 0)
-#define DPI_TURN_ON              (1 << 1)
-#define DPI_COLOR_MODE_ON        (1 << 2)
-#define DPI_COLOR_MODE_OFF       (1 << 3)
-#define DPI_BACK_LIGHT_ON        (1 << 4)
-#define DPI_BACK_LIGHT_OFF       (1 << 5)
-#define DPI_LP                   (1 << 6)
-#define DPI_DATA_REG                 0xb04c
-#define DPI_BACK_LIGHT_ON_DATA   0x07
-#define DPI_BACK_LIGHT_OFF_DATA  0x17
-#define INIT_COUNT_REG               0xb050
-#define MAX_RET_PAK_REG              0xb054
-#define VIDEO_FMT_REG                0xb058
-#define COMPLETE_LAST_PCKT       (1 << 2)
-#define EOT_DISABLE_REG              0xb05c
-#define ENABLE_CLOCK_STOPPING    (1 << 1)
-#define LP_BYTECLK_REG               0xb060
-#define LP_GEN_DATA_REG              0xb064
-#define HS_GEN_DATA_REG              0xb068
-#define LP_GEN_CTRL_REG              0xb06C
-#define HS_GEN_CTRL_REG              0xb070
-#define DCS_CHANNEL_NUMBER_POS   0x06
-#define MCS_COMMANDS_POS	0x8
-#define WORD_COUNTS_POS		0x8
-#define MCS_PARAMETER_POS	0x10
-#define GEN_FIFO_STAT_REG            0xb074
-#define HS_DATA_FIFO_FULL        (1 << 0)
-#define HS_DATA_FIFO_HALF_EMPTY  (1 << 1)
-#define HS_DATA_FIFO_EMPTY       (1 << 2)
-#define LP_DATA_FIFO_FULL        (1 << 8)
-#define LP_DATA_FIFO_HALF_EMPTY  (1 << 9)
-#define LP_DATA_FIFO_EMPTY       (1 << 10)
-#define HS_CTRL_FIFO_FULL        (1 << 16)
-#define HS_CTRL_FIFO_HALF_EMPTY  (1 << 17)
-#define HS_CTRL_FIFO_EMPTY       (1 << 18)
-#define LP_CTRL_FIFO_FULL        (1 << 24)
-#define LP_CTRL_FIFO_HALF_EMPTY  (1 << 25)
-#define LP_CTRL_FIFO_EMPTY       (1 << 26)
-#define DBI_FIFO_EMPTY           (1 << 27)
-#define DPI_FIFO_EMPTY           (1 << 28)
-#define HS_LS_DBI_ENABLE_REG         0xb078
-#define TXCLKESC_REG		     0xb07c
-#define DPHY_PARAM_REG               0xb080
-#define DBI_BW_CTRL_REG              0xb084
-#define CLK_LANE_SWT_REG             0xb088
+#define DBI_DATA_WIDTH_OPT1			0x04	/* option 1 */
+#define DBI_DATA_WIDTH_OPT2			0x05	/* option 2 */
+
+#define HS_TX_TIMEOUT_REG		0xb010
+#define LP_RX_TIMEOUT_REG		0xb014
+#define TURN_AROUND_TIMEOUT_REG		0xb018
+#define DEVICE_RESET_REG		0xb01C
+#define DPI_RESOLUTION_REG		0xb020
+#define RES_V_POS				0x10
+#define DBI_RESOLUTION_REG		0xb024 /* Reserved for MDFLD */
+#define HORIZ_SYNC_PAD_COUNT_REG	0xb028
+#define HORIZ_BACK_PORCH_COUNT_REG	0xb02C
+#define HORIZ_FRONT_PORCH_COUNT_REG	0xb030
+#define HORIZ_ACTIVE_AREA_COUNT_REG	0xb034
+#define VERT_SYNC_PAD_COUNT_REG		0xb038
+#define VERT_BACK_PORCH_COUNT_REG	0xb03c
+#define VERT_FRONT_PORCH_COUNT_REG	0xb040
+#define HIGH_LOW_SWITCH_COUNT_REG	0xb044
+#define DPI_CONTROL_REG			0xb048
+#define DPI_SHUT_DOWN				(1 << 0)
+#define DPI_TURN_ON				(1 << 1)
+#define DPI_COLOR_MODE_ON			(1 << 2)
+#define DPI_COLOR_MODE_OFF			(1 << 3)
+#define DPI_BACK_LIGHT_ON			(1 << 4)
+#define DPI_BACK_LIGHT_OFF			(1 << 5)
+#define DPI_LP					(1 << 6)
+#define DPI_DATA_REG			0xb04c
+#define DPI_BACK_LIGHT_ON_DATA			0x07
+#define DPI_BACK_LIGHT_OFF_DATA			0x17
+#define INIT_COUNT_REG			0xb050
+#define MAX_RET_PAK_REG			0xb054
+#define VIDEO_FMT_REG			0xb058
+#define COMPLETE_LAST_PCKT			(1 << 2)
+#define EOT_DISABLE_REG			0xb05c
+#define ENABLE_CLOCK_STOPPING			(1 << 1)
+#define LP_BYTECLK_REG			0xb060
+#define LP_GEN_DATA_REG			0xb064
+#define HS_GEN_DATA_REG			0xb068
+#define LP_GEN_CTRL_REG			0xb06C
+#define HS_GEN_CTRL_REG			0xb070
+#define DCS_CHANNEL_NUMBER_POS		0x6
+#define MCS_COMMANDS_POS		0x8
+#define WORD_COUNTS_POS			0x8
+#define MCS_PARAMETER_POS			0x10
+#define GEN_FIFO_STAT_REG		0xb074
+#define HS_DATA_FIFO_FULL			(1 << 0)
+#define HS_DATA_FIFO_HALF_EMPTY			(1 << 1)
+#define HS_DATA_FIFO_EMPTY			(1 << 2)
+#define LP_DATA_FIFO_FULL			(1 << 8)
+#define LP_DATA_FIFO_HALF_EMPTY			(1 << 9)
+#define LP_DATA_FIFO_EMPTY			(1 << 10)
+#define HS_CTRL_FIFO_FULL			(1 << 16)
+#define HS_CTRL_FIFO_HALF_EMPTY			(1 << 17)
+#define HS_CTRL_FIFO_EMPTY			(1 << 18)
+#define LP_CTRL_FIFO_FULL			(1 << 24)
+#define LP_CTRL_FIFO_HALF_EMPTY			(1 << 25)
+#define LP_CTRL_FIFO_EMPTY			(1 << 26)
+#define DBI_FIFO_EMPTY				(1 << 27)
+#define DPI_FIFO_EMPTY				(1 << 28)
+#define HS_LS_DBI_ENABLE_REG		0xb078
+#define TXCLKESC_REG			0xb07c
+#define DPHY_PARAM_REG			0xb080
+#define DBI_BW_CTRL_REG			0xb084
+#define CLK_LANE_SWT_REG		0xb088
 
 /*
  * MIPI Adapter registers
  */
-#define MIPI_CONTROL_REG             0xb104
-#define MIPI_2X_CLOCK_BITS       ((1 << 0) | (1 << 1))
-#define MIPI_DATA_ADDRESS_REG        0xb108
-#define MIPI_DATA_LENGTH_REG         0xb10C
-#define MIPI_COMMAND_ADDRESS_REG     0xb110
-#define MIPI_COMMAND_LENGTH_REG      0xb114
-#define MIPI_READ_DATA_RETURN_REG0   0xb118
-#define MIPI_READ_DATA_RETURN_REG1   0xb11C
-#define MIPI_READ_DATA_RETURN_REG2   0xb120
-#define MIPI_READ_DATA_RETURN_REG3   0xb124
-#define MIPI_READ_DATA_RETURN_REG4   0xb128
-#define MIPI_READ_DATA_RETURN_REG5   0xb12C
-#define MIPI_READ_DATA_RETURN_REG6   0xb130
-#define MIPI_READ_DATA_RETURN_REG7   0xb134
-#define MIPI_READ_DATA_VALID_REG     0xb138
+#define MIPI_CONTROL_REG		0xb104
+#define MIPI_2X_CLOCK_BITS			((1 << 0) | (1 << 1))
+#define MIPI_DATA_ADDRESS_REG		0xb108
+#define MIPI_DATA_LENGTH_REG		0xb10C
+#define MIPI_COMMAND_ADDRESS_REG	0xb110
+#define MIPI_COMMAND_LENGTH_REG		0xb114
+#define MIPI_READ_DATA_RETURN_REG0	0xb118
+#define MIPI_READ_DATA_RETURN_REG1	0xb11C
+#define MIPI_READ_DATA_RETURN_REG2	0xb120
+#define MIPI_READ_DATA_RETURN_REG3	0xb124
+#define MIPI_READ_DATA_RETURN_REG4	0xb128
+#define MIPI_READ_DATA_RETURN_REG5	0xb12C
+#define MIPI_READ_DATA_RETURN_REG6	0xb130
+#define MIPI_READ_DATA_RETURN_REG7	0xb134
+#define MIPI_READ_DATA_VALID_REG	0xb138
+
 /* DBI COMMANDS */
-#define soft_reset                   0x01
+#define soft_reset			0x01
 /*
  *	The display module performs a software reset.
  *	Registers are written with their SW Reset default values.
  */
-#define get_power_mode               0x0a
+#define get_power_mode			0x0a
 /*
  *	The display module returns the current power mode
  */
-#define get_address_mode             0x0b
+#define get_address_mode		0x0b
 /*
  *	The display module returns the current status.
  */
-#define get_pixel_format             0x0c
+#define get_pixel_format		0x0c
 /*
  *	This command gets the pixel format for the RGB image data
  *	used by the interface.
  */
-#define get_display_mode             0x0d
+#define get_display_mode		0x0d
 /*
  *	The display module returns the Display Image Mode status.
  */
-#define get_signal_mode              0x0e
+#define get_signal_mode			0x0e
 /*
  *	The display module returns the Display Signal Mode.
  */
-#define get_diagnostic_result        0x0f
+#define get_diagnostic_result		0x0f
 /*
  *	The display module returns the self-diagnostic results following
  *	a Sleep Out command.
  */
-#define enter_sleep_mode             0x10
+#define enter_sleep_mode		0x10
 /*
  *	This command causes the display module to enter the Sleep mode.
  *	In this mode, all unnecessary blocks inside the display module are
  *	disabled except interface communication. This is the lowest power
  *	mode the display module supports.
  */
-#define exit_sleep_mode              0x11
+#define exit_sleep_mode			0x11
 /*
  *	This command causes the display module to exit Sleep mode.
  *	All blocks inside the display module are enabled.
  */
-#define enter_partial_mode           0x12
+#define enter_partial_mode		0x12
 /*
  *	This command causes the display module to enter the Partial Display
  *	Mode. The Partial Display Mode window is described by the
  *	set_partial_area command.
  */
-#define enter_normal_mode            0x13
+#define enter_normal_mode		0x13
 /*
  *	This command causes the display module to enter the Normal mode.
  *	Normal Mode is defined as Partial Display mode and Scroll mode are off
  */
-#define exit_invert_mode             0x20
+#define exit_invert_mode		0x20
 /*
  *	This command causes the display module to stop inverting the image
  *	data on the display device. The frame memory contents remain unchanged.
  *	No status bits are changed.
  */
-#define enter_invert_mode            0x21
+#define enter_invert_mode		0x21
 /*
  *	This command causes the display module to invert the image data only on
  *	the display device. The frame memory contents remain unchanged.
  *	No status bits are changed.
  */
-#define set_gamma_curve              0x26
+#define set_gamma_curve			0x26
 /*
  *	This command selects the desired gamma curve for the display device.
  *	Four fixed gamma curves are defined in section DCS spec.
  */
-#define set_display_off              0x28
+#define set_display_off			0x28
 /* ************************************************************************* *\
 This command causes the display module to stop displaying the image data
 on the display device. The frame memory contents remain unchanged.
 No status bits are changed.
 \* ************************************************************************* */
-#define set_display_on               0x29
+#define set_display_on			0x29
 /* ************************************************************************* *\
 This command causes the display module to start displaying the image data
 on the display device. The frame memory contents remain unchanged.
 No status bits are changed.
 \* ************************************************************************* */
-#define set_column_address           0x2a
+#define set_column_address		0x2a
 /*
  *	This command defines the column extent of the frame memory accessed by
  *	the hostprocessor with the read_memory_continue and
  *	write_memory_continue commands.
  *	No status bits are changed.
  */
-#define set_page_addr             0x2b
+#define set_page_addr			0x2b
 /*
  *	This command defines the page extent of the frame memory accessed by
  *	the host processor with the write_memory_continue and
- *	read_memory_continue command. 
+ *	read_memory_continue command.
  *	No status bits are changed.
  */
-#define write_mem_start              0x2c
+#define write_mem_start			0x2c
 /*
  *	This command transfers image data from the host processor to the
- *	display module s frame memory starting at the pixel location specified
+ *	display modules frame memory starting at the pixel location specified
  *	by preceding set_column_address and set_page_address commands.
  */
-#define set_partial_area             0x30
+#define set_partial_area		0x30
 /*
  *	This command defines the Partial Display mode s display area.
  *	There are two parameters associated with this command, the first
  *	defines the Start Row (SR) and the second the End Row (ER). SR and ER
  *	refer to the Frame Memory Line Pointer.
  */
-#define set_scroll_area              0x33
+#define set_scroll_area			0x33
 /*
  *	This command defines the display modules Vertical Scrolling Area.
  */
-#define set_tear_off                 0x34
+#define set_tear_off			0x34
 /*
  *	This command turns off the display modules Tearing Effect output
  *	signal on the TE signal line.
  */
-#define set_tear_on                  0x35
+#define set_tear_on			0x35
 /*
  *	This command turns on the display modules Tearing Effect output signal
  *	on the TE signal line.
  */
-#define set_address_mode             0x36
+#define set_address_mode		0x36
 /*
  *	This command sets the data order for transfers from the host processor
  *	to display modules frame memory,bits B[7:5] and B3, and from the
  *	display modules frame memory to the display device, bits B[2:0] and B4.
  */
-#define set_scroll_start             0x37
+#define set_scroll_start		0x37
 /*
  *	This command sets the start of the vertical scrolling area in the frame
  *	memory. The vertical scrolling area is fully defined when this command
@@ -1007,18 +1011,18 @@ No status bits are changed.
  *	line in the frame memory that is written to the display device as the
  *	first line of the vertical scroll area.
  */
-#define exit_idle_mode               0x38
+#define exit_idle_mode			0x38
 /*
  *	This command causes the display module to exit Idle mode.
  */
-#define enter_idle_mode              0x39
+#define enter_idle_mode			0x39
 /*
  *	This command causes the display module to enter Idle Mode.
  *	In Idle Mode, color expression is reduced. Colors are shown on the
  *	display device using the MSB of each of the R, G and B color
  *	components in the frame memory
  */
-#define set_pixel_format             0x3a
+#define set_pixel_format		0x3a
 /*
  *	This command sets the pixel format for the RGB image data used by the
  *	interface.
@@ -1026,25 +1030,27 @@ No status bits are changed.
  *	Bits D[2:0]  DBI Pixel Format Definition
  *	Bits D7 and D3 are not used.
  */
-  #define DCS_PIXEL_FORMAT_3bbp	 	0x1
-  #define DCS_PIXEL_FORMAT_8bbp 	0x2
-  #define DCS_PIXEL_FORMAT_12bbp 	0x3
-  #define DCS_PIXEL_FORMAT_16bbp	0x5
-  #define DCS_PIXEL_FORMAT_18bbp	0x6
-  #define DCS_PIXEL_FORMAT_24bbp 	0x7
-#define write_mem_cont               0x3c
+#define DCS_PIXEL_FORMAT_3bpp		0x1
+#define DCS_PIXEL_FORMAT_8bpp		0x2
+#define DCS_PIXEL_FORMAT_12bpp		0x3
+#define DCS_PIXEL_FORMAT_16bpp		0x5
+#define DCS_PIXEL_FORMAT_18bpp		0x6
+#define DCS_PIXEL_FORMAT_24bpp		0x7
+
+#define write_mem_cont			0x3c
+
 /*
  *	This command transfers image data from the host processor to the
  *	display module's frame memory continuing from the pixel location
  *	following the previous write_memory_continue or write_memory_start
  *	command.
  */
-#define set_tear_scanline            0x44
+#define set_tear_scanline		0x44
 /*
  *	This command turns on the display modules Tearing Effect output signal
  *	on the TE signal line when the display module reaches line N.
  */
-#define get_scanline                 0x45
+#define get_scanline			0x45
 /*
  *	The display module returns the current scanline, N, used to update the
  *	 display device. The total number of scanlines on a display device is
@@ -1094,22 +1100,22 @@ No status bits are changed.
 #define GAMMA_AUTO		(1 << 0)
 
 /* DCS Interface Pixel Formats */
-#define DCS_PIXEL_FORMAT_3BPP         0x1
-#define DCS_PIXEL_FORMAT_8BPP         0x2
-#define DCS_PIXEL_FORMAT_12BPP        0x3
-#define DCS_PIXEL_FORMAT_16BPP        0x5
-#define DCS_PIXEL_FORMAT_18BPP        0x6
-#define DCS_PIXEL_FORMAT_24BPP        0x7
+#define DCS_PIXEL_FORMAT_3BPP	0x1
+#define DCS_PIXEL_FORMAT_8BPP	0x2
+#define DCS_PIXEL_FORMAT_12BPP	0x3
+#define DCS_PIXEL_FORMAT_16BPP	0x5
+#define DCS_PIXEL_FORMAT_18BPP	0x6
+#define DCS_PIXEL_FORMAT_24BPP	0x7
 /* ONE PARAMETER READ DATA */
-#define addr_mode_data           0xfc
-#define diag_res_data            0x00
-#define disp_mode_data           0x23
-#define pxl_fmt_data             0x77
-#define pwr_mode_data            0x74
-#define sig_mode_data            0x00
+#define addr_mode_data		0xfc
+#define diag_res_data		0x00
+#define disp_mode_data		0x23
+#define pxl_fmt_data		0x77
+#define pwr_mode_data		0x74
+#define sig_mode_data		0x00
 /* TWO PARAMETERS READ DATA */
-#define scanline_data1           0xff
-#define scanline_data2           0xff
+#define scanline_data1		0xff
+#define scanline_data2		0xff
 #define NON_BURST_MODE_SYNC_PULSE	0x01	/* Non Burst Mode
 						 * with Sync Pulse
 						 */
@@ -1117,7 +1123,8 @@ No status bits are changed.
 						 * with Sync events
 						 */
 #define BURST_MODE			0x03	/* Burst Mode */
-#define DBI_COMMAND_BUFFER_SIZE		0x240  /* 0x32 */    /* 0x120 */	/* Allocate at least
+#define DBI_COMMAND_BUFFER_SIZE		0x240   /* 0x32 */    /* 0x120 */
+						/* Allocate at least
 						 * 0x100 Byte with 32
 						 * byte alignment
 						 */
@@ -1125,13 +1132,13 @@ No status bits are changed.
 						 * 0x100 Byte with 32
 						 * byte alignment
 						 */
-#define DBI_CB_TIME_OUT 0xFFFF
-
-#define GEN_FB_TIME_OUT 2000 
-#define ALIGNMENT_32BYTE_MASK		(~((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)))
-#define SKU_83 						0x01
-#define SKU_100 					0x02
-#define SKU_100L 					0x04
-#define SKU_BYPASS 					0x08
+#define DBI_CB_TIME_OUT			0xFFFF
+
+#define GEN_FB_TIME_OUT			2000
+
+#define SKU_83				0x01
+#define SKU_100				0x02
+#define SKU_100L			0x04
+#define SKU_BYPASS			0x08
 
 #endif
diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c
index e313ce2..a4bad1a 100644
--- a/drivers/staging/gma500/psb_intel_sdvo.c
+++ b/drivers/staging/gma500/psb_intel_sdvo.c
@@ -211,7 +211,8 @@ static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output,
 		     sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]);
 		     i++) {
 			if (cmd == sdvo_cmd_names[i].cmd) {
-				printk(KERN_CONT "(%s)", sdvo_cmd_names[i].name);
+				printk(KERN_CONT
+					"(%s)", sdvo_cmd_names[i].name);
 				break;
 			}
 		}
diff --git a/drivers/staging/gma500/psb_intel_sdvo_regs.h b/drivers/staging/gma500/psb_intel_sdvo_regs.h
index c7107a3..96862ea 100644
--- a/drivers/staging/gma500/psb_intel_sdvo_regs.h
+++ b/drivers/staging/gma500/psb_intel_sdvo_regs.h
@@ -51,7 +51,7 @@ struct psb_intel_sdvo_caps {
 	unsigned int stall_support:1;
 	unsigned int pad:1;
 	u16 output_flags;
-} __attribute__ ((packed));
+} __packed;
 
 /** This matches the EDID DTD structure, more or less */
 struct psb_intel_sdvo_dtd {
@@ -82,18 +82,18 @@ struct psb_intel_sdvo_dtd {
 		u8 v_sync_off_high;
 		u8 reserved;
 	} part2;
-} __attribute__ ((packed));
+} __packed;
 
 struct psb_intel_sdvo_pixel_clock_range {
 	u16 min;		/**< pixel clock, in 10kHz units */
 	u16 max;		/**< pixel clock, in 10kHz units */
-} __attribute__ ((packed));
+} __packed;
 
 struct psb_intel_sdvo_preferred_input_timing_args {
 	u16 clock;
 	u16 width;
 	u16 height;
-} __attribute__ ((packed));
+} __packed;
 
 /* I2C registers for SDVO */
 #define SDVO_I2C_ARG_0				0x07
@@ -147,7 +147,7 @@ struct psb_intel_sdvo_get_trained_inputs_response {
 	unsigned int input0_trained:1;
 	unsigned int input1_trained:1;
 	unsigned int pad:6;
-} __attribute__ ((packed));
+} __packed;
 
 /** Returns a struct psb_intel_sdvo_output_flags of active outputs. */
 #define SDVO_CMD_GET_ACTIVE_OUTPUTS			0x04
@@ -201,7 +201,7 @@ struct psb_intel_sdvo_get_interrupt_event_source_response {
 	u16 interrupt_status;
 	unsigned int ambient_light_interrupt:1;
 	unsigned int pad:7;
-} __attribute__ ((packed));
+} __packed;
 
 /**
  * Selects which input is affected by future input commands.
@@ -214,7 +214,7 @@ struct psb_intel_sdvo_get_interrupt_event_source_response {
 struct psb_intel_sdvo_set_target_input_args {
 	unsigned int target_1:1;
 	unsigned int pad:7;
-} __attribute__ ((packed));
+} __packed;
 
 /**
  * Takes a struct psb_intel_sdvo_output_flags of which outputs are targeted by
diff --git a/drivers/staging/gma500/psb_reg.h b/drivers/staging/gma500/psb_reg.h
index 529fda8..b81c7c1 100644
--- a/drivers/staging/gma500/psb_reg.h
+++ b/drivers/staging/gma500/psb_reg.h
@@ -22,161 +22,157 @@
 #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)
+#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.
@@ -186,121 +182,121 @@
  * 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)
+#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)
+#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)
+#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)
+#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)
+#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)
+#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)
+#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)
+#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)
+#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)
+#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)
+#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
@@ -310,118 +306,118 @@
  *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)
+#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)
+#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_ROP3A_MASK		(0x000000FF)
+#define PSB_2D_ROP3A_CLRMASK		(0xFFFFFF00)
+#define PSB_2D_ROP3A_SHIFT		(0)
 
-#define PSB_2D_ROP4_MASK                 (0x0000FFFF)
+#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)
+#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)
+#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)
+#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
+ * 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)
+#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)
+#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)
@@ -430,31 +426,31 @@
  *  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)
+#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)
+#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)
@@ -463,26 +459,26 @@
  * 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)
+#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)
+#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)
@@ -490,99 +486,97 @@
 /*
  * WORD 0
  */
-#define PSB_2D_MASK_STRIDE_MASK          (0x00007FFF)
-#define PSB_2D_MASK_STRIDE_CLRMASK       (0xFFFF8000)
-#define PSB_2D_MASK_STRIDE_SHIFT         (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)
+#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)
+#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)
+#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)
-
+#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
+#define PSB_SCENE_HW_COOKIE_SIZE	16
+#define PSB_TA_MEM_HW_COOKIE_SIZE	16
 
 /*
  * Scene stuff.
  */
 
-#define PSB_NUM_HW_SCENES          2
+#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
+#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 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
+#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


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 13/49] gma500: 2D polish
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (11 preceding siblings ...)
  2011-07-05 14:36 ` [PATCH 12/49] gma500: CodingStyle pass Alan Cox
@ 2011-07-05 14:36 ` Alan Cox
  2011-07-05 14:36 ` [PATCH 14/49] gma500: Medfield support Alan Cox
                   ` (36 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:36 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Tidy up the 2D bits. For the fill case the CPU seems to be able to
outperform the graphics engine for the cases we get, so don't bother
fixing it but throw it out.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_2d.c  |  191 ++++++++++++++------------------------
 drivers/staging/gma500/psb_drv.h |    6 -
 drivers/staging/gma500/psb_fb.c  |    4 -
 3 files changed, 74 insertions(+), 127 deletions(-)

diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c
index dea4bc1..df4c519 100644
--- a/drivers/staging/gma500/psb_2d.c
+++ b/drivers/staging/gma500/psb_2d.c
@@ -41,6 +41,14 @@
 #include "psb_drv.h"
 #include "psb_fb.h"
 
+/**
+ *	psb_spank		-	reset the 2D engine
+ *	@dev_priv: our PSB DRM device
+ *
+ *	Soft reset the graphics engine and then reload the necessary registers.
+ *	We use this at initialisation time but it will become relevant for
+ *	accelerated X later
+ */
 void psb_spank(struct drm_psb_private *dev_priv)
 {
 	PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
@@ -65,6 +73,14 @@ void psb_spank(struct drm_psb_private *dev_priv)
 	PSB_WSGX32(dev_priv->pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
 }
 
+/**
+ *	psb2_2d_wait_available	-	wait for FIFO room
+ *	@dev_priv: our DRM device
+ *	@size: size (in dwords) of the command we want to issue
+ *
+ *	Wait until there is room to load the FIFO with our data. If the
+ *	device is not responding then reset it
+ */
 static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
 			  unsigned size)
 {
@@ -81,9 +97,15 @@ static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
 	return 0;
 }
 
-/* FIXME: Remember if we expose the 2D engine to the DRM we need to serialize
-   it with console use */
-
+/**
+ *	psb_2d_submit		-	submit a 2D command
+ *	@dev_priv: our DRM device
+ *	@cmdbuf: command to issue
+ *	@size: length (in dwords)
+ *
+ *	Issue one or more 2D commands to the accelerator. This needs to be
+ *	serialized later when we add the GEM interfaces for acceleration
+ */
 int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
 								unsigned size)
 {
@@ -108,104 +130,15 @@ int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
 	return 0;
 }
 
-static int psb_accel_2d_fillrect(struct drm_psb_private *dev_priv,
-				 uint32_t dst_offset, uint32_t dst_stride,
-				 uint32_t dst_format, uint16_t dst_x,
-				 uint16_t dst_y, uint16_t size_x,
-				 uint16_t size_y, uint32_t fill)
-{
-	uint32_t buffer[10];
-	uint32_t *buf;
-
-	buf = buffer;
-
-	*buf++ = PSB_2D_FENCE_BH;
-
-	*buf++ =
-	    PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
-					       PSB_2D_DST_STRIDE_SHIFT);
-	*buf++ = dst_offset;
-
-	*buf++ =
-	    PSB_2D_BLIT_BH |
-	    PSB_2D_ROT_NONE |
-	    PSB_2D_COPYORDER_TL2BR |
-	    PSB_2D_DSTCK_DISABLE |
-	    PSB_2D_SRCCK_DISABLE | PSB_2D_USE_FILL | PSB_2D_ROP3_PATCOPY;
-
-	*buf++ = fill << PSB_2D_FILLCOLOUR_SHIFT;
-	*buf++ =
-	    (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
-						  PSB_2D_DST_YSTART_SHIFT);
-	*buf++ =
-	    (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
-						  PSB_2D_DST_YSIZE_SHIFT);
-	*buf++ = PSB_2D_FLUSH_BH;
-
-	return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
-}
-
-static void psbfb_fillrect_accel(struct fb_info *info,
-				 const struct fb_fillrect *r)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = &fbdev->pfb;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	uint32_t offset;
-	uint32_t stride;
-	uint32_t format;
-
-	if (!fb)
-		return;
-
-	offset = psbfb->gtt->offset;
-	stride = fb->pitch;
-
-	switch (fb->depth) {
-	case 8:
-		format = PSB_2D_DST_332RGB;
-		break;
-	case 15:
-		format = PSB_2D_DST_555RGB;
-		break;
-	case 16:
-		format = PSB_2D_DST_565RGB;
-		break;
-	case 24:
-	case 32:
-		/* this is wrong but since we don't do blending its okay */
-		format = PSB_2D_DST_8888ARGB;
-		break;
-	default:
-		/* software fallback */
-		cfb_fillrect(info, r);
-		return;
-	}
-	if (!gma_power_begin(dev, false)) {
-		cfb_fillrect(info, r);
-		return;
-	}
-	psb_accel_2d_fillrect(dev_priv,
-			      offset, stride, format,
-			      r->dx, r->dy, r->width, r->height, r->color);
-	gma_power_end(dev);
-}
-
-void psbfb_fillrect(struct fb_info *info,
-			   const struct fb_fillrect *rect)
-{
-	if (unlikely(info->state != FBINFO_STATE_RUNNING))
-		return;
-
-	if (1 || (info->flags & FBINFO_HWACCEL_DISABLED))
-		return cfb_fillrect(info, rect);
-
-	psbfb_fillrect_accel(info, rect);
-}
 
+/**
+ *	psb_accel_2d_copy_direction	-	compute blit order
+ *	@xdir: X direction of move
+ *	@ydir: Y direction of move
+ *
+ *	Compute the correct order setings to ensure that an overlapping blit
+ *	correctly copies all the pixels.
+ */
 static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
 {
 	if (xdir < 0)
@@ -216,19 +149,23 @@ static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
 						PSB_2D_COPYORDER_TL2BR;
 }
 
-/*
- * @src_offset in bytes
- * @src_stride in bytes
- * @src_format psb 2D format defines
- * @dst_offset in bytes
- * @dst_stride in bytes
- * @dst_format psb 2D format defines
- * @src_x offset in pixels
- * @src_y offset in pixels
- * @dst_x offset in pixels
- * @dst_y offset in pixels
- * @size_x of the copied area
- * @size_y of the copied area
+/**
+ *	psb_accel_2d_copy		-	accelerated 2D copy
+ *	@dev_priv: our DRM device
+ *	@src_offset in bytes
+ *	@src_stride in bytes
+ *	@src_format psb 2D format defines
+ *	@dst_offset in bytes
+ *	@dst_stride in bytes
+ *	@dst_format psb 2D format defines
+ *	@src_x offset in pixels
+ *	@src_y offset in pixels
+ *	@dst_x offset in pixels
+ *	@dst_y offset in pixels
+ *	@size_x of the copied area
+ *	@size_y of the copied area
+ *
+ *	Format and issue a 2D accelerated copy command.
  */
 static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
 			     uint32_t src_offset, uint32_t src_stride,
@@ -290,6 +227,13 @@ static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
 	return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
 }
 
+/**
+ *	psbfb_copyarea_accel	-	copyarea acceleration for /dev/fb
+ *	@info: our framebuffer
+ *	@a: copyarea parameters from the framebuffer core
+ *
+ *	Perform a 2D copy via the accelerator
+ */
 static void psbfb_copyarea_accel(struct fb_info *info,
 				 const struct fb_copyarea *a)
 {
@@ -345,6 +289,14 @@ static void psbfb_copyarea_accel(struct fb_info *info,
 	gma_power_end(dev);
 }
 
+/**
+ *	psbfb_copyarea	-	2D copy interface
+ *	@info: our framebuffer
+ *	@region: region to copy
+ *
+ *	Copy an area of the framebuffer console either by the accelerator
+ *	or directly using the cfb helpers according to the request
+ */
 void psbfb_copyarea(struct fb_info *info,
 			   const struct fb_copyarea *region)
 {
@@ -359,12 +311,13 @@ void psbfb_copyarea(struct fb_info *info,
 	psbfb_copyarea_accel(info, region);
 }
 
-void psbfb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	/* For now */
-	cfb_imageblit(info, image);
-}
-
+/**
+ *	psbfb_sync	-	synchronize 2D
+ *	@info: our framebuffer
+ *
+ *	Wait for the 2D engine to quiesce so that we can do CPU
+ *	access to the framebuffer again
+ */
 int psbfb_sync(struct fb_info *info)
 {
 	struct psb_fbdev *fbdev = info->par;
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 1114021..cafbfcd 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -587,16 +587,10 @@ extern void *psbfb_vdc_reg(struct drm_device* dev);
 /*
  * psb_2d.c
  */
-extern void psbfb_fillrect(struct fb_info *info,
-					const struct fb_fillrect *rect);
 extern void psbfb_copyarea(struct fb_info *info,
 					const struct fb_copyarea *region);
-extern void psbfb_imageblit(struct fb_info *info,
-					const struct fb_image *image);
 extern int psbfb_sync(struct fb_info *info);
-
 extern void psb_spank(struct drm_psb_private *dev_priv);
-
 extern int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
 					unsigned size);
 
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index f1a7e8d..c2d4b23 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -289,9 +289,9 @@ static struct fb_ops psbfb_ops = {
 	.fb_set_par = drm_fb_helper_set_par,
 	.fb_blank = drm_fb_helper_blank,
 	.fb_setcolreg = psbfb_setcolreg,
-	.fb_fillrect = psbfb_fillrect,
+	.fb_fillrect = cfb_fillrect,
 	.fb_copyarea = psbfb_copyarea,
-	.fb_imageblit = psbfb_imageblit,
+	.fb_imageblit = cfb_imageblit,
 	.fb_mmap = psbfb_mmap,
 	.fb_sync = psbfb_sync,
 	.fb_ioctl = psbfb_ioctl,


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 14/49] gma500: Medfield support
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (12 preceding siblings ...)
  2011-07-05 14:36 ` [PATCH 13/49] gma500: 2D polish Alan Cox
@ 2011-07-05 14:36 ` Alan Cox
  2011-07-05 14:37 ` [PATCH 15/49] gma500: Move our other GEM helper into the bits want to push into GEM Alan Cox
                   ` (35 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:36 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

This large patch adds all the basics for Medfield support. Lots of clean up
needed in this area still.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile               |   12 
 drivers/staging/gma500/displays/hdmi.h        |   33 +
 drivers/staging/gma500/displays/pyr_cmd.h     |   34 +
 drivers/staging/gma500/displays/pyr_vid.h     |   34 +
 drivers/staging/gma500/displays/tmd_cmd.h     |   34 +
 drivers/staging/gma500/displays/tmd_vid.h     |   34 +
 drivers/staging/gma500/displays/tpo_cmd.h     |   35 +
 drivers/staging/gma500/displays/tpo_vid.h     |   33 +
 drivers/staging/gma500/mdfld_dsi_dbi.c        |  872 ++++++++++++++++
 drivers/staging/gma500/mdfld_dsi_dbi.h        |  188 +++
 drivers/staging/gma500/mdfld_dsi_dbi_dpu.h    |  157 +++
 drivers/staging/gma500/mdfld_dsi_dpi.c        |  991 ++++++++++++++++++
 drivers/staging/gma500/mdfld_dsi_dpi.h        |   80 +
 drivers/staging/gma500/mdfld_dsi_output.c     |  977 ++++++++++++++++++
 drivers/staging/gma500/mdfld_dsi_output.h     |  328 ++++++
 drivers/staging/gma500/mdfld_dsi_pkg_sender.c | 1097 ++++++++++++++++++++
 drivers/staging/gma500/mdfld_dsi_pkg_sender.h |  158 +++
 drivers/staging/gma500/mdfld_intel_display.c  | 1388 +++++++++++++++++++++++++
 drivers/staging/gma500/mdfld_msic.h           |   31 +
 drivers/staging/gma500/mdfld_output.c         |  135 ++
 drivers/staging/gma500/mdfld_output.h         |   77 +
 drivers/staging/gma500/mdfld_pyr_cmd.c        |  575 ++++++++++
 drivers/staging/gma500/mdfld_tmd_vid.c        |  144 +++
 drivers/staging/gma500/mdfld_tpo_cmd.c        |  495 +++++++++
 drivers/staging/gma500/mdfld_tpo_vid.c        |  140 +++
 drivers/staging/gma500/psb_bl.c               |   68 +
 drivers/staging/gma500/psb_drm.h              |    7 
 drivers/staging/gma500/psb_drv.c              |   25 
 drivers/staging/gma500/psb_drv.h              |  132 ++
 drivers/staging/gma500/psb_fb.c               |   28 -
 drivers/staging/gma500/psb_intel_display.c    |   18 
 drivers/staging/gma500/psb_intel_display.h    |    3 
 drivers/staging/gma500/psb_intel_drv.h        |    3 
 drivers/staging/gma500/psb_intel_lvds.c       |    1 
 drivers/staging/gma500/psb_irq.c              |   61 +
 drivers/staging/gma500/psb_powermgmt.c        |  626 +++++++++++
 36 files changed, 9005 insertions(+), 49 deletions(-)
 create mode 100644 drivers/staging/gma500/displays/hdmi.h
 create mode 100644 drivers/staging/gma500/displays/pyr_cmd.h
 create mode 100644 drivers/staging/gma500/displays/pyr_vid.h
 create mode 100644 drivers/staging/gma500/displays/tmd_cmd.h
 create mode 100644 drivers/staging/gma500/displays/tmd_vid.h
 create mode 100644 drivers/staging/gma500/displays/tpo_cmd.h
 create mode 100644 drivers/staging/gma500/displays/tpo_vid.h
 create mode 100644 drivers/staging/gma500/mdfld_dsi_dbi.c
 create mode 100644 drivers/staging/gma500/mdfld_dsi_dbi.h
 create mode 100644 drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
 create mode 100644 drivers/staging/gma500/mdfld_dsi_dpi.c
 create mode 100644 drivers/staging/gma500/mdfld_dsi_dpi.h
 create mode 100644 drivers/staging/gma500/mdfld_dsi_output.c
 create mode 100644 drivers/staging/gma500/mdfld_dsi_output.h
 create mode 100644 drivers/staging/gma500/mdfld_dsi_pkg_sender.c
 create mode 100644 drivers/staging/gma500/mdfld_dsi_pkg_sender.h
 create mode 100644 drivers/staging/gma500/mdfld_intel_display.c
 create mode 100644 drivers/staging/gma500/mdfld_msic.h
 create mode 100644 drivers/staging/gma500/mdfld_output.c
 create mode 100644 drivers/staging/gma500/mdfld_output.h
 create mode 100644 drivers/staging/gma500/mdfld_pyr_cmd.c
 create mode 100644 drivers/staging/gma500/mdfld_tmd_vid.c
 create mode 100644 drivers/staging/gma500/mdfld_tpo_cmd.c
 create mode 100644 drivers/staging/gma500/mdfld_tpo_vid.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index 01aaa28..4c9c475 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -22,6 +22,16 @@ psb_gfx-y += gem_glue.o \
 	  psb_powermgmt.o \
 	  psb_irq.o \
 	  mrst_crtc.o \
-	  mrst_lvds.o
+	  mrst_lvds.o \
+	  mdfld_output.o \
+	  mdfld_pyr_cmd.o \
+	  mdfld_tmd_vid.o \
+	  mdfld_tpo_cmd.o \
+	  mdfld_tpo_vid.o \
+	  mdfld_dsi_pkg_sender.o \
+	  mdfld_dsi_dpi.o \
+	  mdfld_dsi_output.o \
+	  mdfld_dsi_dbi.o \
+	  mdfld_intel_display.o
 
 obj-$(CONFIG_DRM_PSB) += psb_gfx.o
diff --git a/drivers/staging/gma500/displays/hdmi.h b/drivers/staging/gma500/displays/hdmi.h
new file mode 100644
index 0000000..d58ba9b
--- /dev/null
+++ b/drivers/staging/gma500/displays/hdmi.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#ifndef HDMI_H
+#define HDMI_H
+
+extern void hdmi_init(struct drm_device *dev);
+
+#endif
diff --git a/drivers/staging/gma500/displays/pyr_cmd.h b/drivers/staging/gma500/displays/pyr_cmd.h
new file mode 100644
index 0000000..84bae5c
--- /dev/null
+++ b/drivers/staging/gma500/displays/pyr_cmd.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#ifndef PYR_CMD_H
+#define PYR_CMD_H
+
+extern void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+
+#endif
+
diff --git a/drivers/staging/gma500/displays/pyr_vid.h b/drivers/staging/gma500/displays/pyr_vid.h
new file mode 100644
index 0000000..ce98860
--- /dev/null
+++ b/drivers/staging/gma500/displays/pyr_vid.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#ifndef PYR_VID_H
+#define PYR_VID_H
+
+extern void pyr_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+extern struct drm_display_mode *pyr_vid_get_config_mode(struct drm_device* dev);
+
+#endif
diff --git a/drivers/staging/gma500/displays/tmd_cmd.h b/drivers/staging/gma500/displays/tmd_cmd.h
new file mode 100644
index 0000000..641e85e
--- /dev/null
+++ b/drivers/staging/gma500/displays/tmd_cmd.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#ifndef TMD_CMD_H
+#define TMD_CMD_H
+
+extern void tmd_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+extern struct drm_display_mode *tmd_cmd_get_config_mode(struct drm_device *dev);
+
+#endif
diff --git a/drivers/staging/gma500/displays/tmd_vid.h b/drivers/staging/gma500/displays/tmd_vid.h
new file mode 100644
index 0000000..7a5fa3b
--- /dev/null
+++ b/drivers/staging/gma500/displays/tmd_vid.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#ifndef TMD_VID_H
+#define TMD_VID_H
+
+extern void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+extern struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev);
+
+#endif
diff --git a/drivers/staging/gma500/displays/tpo_cmd.h b/drivers/staging/gma500/displays/tpo_cmd.h
new file mode 100644
index 0000000..6105527
--- /dev/null
+++ b/drivers/staging/gma500/displays/tpo_cmd.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#ifndef TPO_CMD_H
+#define TPO_CMD_H
+
+extern void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+/* extern struct drm_display_mode * */
+/* tpo_cmd_get_config_mode(struct drm_device *dev); */
+
+#endif
diff --git a/drivers/staging/gma500/displays/tpo_vid.h b/drivers/staging/gma500/displays/tpo_vid.h
new file mode 100644
index 0000000..c24f057
--- /dev/null
+++ b/drivers/staging/gma500/displays/tpo_vid.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#ifndef TPO_VID_H
+#define TPO_VID_H
+
+extern void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
+
+#endif
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c
new file mode 100644
index 0000000..15055c8
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.c
@@ -0,0 +1,872 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *  jim liu <jim.liu@intel.com>
+ *  Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dbi_dpu.h"
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "psb_powermgmt.h"
+#include <linux/pm_runtime.h>
+
+int enable_gfx_rtpm;
+
+extern struct drm_device *gpDrmDevice;
+extern int gfxrtdelay;
+int enter_dsr;
+struct mdfld_dsi_dbi_output *gdbi_output;
+extern bool gbgfxsuspended;
+extern int gfxrtdelay;
+
+#ifdef CONFIG_GFX_RTPM
+static void psb_runtimepm_wq_handler(struct work_struct *work);
+DECLARE_DELAYED_WORK(rtpm_work, psb_runtimepm_wq_handler);
+
+void psb_runtimepm_wq_handler(struct work_struct *work)
+{
+	struct drm_psb_private *dev_priv =  gpDrmDevice->dev_private;
+
+	if (drm_psb_ospm && !enable_gfx_rtpm) {
+		pr_info("Enable GFX runtime_pm\n");
+		dev_priv->rpm_enabled = 1;
+		enable_gfx_rtpm = 1;
+
+		pm_runtime_enable(&gpDrmDevice->pdev->dev);
+		pm_runtime_set_active(&gpDrmDevice->pdev->dev);
+
+		pm_runtime_allow(&gpDrmDevice->pdev->dev);
+	}
+}
+#endif
+
+
+/*
+ * set refreshing area
+ */
+int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
+				u16 x1, u16 y1, u16 x2, u16 y2)
+{
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+	u8 param[4];
+	u8 cmd;
+	int err;
+
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	/*set column*/
+	cmd = set_column_address;
+	param[0] = x1 >> 8;
+	param[1] = x1;
+	param[2] = x2 >> 8;
+	param[3] = x2;
+
+	err = mdfld_dsi_send_dcs(sender,
+				 cmd,
+				 param,
+				 4,
+				 CMD_DATA_SRC_SYSTEM_MEM,
+				 MDFLD_DSI_QUEUE_PACKAGE);
+	if (err) {
+		dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
+		goto err_out;
+	}
+
+	/*set page*/
+	cmd = set_page_addr;
+	param[0] = y1 >> 8;
+	param[1] = y1;
+	param[2] = y2 >> 8;
+	param[3] = y2;
+
+	err = mdfld_dsi_send_dcs(sender,
+				 cmd,
+				 param,
+				 4,
+				 CMD_DATA_SRC_SYSTEM_MEM,
+				 MDFLD_DSI_QUEUE_PACKAGE);
+	if (err) {
+		dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
+		goto err_out;
+	}
+
+	/*update screen*/
+	err = mdfld_dsi_send_dcs(sender,
+				 write_mem_start,
+				 NULL,
+				 0,
+				 CMD_DATA_SRC_PIPE,
+				 MDFLD_DSI_QUEUE_PACKAGE);
+	if (err) {
+		dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
+		goto err_out;
+	}
+	mdfld_dsi_cmds_kick_out(sender);
+err_out:
+	return err;
+}
+
+/*
+ * set panel's power state
+ */
+int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
+								int mode)
+{
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+	u8 param = 0;
+	u32 err = 0;
+
+	if (!dev_priv->dispstatus && mode != DRM_MODE_DPMS_ON) {
+		dev_err(dev->dev, "%s: already OFF ignoring\n", __func__);
+		return 0;
+	}
+	if (dev_priv->dispstatus && mode == DRM_MODE_DPMS_ON) {
+		dev_err(dev->dev, "%s: already ON ignoring\n", __func__);
+		return 0;
+	}
+
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	if (mode == DRM_MODE_DPMS_ON) {
+		/*exit sleep mode*/
+		err = mdfld_dsi_send_dcs(sender,
+					 exit_sleep_mode,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+						exit_sleep_mode);
+			goto power_err;
+		}
+
+		/*set display on*/
+		err = mdfld_dsi_send_dcs(sender,
+					 set_display_on,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+							set_display_on);
+			goto power_err;
+		}
+
+		/* set tear effect on */
+		err = mdfld_dsi_send_dcs(sender,
+					 set_tear_on,
+					 &param,
+					 1,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+							set_tear_on);
+			goto power_err;
+		}
+
+		/**
+		 * FIXME: remove this later
+		 */
+		err = mdfld_dsi_send_dcs(sender,
+					 write_mem_start,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_PIPE,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+							set_display_on);
+			goto power_err;
+		}
+	} else {
+		/*set tear effect off */
+		err = mdfld_dsi_send_dcs(sender,
+					 set_tear_off,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+							set_tear_off);
+			goto power_err;
+		}
+
+		/*set display off*/
+		err = mdfld_dsi_send_dcs(sender,
+					 set_display_off,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+							set_display_off);
+			goto power_err;
+		}
+
+		/*enter sleep mode*/
+		err = mdfld_dsi_send_dcs(sender,
+					 enter_sleep_mode,
+					 NULL,
+					 0,
+					 CMD_DATA_SRC_SYSTEM_MEM,
+					 MDFLD_DSI_QUEUE_PACKAGE);
+		if (err) {
+			dev_err(dev->dev, "DCS 0x%x sent failed\n",
+							enter_sleep_mode);
+			goto power_err;
+		}
+	}
+	mdfld_dsi_cmds_kick_out(sender);
+power_err:
+	return err;
+}
+
+/*
+ * send a generic DCS command with a parameter list
+ */
+int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
+			u8 dcs,  u8 *param, u32 num, u8 data_src)
+{
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+	int ret;
+
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	ret = mdfld_dsi_send_dcs(sender,
+				 dcs,
+				 param,
+				 num,
+				 data_src,
+				 MDFLD_DSI_SEND_PACKAGE);
+
+	return ret;
+}
+
+
+/*
+ * Enter DSR
+ */
+void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
+{
+	u32 reg_val;
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = dbi_output->base.base.crtc;
+	struct psb_intel_crtc *psb_crtc = (crtc) ?
+					to_psb_intel_crtc(crtc) : NULL;
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dspcntr_reg = DSPACNTR;
+
+	dev_priv->is_in_idle = true;
+
+	if (!dbi_output)
+		return;
+
+	gdbi_output = dbi_output;
+	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
+		return;
+
+	if (pipe == 2) {
+		dpll_reg = MRST_DPLL_A;
+		pipeconf_reg = PIPECCONF;
+		dspcntr_reg = DSPCCNTR;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+	/*disable te interrupts. */
+	mdfld_disable_te(dev, pipe);
+
+	/*disable plane*/
+	reg_val = REG_READ(dspcntr_reg);
+	if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
+		REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE);
+		REG_READ(dspcntr_reg);
+	}
+	/*disable pipe*/
+	reg_val = REG_READ(pipeconf_reg);
+	if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
+		reg_val &= ~DISPLAY_PLANE_ENABLE;
+		reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF);
+		REG_WRITE(pipeconf_reg, reg_val);
+		REG_READ(pipeconf_reg);
+		mdfldWaitForPipeDisable(dev, pipe);
+	}
+
+	/*disable DPLL*/
+	reg_val = REG_READ(dpll_reg);
+	if (!(reg_val & DPLL_VCO_ENABLE)) {
+		reg_val &= ~DPLL_VCO_ENABLE;
+		REG_WRITE(dpll_reg, reg_val);
+		REG_READ(dpll_reg);
+		udelay(500);
+	}
+
+	gma_power_end(dev);
+	dbi_output->mode_flags |= MODE_SETTING_IN_DSR;
+	if (pipe == 2) {
+		enter_dsr = 1;
+		/* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */
+	}
+}
+
+#ifndef CONFIG_MDFLD_DSI_DPU
+static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
+			int pipe, void *p_surfaceAddr, bool check_hw_on_only)
+{
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc = dbi_output->base.base.crtc;
+	struct psb_intel_crtc *psb_crtc = (crtc) ?
+					to_psb_intel_crtc(crtc) : NULL;
+	u32 reg_val;
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 dspsurf_reg = DSPASURF;
+	u32 reg_offset = 0;
+
+	/*if mode setting on-going, back off*/
+	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
+		return;
+
+	if (pipe == 2) {
+		dpll_reg = MRST_DPLL_A;
+		pipeconf_reg = PIPECCONF;
+		dspcntr_reg = DSPCCNTR;
+		dspsurf_reg = DSPCSURF;
+		reg_offset = MIPIC_REG_OFFSET;
+	}
+
+	if (check_hw_on_only) {
+		if (0/* FIXME!ospm_power_is_hw_on(_DISPLAY_ISLAND)*/) {
+			dev_err(dev->dev, "hw begin failed\n");
+			return;
+		}
+	} else if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	/*enable DPLL*/
+	reg_val = REG_READ(dpll_reg);
+	if (!(reg_val & DPLL_VCO_ENABLE)) {
+
+		if (reg_val & MDFLD_PWR_GATE_EN) {
+			reg_val &= ~MDFLD_PWR_GATE_EN;
+			REG_WRITE(dpll_reg, reg_val);
+			REG_READ(dpll_reg);
+			udelay(500);
+		}
+
+		reg_val |= DPLL_VCO_ENABLE;
+		REG_WRITE(dpll_reg, reg_val);
+		REG_READ(dpll_reg);
+		udelay(500);
+
+		/* Add timeout */
+		while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK))
+			cpu_relax();
+	}
+
+	/*enable pipe*/
+	reg_val = REG_READ(pipeconf_reg);
+	if (!(reg_val & PIPEACONF_ENABLE)) {
+		reg_val |= PIPEACONF_ENABLE;
+		REG_WRITE(pipeconf_reg, reg_val);
+		REG_READ(pipeconf_reg);
+		udelay(500);
+		mdfldWaitForPipeEnable(dev, pipe);
+	}
+
+	/*enable plane*/
+	reg_val = REG_READ(dspcntr_reg);
+	if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
+		reg_val |= DISPLAY_PLANE_ENABLE;
+		REG_WRITE(dspcntr_reg, reg_val);
+		REG_READ(dspcntr_reg);
+		udelay(500);
+	}
+
+	/* update the surface base address. */
+	if (p_surfaceAddr)
+		REG_WRITE(dspsurf_reg, *((u32 *)p_surfaceAddr));
+
+	if (!check_hw_on_only)
+		gma_power_end(dev);
+
+	/*enable TE interrupt on this pipe*/
+	mdfld_enable_te(dev, pipe);
+
+	/*clean IN_DSR flag*/
+	dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+}
+
+/*
+ * Exit from DSR
+ */
+void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src,
+				void *p_surfaceAddr, bool check_hw_on_only)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+	struct mdfld_dsi_dbi_output **dbi_output;
+	int i;
+
+	dev_priv->is_in_idle = false;
+	dbi_output = dsr_info->dbi_outputs;
+
+#ifdef CONFIG_PM_RUNTIME
+	 if (!enable_gfx_rtpm) {
+/*                pm_runtime_allow(&gpDrmDevice->pdev->dev); */
+/*		schedule_delayed_work(&rtpm_work, 120 * 1000); */
+	}
+#endif
+
+	/*for each output, exit dsr*/
+	for (i = 0; i < dsr_info->dbi_output_num; i++) {
+		/*if panel has been turned off, skip*/
+		if (!dbi_output[i]->dbi_panel_on)
+			continue;
+		if (dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR) {
+			enter_dsr = 0;
+			mdfld_dbi_output_exit_dsr(dbi_output[i], dbi_output[i]->channel_num ? 2 : 0, p_surfaceAddr, check_hw_on_only);
+		}
+	}
+	dev_priv->dsr_fb_update |= update_src;
+}
+
+static bool mdfld_dbi_is_in_dsr(struct drm_device *dev)
+{
+	if (REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE)
+		return false;
+	if ((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) ||
+	   (REG_READ(PIPECCONF) & PIPEACONF_ENABLE))
+		return false;
+	if ((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) ||
+	   (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE))
+		return false;
+
+	return true;
+}
+
+/* Perodically update dbi panel */
+void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+	struct mdfld_dsi_dbi_output **dbi_outputs;
+	struct mdfld_dsi_dbi_output *dbi_output;
+	int i;
+	int enter_dsr = 0;
+	u32 damage_mask = 0;
+
+	dbi_outputs = dsr_info->dbi_outputs;
+	dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0];
+
+	if (!dbi_output)
+		return;
+
+	if (pipe == 0)
+		damage_mask = dev_priv->dsr_fb_update & (MDFLD_DSR_DAMAGE_MASK_0);
+	else if (pipe == 2)
+		damage_mask = dev_priv->dsr_fb_update & (MDFLD_DSR_DAMAGE_MASK_2);
+	else
+		return;
+
+	/*if FB is damaged and panel is on update on-panel FB*/
+	if (damage_mask && dbi_output->dbi_panel_on) {
+		dbi_output->dsr_fb_update_done = false;
+
+		if (dbi_output->p_funcs->update_fb)
+			dbi_output->p_funcs->update_fb(dbi_output, pipe);
+
+		if (dev_priv->dsr_enable && dbi_output->dsr_fb_update_done)
+			dev_priv->dsr_fb_update &= ~damage_mask;
+
+		/*clean IN_DSR flag*/
+		dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
+
+		dbi_output->dsr_idle_count = 0;
+	} else {
+		dbi_output->dsr_idle_count++;
+	}
+
+	/*try to enter DSR*/
+	if (dbi_outputs[0]->dsr_idle_count > 1
+	    && dbi_outputs[1]->dsr_idle_count > 1) {
+		for (i = 0; i < dsr_info->dbi_output_num; i++) {
+			if (!mdfld_dbi_is_in_dsr(dev) &&
+			   !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) {
+				mdfld_dsi_dbi_enter_dsr(dbi_outputs[i],
+					dbi_outputs[i]->channel_num ? 2 : 0);
+#if 0
+				enter_dsr = 1;
+				pr_err("%s: enter_dsr = 1\n", __func__);
+#endif
+			}
+		}
+	/*schedule rpm suspend after gfxrtdelay*/
+#ifdef CONFIG_GFX_RTPM
+		if (!dev_priv->rpm_enabled
+			|| !enter_dsr
+	/*		|| (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN) */
+			|| pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay))
+			dev_warn(dev->dev,
+				"Runtime PM schedule suspend failed, rpm %d\n",
+					dev_priv->rpm_enabled);
+#endif
+	}
+}
+
+/*timers for DSR*/
+static void mdfld_dsi_dbi_dsr_timer_func(unsigned long data)
+{
+	struct drm_device *dev = (struct drm_device *)data;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+	struct timer_list *dsr_timer = &dsr_info->dsr_timer;
+	unsigned long flags;
+
+	mdfld_dbi_update_panel(dev, 0);
+
+	if (dsr_info->dsr_idle_count > 1)
+		return;
+
+	spin_lock_irqsave(&dsr_info->dsr_timer_lock, flags);
+	if (!timer_pending(dsr_timer)) {
+		dsr_timer->expires = jiffies + MDFLD_DSR_DELAY;
+		add_timer(dsr_timer);
+	}
+	spin_unlock_irqrestore(&dsr_info->dsr_timer_lock, flags);
+}
+
+static int mdfld_dsi_dbi_dsr_timer_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+	struct timer_list *dsr_timer = &dsr_info->dsr_timer;
+	unsigned long flags;
+
+	spin_lock_init(&dsr_info->dsr_timer_lock);
+	spin_lock_irqsave(&dsr_info->dsr_timer_lock, flags);
+
+	init_timer(dsr_timer);
+
+	dsr_timer->data = (unsigned long)dev;
+	dsr_timer->function = mdfld_dsi_dbi_dsr_timer_func;
+	dsr_timer->expires = jiffies + MDFLD_DSR_DELAY;
+
+	spin_unlock_irqrestore(&dsr_info->dsr_timer_lock, flags);
+	return 0;
+}
+
+void mdfld_dbi_dsr_timer_start(struct mdfld_dbi_dsr_info *dsr_info)
+{
+	struct timer_list *dsr_timer = &dsr_info->dsr_timer;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dsr_info->dsr_timer_lock, flags);
+	if (!timer_pending(dsr_timer)) {
+		dsr_timer->expires = jiffies + MDFLD_DSR_DELAY;
+		add_timer(dsr_timer);
+	}
+	spin_unlock_irqrestore(&dsr_info->dsr_timer_lock, flags);
+}
+
+int mdfld_dbi_dsr_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+
+	if (!dsr_info || IS_ERR(dsr_info)) {
+		dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info),
+								GFP_KERNEL);
+		if (!dsr_info) {
+			dev_err(dev->dev, "No memory\n");
+			return -ENOMEM;
+		}
+		dev_priv->dbi_dsr_info = dsr_info;
+	}
+	return 0;
+}
+
+void mdfld_dbi_dsr_exit(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
+
+	if (!dsr_info) {
+		del_timer_sync(&dsr_info->dsr_timer);
+		kfree(dsr_info);
+		dev_priv->dbi_dsr_info = NULL;
+	}
+}
+#endif
+
+void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
+								int pipe)
+{
+	struct drm_device *dev = dsi_config->dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int lane_count = dsi_config->lane_count;
+	u32 val = 0;
+
+	dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
+
+	/*un-ready device*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
+
+	/*init dsi adapter before kicking off*/
+	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
+
+	/*TODO: figure out how to setup these registers*/
+	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
+	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
+							0x000a0014);
+	REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
+	REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
+	REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
+
+	/*enable all interrupts*/
+	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
+	/*max value: 20 clock cycles of txclkesc*/
+	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
+	/*min 21 txclkesc, max: ffffh*/
+	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
+	/*min: 7d0 max: 4e20*/
+	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
+
+	/*set up func_prg*/
+	val |= lane_count;
+	val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
+	val |= DSI_DBI_COLOR_FORMAT_OPTION2;
+	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
+
+	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
+	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
+
+	/*de-assert dbi_stall when half of DBI FIFO is empty*/
+	/* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
+
+	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
+	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
+	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
+}
+
+#if 0
+/*DBI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
+	.dpms = mdfld_dsi_dbi_dpms,
+	.mode_fixup = mdfld_dsi_dbi_mode_fixup,
+	.prepare = mdfld_dsi_dbi_prepare,
+	.mode_set = mdfld_dsi_dbi_mode_set,
+	.commit = mdfld_dsi_dbi_commit,
+};
+
+/*DBI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+#endif
+
+static int mdfld_dbi_panel_reset(struct mdfld_dsi_dbi_output *output)
+{
+	unsigned gpio;
+	int ret;
+
+	switch (output->channel_num) {
+	case 0:
+		gpio = 128;
+		break;
+	case 1:
+		gpio = 34;
+		break;
+	default:
+		pr_err("Invalid output\n");
+		return -EINVAL;
+	}
+
+	ret = gpio_request(gpio, "gfx");
+	if (ret) {
+		pr_err("gpio_rqueset failed\n");
+		return ret;
+	}
+
+	ret = gpio_direction_output(gpio, 1);
+	if (ret) {
+		pr_err("gpio_direction_output failed\n");
+		goto gpio_error;
+	}
+	gpio_get_value(128);
+gpio_error:
+	if (gpio_is_valid(gpio))
+		gpio_free(gpio);
+
+	return ret;
+}
+
+/*
+ * Init DSI DBI encoder.
+ * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
+ * return pointer of newly allocated DBI encoder, NULL on error
+ */
+struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
+				struct mdfld_dsi_connector *dsi_connector,
+				struct panel_funcs *p_funcs)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_dbi_output *dbi_output = NULL;
+	struct mdfld_dsi_config *dsi_config;
+	struct drm_connector *connector = NULL;
+	struct drm_encoder *encoder = NULL;
+	struct drm_display_mode *fixed_mode = NULL;
+	struct psb_gtt *pg = dev_priv ? (dev_priv->pg) : NULL;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+	struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
+#else
+	struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
+#endif
+	int ret;
+
+	if (!pg || !dsi_connector) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
+	if (!dbi_output) {
+		dev_err(dev->dev, "No memory\n");
+		return NULL;
+	}
+
+	if (dsi_connector->pipe == 0) {
+		dbi_output->channel_num = 0;
+		dev_priv->dbi_output = dbi_output;
+	} else if (dsi_connector->pipe == 2) {
+		dbi_output->channel_num = 1;
+		dev_priv->dbi_output2 = dbi_output;
+	} else {
+		dev_err(dev->dev, "only support 2 DSI outputs\n");
+		goto out_err1;
+	}
+
+	dbi_output->dev = dev;
+	dbi_output->p_funcs = p_funcs;
+
+	/*panel reset*/
+	ret = mdfld_dbi_panel_reset(dbi_output);
+	if (ret) {
+		dev_err(dev->dev, "reset panel error\n");
+		goto out_err1;
+	}
+
+	/*TODO: get panel info from DDB*/
+
+	/*get fixed mode*/
+	dsi_config = mdfld_dsi_get_config(dsi_connector);
+	fixed_mode = dsi_config->fixed_mode;
+
+	dbi_output->panel_fixed_mode = fixed_mode;
+
+	/*create drm encoder object*/
+	connector = &dsi_connector->base.base;
+	encoder = &dbi_output->base.base;
+	drm_encoder_init(dev,
+			encoder,
+			p_funcs->encoder_funcs,
+			DRM_MODE_ENCODER_MIPI);
+	drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs);
+
+	/*attach to given connector*/
+	drm_mode_connector_attach_encoder(connector, encoder);
+
+	/*set possible crtcs and clones*/
+	if (dsi_connector->pipe) {
+		encoder->possible_crtcs = (1 << 2);
+		encoder->possible_clones = (1 << 1);
+	} else {
+		encoder->possible_crtcs = (1 << 0);
+		encoder->possible_clones = (1 << 0);
+	}
+
+	dev_priv->dsr_fb_update = 0;
+	dev_priv->dsr_enable = false;
+	dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr;
+#if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR)
+	dev_priv->dsr_enable_config = false;
+#endif /*CONFIG_MDFLD_DSI_DSR*/
+
+	dbi_output->first_boot = true;
+	dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+	/*add this output to dpu_info*/
+	if (dsi_connector->pipe == 0)
+		dpu_info->dbi_outputs[0] = dbi_output;
+	} else {
+		dpu_info->dbi_outputs[1] = dbi_output;
+	}
+	dpu_info->dbi_output_num++;
+#else /*CONFIG_MDFLD_DSI_DPU*/
+	/*add this output to dsr_info*/
+	if (dsi_connector->pipe == 0)
+		dsr_info->dbi_outputs[0] = dbi_output;
+	else
+		dsr_info->dbi_outputs[1] = dbi_output;
+	dsr_info->dbi_output_num++;
+#endif
+	return &dbi_output->base;
+out_err1:
+	kfree(dbi_output);
+	return NULL;
+}
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.h b/drivers/staging/gma500/mdfld_dsi_dbi.h
new file mode 100644
index 0000000..5b04951
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DBI_H__
+#define __MDFLD_DSI_DBI_H__
+
+#include <linux/backlight.h>
+#include <linux/version.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+#define DRM_MODE_ENCODER_MIPI  5
+
+
+/*
+ * DBI encoder which inherits from mdfld_dsi_encoder
+ */
+struct mdfld_dsi_dbi_output {
+	struct mdfld_dsi_encoder base;
+	struct drm_display_mode *panel_fixed_mode;
+	u8 last_cmd;
+	u8 lane_count;
+	u8 channel_num;
+	struct drm_device *dev;
+
+	/* Backlight operations */
+
+	/* DSR timer */
+	spinlock_t dsr_timer_lock;
+	struct timer_list dsr_timer;
+	void(*dsi_timer_func)(unsigned long data);
+	u32 dsr_idle_count;
+	bool dsr_fb_update_done;
+
+	/* Mode setting flags */
+	u32 mode_flags;
+
+	/* Panel status */
+	bool dbi_panel_on;
+	bool first_boot;
+	struct panel_funcs *p_funcs;
+};
+
+#define MDFLD_DSI_DBI_OUTPUT(dsi_encoder) \
+	container_of(dsi_encoder, struct mdfld_dsi_dbi_output, base)
+
+struct mdfld_dbi_dsr_info {
+	int dbi_output_num;
+	struct mdfld_dsi_dbi_output *dbi_outputs[2];
+
+	spinlock_t dsr_timer_lock;
+	struct timer_list dsr_timer;
+	u32 dsr_idle_count;
+};
+
+#define DBI_CB_TIMEOUT_COUNT	0xffff
+
+/* DCS commands */
+#define enter_sleep_mode	0x10
+#define exit_sleep_mode		0x11
+#define set_display_off		0x28
+#define	set_dispaly_on		0x29
+#define set_column_address	0x2a
+#define set_page_addr		0x2b
+#define write_mem_start		0x2c
+
+/* Offsets */
+#define CMD_MEM_ADDR_OFFSET	0
+
+#define CMD_DATA_SRC_SYSTEM_MEM	0
+#define CMD_DATA_SRC_PIPE	1
+
+static inline int mdfld_dsi_dbi_fifo_ready(struct mdfld_dsi_dbi_output *dbi_output)
+{
+	struct drm_device *dev = dbi_output->dev;
+	u32 retry = DBI_CB_TIMEOUT_COUNT;
+	int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0;
+	int ret = 0;
+
+	/* Query the dbi fifo status*/
+	while (retry--) {
+		if (REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset) & (1 << 27))
+			break;
+	}
+
+	if (!retry) {
+		DRM_ERROR("Timeout waiting for DBI FIFO empty\n");
+		ret = -EAGAIN;
+	}
+	return ret;
+}
+
+static inline int mdfld_dsi_dbi_cmd_sent(struct mdfld_dsi_dbi_output *dbi_output)
+{
+	struct drm_device *dev = dbi_output->dev;
+	u32 retry = DBI_CB_TIMEOUT_COUNT;
+	int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0;
+	int ret = 0;
+
+	/* Query the command execution status */
+	while (retry--)
+		if (!(REG_READ(MIPIA_CMD_ADD_REG + reg_offset) & (1 << 10)))
+			break;
+
+	if (!retry) {
+		DRM_ERROR("Timeout waiting for DBI command status\n");
+		ret = -EAGAIN;
+	}
+
+	return ret;
+}
+
+static inline int mdfld_dsi_dbi_cb_ready(struct mdfld_dsi_dbi_output *dbi_output)
+{
+	int ret = 0;
+
+	/* Query the command execution status*/
+	ret = mdfld_dsi_dbi_cmd_sent(dbi_output);
+	if (ret) {
+		DRM_ERROR("Peripheral is busy\n");
+		ret = -EAGAIN;
+	}
+	/* Query the dbi fifo status*/
+	ret = mdfld_dsi_dbi_fifo_ready(dbi_output);
+	if (ret) {
+		DRM_ERROR("DBI FIFO is not empty\n");
+		ret = -EAGAIN;
+	}
+	return ret;
+}
+
+extern void mdfld_dsi_dbi_output_init(struct drm_device *dev,
+			struct psb_intel_mode_device *mode_dev, int pipe);
+extern void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src,
+			void *p_surfaceAddr, bool check_hw_on_only);
+extern void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output,
+			int pipe);
+extern int mdfld_dbi_dsr_init(struct drm_device *dev);
+extern void mdfld_dbi_dsr_exit(struct drm_device *dev);
+extern void mdfld_dbi_dsr_timer_start(struct mdfld_dbi_dsr_info *dsr_info);
+extern struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
+			struct mdfld_dsi_connector *dsi_connector,
+			struct panel_funcs *p_funcs);
+extern int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
+			u8 dcs, u8 *param, u32 num, u8 data_src);
+extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
+			u16 x1, u16 y1, u16 x2, u16 y2);
+extern void mdfld_dbi_dsr_timer_start(struct mdfld_dbi_dsr_info *dsr_info);
+extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
+			int mode);
+extern void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
+			int pipe);
+
+#endif /*__MDFLD_DSI_DBI_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
new file mode 100644
index 0000000..4ca9682
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DBI_DPU_H__
+#define __MDFLD_DSI_DBI_DPU_H__
+
+#include "mdfld_dsi_dbi.h"
+
+typedef enum {
+	MDFLD_PLANEA,
+	MDFLD_PLANEC,
+	MDFLD_CURSORA,
+	MDFLD_CURSORC,
+	MDFLD_OVERLAYA,
+	MDFLD_OVERLAYC,
+	MDFLD_PLANE_NUM,
+} mdfld_plane_t;
+
+#define MDFLD_PIPEA_PLANE_MASK	0x15
+#define MDFLD_PIPEC_PLANE_MASK	0x2A
+
+struct mdfld_cursor_info {
+	int x, y;
+	int size;
+};
+
+#define MDFLD_CURSOR_SIZE	64
+
+/*
+ * enter DSR mode if screen has no update for 2 frames.
+ */
+#define MDFLD_MAX_IDLE_COUNT	2
+
+struct mdfld_dbi_dpu_info {
+	struct drm_device *dev;
+	/* Lock */
+	spinlock_t dpu_update_lock;
+
+	/* Cursor postion */
+	struct mdfld_cursor_info cursors[2];
+
+	/* Damaged area for each plane */
+	struct psb_drm_dpu_rect damaged_rects[MDFLD_PLANE_NUM];
+
+	/* Final damaged area */
+	struct psb_drm_dpu_rect damage_pipea;
+	struct psb_drm_dpu_rect damage_pipec;
+
+	/* Pending */
+	u32 pending;
+
+	/* DPU timer */
+	struct timer_list dpu_timer;
+	spinlock_t dpu_timer_lock;
+
+	/* DPU idle count */
+	u32 idle_count;
+
+	/* DSI outputs */
+	struct mdfld_dsi_dbi_output *dbi_outputs[2];
+	int dbi_output_num;
+};
+
+static inline int mdfld_dpu_region_extent(struct psb_drm_dpu_rect *origin,
+			 struct psb_drm_dpu_rect *rect)
+{
+	int x1, y1, x2, y2;
+
+	/* PSB_DEBUG_ENTRY("rect (%d, %d, %d, %d)\n",
+		rect->x, rect->y, rect->width, rect->height); */
+
+	x1 = origin->x + origin->width;
+	y1 = origin->y + origin->height;
+
+	x2 = rect->x + rect->width;
+	y2 = rect->y + rect->height;
+
+	origin->x = min(origin->x, rect->x);
+	origin->y = min(origin->y, rect->y);
+	origin->width = max(x1, x2) - origin->x;
+	origin->height = max(y1, y2) - origin->y;
+
+	return 0;
+}
+
+static inline void mdfld_check_boundary(struct mdfld_dbi_dpu_info *dpu_info,
+				struct psb_drm_dpu_rect *rect)
+{
+	if (rect->x < 0)
+		rect->x = 0;
+	if (rect->y < 0)
+		rect->y = 0;
+
+	if (rect->x + rect->width > 864)
+		rect->width = 864 - rect->x;
+	if (rect->y + rect->height > 480)
+		rect->height = 480 - rect->height;
+
+	if (!rect->width)
+		rect->width = 1;
+	if (!rect->height)
+		rect->height = 1;
+}
+
+static inline void mdfld_dpu_init_damage(struct mdfld_dbi_dpu_info *dpu_info,
+				int pipe)
+{
+	struct psb_drm_dpu_rect *rect;
+
+	if (pipe == 0)
+		rect = &dpu_info->damage_pipea;
+	else
+		rect = &dpu_info->damage_pipec;
+
+	rect->x = 864;
+	rect->y = 480;
+	rect->width = -864;
+	rect->height = -480;
+}
+
+extern int mdfld_dsi_dbi_dsr_off(struct drm_device *dev,
+				struct psb_drm_dpu_rect *rect);
+extern int mdfld_dbi_dpu_report_damage(struct drm_device *dev,
+				mdfld_plane_t plane,
+				struct psb_drm_dpu_rect *rect);
+extern int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev);
+extern int mdfld_dpu_exit_dsr(struct drm_device *dev);
+extern void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info);
+extern int mdfld_dbi_dpu_init(struct drm_device *dev);
+extern void mdfld_dbi_dpu_exit(struct drm_device *dev);
+extern void mdfld_dpu_update_panel(struct drm_device *dev);
+
+#endif /*__MDFLD_DSI_DBI_DPU_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.c b/drivers/staging/gma500/mdfld_dsi_dpi.c
new file mode 100644
index 0000000..fce3c20
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dpi.c
@@ -0,0 +1,991 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+
+
+static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe)
+{
+	u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
+	int timeout = 0;
+
+	if (pipe == 2)
+		gen_fifo_stat_reg += MIPIC_REG_OFFSET;
+
+	udelay(500);
+
+	/* This will time out after approximately 2+ seconds */
+	while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) {
+		udelay(100);
+		timeout++;
+	}
+
+	if (timeout == 20000)
+		dev_warn(dev->dev, "MIPI: HS Data FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
+{
+	u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
+	int timeout = 0;
+
+	if (pipe == 2)
+		gen_fifo_stat_reg += MIPIC_REG_OFFSET;
+
+	udelay(500);
+
+	/* This will time out after approximately 2+ seconds */
+	while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_CTRL_FULL)) {
+		udelay(100);
+		timeout++;
+	}
+	if (timeout == 20000)
+		dev_warn(dev->dev, "MIPI: HS CMD FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_PIPEA_DISABLE(struct drm_device *dev, u32 pipe)
+{
+        u32 pipeconf_reg = PIPEACONF;
+        int timeout = 0;
+
+        if (pipe == 2)
+                pipeconf_reg = PIPECCONF;
+
+        udelay(500);
+
+        /* This will time out after approximately 2+ seconds */
+        while ((timeout < 20000) && (REG_READ(pipeconf_reg) & 0x40000000)) {
+                udelay(100);
+                timeout++;
+        }
+
+        if (timeout == 20000)
+                dev_warn(dev->dev, "MIPI: PIPE was not disabled!\n");
+}
+
+static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe)
+{
+	u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
+        int timeout = 0;
+
+	if (pipe == 2)
+		gen_fifo_stat_reg += MIPIC_REG_OFFSET;
+
+        udelay(500);
+
+        /* This will time out after approximately 2+ seconds */
+        while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & DPI_FIFO_EMPTY)
+                                                        != DPI_FIFO_EMPTY)) {
+                udelay(100);
+                timeout++;
+        }
+
+        if (timeout == 20000)
+                dev_warn(dev->dev, "MIPI: DPI FIFO was never cleared!\n");
+}
+
+static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
+{
+	u32 intr_stat_reg = MIPIA_INTR_STAT_REG;
+	int timeout = 0;
+
+	if (pipe == 2)
+		intr_stat_reg += MIPIC_REG_OFFSET;
+
+        udelay(500);
+
+        /* This will time out after approximately 2+ seconds */
+        while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) & DSI_INTR_STATE_SPL_PKG_SENT))) {
+                udelay(100);
+                timeout++;
+        }
+
+        if (timeout == 20000)
+                dev_warn(dev->dev, "MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n");
+}
+
+
+/* ************************************************************************* *\
+ * FUNCTION: mdfld_dsi_tpo_ic_init
+ *
+ * DESCRIPTION:  This function is called only by mrst_dsi_mode_set and
+ *               restore_display_registers.  since this function does not
+ *               acquire the mutex, it is important that the calling function
+ *               does!
+\* ************************************************************************* */
+void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
+{
+	struct drm_device *dev = dsi_config->dev;
+	u32 dcsChannelNumber = dsi_config->channel_num;
+	u32 gen_data_reg = MIPIA_HS_GEN_DATA_REG; 
+	u32 gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG;
+	u32 gen_ctrl_val = GEN_LONG_WRITE;
+
+	dev_warn(dev->dev, "Enter mrst init TPO MIPI display.\n");
+
+	if (pipe == 2) {
+		gen_data_reg = HS_GEN_DATA_REG + MIPIC_REG_OFFSET; 
+		gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
+	}
+
+	gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS;
+
+	/* Flip page order */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00008036);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
+
+	/* 0xF0 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x005a5af0);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+	/* Write protection key */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x005a5af1);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+	/* 0xFC */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x005a5afc);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+	/* 0xB7 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x770000b7);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000044);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS));
+
+	/* 0xB6 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x000a0ab6);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+
+	/* 0xF2 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x081010f2);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x4a070708);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x000000c5);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+	/* 0xF8 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x024003f8);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x01030a04);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x0e020220);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000004);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS));
+
+	/* 0xE2 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x398fc3e2);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x0000916f);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS));
+
+	/* 0xB0 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x000000b0);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
+
+	/* 0xF4 */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x240242f4);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x78ee2002);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x2a071050);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x507fee10);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x10300710);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS));
+
+	/* 0xBA */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x19fe07ba);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x101c0a31);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000010);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+	/* 0xBB */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x28ff07bb);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x24280a31);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000034);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
+
+	/* 0xFB */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x535d05fb);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1b1a2130);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x221e180e);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x131d2120);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x535d0508);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1c1a2131);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x231f160d);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x111b2220);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x535c2008);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1f1d2433);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x2c251a10);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x2c34372d);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000023);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
+
+	/* 0xFA */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x525c0bfa);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1c1c232f);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x2623190e);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x18212625);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x545d0d0e);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1e1d2333);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x26231a10);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x1a222725);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x545d280f);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x21202635);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x31292013);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x31393d33);
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x00000029);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
+
+	/* Set DM */
+	mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
+	REG_WRITE(gen_data_reg, 0x000100f7);
+	mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
+	REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
+}
+
+/* ************************************************************************* *\
+ * FUNCTION: mdfld_init_TMD_MIPI
+ *
+ * DESCRIPTION:  This function is called only by mrst_dsi_mode_set and
+ *               restore_display_registers.  since this function does not
+ *               acquire the mutex, it is important that the calling function
+ *               does!
+\* ************************************************************************* */
+
+static u32 tmd_cmd_mcap_off[] = {0x000000b2};
+static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef};
+static u32 tmd_cmd_set_lane_num[] = {0x006360ef};
+static u32 tmd_cmd_set_mode[] = {0x000000b3};
+static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef};
+static u32 tmd_cmd_set_video_mode[] = {0x00000153};
+static u32 tmd_cmd_enable_backlight[] = {0x00005ab4};//no auto_bl,need add in furtrue
+static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd}; 
+
+void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
+{
+	struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+		WARN_ON(1);
+		return;
+	}
+
+	if(dsi_config->dvr_ic_inited)
+		return;
+
+	msleep(3);
+
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_mcap_off, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_lane_switch, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_lane_num, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_mode, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_sync_pulse_mode, 1, 0);
+	/*TODO: set page and column here*/
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_video_mode, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_backlight, 1, 0);
+	mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_backlight_dimming,1,0);
+	dsi_config->dvr_ic_inited = 1;
+}
+
+static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, int num_lane, int bpp)
+{
+	return (u16)((pixel_clock_count * bpp) / (num_lane * 8)); 
+}
+
+/*
+ * Calculate the dpi time basing on a given drm mode @mode
+ * return 0 on success.
+ * FIXME: I was using proposed mode value for calculation, may need to 
+ * use crtc mode values later 
+ */
+int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, 
+									struct mdfld_dsi_dpi_timing *dpi_timing,
+									int num_lane, int bpp)
+{
+	int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive;
+	int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive;
+	
+	if(!mode || !dpi_timing) {
+		DRM_ERROR("Invalid parameter\n");
+		return -EINVAL;
+	}
+	
+	pclk_hactive = mode->hdisplay;
+	pclk_hfp = mode->hsync_start - mode->hdisplay;
+	pclk_hsync = mode->hsync_end - mode->hsync_start;
+	pclk_hbp = mode->htotal - mode->hsync_end;
+	
+	pclk_vactive = mode->vdisplay;
+	pclk_vfp = mode->vsync_start - mode->vdisplay;
+	pclk_vsync = mode->vsync_end - mode->vsync_start;
+	pclk_vbp = mode->vtotal - mode->vsync_end;
+
+#ifdef MIPI_DEBUG_LOG
+	printk(KERN_ALERT "[DISPLAY] %s: pclk_hactive = %d\n", __func__, pclk_hactive);
+	printk(KERN_ALERT "[DISPLAY] %s: pclk_hfp = %d\n", __func__, pclk_hfp);
+	printk(KERN_ALERT "[DISPLAY] %s: pclk_hsync = %d\n", __func__, pclk_hsync);
+	printk(KERN_ALERT "[DISPLAY] %s: pclk_hbp = %d\n", __func__, pclk_hbp);
+	printk(KERN_ALERT "[DISPLAY] %s: pclk_vactive = %d\n", __func__, pclk_vactive);
+	printk(KERN_ALERT "[DISPLAY] %s: pclk_vfp = %d\n", __func__, pclk_vfp);
+	printk(KERN_ALERT "[DISPLAY] %s: pclk_vsync = %d\n", __func__, pclk_vsync);
+	printk(KERN_ALERT "[DISPLAY] %s: pclk_vbp = %d\n", __func__, pclk_vbp);
+#endif
+	/*
+	 * byte clock counts were calculated by following formula
+	 * bclock_count = pclk_count * bpp / num_lane / 8
+	 */
+	dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hsync, num_lane, bpp);
+	dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hbp, num_lane, bpp);
+	dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hfp, num_lane, bpp);
+	dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hactive, num_lane, bpp);
+	dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vsync, num_lane, bpp);
+	dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vbp, num_lane, bpp);
+	dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vfp, num_lane, bpp);
+
+	return 0; 
+}
+
+void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+	struct drm_device *dev = dsi_config->dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int lane_count = dsi_config->lane_count;
+	struct mdfld_dsi_dpi_timing dpi_timing;
+	struct drm_display_mode *mode = dsi_config->mode;
+	u32 val = 0;
+	
+	/*un-ready device*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
+	
+	/*init dsi adapter before kicking off*/
+	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
+	
+	/*enable all interrupts*/
+	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
+	
+
+	/*set up func_prg*/
+	val |= lane_count;
+	val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
+		
+	switch(dsi_config->bpp) {
+	case 16:
+		val |= DSI_DPI_COLOR_FORMAT_RGB565;
+		break;
+	case 18:
+		val |= DSI_DPI_COLOR_FORMAT_RGB666;
+		break;
+	case 24:
+		val |= DSI_DPI_COLOR_FORMAT_RGB888;
+		break;
+	default:
+		DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp);
+	}
+	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
+	
+	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 
+			(mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
+	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK);
+	
+	/*max value: 20 clock cycles of txclkesc*/
+	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
+	
+	/*min 21 txclkesc, max: ffffh*/
+	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK);
+
+	REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay);
+	
+	/*set DPI timing registers*/
+	mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp);
+	
+	REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
+	REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
+	
+	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
+	
+	/*min: 7d0 max: 4e20*/
+	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0);
+	
+	/*set up video mode*/
+	val = 0;
+	val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
+	REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val);
+	
+	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
+	
+	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
+	
+	/*TODO: figure out how to setup these registers*/
+	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
+	
+	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14);
+	/*set device ready*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
+}
+
+void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe)
+{
+	struct drm_device *dev = output->dev;
+	/* struct drm_psb_private *dev_priv = dev->dev_private; */
+	u32 reg_offset = 0;
+	
+	if(output->panel_on) 
+		return;
+		
+	if(pipe) 
+		reg_offset = MIPIC_REG_OFFSET;
+
+	/* clear special packet sent bit */
+	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
+		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
+	}
+		
+	/*send turn on package*/
+	REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
+	
+	/*wait for SPL_PKG_SENT interrupt*/
+	mdfld_wait_for_SPL_PKG_SENT(dev, pipe);
+	
+	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
+		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
+	}
+
+	output->panel_on = 1;
+
+	/* FIXME the following is disabled to WA the X slow start issue for TMD panel */
+	/* if(pipe == 2) */
+	/* 	dev_priv->dpi_panel_on2 = true; */
+	/* else if (pipe == 0) */
+	/* 	dev_priv->dpi_panel_on = true; */
+}
+
+static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe)
+{
+	struct drm_device *dev = output->dev;
+	/* struct drm_psb_private *dev_priv = dev->dev_private; */
+	u32 reg_offset = 0;
+	
+	/*if output is on, or mode setting didn't happen, ignore this*/
+	if((!output->panel_on) || output->first_boot) {
+		output->first_boot = 0; 
+		return;
+	}
+	
+	if(pipe)
+		reg_offset = MIPIC_REG_OFFSET;
+
+	/* Wait for dpi fifo to empty */
+	mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
+
+	/* Clear the special packet interrupt bit if set */
+	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
+		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
+	}
+	
+	if(REG_READ(MIPIA_DPI_CONTROL_REG + reg_offset) == DSI_DPI_CTRL_HS_SHUTDOWN) {
+		goto shutdown_out;
+	}
+	
+	REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
+
+shutdown_out:
+	output->panel_on = 0;
+	output->first_boot = 0;
+
+	/* FIXME the following is disabled to WA the X slow start issue for TMD panel */
+	/* if(pipe == 2) */
+	/* 	dev_priv->dpi_panel_on2 = false; */
+	/* else if (pipe == 0) */
+	/* 	dev_priv->dpi_panel_on = false;	 */
+}
+
+void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+	struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+	int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
+	struct drm_device *dev = dsi_config->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 mipi_reg = MIPI;
+	u32 pipeconf_reg = PIPEACONF;
+	
+	if(pipe) {
+		mipi_reg = MIPI_C;
+		pipeconf_reg = PIPECCONF;
+	}
+	
+	/* Start up display island if it was shutdown */
+	if (!gma_power_begin(dev, true))
+		return;
+
+	if(on) {
+		if (mdfld_get_panel_type(dev, pipe) == TMD_VID){
+ 			mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+ 		} else {
+			/*enable mipi port*/
+			REG_WRITE(mipi_reg, (REG_READ(mipi_reg) | (1 << 31)));
+			REG_READ(mipi_reg);
+
+			mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+			mdfld_dsi_tpo_ic_init(dsi_config, pipe);
+		}
+
+		if(pipe == 2) {
+			dev_priv->dpi_panel_on2 = true;
+		}
+		else {
+			dev_priv->dpi_panel_on  = true;
+		}
+
+	} else {
+ 		if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
+ 			mdfld_dsi_dpi_shut_down(dpi_output, pipe);
+ 		} else {
+			mdfld_dsi_dpi_shut_down(dpi_output, pipe);
+			/*disable mipi port*/
+			REG_WRITE(mipi_reg, (REG_READ(mipi_reg) & ~(1<<31)));
+			REG_READ(mipi_reg);
+		}
+
+		if(pipe == 2)
+			dev_priv->dpi_panel_on2 = false;
+		else
+			dev_priv->dpi_panel_on  = false;
+	}
+	gma_power_end(dev);
+}
+
+void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode)
+{
+	dev_dbg(encoder->dev->dev, "DPMS %s\n",
+			(mode == DRM_MODE_DPMS_ON ? "on":"off"));
+
+	if (mode == DRM_MODE_DPMS_ON)
+		mdfld_dsi_dpi_set_power(encoder, true);
+	else
+		mdfld_dsi_dpi_set_power(encoder, false);
+}
+
+bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adjusted_mode)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+	struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
+
+	if(fixed_mode) {
+		adjusted_mode->hdisplay = fixed_mode->hdisplay;
+		adjusted_mode->hsync_start = fixed_mode->hsync_start;
+		adjusted_mode->hsync_end = fixed_mode->hsync_end;
+		adjusted_mode->htotal = fixed_mode->htotal;
+		adjusted_mode->vdisplay = fixed_mode->vdisplay;
+		adjusted_mode->vsync_start = fixed_mode->vsync_start;
+		adjusted_mode->vsync_end = fixed_mode->vsync_end;
+		adjusted_mode->vtotal = fixed_mode->vtotal;
+		adjusted_mode->clock = fixed_mode->clock;
+		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+	}
+	
+	return true;
+}
+
+void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder) 
+{
+	mdfld_dsi_dpi_set_power(encoder, false);
+}
+
+void mdfld_dsi_dpi_commit(struct drm_encoder *encoder) 
+{
+	mdfld_dsi_dpi_set_power(encoder, true);
+}
+
+void dsi_debug_MIPI_reg(struct drm_device *dev)
+{
+	u32 temp_val = 0;
+
+	temp_val = REG_READ(MIPI);
+	printk(KERN_ALERT "[DISPLAY] MIPI = %x\n", temp_val);
+
+	/* set the lane speed */
+	temp_val = REG_READ(MIPI_CONTROL_REG);
+	printk(KERN_ALERT "[DISPLAY] MIPI_CONTROL_REG = %x\n", temp_val);
+
+	/* Enable all the error interrupt */
+	temp_val = REG_READ(INTR_EN_REG);
+	printk(KERN_ALERT "[DISPLAY] INTR_EN_REG = %x\n", temp_val);
+	temp_val = REG_READ(TURN_AROUND_TIMEOUT_REG);
+	printk(KERN_ALERT "[DISPLAY] TURN_AROUND_TIMEOUT_REG = %x\n", temp_val);
+	temp_val = REG_READ(DEVICE_RESET_REG);
+	printk(KERN_ALERT "[DISPLAY] DEVICE_RESET_REG = %x\n", temp_val);
+	temp_val = REG_READ(INIT_COUNT_REG);
+	printk(KERN_ALERT "[DISPLAY] INIT_COUNT_REG = %x\n", temp_val);
+
+	temp_val = REG_READ(DSI_FUNC_PRG_REG);
+	printk(KERN_ALERT "[DISPLAY] DSI_FUNC_PRG_REG = %x\n", temp_val);
+
+	temp_val = REG_READ(DPI_RESOLUTION_REG);
+	printk(KERN_ALERT "[DISPLAY] DPI_RESOLUTION_REG = %x\n", temp_val);
+
+	temp_val = REG_READ(VERT_SYNC_PAD_COUNT_REG);
+	printk(KERN_ALERT "[DISPLAY] VERT_SYNC_PAD_COUNT_REG = %x\n", temp_val);
+	temp_val = REG_READ(VERT_BACK_PORCH_COUNT_REG);
+	printk(KERN_ALERT "[DISPLAY] VERT_BACK_PORCH_COUNT_REG = %x\n", temp_val);
+	temp_val = REG_READ(VERT_FRONT_PORCH_COUNT_REG);
+	printk(KERN_ALERT "[DISPLAY] VERT_FRONT_PORCH_COUNT_REG = %x\n", temp_val);
+
+	temp_val = REG_READ(HORIZ_SYNC_PAD_COUNT_REG);
+	printk(KERN_ALERT "[DISPLAY] HORIZ_SYNC_PAD_COUNT_REG = %x\n", temp_val);
+	temp_val = REG_READ(HORIZ_BACK_PORCH_COUNT_REG);
+	printk(KERN_ALERT "[DISPLAY] HORIZ_BACK_PORCH_COUNT_REG = %x\n", temp_val);
+	temp_val = REG_READ(HORIZ_FRONT_PORCH_COUNT_REG);
+	printk(KERN_ALERT "[DISPLAY] HORIZ_FRONT_PORCH_COUNT_REG = %x\n", temp_val);
+	temp_val = REG_READ(HORIZ_ACTIVE_AREA_COUNT_REG);
+	printk(KERN_ALERT "[DISPLAY] HORIZ_ACTIVE_AREA_COUNT_REG = %x\n", temp_val);
+
+	temp_val = REG_READ(VIDEO_FMT_REG);
+	printk(KERN_ALERT "[DISPLAY] VIDEO_FMT_REG = %x\n", temp_val);
+
+	temp_val = REG_READ(HS_TX_TIMEOUT_REG);
+	printk(KERN_ALERT "[DISPLAY] HS_TX_TIMEOUT_REG = %x\n", temp_val);
+	temp_val = REG_READ(LP_RX_TIMEOUT_REG);
+	printk(KERN_ALERT "[DISPLAY] LP_RX_TIMEOUT_REG = %x\n", temp_val);
+
+	temp_val = REG_READ(HIGH_LOW_SWITCH_COUNT_REG);
+	printk(KERN_ALERT "[DISPLAY] HIGH_LOW_SWITCH_COUNT_REG = %x\n", temp_val);
+
+	temp_val = REG_READ(EOT_DISABLE_REG);
+	printk(KERN_ALERT "[DISPLAY] EOT_DISABLE_REG = %x\n", temp_val);
+
+	temp_val = REG_READ(LP_BYTECLK_REG);
+	printk(KERN_ALERT "[DISPLAY] LP_BYTECLK_REG = %x\n", temp_val);
+	temp_val = REG_READ(MAX_RET_PAK_REG);
+	printk(KERN_ALERT "[DISPLAY] MAX_RET_PAK_REG = %x\n", temp_val);
+	temp_val = REG_READ(DPI_CONTROL_REG);
+	printk(KERN_ALERT "[DISPLAY] DPI_CONTROL_REG = %x\n", temp_val);
+	temp_val = REG_READ(DPHY_PARAM_REG);
+	printk(KERN_ALERT "[DISPLAY] DPHY_PARAM_REG = %x\n", temp_val);
+//	temp_val = REG_READ(PIPEACONF);
+//	printk(KERN_INFO "[DISPLAY] PIPEACONF = %x\n", temp_val);
+//	temp_val = REG_READ(DSPACNTR);
+//	printk(KERN_INFO "[DISPLAY] DSPACNTR = %x\n", temp_val);
+}
+
+void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
+	struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder);
+	struct drm_device *dev = dsi_config->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
+	
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 mipi_reg = MIPI;
+	u32 reg_offset = 0;
+	
+	u32 pipeconf = dev_priv->pipeconf;
+	u32 dspcntr = dev_priv->dspcntr;
+	u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
+	
+	dev_dbg(dev->dev, "set mode %dx%d on pipe %d\n",
+				mode->hdisplay, mode->vdisplay, pipe);
+
+	if(pipe) {
+		pipeconf_reg = PIPECCONF;
+		dspcntr_reg = DSPCCNTR;
+		mipi_reg = MIPI_C;
+		reg_offset = MIPIC_REG_OFFSET;
+	} else {
+		mipi |= 2;
+	}
+	
+	if (!gma_power_begin(dev, true))
+		return;
+
+	/* Set up mipi port FIXME: do at init time */
+	REG_WRITE(mipi_reg, mipi);
+	REG_READ(mipi_reg);
+
+	/* Set up DSI controller DPI interface*/
+	mdfld_dsi_dpi_controller_init(dsi_config, pipe);
+
+	if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
+ 		/* init driver ic */
+ 		mdfld_dsi_tmd_drv_ic_init(dsi_config, pipe);
+	} else {
+		/*turn on DPI interface*/
+		mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+	}
+	
+	/* Set up pipe */
+	REG_WRITE(pipeconf_reg, pipeconf);
+	REG_READ(pipeconf_reg);
+	
+	/* Set up display plane */
+	REG_WRITE(dspcntr_reg, dspcntr);
+	REG_READ(dspcntr_reg);
+	
+	msleep(20); /* FIXME: this should wait for vblank */
+	
+	dev_dbg(dev->dev, "State %x, power %d\n",
+		REG_READ(MIPIA_INTR_STAT_REG + reg_offset),
+		dpi_output->panel_on);
+
+	if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
+		//mdfld_dsi_dpi_turn_on(dpi_output, pipe);
+	} else {
+		/* init driver ic */
+		mdfld_dsi_tpo_ic_init(dsi_config, pipe);
+		/*init backlight*/
+		mdfld_dsi_brightness_init(dsi_config, pipe);
+	}
+	
+#ifdef MIPI_DEBUG_LOG
+	dsi_debug_MIPI_reg(dev);
+#endif
+	gma_power_end(dev);
+}
+
+static int mdfld_dpi_panel_reset(int pipe)
+{
+	unsigned gpio;
+	int ret = 0;
+	
+	switch(pipe) {
+	case 0:
+		gpio = 128;
+		break;
+	case 2:
+		gpio = 34;
+		break;
+	default:
+		DRM_ERROR("Invalid output\n");
+		return -EINVAL;
+	}
+	
+	ret = gpio_request(gpio, "gfx");
+	if(ret) {
+		DRM_ERROR("gpio_rqueset failed\n");
+		return ret;
+	}
+	ret = gpio_direction_output(gpio, 1);
+	if(ret) {
+		DRM_ERROR("gpio_direction_output failed\n");
+		goto gpio_error;
+	}
+	
+	gpio_get_value(128);
+	
+gpio_error:
+	if(gpio_is_valid(gpio))
+		gpio_free(gpio);
+	return ret;
+}
+
+/**
+ * Exit from DSR
+ */
+void mdfld_dsi_dpi_exit_idle (struct drm_device *dev, u32 update_src, void *p_surfaceAddr, bool check_hw_on_only)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (!gma_power_begin(dev, true)) {
+		DRM_ERROR("hw begin failed\n");
+		return;
+	}
+
+	/* update the surface base address. */
+	if (p_surfaceAddr) {
+		REG_WRITE(DSPASURF, *((u32 *)p_surfaceAddr));
+#if defined(CONFIG_MDFD_DUAL_MIPI)
+		REG_WRITE(DSPCSURF, *((u32 *)p_surfaceAddr));
+#endif
+	}
+	mid_enable_pipe_event(dev_priv, 0);
+	psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
+	dev_priv->is_in_idle = false;
+	dev_priv->dsr_idle_count = 0;
+}
+
+/*
+ * Init DSI DPI encoder. 
+ * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
+ * return pointer of newly allocated DPI encoder, NULL on error
+ */ 
+struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, 
+				struct mdfld_dsi_connector *dsi_connector,
+				struct panel_funcs*p_funcs)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_dpi_output *dpi_output = NULL;
+	struct mdfld_dsi_config *dsi_config;
+	struct drm_connector *connector = NULL;
+	struct drm_encoder *encoder = NULL;
+	struct drm_display_mode *fixed_mode = NULL;
+	int ret;
+
+	if (!dsi_connector) {
+		WARN_ON(1);
+		return NULL;
+	}
+
+	dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
+	if(!dpi_output) {
+		dev_err(dev->dev, "No memory for dsi_dpi_output\n");
+		return NULL;
+	}
+	/* Panel reset */
+	ret = mdfld_dpi_panel_reset(dsi_connector->pipe);
+	if(ret) {
+		DRM_ERROR("reset panel error\n");
+		goto out_err1;
+	}
+	
+	if(dsi_connector->pipe) 
+		dpi_output->panel_on = 0;
+
+		dpi_output->panel_on = 0;
+	
+	
+	dpi_output->dev = dev;
+	dpi_output->first_boot = 1;
+	
+	/* Get fixed mode */
+	dsi_config = mdfld_dsi_get_config(dsi_connector);
+	fixed_mode = dsi_config->fixed_mode;
+	
+	/* Create drm encoder object */
+	connector = &dsi_connector->base.base;
+	encoder = &dpi_output->base.base;
+	drm_encoder_init(dev,
+			encoder,
+			p_funcs->encoder_funcs,
+			DRM_MODE_ENCODER_MIPI);
+	drm_encoder_helper_add(encoder,
+				p_funcs->encoder_helper_funcs);
+	
+	/* Attach to given connector */
+	drm_mode_connector_attach_encoder(connector, encoder);
+	
+	/* Set possible crtcs and clones */
+	if(dsi_connector->pipe) {
+		encoder->possible_crtcs = (1 << 2);
+		encoder->possible_clones = (1 << 1);
+	} else {
+		encoder->possible_crtcs = (1 << 0);
+		encoder->possible_clones = (1 << 0);
+	}
+
+	dev_priv->dsr_fb_update = 0;
+	dev_priv->dsr_enable = false;
+	dev_priv->exit_idle = mdfld_dsi_dpi_exit_idle;
+#if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR)
+	dev_priv->dsr_enable_config = true;
+#endif /*CONFIG_MDFLD_DSI_DSR*/
+
+	return &dpi_output->base;
+	
+out_err1: 
+	if(dpi_output)
+		kfree(dpi_output);
+	return NULL;	
+}
+
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.h b/drivers/staging/gma500/mdfld_dsi_dpi.h
new file mode 100644
index 0000000..68e65cc
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dpi.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_DPI_H__
+#define __MDFLD_DSI_DPI_H__
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+struct mdfld_dsi_dpi_timing {
+	u16 hsync_count;
+	u16 hbp_count;
+	u16 hfp_count;
+	u16 hactive_count;
+	u16 vsync_count;
+	u16 vbp_count;
+	u16 vfp_count;
+};
+
+struct mdfld_dsi_dpi_output {
+	struct mdfld_dsi_encoder base;
+	struct drm_device *dev;
+
+	int panel_on;
+	int first_boot;
+};
+
+#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder) \
+	container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base)
+
+extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
+			struct mdfld_dsi_dpi_timing *dpi_timing,
+			int num_lane, int bpp);
+extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
+			struct mdfld_dsi_connector *dsi_connector,
+			struct panel_funcs *p_funcs);
+
+/* Medfield DPI helper functions */
+extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode);
+extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
+			struct drm_display_mode *mode,
+			struct drm_display_mode *adjusted_mode);
+extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder);
+extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder);
+extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
+			struct drm_display_mode *mode,
+			struct drm_display_mode *adjusted_mode);
+extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output,
+			int pipe);
+extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *si_config,
+			int pipe);
+extern void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe);
+extern void psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe,
+			u32 mask);
+
+#endif /*__MDFLD_DSI_DPI_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
new file mode 100644
index 0000000..44ee3f6
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_output.c
@@ -0,0 +1,977 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_output.h"
+#include <asm/intel_scu_ipc.h>
+#include "mdfld_dsi_pkg_sender.h"
+#include <linux/pm_runtime.h>
+
+#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
+
+/* get the CABC LABC from command line. */
+static int CABC_control = 1;
+static int LABC_control = 1;
+
+#ifdef MODULE
+module_param (CABC_control, int, 0644);
+module_param (LABC_control, int, 0644);
+#else
+static int __init parse_CABC_control(char *arg)
+{
+	/* CABC control can be passed in as a cmdline parameter */
+	/* to enable this feature add CABC=1 to cmdline */
+	/* to disable this feature add CABC=0 to cmdline */
+	if (!arg)
+		return -EINVAL;
+
+	if (!strcasecmp(arg, "0"))
+		CABC_control = 0;
+	else if (!strcasecmp (arg, "1"))
+		CABC_control = 1;
+
+	return 0;
+}
+early_param ("CABC", parse_CABC_control);
+
+static int __init parse_LABC_control(char *arg)
+{
+	/* LABC control can be passed in as a cmdline parameter */
+	/* to enable this feature add LABC=1 to cmdline */
+	/* to disable this feature add LABC=0 to cmdline */
+	if (!arg)
+		return -EINVAL;
+
+	if (!strcasecmp(arg, "0"))
+		LABC_control = 0;
+	else if (!strcasecmp (arg, "1"))
+		LABC_control = 1;
+
+	return 0;
+}
+early_param ("LABC", parse_LABC_control);
+#endif
+
+/**
+ * make these MCS command global 
+ * we don't need 'movl' everytime we send them.
+ * FIXME: these datas were provided by OEM, we should get them from GCT.
+ **/
+static u32 mdfld_dbi_mcs_hysteresis[] = {
+	0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0x000000ff,
+};
+
+static u32 mdfld_dbi_mcs_display_profile[] = {
+	0x50281450, 0x0000c882, 0x00000000, 0x00000000,
+	0x00000000,
+};
+
+static u32 mdfld_dbi_mcs_kbbc_profile[] = {
+	0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
+}; 
+	
+static u32 mdfld_dbi_mcs_gamma_profile[] = {
+	0x81111158, 0x88888888, 0x88888888,
+}; 
+
+/*
+ * write hysteresis values.
+ */
+static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+	        WARN_ON(1);
+		return;
+	}
+	mdfld_dsi_send_mcs_long_hs(sender,
+				   mdfld_dbi_mcs_hysteresis,
+				   17,
+				   MDFLD_DSI_SEND_PACKAGE);
+}
+
+/*
+ * write display profile values.
+ */
+static void mdfld_dsi_write_display_profile (struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+	        WARN_ON(1);
+		return;
+        }
+	mdfld_dsi_send_mcs_long_hs(sender,
+				   mdfld_dbi_mcs_display_profile,
+				   5,
+				   MDFLD_DSI_SEND_PACKAGE);
+}
+
+/*
+ * write KBBC profile values.
+ */
+static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+	        WARN_ON(1);
+		return;
+        }
+	mdfld_dsi_send_mcs_long_hs(sender,
+				   mdfld_dbi_mcs_kbbc_profile,
+				   4,
+				   MDFLD_DSI_SEND_PACKAGE);
+}
+
+/**
+ * write gamma setting.
+ */
+static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+	        WARN_ON(1);
+		return;
+	}
+	mdfld_dsi_send_mcs_long_hs(sender,
+				   mdfld_dbi_mcs_gamma_profile,
+				   3,
+				   MDFLD_DSI_SEND_PACKAGE);
+}
+
+/**
+ * Check and see if the generic control or data buffer is empty and ready.
+ */
+void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat)
+{
+	u32 GEN_BF_time_out_count = 0;
+	
+	/* Check MIPI Adatper command registers */
+	for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++)
+	{
+		if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
+			break;
+		udelay (100);
+	}
+
+	if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
+		dev_err(dev->dev,
+        "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n",
+                                                gen_fifo_stat_reg);
+}
+
+/**
+ * Manage the DSI MIPI keyboard and display brightness.
+ * FIXME: this is exported to OSPM code. should work out an specific 
+ * display interface to OSPM. 
+ */
+void mdfld_dsi_brightness_init (struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct mdfld_dsi_pkg_sender * sender = mdfld_dsi_get_pkg_sender(dsi_config);
+	struct drm_device * dev = sender->dev;
+	struct drm_psb_private * dev_priv = dev->dev_private;
+	u32 gen_ctrl_val;
+	
+	if(!sender) {
+	        WARN_ON(1);
+	        return;
+	}
+	/* Set default display backlight value to 85% (0xd8)*/
+	mdfld_dsi_send_mcs_short_hs(sender,
+				    write_display_brightness,
+				    0xd8,
+				    1,
+				    MDFLD_DSI_SEND_PACKAGE);
+
+	/* Set minimum brightness setting of CABC function to 20% (0x33)*/
+	mdfld_dsi_send_mcs_short_hs(sender,
+				    write_cabc_min_bright,
+				    0x33,
+				    1,
+				    MDFLD_DSI_SEND_PACKAGE);
+
+	mdfld_dsi_write_hysteresis (dsi_config, pipe);
+	mdfld_dsi_write_display_profile (dsi_config, pipe);
+	mdfld_dsi_write_kbbc_profile (dsi_config, pipe);
+	mdfld_dsi_write_gamma_setting (dsi_config, pipe);
+
+	/* Enable backlight or/and LABC */
+	gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON;
+	if (LABC_control == 1 || CABC_control == 1)
+		gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO;
+
+	if (LABC_control == 1)
+		gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
+
+	dev_priv->mipi_ctrl_display = gen_ctrl_val;
+
+	mdfld_dsi_send_mcs_short_hs(sender,
+				    write_ctrl_display,
+				    (u8)gen_ctrl_val,
+				    1,
+				    MDFLD_DSI_SEND_PACKAGE);
+
+	if (CABC_control == 0)
+		return;
+	mdfld_dsi_send_mcs_short_hs(sender,
+				    write_ctrl_cabc,
+				    UI_IMAGE,
+				    1,
+				    MDFLD_DSI_SEND_PACKAGE);
+}
+
+/**
+ * Manage the mipi display brightness.
+ * TODO: refine this interface later
+ */
+void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
+{
+	struct mdfld_dsi_pkg_sender *sender;
+	struct drm_psb_private *dev_priv;
+	struct mdfld_dsi_config *dsi_config;
+	u32 gen_ctrl_val = 0;
+	int p_type = TMD_VID;	
+	
+	if (!dev || (pipe != 0 && pipe != 2)) {
+		dev_err(dev->dev, "Invalid parameter\n");
+		return;
+	}
+
+	p_type = mdfld_get_panel_type(dev, 0);
+
+	dev_priv = dev->dev_private;
+
+	if(pipe)
+		dsi_config = dev_priv->dsi_configs[1];
+	else
+		dsi_config = dev_priv->dsi_configs[0];
+
+	sender = mdfld_dsi_get_pkg_sender(dsi_config);
+
+	if(!sender) {
+	        WARN_ON(1);
+		return;
+	}
+
+	gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
+
+	dev_dbg(dev->dev, "pipe = %d, gen_ctrl_val = %d.  \n", pipe, gen_ctrl_val);
+	
+	if(p_type == TMD_VID || p_type == TMD_CMD){
+		/* Set display backlight value */
+		mdfld_dsi_send_mcs_short_hs(sender, 
+					tmd_write_display_brightness, 
+					(u8)gen_ctrl_val, 
+	                                 1, 
+	                        	MDFLD_DSI_SEND_PACKAGE);		
+	} else {			
+		/* Set display backlight value */
+		mdfld_dsi_send_mcs_short_hs(sender,
+				    write_display_brightness,
+				    (u8)gen_ctrl_val,
+                                    1,
+                                    MDFLD_DSI_SEND_PACKAGE);
+
+
+		/* Enable backlight control */
+		if (level == 0)
+			gen_ctrl_val = 0;
+		else 
+			gen_ctrl_val = dev_priv->mipi_ctrl_display;
+
+		mdfld_dsi_send_mcs_short_hs(sender,
+                                    write_ctrl_display,
+                                   (u8)gen_ctrl_val,
+                                   1,
+                                   MDFLD_DSI_SEND_PACKAGE);
+	}
+}
+
+/*
+ * shut down DSI controller
+ */ 
+void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct drm_device * dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int retry = 100;
+	
+	if (!dsi_config) {
+	        WARN_ON(1);
+		return;
+	}
+	
+	dev = dsi_config->dev;
+	
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+		
+	if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) &  DSI_DEVICE_READY)) 
+		goto shutdown_out;
+	
+	/*send shut down package, clean packet send bit first*/
+	if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
+		REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), 
+				(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT));
+	}
+	
+	/*send shut down package in HS*/
+	REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
+	
+	
+	/*
+	 * make sure shut down is sent.
+	 * FIXME: add max retry counter
+	 */
+	while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
+		retry--;
+		
+		if(!retry) {
+			dev_err(dev->dev, "timeout\n");
+			break;
+		}
+	}
+	
+	/*sleep 1 ms to ensure shutdown finished*/
+	msleep(100);
+	
+	/*un-ready device*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
+			   (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & ~DSI_DEVICE_READY));
+
+shutdown_out:			   
+	gma_power_end(dev);
+}
+
+void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct drm_device * dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int retry = 100;
+	
+	
+	if (!dsi_config) {
+		WARN_ON(1);
+		return;
+	}
+	
+	dev = dsi_config->dev;
+	dev_dbg(dev->dev, "starting up DSI controller on pipe %d...\n", pipe);
+	
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+	
+	if((REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY)) 
+		goto startup_out;
+	
+	/*if config DPI, turn on DPI interface*/
+	if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
+		if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
+			REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
+		}
+		
+		REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
+		
+		/*
+		 * make sure shut down is sent.
+		 * FIXME: add max retry counter
+		 */
+		while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
+			retry--;
+			if(!retry) {
+				dev_err(dev->dev, "timeout\n");
+				break;
+			}
+		}
+		
+		msleep(100);
+	}
+	
+	/*set device ready*/
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
+			   (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) | DSI_DEVICE_READY));
+
+startup_out:	
+	gma_power_end(dev);
+}
+
+/*
+ * NOTE: this function was used by OSPM.
+ * TODO: will be removed later, should work out display interfaces for OSPM
+ */
+void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	if(!dsi_config || ((pipe != 0) && (pipe != 2))) {
+	        WARN_ON(1);
+		return;
+	}
+
+	if(dsi_config->type)
+		mdfld_dsi_dpi_controller_init(dsi_config, pipe);
+	else
+		mdfld_dsi_controller_dbi_init(dsi_config, pipe);
+}
+
+static void mdfld_dsi_connector_save(struct drm_connector * connector)
+{
+}
+
+static void mdfld_dsi_connector_restore(struct drm_connector * connector)
+{
+}
+
+static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
+											struct drm_property * property,
+											uint64_t value)
+{
+	struct drm_encoder * encoder = connector->encoder;
+	struct backlight_device * psb_bd;
+
+	if (!strcmp(property->name, "scaling mode") && encoder) {
+		struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
+		bool bTransitionFromToCentered;
+		uint64_t curValue;
+
+		if (!psb_crtc)
+			goto set_prop_error;
+
+		switch (value) {
+		case DRM_MODE_SCALE_FULLSCREEN:
+			break;
+		case DRM_MODE_SCALE_NO_SCALE:
+			break;
+		case DRM_MODE_SCALE_ASPECT:
+			break;
+		default:
+			goto set_prop_error;
+		}
+
+		if (drm_connector_property_get_value(connector, property, &curValue))
+			goto set_prop_error;
+
+		if (curValue == value)
+			goto set_prop_done;
+
+		if (drm_connector_property_set_value(connector, property, value))
+			goto set_prop_error;
+
+		bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
+			(value == DRM_MODE_SCALE_NO_SCALE);
+
+		if (psb_crtc->saved_mode.hdisplay != 0 &&
+		    psb_crtc->saved_mode.vdisplay != 0) {
+			if (bTransitionFromToCentered) {
+				if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode,
+					    encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
+					goto set_prop_error;
+			} else {
+				struct drm_encoder_helper_funcs *pEncHFuncs  = encoder->helper_private;
+				pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode,
+						     &psb_crtc->saved_adjusted_mode);
+			}
+		}
+	} else if (!strcmp(property->name, "backlight") && encoder) {
+		dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value);
+		if (drm_connector_property_set_value(connector, property, value))
+			goto set_prop_error;
+		else {
+			dev_dbg(encoder->dev->dev,
+			                "set brightness to %d", (int)value);
+			psb_bd = psb_get_backlight_device();
+			if(psb_bd) {
+				psb_bd->props.brightness = value;
+				psb_set_brightness(psb_bd);
+			}
+		}
+	} 
+set_prop_done:
+    return 0;
+set_prop_error:
+    return -1;
+}
+
+static void mdfld_dsi_connector_destroy(struct drm_connector * connector)
+{
+	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+	struct mdfld_dsi_pkg_sender * sender;
+	
+	if(!dsi_connector)
+	        return;
+	
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	
+	sender = dsi_connector->pkg_sender;
+
+	mdfld_dsi_pkg_sender_destroy(sender);
+
+	kfree(dsi_connector);
+}
+
+static int mdfld_dsi_connector_get_modes(struct drm_connector * connector)
+{
+	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+	struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
+	struct drm_display_mode * dup_mode = NULL;
+	struct drm_device * dev = connector->dev;
+	
+	connector->display_info.min_vfreq = 0;
+	connector->display_info.max_vfreq = 200;
+	connector->display_info.min_hfreq = 0;
+	connector->display_info.max_hfreq = 200;
+
+	if(fixed_mode) {
+		dev_dbg(dev->dev, "fixed_mode %dx%d\n",
+		        fixed_mode->hdisplay, fixed_mode->vdisplay);
+		
+		dup_mode = drm_mode_duplicate(dev, fixed_mode);
+		drm_mode_probed_add(connector, dup_mode);
+		return 1;
+	}
+	dev_err(dev->dev, "Didn't get any modes!\n");
+	return 0;
+}
+
+static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode)
+{
+	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+	struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
+
+	dev_dbg(connector->dev->dev, "mode %p, fixed mode %p\n",
+	                                                mode, fixed_mode);
+
+	if(mode->flags & DRM_MODE_FLAG_DBLSCAN) 
+		return MODE_NO_DBLESCAN;
+
+	if(mode->flags & DRM_MODE_FLAG_INTERLACE)
+		return MODE_NO_INTERLACE;
+
+	/**
+	 * FIXME: current DC has no fitting unit, reject any mode setting request
+	 * will figure out a way to do up-scaling(pannel fitting) later.  
+	 **/
+	if(fixed_mode) {
+		if(mode->hdisplay != fixed_mode->hdisplay)
+			return MODE_PANEL;
+
+		if(mode->vdisplay != fixed_mode->vdisplay)
+			return MODE_PANEL;
+	}
+	dev_dbg(connector->dev->dev, "mode ok\n");
+
+	return MODE_OK;
+}
+
+static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
+{
+#ifdef CONFIG_PM_RUNTIME
+	struct drm_device * dev = connector->dev;
+	struct drm_psb_private * dev_priv = dev->dev_private;
+	bool panel_on, panel_on2;
+#endif
+	/* First, execute DPMS */
+	drm_helper_connector_dpms(connector, mode);
+
+#ifdef CONFIG_PM_RUNTIME
+	if(mdfld_panel_dpi(dev)) {
+		/* DPI panel */
+		panel_on = dev_priv->dpi_panel_on;
+		panel_on2 = dev_priv->dpi_panel_on2;
+	} else {
+		/* DBI panel */
+		panel_on = dev_priv->dbi_panel_on;
+		panel_on2 = dev_priv->dbi_panel_on2;
+	}
+
+	/* Then check all display panels + monitors status */
+	if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL)
+	                                        & HDMIB_PORT_EN)) {
+		/*request rpm idle*/
+		if(dev_priv->rpm_enabled)
+			pm_request_idle(&dev->pdev->dev);
+	}
+	/*
+	 * if rpm wasn't enabled yet, try to allow it
+	 * FIXME: won't enable rpm for DPI since DPI
+	 * CRTC setting is a little messy now.
+	 * Enable it later!
+	 */
+#if 0
+	if(!dev_priv->rpm_enabled && !mdfld_panel_dpi(dev))
+		ospm_runtime_pm_allow(dev);
+#endif
+#endif
+}
+
+static struct drm_encoder * mdfld_dsi_connector_best_encoder(
+                                        struct drm_connector * connector) 
+{
+	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
+	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
+	struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
+	struct mdfld_dsi_encoder * encoder = NULL;
+	
+	if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) 
+		encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI];
+	else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) 
+		encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI];
+	
+	dev_dbg(connector->dev->dev, "get encoder %p\n", encoder);
+	
+	if(!encoder) {
+		dev_err(connector->dev->dev,
+                        "Invalid encoder for type %d\n", dsi_config->type);
+		return NULL;
+	}
+	dsi_config->encoder = encoder;	
+	return &encoder->base;	
+}
+
+/* DSI connector funcs */
+static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
+	.dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
+	.save = mdfld_dsi_connector_save,
+	.restore = mdfld_dsi_connector_restore,
+	.detect = mdfld_dsi_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = mdfld_dsi_connector_set_property,
+	.destroy = mdfld_dsi_connector_destroy,
+};
+
+/* DSI connector helper funcs */
+static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = {
+	.get_modes = mdfld_dsi_connector_get_modes,
+	.mode_valid = mdfld_dsi_connector_mode_valid,
+	.best_encoder = mdfld_dsi_connector_best_encoder,
+};
+
+static int mdfld_dsi_get_default_config(struct drm_device * dev, 
+										struct mdfld_dsi_config * config, int pipe)
+{
+	if(!dev || !config) {
+	        WARN_ON(1);
+		return -EINVAL;
+	}
+	
+	config->bpp = 24;
+	config->type = mdfld_panel_dpi(dev);
+	config->lane_count = 2;
+	config->channel_num = 0;
+	/*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
+	if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
+		config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
+	} else {
+		config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
+	}
+	
+	return 0;
+}
+
+/*
+ * Returns the panel fixed mode from configuration. 
+ */
+struct drm_display_mode *
+mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
+{
+	struct drm_device *dev = dsi_config->dev;
+	struct drm_display_mode *mode;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+	bool use_gct = false;
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode) {
+	        dev_err(dev->dev, "Out of memory for mode\n");
+		return NULL;
+        }
+	if (use_gct) {
+		dev_dbg(dev->dev, "gct find MIPI panel.\n");
+
+		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+		mode->hsync_start = mode->hdisplay + \
+				((ti->hsync_offset_hi << 8) | \
+				ti->hsync_offset_lo);
+		mode->hsync_end = mode->hsync_start + \
+				((ti->hsync_pulse_width_hi << 8) | \
+				ti->hsync_pulse_width_lo);
+		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+								ti->hblank_lo);
+		mode->vsync_start = \
+			mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+						ti->vsync_offset_lo);
+		mode->vsync_end = \
+			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+						ti->vsync_pulse_width_lo);
+		mode->vtotal = mode->vdisplay + \
+				((ti->vblank_hi << 8) | ti->vblank_lo);
+		mode->clock = ti->pixel_clock * 10;
+
+		dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
+		dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
+		dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
+		dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
+		dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
+		dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
+		dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
+		dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
+		dev_dbg(dev->dev, "clock is %d\n", mode->clock);
+	} else {
+		if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { 
+			if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
+				mode->hdisplay = 480;
+				mode->vdisplay = 854;
+				mode->hsync_start = 487;
+				mode->hsync_end = 490;
+				mode->htotal = 499;
+				mode->vsync_start = 861;
+				mode->vsync_end = 865;
+				mode->vtotal = 873;
+				mode->clock = 33264;
+			} else {
+				mode->hdisplay = 864;
+				mode->vdisplay = 480;
+				mode->hsync_start = 873;
+				mode->hsync_end = 876;
+				mode->htotal = 887;
+				mode->vsync_start = 487;
+				mode->vsync_end = 490;
+				mode->vtotal = 499;
+				mode->clock = 33264;
+			}
+		} else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+			mode->hdisplay = 864;
+			mode->vdisplay = 480;
+			mode->hsync_start = 872;
+			mode->hsync_end = 876;
+			mode->htotal = 884;
+			mode->vsync_start = 482;
+			mode->vsync_end = 494;
+			mode->vtotal = 486;
+			mode->clock = 25777;
+			
+		}
+	}
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+	
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+/*
+ * MIPI output init
+ * @dev drm device
+ * @pipe pipe number. 0 or 2
+ * @config 
+ * 
+ * Do the initialization of a MIPI output, including create DRM mode objects
+ * initialization of DSI output on @pipe 
+ */
+void mdfld_dsi_output_init(struct drm_device * dev,
+			   int pipe, 
+			   struct mdfld_dsi_config * config,
+			   struct panel_funcs* p_cmd_funcs,
+			   struct panel_funcs* p_vid_funcs)
+{
+	struct mdfld_dsi_config * dsi_config;
+	struct mdfld_dsi_connector * dsi_connector;
+	struct psb_intel_output * psb_output;
+	struct drm_connector * connector;
+	struct mdfld_dsi_encoder * encoder;
+	struct drm_psb_private * dev_priv = dev->dev_private;
+	struct panel_info dsi_panel_info;
+	u32 width_mm, height_mm;
+
+	dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
+	
+	if(!dev || ((pipe != 0) && (pipe != 2))) {
+	        WARN_ON(1);
+		return;
+	}
+	
+	/*create a new connetor*/
+	dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
+	if(!dsi_connector) {
+		DRM_ERROR("No memory");
+		return;
+	}
+	
+	dsi_connector->pipe =  pipe;
+	
+	/*set DSI config*/
+	if(config) { 
+		dsi_config = config;
+	} else {
+		dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL);
+		if(!dsi_config) {
+			dev_err(dev->dev,
+			        "cannot allocate memory for DSI config\n");
+			goto dsi_init_err0;
+		}
+		
+		mdfld_dsi_get_default_config(dev, dsi_config, pipe);
+	}
+	
+	dsi_connector->private = dsi_config;
+	
+	dsi_config->changed = 1;
+	dsi_config->dev = dev;
+	
+	/*init fixed mode basing on DSI config type*/
+	if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+		dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev);
+		if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
+			goto dsi_init_err0;
+	} else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
+		dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
+		if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
+			goto dsi_init_err0;
+	}
+
+	width_mm = dsi_panel_info.width_mm;
+	height_mm = dsi_panel_info.height_mm;
+
+	dsi_config->mode = dsi_config->fixed_mode;
+	dsi_config->connector = dsi_connector;
+	
+	if(!dsi_config->fixed_mode) {
+		dev_err(dev->dev, "No pannel fixed mode was found\n");
+		goto dsi_init_err0;
+	}
+	
+	if(pipe && dev_priv->dsi_configs[0]) {
+		dsi_config->dvr_ic_inited = 0;
+		dev_priv->dsi_configs[1] = dsi_config;
+	} else if(pipe == 0) {
+		dsi_config->dvr_ic_inited = 1;
+		dev_priv->dsi_configs[0] = dsi_config;
+	} else {
+		dev_err(dev->dev, "Trying to init MIPI1 before MIPI0\n");
+		goto dsi_init_err0;
+	}
+
+	/*init drm connector object*/
+	psb_output = &dsi_connector->base;
+	
+	psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2;
+
+	connector = &psb_output->base;
+	drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs, DRM_MODE_CONNECTOR_MIPI);
+	drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
+	
+	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+	connector->display_info.width_mm = width_mm;
+	connector->display_info.height_mm = height_mm;
+	connector->interlace_allowed = false;
+	connector->doublescan_allowed = false;
+	
+	/*attach properties*/
+	drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
+	drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
+
+	/*init DBI & DPI encoders*/
+	if(p_cmd_funcs) {
+		encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs);
+		if(!encoder) {
+			dev_err(dev->dev, "Create DBI encoder failed\n");
+			goto dsi_init_err1;
+		}
+		encoder->private = dsi_config;
+		dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder;
+		if(pipe == 2)
+			dev_priv->encoder2 = encoder;
+	
+		if(pipe == 0)
+			dev_priv->encoder0 = encoder;
+			
+	}
+	
+	if(p_vid_funcs) {
+		encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
+		if(!encoder) {
+			dev_err(dev->dev, "Create DPI encoder failed\n");
+			goto dsi_init_err1;
+		}
+		encoder->private = dsi_config;
+		dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder;
+
+        if(pipe == 2)
+            dev_priv->encoder2 = encoder;
+
+		if(pipe == 0)
+            dev_priv->encoder0 = encoder;
+	}
+	
+	drm_sysfs_connector_add(connector);
+	
+	/*init DSI package sender on this output*/
+	if(mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
+		dev_err(dev->dev, 
+		        "Package Sender initialization failed on pipe %d\n",
+		                                                pipe);
+		goto dsi_init_err2;
+	}
+
+	dev_dbg(dev->dev, "successfully\n");
+	return;
+	
+	/*TODO: add code to destroy outputs on error*/
+dsi_init_err2:
+	drm_sysfs_connector_remove(connector);
+dsi_init_err1:
+	drm_connector_cleanup(connector);
+	kfree(dsi_config->fixed_mode);
+	kfree(dsi_config);
+dsi_init_err0:
+	kfree(dsi_connector);
+}
diff --git a/drivers/staging/gma500/mdfld_dsi_output.h b/drivers/staging/gma500/mdfld_dsi_output.h
new file mode 100644
index 0000000..ac25e55
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_output.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#ifndef __MDFLD_DSI_OUTPUT_H__
+#define __MDFLD_DSI_OUTPUT_H__
+
+#include <linux/backlight.h>
+#include <linux/version.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+#include "mdfld_output.h"
+
+#include <asm/mrst.h>
+
+#define DRM_MODE_ENCODER_MIPI  5
+
+/* Medfield DSI controller registers */
+
+#define MIPIA_DEVICE_READY_REG				0xb000
+#define MIPIA_INTR_STAT_REG				0xb004
+#define MIPIA_INTR_EN_REG				0xb008
+#define MIPIA_DSI_FUNC_PRG_REG				0xb00c
+#define MIPIA_HS_TX_TIMEOUT_REG				0xb010
+#define MIPIA_LP_RX_TIMEOUT_REG				0xb014
+#define MIPIA_TURN_AROUND_TIMEOUT_REG			0xb018
+#define MIPIA_DEVICE_RESET_TIMER_REG			0xb01c
+#define MIPIA_DPI_RESOLUTION_REG			0xb020
+#define MIPIA_DBI_FIFO_THROTTLE_REG			0xb024
+#define MIPIA_HSYNC_COUNT_REG				0xb028
+#define MIPIA_HBP_COUNT_REG				0xb02c
+#define MIPIA_HFP_COUNT_REG				0xb030
+#define MIPIA_HACTIVE_COUNT_REG				0xb034
+#define MIPIA_VSYNC_COUNT_REG				0xb038
+#define MIPIA_VBP_COUNT_REG				0xb03c
+#define MIPIA_VFP_COUNT_REG				0xb040
+#define MIPIA_HIGH_LOW_SWITCH_COUNT_REG			0xb044
+#define MIPIA_DPI_CONTROL_REG				0xb048
+#define MIPIA_DPI_DATA_REG				0xb04c
+#define MIPIA_INIT_COUNT_REG				0xb050
+#define MIPIA_MAX_RETURN_PACK_SIZE_REG			0xb054
+#define MIPIA_VIDEO_MODE_FORMAT_REG			0xb058
+#define MIPIA_EOT_DISABLE_REG				0xb05c
+#define MIPIA_LP_BYTECLK_REG				0xb060
+#define MIPIA_LP_GEN_DATA_REG				0xb064
+#define MIPIA_HS_GEN_DATA_REG				0xb068
+#define MIPIA_LP_GEN_CTRL_REG				0xb06c
+#define MIPIA_HS_GEN_CTRL_REG				0xb070
+#define MIPIA_GEN_FIFO_STAT_REG				0xb074
+#define MIPIA_HS_LS_DBI_ENABLE_REG			0xb078
+#define MIPIA_DPHY_PARAM_REG				0xb080
+#define MIPIA_DBI_BW_CTRL_REG				0xb084
+#define MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG		0xb088
+
+#define DSI_DEVICE_READY				(0x1)
+#define DSI_POWER_STATE_ULPS_ENTER			(0x2 << 1)
+#define DSI_POWER_STATE_ULPS_EXIT			(0x1 << 1)
+#define DSI_POWER_STATE_ULPS_OFFSET			(0x1)
+
+
+#define DSI_ONE_DATA_LANE				(0x1)
+#define DSI_TWO_DATA_LANE				(0x2)
+#define DSI_THREE_DATA_LANE				(0X3)
+#define DSI_FOUR_DATA_LANE				(0x4)
+#define DSI_DPI_VIRT_CHANNEL_OFFSET			(0x3)
+#define DSI_DBI_VIRT_CHANNEL_OFFSET			(0x5)
+#define DSI_DPI_COLOR_FORMAT_RGB565			(0x01 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB666			(0x02 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK		(0x03 << 7)
+#define DSI_DPI_COLOR_FORMAT_RGB888			(0x04 << 7)
+#define DSI_DBI_COLOR_FORMAT_OPTION2			(0x05 << 13)
+
+#define DSI_INTR_STATE_RXSOTERROR			1
+
+#define DSI_INTR_STATE_SPL_PKG_SENT			(1 << 30)
+#define DSI_INTR_STATE_TE				(1 << 31)
+
+#define DSI_HS_TX_TIMEOUT_MASK				(0xffffff)
+
+#define DSI_LP_RX_TIMEOUT_MASK				(0xffffff)
+
+#define DSI_TURN_AROUND_TIMEOUT_MASK			(0x3f)
+
+#define DSI_RESET_TIMER_MASK				(0xffff)
+
+#define DSI_DBI_FIFO_WM_HALF				(0x0)
+#define DSI_DBI_FIFO_WM_QUARTER				(0x1)
+#define DSI_DBI_FIFO_WM_LOW				(0x2)
+
+#define DSI_DPI_TIMING_MASK				(0xffff)
+
+#define DSI_INIT_TIMER_MASK				(0xffff)
+
+#define DSI_DBI_RETURN_PACK_SIZE_MASK			(0x3ff)
+
+#define DSI_LP_BYTECLK_MASK				(0x0ffff)
+
+#define DSI_HS_CTRL_GEN_SHORT_W0			(0x03)
+#define DSI_HS_CTRL_GEN_SHORT_W1			(0x13)
+#define DSI_HS_CTRL_GEN_SHORT_W2			(0x23)
+#define DSI_HS_CTRL_GEN_R0				(0x04)
+#define DSI_HS_CTRL_GEN_R1				(0x14)
+#define DSI_HS_CTRL_GEN_R2				(0x24)
+#define DSI_HS_CTRL_GEN_LONG_W				(0x29)
+#define DSI_HS_CTRL_MCS_SHORT_W0			(0x05)
+#define DSI_HS_CTRL_MCS_SHORT_W1			(0x15)
+#define DSI_HS_CTRL_MCS_R0				(0x06)
+#define DSI_HS_CTRL_MCS_LONG_W				(0x39)
+#define DSI_HS_CTRL_VC_OFFSET				(0x06)
+#define DSI_HS_CTRL_WC_OFFSET				(0x08)
+
+#define	DSI_FIFO_GEN_HS_DATA_FULL			(1 << 0)
+#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY			(1 << 1)
+#define DSI_FIFO_GEN_HS_DATA_EMPTY			(1 << 2)
+#define DSI_FIFO_GEN_LP_DATA_FULL			(1 << 8)
+#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY			(1 << 9)
+#define DSI_FIFO_GEN_LP_DATA_EMPTY			(1 << 10)
+#define DSI_FIFO_GEN_HS_CTRL_FULL			(1 << 16)
+#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY			(1 << 17)
+#define DSI_FIFO_GEN_HS_CTRL_EMPTY			(1 << 18)
+#define DSI_FIFO_GEN_LP_CTRL_FULL			(1 << 24)
+#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY			(1 << 25)
+#define DSI_FIFO_GEN_LP_CTRL_EMPTY			(1 << 26)
+#define DSI_FIFO_DBI_EMPTY				(1 << 27)
+#define DSI_FIFO_DPI_EMPTY				(1 << 28)
+
+#define DSI_DBI_HS_LP_SWITCH_MASK			(0x1)
+
+#define DSI_HS_LP_SWITCH_COUNTER_OFFSET			(0x0)
+#define DSI_LP_HS_SWITCH_COUNTER_OFFSET			(0x16)
+
+#define DSI_DPI_CTRL_HS_SHUTDOWN			(0x00000001)
+#define DSI_DPI_CTRL_HS_TURN_ON				(0x00000002)
+
+/* Medfield DSI adapter registers */
+#define MIPIA_CONTROL_REG				0xb104
+#define MIPIA_DATA_ADD_REG				0xb108
+#define MIPIA_DATA_LEN_REG				0xb10c
+#define MIPIA_CMD_ADD_REG				0xb110
+#define MIPIA_CMD_LEN_REG				0xb114
+
+enum {
+	MDFLD_DSI_ENCODER_DBI = 0,
+	MDFLD_DSI_ENCODER_DPI,
+};
+
+enum {
+	MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1,
+	MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2,
+	MDFLD_DSI_VIDEO_BURST_MODE = 3,
+};
+
+#define DSI_DPI_COMPLETE_LAST_LINE			(1 << 2)
+#define DSI_DPI_DISABLE_BTA				(1 << 3)
+
+struct mdfld_dsi_connector_state {
+	u32 mipi_ctrl_reg;
+};
+
+struct mdfld_dsi_encoder_state {
+
+};
+
+struct mdfld_dsi_connector {
+	/*
+	 * This is ugly, but I have to use connector in it! :-(
+	 * FIXME: use drm_connector instead.
+	 */
+	struct psb_intel_output base;
+
+	int pipe;
+	void *private;
+	void *pkg_sender;
+};
+
+struct mdfld_dsi_encoder {
+	struct drm_encoder base;
+	void *private;
+};
+
+/*
+ * DSI config, consists of one DSI connector, two DSI encoders.
+ * DRM will pick up on DSI encoder basing on differents configs.
+ */
+struct mdfld_dsi_config {
+	struct drm_device *dev;
+	struct drm_display_mode *fixed_mode;
+	struct drm_display_mode *mode;
+
+	struct mdfld_dsi_connector *connector;
+	struct mdfld_dsi_encoder *encoders[DRM_CONNECTOR_MAX_ENCODER];
+	struct mdfld_dsi_encoder *encoder;
+
+	int changed;
+
+	int bpp;
+	int type;
+	int lane_count;
+	/*Virtual channel number for this encoder*/
+	int channel_num;
+	/*video mode configure*/
+	int video_mode;
+
+	int dvr_ic_inited;
+};
+
+#define MDFLD_DSI_CONNECTOR(psb_output) \
+		(container_of(psb_output, struct mdfld_dsi_connector, base))
+
+#define MDFLD_DSI_ENCODER(encoder) \
+		(container_of(encoder, struct mdfld_dsi_encoder, base))
+
+static inline struct mdfld_dsi_config *
+	mdfld_dsi_get_config(struct mdfld_dsi_connector *connector)
+{
+	if (!connector)
+		return NULL;
+	return (struct mdfld_dsi_config *)connector->private;
+}
+
+static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config)
+{
+	struct mdfld_dsi_connector *dsi_connector;
+
+	if (!config)
+		return NULL;
+
+	dsi_connector = config->connector;
+
+	if (!dsi_connector)
+		return NULL;
+
+	return dsi_connector->pkg_sender;
+}
+
+static inline struct mdfld_dsi_config *
+	mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder)
+{
+	if (!encoder)
+		return NULL;
+	return (struct mdfld_dsi_config *)encoder->private;
+}
+
+static inline struct mdfld_dsi_connector *
+	mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder)
+{
+	struct mdfld_dsi_config *config;
+
+	if (!encoder)
+		return NULL;
+
+	config = mdfld_dsi_encoder_get_config(encoder);
+	if (!config)
+		return NULL;
+
+	return config->connector;
+}
+
+static inline void *mdfld_dsi_encoder_get_pkg_sender(
+	struct mdfld_dsi_encoder *encoder)
+{
+	struct mdfld_dsi_config *dsi_config;
+
+	dsi_config = mdfld_dsi_encoder_get_config(encoder);
+	if (!dsi_config)
+		return NULL;
+
+	return mdfld_dsi_get_pkg_sender(dsi_config);
+}
+
+static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder)
+{
+	struct mdfld_dsi_connector *connector;
+
+	if (!encoder)
+		return -1;
+
+	connector = mdfld_dsi_encoder_get_connector(encoder);
+	if (!connector)
+		return -1;
+
+	return connector->pipe;
+}
+
+extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev,
+				u32 gen_fifo_stat_reg, u32 fifo_stat);
+extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config,
+				int pipe);
+extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe,
+				int level);
+extern void mdfld_dsi_output_init(struct drm_device *dev, int pipe,
+				struct mdfld_dsi_config *config,
+				struct panel_funcs *p_cmd_funcs,
+				struct panel_funcs *p_vid_funcs);
+extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config,
+				int pipe);
+
+#endif /*__MDFLD_DSI_OUTPUT_H__*/
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
new file mode 100644
index 0000000..9198aa8
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
@@ -0,0 +1,1097 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include <linux/freezer.h>
+
+#include "mdfld_dsi_output.h"
+#include "mdfld_dsi_pkg_sender.h"
+#include "mdfld_dsi_dbi.h"
+
+#define MDFLD_DSI_DBI_FIFO_TIMEOUT	100
+
+static const char * const dsi_errors[] = {
+	"RX SOT Error",
+	"RX SOT Sync Error",
+	"RX EOT Sync Error",
+	"RX Escape Mode Entry Error",
+	"RX LP TX Sync Error",
+	"RX HS Receive Timeout Error",
+	"RX False Control Error",
+	"RX ECC Single Bit Error",
+	"RX ECC Multibit Error",
+	"RX Checksum Error",
+	"RX DSI Data Type Not Recognised",
+	"RX DSI VC ID Invalid",
+	"TX False Control Error",
+	"TX ECC Single Bit Error",
+	"TX ECC Multibit Error",
+	"TX Checksum Error",
+	"TX DSI Data Type Not Recognised",
+	"TX DSI VC ID invalid",
+	"High Contention",
+	"Low contention",
+	"DPI FIFO Under run",
+	"HS TX Timeout",
+	"LP RX Timeout",
+	"Turn Around ACK Timeout",
+	"ACK With No Error",
+	"RX Invalid TX Length",
+	"RX Prot Violation",
+	"HS Generic Write FIFO Full",
+	"LP Generic Write FIFO Full",
+	"Generic Read Data Avail"
+	"Special Packet Sent",
+	"Tearing Effect",
+};
+
+static int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender,
+								u32 mask)
+{
+	struct drm_device *dev = sender->dev;
+	u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
+	int retry = 0xffff;
+
+	while (retry--) {
+		if ((mask & REG_READ(gen_fifo_stat_reg)) == mask)
+			return 0;
+		udelay(100);
+	}
+	dev_err(dev->dev, "fifo is NOT empty 0x%08x\n",
+					REG_READ(gen_fifo_stat_reg));
+	return -EIO;
+}
+
+static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+	return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 10) | (1 << 18)
+		| (1 << 26) | (1 << 27) | (1 << 28));
+}
+
+static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+	return wait_for_gen_fifo_empty(sender, (1 << 10) | (1 << 26));
+}
+
+static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+	return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 18));
+}
+
+static int wait_for_dbi_fifo_empty(struct mdfld_dsi_pkg_sender *sender)
+{
+	return wait_for_gen_fifo_empty(sender, (1 << 27));
+}
+
+static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask)
+{
+	u32 intr_stat_reg = sender->mipi_intr_stat_reg;
+	struct drm_device *dev = sender->dev;
+
+	switch (mask) {
+	case (1 << 0):
+	case (1 << 1):
+	case (1 << 2):
+	case (1 << 3):
+	case (1 << 4):
+	case (1 << 5):
+	case (1 << 6):
+	case (1 << 7):
+	case (1 << 8):
+	case (1 << 9):
+	case (1 << 10):
+	case (1 << 11):
+	case (1 << 12):
+	case (1 << 13):
+		break;
+	case (1 << 14):
+		/*wait for all fifo empty*/
+		/*wait_for_all_fifos_empty(sender)*/;
+		break;
+	case (1 << 15):
+		break;
+	case (1 << 16):
+		break;
+	case (1 << 17):
+		break;
+	case (1 << 18):
+	case (1 << 19):
+		/*wait for contention recovery time*/
+		/*mdelay(10);*/
+		/*wait for all fifo empty*/
+		if (0)
+			wait_for_all_fifos_empty(sender);
+		break;
+	case (1 << 20):
+		break;
+	case (1 << 21):
+		/*wait for all fifo empty*/
+		/*wait_for_all_fifos_empty(sender);*/
+		break;
+	case (1 << 22):
+		break;
+	case (1 << 23):
+	case (1 << 24):
+	case (1 << 25):
+	case (1 << 26):
+	case (1 << 27):
+		/* HS Gen fifo full */
+		REG_WRITE(intr_stat_reg, mask);
+		wait_for_hs_fifos_empty(sender);
+		break;
+	case (1 << 28):
+		/* LP Gen fifo full\n */
+		REG_WRITE(intr_stat_reg, mask);
+		wait_for_lp_fifos_empty(sender);
+		break;
+	case (1 << 29):
+	case (1 << 30):
+	case (1 << 31):
+		break;
+	}
+
+	if (mask & REG_READ(intr_stat_reg))
+		dev_warn(dev->dev, "Cannot clean interrupt 0x%08x\n", mask);
+
+	return 0;
+}
+
+static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender)
+{
+	struct drm_device *dev = sender->dev;
+	u32 intr_stat_reg = sender->mipi_intr_stat_reg;
+	u32 mask;
+	u32 intr_stat;
+	int i;
+	int err = 0;
+
+	intr_stat = REG_READ(intr_stat_reg);
+
+	for (i = 0; i < 32; i++) {
+		mask = (0x00000001UL) << i;
+		if (intr_stat & mask) {
+			dev_dbg(dev->dev, "[DSI]: %s\n", dsi_errors[i]);
+			err = handle_dsi_error(sender, mask);
+			if (err)
+				dev_err(dev->dev, "Cannot handle error\n");
+		}
+	}
+	return err;
+}
+
+static inline int dbi_cmd_sent(struct mdfld_dsi_pkg_sender *sender)
+{
+	struct drm_device *dev = sender->dev;
+	u32 retry = 0xffff;
+	u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg;
+
+	/* Query the command execution status */
+	while (retry--) {
+		if (!(REG_READ(dbi_cmd_addr_reg) & (1 << 0)))
+			break;
+	}
+
+	if (!retry) {
+		dev_err(dev->dev, "Timeout waiting for DBI Command status\n");
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+/*
+ * NOTE: this interface is abandoned expect for write_mem_start DCS
+ * other DCS are sent via generic pkg interfaces
+ */
+static int send_dcs_pkg(struct mdfld_dsi_pkg_sender *sender,
+			struct mdfld_dsi_pkg *pkg)
+{
+	struct drm_device *dev = sender->dev;
+	struct mdfld_dsi_dcs_pkg *dcs_pkg = &pkg->pkg.dcs_pkg;
+	u32 dbi_cmd_len_reg = sender->mipi_cmd_len_reg;
+	u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg;
+	u32 cb_phy = sender->dbi_cb_phy;
+	u32 index = 0;
+	u8 *cb = (u8 *)sender->dbi_cb_addr;
+	int i;
+	int ret;
+
+	if (!sender->dbi_pkg_support) {
+		dev_err(dev->dev, "Trying to send DCS on a non DBI output, abort!\n");
+		return -ENOTSUPP;
+	}
+
+	/*wait for DBI fifo empty*/
+	wait_for_dbi_fifo_empty(sender);
+
+	*(cb + (index++)) = dcs_pkg->cmd;
+	if (dcs_pkg->param_num) {
+		for (i = 0; i < dcs_pkg->param_num; i++)
+			*(cb + (index++)) = *(dcs_pkg->param + i);
+	}
+
+	REG_WRITE(dbi_cmd_len_reg, (1 + dcs_pkg->param_num));
+	REG_WRITE(dbi_cmd_addr_reg,
+		(cb_phy << CMD_MEM_ADDR_OFFSET)
+		| (1 << 0)
+		| ((dcs_pkg->data_src == CMD_DATA_SRC_PIPE) ? (1 << 1) : 0));
+
+	ret = dbi_cmd_sent(sender);
+	if (ret) {
+		dev_err(dev->dev, "command 0x%x not complete\n", dcs_pkg->cmd);
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+static int __send_short_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	struct drm_device *dev = sender->dev;
+	u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
+	u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
+	u32 gen_ctrl_val = 0;
+	struct mdfld_dsi_gen_short_pkg *short_pkg = &pkg->pkg.short_pkg;
+
+	gen_ctrl_val |= short_pkg->cmd << MCS_COMMANDS_POS;
+	gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS;
+	gen_ctrl_val |= pkg->pkg_type;
+	gen_ctrl_val |= short_pkg->param << MCS_PARAMETER_POS;
+
+	if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) {
+		/* wait for hs fifo empty */
+		/* wait_for_hs_fifos_empty(sender); */
+		/* Send pkg */
+		REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val);
+	} else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) {
+		/* wait_for_lp_fifos_empty(sender); */
+		/* Send pkg*/
+		REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val);
+	} else {
+		dev_err(dev->dev, "Unknown transmission type %d\n",
+							pkg->transmission_type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int __send_long_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	struct drm_device *dev = sender->dev;
+	u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
+	u32 hs_gen_data_reg = sender->mipi_hs_gen_data_reg;
+	u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
+	u32 lp_gen_data_reg = sender->mipi_lp_gen_data_reg;
+	u32 gen_ctrl_val = 0;
+	u32 *dp;
+	int i;
+	struct mdfld_dsi_gen_long_pkg *long_pkg = &pkg->pkg.long_pkg;
+
+	dp = long_pkg->data;
+
+	/*
+	 * Set up word count for long pkg
+	 * FIXME: double check word count field.
+	 * currently, using the byte counts of the payload as the word count.
+	 * ------------------------------------------------------------
+	 * | DI |   WC   | ECC|         PAYLOAD              |CHECKSUM|
+	 * ------------------------------------------------------------
+	 */
+	gen_ctrl_val |= (long_pkg->len << 2) << WORD_COUNTS_POS;
+	gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS;
+	gen_ctrl_val |= pkg->pkg_type;
+
+	if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) {
+		/* Wait for hs ctrl and data fifos to be empty */
+		/* wait_for_hs_fifos_empty(sender); */
+		for (i = 0; i < long_pkg->len; i++)
+			REG_WRITE(hs_gen_data_reg, *(dp + i));
+		REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val);
+	} else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) {
+		/* wait_for_lp_fifos_empty(sender); */
+		for (i = 0; i < long_pkg->len; i++)
+			REG_WRITE(lp_gen_data_reg, *(dp + i));
+		REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val);
+	} else {
+		dev_err(dev->dev, "Unknown transmission type %d\n",
+						pkg->transmission_type);
+		return -EINVAL;
+	}
+
+	return 0;
+
+}
+
+static int send_mcs_short_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	return __send_short_pkg(sender, pkg);
+}
+
+static int send_mcs_long_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	return __send_long_pkg(sender, pkg);
+}
+
+static int send_gen_short_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	return __send_short_pkg(sender, pkg);
+}
+
+static int send_gen_long_pkg(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	return __send_long_pkg(sender, pkg);
+}
+
+static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	u8 cmd;
+	u8 *data;
+
+	switch (pkg->pkg_type) {
+	case MDFLD_DSI_PKG_DCS:
+		cmd = pkg->pkg.dcs_pkg.cmd;
+		break;
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
+		cmd = pkg->pkg.short_pkg.cmd;
+		break;
+	case MDFLD_DSI_PKG_MCS_LONG_WRITE:
+		data = (u8 *)pkg->pkg.long_pkg.data;
+		cmd = *data;
+		break;
+	default:
+		return 0;
+	}
+
+	/* This prevents other package sending while doing msleep */
+	sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
+
+	/* Check panel mode v.s. sending command */
+	if ((sender->panel_mode & MDFLD_DSI_PANEL_MODE_SLEEP) &&
+		cmd != exit_sleep_mode) {
+		dev_err(sender->dev->dev,
+				"sending 0x%x when panel sleep in\n", cmd);
+		sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+		return -EINVAL;
+	}
+
+	/* Wait for 120 milliseconds in case exit_sleep_mode just be sent */
+	if (cmd == enter_sleep_mode)
+		mdelay(120);
+	return 0;
+}
+
+static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender,
+				struct mdfld_dsi_pkg *pkg)
+{
+	u8 cmd;
+	u8 *data;
+
+	switch (pkg->pkg_type) {
+	case MDFLD_DSI_PKG_DCS:
+		cmd = pkg->pkg.dcs_pkg.cmd;
+		break;
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
+		cmd = pkg->pkg.short_pkg.cmd;
+		break;
+	case MDFLD_DSI_PKG_MCS_LONG_WRITE:
+		data = (u8 *)pkg->pkg.long_pkg.data;
+		cmd = *data;
+		break;
+	default:
+		return 0;
+	}
+
+	/* Update panel status */
+	if (cmd == enter_sleep_mode) {
+		sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
+		/*TODO: replace it with msleep later*/
+		mdelay(120);
+	} else if (cmd == exit_sleep_mode) {
+		sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
+		/*TODO: replace it with msleep later*/
+		mdelay(120);
+	}
+
+	sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+	return 0;
+
+}
+
+static int do_send_pkg(struct mdfld_dsi_pkg_sender *sender,
+			struct mdfld_dsi_pkg *pkg)
+{
+	int ret;
+
+	if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
+		dev_err(sender->dev->dev, "sender is busy\n");
+		return -EAGAIN;
+	}
+
+	ret = send_pkg_prepare(sender, pkg);
+	if (ret) {
+		dev_err(sender->dev->dev, "send_pkg_prepare error\n");
+		return ret;
+	}
+
+	switch (pkg->pkg_type) {
+	case MDFLD_DSI_PKG_DCS:
+		ret = send_dcs_pkg(sender, pkg);
+		break;
+	case MDFLD_DSI_PKG_GEN_SHORT_WRITE_0:
+	case MDFLD_DSI_PKG_GEN_SHORT_WRITE_1:
+	case MDFLD_DSI_PKG_GEN_SHORT_WRITE_2:
+		ret = send_gen_short_pkg(sender, pkg);
+		break;
+	case MDFLD_DSI_PKG_GEN_LONG_WRITE:
+		ret = send_gen_long_pkg(sender, pkg);
+		break;
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0:
+	case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1:
+		ret = send_mcs_short_pkg(sender, pkg);
+		break;
+	case MDFLD_DSI_PKG_MCS_LONG_WRITE:
+		ret = send_mcs_long_pkg(sender, pkg);
+		break;
+	default:
+		dev_err(sender->dev->dev, "Invalid pkg type 0x%x\n",
+							pkg->pkg_type);
+		ret = -EINVAL;
+	}
+	send_pkg_done(sender, pkg);
+	return ret;
+}
+
+static int send_pkg(struct mdfld_dsi_pkg_sender *sender,
+			struct mdfld_dsi_pkg *pkg)
+{
+	int err ;
+
+	/* Handle DSI error */
+	err = dsi_error_handler(sender);
+	if (err) {
+		dev_err(sender->dev->dev, "Error handling failed\n");
+		err = -EAGAIN;
+		goto send_pkg_err;
+	}
+
+	/* Send pkg */
+	err = do_send_pkg(sender, pkg);
+	if (err) {
+		dev_err(sender->dev->dev, "sent pkg failed\n");
+		err = -EAGAIN;
+		goto send_pkg_err;
+	}
+
+	/* FIXME: should I query complete and fifo empty here? */
+send_pkg_err:
+	return err;
+}
+
+static struct mdfld_dsi_pkg *pkg_sender_get_pkg_locked(
+					struct mdfld_dsi_pkg_sender *sender)
+{
+	struct mdfld_dsi_pkg *pkg;
+
+	if (list_empty(&sender->free_list)) {
+		dev_err(sender->dev->dev, "No free pkg left\n");
+		return NULL;
+	}
+	pkg = list_first_entry(&sender->free_list, struct mdfld_dsi_pkg, entry);
+	/* Detach from free list */
+	list_del_init(&pkg->entry);
+	return pkg;
+}
+
+static void pkg_sender_put_pkg_locked(struct mdfld_dsi_pkg_sender *sender,
+					struct mdfld_dsi_pkg *pkg)
+{
+	memset(pkg, 0, sizeof(struct mdfld_dsi_pkg));
+	INIT_LIST_HEAD(&pkg->entry);
+	list_add_tail(&pkg->entry, &sender->free_list);
+}
+
+static int mdfld_dbi_cb_init(struct mdfld_dsi_pkg_sender *sender,
+					struct psb_gtt *pg, int pipe)
+{
+	unsigned long phys;
+	void *virt_addr = NULL;
+
+	switch (pipe) {
+	case 0:
+		phys = pg->gtt_phys_start - 0x1000;
+		break;
+	case 2:
+		phys = pg->gtt_phys_start - 0x800;
+		break;
+	default:
+		dev_err(sender->dev->dev, "Unsupported channel %d\n", pipe);
+		return -EINVAL;
+	}
+
+	virt_addr = ioremap_nocache(phys, 0x800);
+	if (!virt_addr) {
+		dev_err(sender->dev->dev, "Map DBI command buffer error\n");
+		return -ENOMEM;
+	}
+	sender->dbi_cb_phy = phys;
+	sender->dbi_cb_addr = virt_addr;
+	return 0;
+}
+
+static void mdfld_dbi_cb_destroy(struct mdfld_dsi_pkg_sender *sender)
+{
+	if (sender && sender->dbi_cb_addr)
+		iounmap(sender->dbi_cb_addr);
+}
+
+static void pkg_sender_queue_pkg(struct mdfld_dsi_pkg_sender *sender,
+					struct mdfld_dsi_pkg *pkg,
+					int delay)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+
+	if (!delay) {
+		send_pkg(sender, pkg);
+		pkg_sender_put_pkg_locked(sender, pkg);
+	} else {
+		/* Queue it */
+		list_add_tail(&pkg->entry, &sender->pkg_list);
+	}
+	spin_unlock_irqrestore(&sender->lock, flags);
+}
+
+static void process_pkg_list(struct mdfld_dsi_pkg_sender *sender)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+
+	while (!list_empty(&sender->pkg_list)) {
+		pkg = list_first_entry(&sender->pkg_list,
+					struct mdfld_dsi_pkg, entry);
+		send_pkg(sender, pkg);
+		list_del_init(&pkg->entry);
+		pkg_sender_put_pkg_locked(sender, pkg);
+	}
+
+	spin_unlock_irqrestore(&sender->lock, flags);
+}
+
+static int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender,
+	u32 *data, u32 len, u8 transmission, int delay)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+	pkg = pkg_sender_get_pkg_locked(sender);
+	spin_unlock_irqrestore(&sender->lock, flags);
+
+	if (!pkg) {
+		dev_err(sender->dev->dev, "No memory\n");
+		return -ENOMEM;
+	}
+	pkg->pkg_type = MDFLD_DSI_PKG_MCS_LONG_WRITE;
+	pkg->transmission_type = transmission;
+	pkg->pkg.long_pkg.data = data;
+	pkg->pkg.long_pkg.len = len;
+	INIT_LIST_HEAD(&pkg->entry);
+
+	pkg_sender_queue_pkg(sender, pkg, delay);
+	return 0;
+}
+
+static int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender,
+					u8 cmd, u8 param, u8 param_num,
+					u8 transmission,
+					int delay)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+	pkg = pkg_sender_get_pkg_locked(sender);
+	spin_unlock_irqrestore(&sender->lock, flags);
+
+	if (!pkg) {
+		dev_err(sender->dev->dev, "No memory\n");
+		return -ENOMEM;
+	}
+
+	if (param_num) {
+		pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_1;
+		pkg->pkg.short_pkg.param = param;
+	} else {
+		pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_0;
+		pkg->pkg.short_pkg.param = 0;
+	}
+	pkg->transmission_type = transmission;
+	pkg->pkg.short_pkg.cmd = cmd;
+	INIT_LIST_HEAD(&pkg->entry);
+
+	pkg_sender_queue_pkg(sender, pkg, delay);
+	return 0;
+}
+
+static int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender,
+					u8 param0, u8 param1, u8 param_num,
+					u8 transmission,
+					int delay)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+	pkg = pkg_sender_get_pkg_locked(sender);
+	spin_unlock_irqrestore(&sender->lock, flags);
+
+	if (!pkg) {
+		dev_err(sender->dev->dev, "No pkg memory\n");
+		return -ENOMEM;
+	}
+
+	switch (param_num) {
+	case 0:
+		pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_0;
+		pkg->pkg.short_pkg.cmd = 0;
+		pkg->pkg.short_pkg.param = 0;
+		break;
+	case 1:
+		pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_1;
+		pkg->pkg.short_pkg.cmd = param0;
+		pkg->pkg.short_pkg.param = 0;
+		break;
+	case 2:
+		pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_2;
+		pkg->pkg.short_pkg.cmd = param0;
+		pkg->pkg.short_pkg.param = param1;
+		break;
+	}
+
+	pkg->transmission_type = transmission;
+	INIT_LIST_HEAD(&pkg->entry);
+
+	pkg_sender_queue_pkg(sender, pkg, delay);
+	return 0;
+}
+
+static int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender,
+				u32 *data, u32 len, u8 transmission, int delay)
+{
+	struct mdfld_dsi_pkg *pkg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sender->lock, flags);
+	pkg = pkg_sender_get_pkg_locked(sender);
+	spin_unlock_irqrestore(&sender->lock, flags);
+
+	if (!pkg) {
+		dev_err(sender->dev->dev, "No pkg memory\n");
+		return -ENOMEM;
+	}
+
+	pkg->pkg_type = MDFLD_DSI_PKG_GEN_LONG_WRITE;
+	pkg->transmission_type = transmission;
+	pkg->pkg.long_pkg.data = data;
+	pkg->pkg.long_pkg.len = len;
+
+	INIT_LIST_HEAD(&pkg->entry);
+
+	pkg_sender_queue_pkg(sender, pkg, delay);
+
+	return 0;
+}
+
+void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender)
+{
+	process_pkg_list(sender);
+}
+
+int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender,
+			u8 dcs, u8 *param, u32 param_num, u8 data_src,
+			int delay)
+{
+	struct mdfld_dsi_pkg *pkg;
+	u32 cb_phy = sender->dbi_cb_phy;
+	struct drm_device *dev = sender->dev;
+	u32 index = 0;
+	u8 *cb = (u8 *)sender->dbi_cb_addr;
+	unsigned long flags;
+	int retry;
+	u8 *dst = NULL;
+	u32 len;
+
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	if (!sender->dbi_pkg_support) {
+		dev_err(dev->dev, "No DBI pkg sending on this sender\n");
+		return -ENOTSUPP;
+	}
+
+	if (param_num > MDFLD_MAX_DCS_PARAM) {
+		dev_err(dev->dev, "Sender only supports up to %d DCS params\n",
+							MDFLD_MAX_DCS_PARAM);
+		return -EINVAL;
+	}
+
+	/*
+	 * If dcs is write_mem_start, send it directly using DSI adapter
+	 * interface
+	 */
+	if (dcs == write_mem_start) {
+		if (!spin_trylock(&sender->lock))
+			return -EAGAIN;
+
+		/*
+		 * query whether DBI FIFO is empty,
+		 * if not wait it becoming empty
+		 */
+		retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
+		while (retry &&
+		    !(REG_READ(sender->mipi_gen_fifo_stat_reg) & (1 << 27))) {
+			udelay(500);
+			retry--;
+		}
+
+		/* If DBI FIFO timeout, drop this frame */
+		if (!retry) {
+			spin_unlock(&sender->lock);
+			return 0;
+		}
+
+		*(cb + (index++)) = write_mem_start;
+
+		REG_WRITE(sender->mipi_cmd_len_reg, 1);
+		REG_WRITE(sender->mipi_cmd_addr_reg,
+					cb_phy | (1 << 0) | (1 << 1));
+
+		retry = MDFLD_DSI_DBI_FIFO_TIMEOUT;
+		while (retry &&
+			(REG_READ(sender->mipi_cmd_addr_reg) & (1 << 0))) {
+			udelay(1);
+			retry--;
+		}
+
+		spin_unlock(&sender->lock);
+		return 0;
+	}
+
+	/* Get a free pkg */
+	spin_lock_irqsave(&sender->lock, flags);
+	pkg = pkg_sender_get_pkg_locked(sender);
+	spin_unlock_irqrestore(&sender->lock, flags);
+
+	if (!pkg) {
+		dev_err(dev->dev, "No packages memory\n");
+		return -ENOMEM;
+	}
+
+	dst = pkg->pkg.dcs_pkg.param;
+	memcpy(dst, param, param_num);
+
+	pkg->pkg_type = MDFLD_DSI_PKG_DCS;
+	pkg->transmission_type = MDFLD_DSI_DCS;
+	pkg->pkg.dcs_pkg.cmd = dcs;
+	pkg->pkg.dcs_pkg.param_num = param_num;
+	pkg->pkg.dcs_pkg.data_src = data_src;
+
+	INIT_LIST_HEAD(&pkg->entry);
+
+	if (param_num == 0)
+		return mdfld_dsi_send_mcs_short_hs(sender, dcs, 0, 0, delay);
+	else if (param_num == 1)
+		return mdfld_dsi_send_mcs_short_hs(sender, dcs,
+							param[0], 1, delay);
+	else if (param_num > 1) {
+		len = (param_num + 1) / 4;
+		if ((param_num + 1) % 4)
+			len++;
+		return mdfld_dsi_send_mcs_long_hs(sender,
+				(u32 *)&pkg->pkg.dcs_pkg, len, delay);
+	}
+	return 0;
+}
+
+int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender,
+				u8 cmd, u8 param, u8 param_num, int delay)
+{
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num,
+					MDFLD_DSI_HS_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender,
+				u8 cmd, u8 param, u8 param_num, int delay)
+{
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num,
+					MDFLD_DSI_LP_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender,
+				u32 *data,
+				u32 len,
+				int delay)
+{
+	if (!sender || !data || !len) {
+		DRM_ERROR("Invalid parameters\n");
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_mcs_long(sender, data, len,
+					MDFLD_DSI_HS_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender,
+				u32 *data,
+				u32 len,
+				int delay)
+{
+	if (!sender || !data || !len) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_mcs_long(sender, data, len,
+				MDFLD_DSI_LP_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender,
+				u8 param0, u8 param1, u8 param_num, int delay)
+{
+	if (!sender) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_gen_short(sender, param0, param1, param_num,
+					MDFLD_DSI_HS_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender,
+				u8 param0, u8 param1, u8 param_num, int delay)
+{
+	if (!sender || param_num < 0 || param_num > 2) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_gen_short(sender, param0, param1, param_num,
+					MDFLD_DSI_LP_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender,
+				u32 *data,
+				u32 len,
+				int delay)
+{
+	if (!sender || !data || !len) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_gen_long(sender, data, len,
+					MDFLD_DSI_HS_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
+				u32 *data,
+				u32 len,
+				int delay)
+{
+	if (!sender || !data || !len) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return mdfld_dsi_send_gen_long(sender, data, len,
+					MDFLD_DSI_LP_TRANSMISSION, delay);
+}
+
+int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
+								int pipe)
+{
+	int ret;
+	struct mdfld_dsi_pkg_sender *pkg_sender;
+	struct mdfld_dsi_config *dsi_config =
+					mdfld_dsi_get_config(dsi_connector);
+	struct drm_device *dev = dsi_config->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_gtt *pg = dev_priv->pg;
+	int i;
+	struct mdfld_dsi_pkg *pkg, *tmp;
+
+	if (!dsi_connector) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	pkg_sender = dsi_connector->pkg_sender;
+
+	if (!pkg_sender || IS_ERR(pkg_sender)) {
+		pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
+								GFP_KERNEL);
+		if (!pkg_sender) {
+			dev_err(dev->dev, "Create DSI pkg sender failed\n");
+			return -ENOMEM;
+		}
+
+		dsi_connector->pkg_sender = (void *)pkg_sender;
+	}
+
+	pkg_sender->dev = dev;
+	pkg_sender->dsi_connector = dsi_connector;
+	pkg_sender->pipe = pipe;
+	pkg_sender->pkg_num = 0;
+	pkg_sender->panel_mode = 0;
+	pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
+
+	/* Init dbi command buffer*/
+
+	if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
+		pkg_sender->dbi_pkg_support = 1;
+		ret = mdfld_dbi_cb_init(pkg_sender, pg, pipe);
+		if (ret) {
+			dev_err(dev->dev, "DBI command buffer map failed\n");
+			goto mapping_err;
+		}
+	}
+
+	/* Init regs */
+	if (pipe == 0) {
+		pkg_sender->dpll_reg = MRST_DPLL_A;
+		pkg_sender->dspcntr_reg = DSPACNTR;
+		pkg_sender->pipeconf_reg = PIPEACONF;
+		pkg_sender->dsplinoff_reg = DSPALINOFF;
+		pkg_sender->dspsurf_reg = DSPASURF;
+		pkg_sender->pipestat_reg = PIPEASTAT;
+
+		pkg_sender->mipi_intr_stat_reg = MIPIA_INTR_STAT_REG;
+		pkg_sender->mipi_lp_gen_data_reg = MIPIA_LP_GEN_DATA_REG;
+		pkg_sender->mipi_hs_gen_data_reg = MIPIA_HS_GEN_DATA_REG;
+		pkg_sender->mipi_lp_gen_ctrl_reg = MIPIA_LP_GEN_CTRL_REG;
+		pkg_sender->mipi_hs_gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG;
+		pkg_sender->mipi_gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG;
+		pkg_sender->mipi_data_addr_reg = MIPIA_DATA_ADD_REG;
+		pkg_sender->mipi_data_len_reg = MIPIA_DATA_LEN_REG;
+		pkg_sender->mipi_cmd_addr_reg = MIPIA_CMD_ADD_REG;
+		pkg_sender->mipi_cmd_len_reg = MIPIA_CMD_LEN_REG;
+	} else if (pipe == 2) {
+		pkg_sender->dpll_reg = MRST_DPLL_A;
+		pkg_sender->dspcntr_reg = DSPCCNTR;
+		pkg_sender->pipeconf_reg = PIPECCONF;
+		pkg_sender->dsplinoff_reg = DSPCLINOFF;
+		pkg_sender->dspsurf_reg = DSPCSURF;
+		pkg_sender->pipestat_reg = 72024;
+
+		pkg_sender->mipi_intr_stat_reg =
+				MIPIA_INTR_STAT_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_lp_gen_data_reg =
+				MIPIA_LP_GEN_DATA_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_hs_gen_data_reg =
+				MIPIA_HS_GEN_DATA_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_lp_gen_ctrl_reg =
+				MIPIA_LP_GEN_CTRL_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_hs_gen_ctrl_reg =
+				MIPIA_HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_gen_fifo_stat_reg =
+				MIPIA_GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_data_addr_reg =
+				MIPIA_DATA_ADD_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_data_len_reg =
+				MIPIA_DATA_LEN_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_cmd_addr_reg =
+				MIPIA_CMD_ADD_REG + MIPIC_REG_OFFSET;
+		pkg_sender->mipi_cmd_len_reg =
+				MIPIA_CMD_LEN_REG + MIPIC_REG_OFFSET;
+	}
+
+	/* Init pkg list */
+	INIT_LIST_HEAD(&pkg_sender->pkg_list);
+	INIT_LIST_HEAD(&pkg_sender->free_list);
+
+	spin_lock_init(&pkg_sender->lock);
+
+	/* Allocate free pkg pool */
+	for (i = 0; i < MDFLD_MAX_PKG_NUM; i++) {
+		pkg = kzalloc(sizeof(struct mdfld_dsi_pkg), GFP_KERNEL);
+		if (!pkg) {
+			dev_err(dev->dev, "Out of memory allocating pkg pool");
+			ret = -ENOMEM;
+			goto pkg_alloc_err;
+		}
+		INIT_LIST_HEAD(&pkg->entry);
+		list_add_tail(&pkg->entry, &pkg_sender->free_list);
+	}
+	return 0;
+
+pkg_alloc_err:
+	list_for_each_entry_safe(pkg, tmp, &pkg_sender->free_list, entry) {
+		list_del(&pkg->entry);
+		kfree(pkg);
+	}
+
+	/* Free mapped command buffer */
+	mdfld_dbi_cb_destroy(pkg_sender);
+mapping_err:
+	kfree(pkg_sender);
+	dsi_connector->pkg_sender = NULL;
+	return ret;
+}
+
+void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender)
+{
+	struct mdfld_dsi_pkg *pkg, *tmp;
+
+	if (!sender || IS_ERR(sender))
+		return;
+
+	/* Free pkg pool */
+	list_for_each_entry_safe(pkg, tmp, &sender->free_list, entry) {
+		list_del(&pkg->entry);
+		kfree(pkg);
+	}
+	/* Free pkg list */
+	list_for_each_entry_safe(pkg, tmp, &sender->pkg_list, entry) {
+		list_del(&pkg->entry);
+		kfree(pkg);
+	}
+	mdfld_dbi_cb_destroy(sender);	/* free mapped command buffer */
+	kfree(sender);
+}
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
new file mode 100644
index 0000000..296b1ea
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jackie Li<yaodong.li@intel.com>
+ */
+#ifndef __MDFLD_DSI_PKG_SENDER_H__
+#define __MDFLD_DSI_PKG_SENDER_H__
+
+#include <linux/kthread.h>
+
+#define MDFLD_MAX_DCS_PARAM	8
+#define MDFLD_MAX_PKG_NUM	2048
+
+enum {
+	MDFLD_DSI_PKG_DCS,
+	MDFLD_DSI_PKG_GEN_SHORT_WRITE_0 = 0x03,
+	MDFLD_DSI_PKG_GEN_SHORT_WRITE_1 = 0x13,
+	MDFLD_DSI_PKG_GEN_SHORT_WRITE_2 = 0x23,
+	MDFLD_DSI_PKG_GEN_LONG_WRITE = 0x29,
+	MDFLD_DSI_PKG_MCS_SHORT_WRITE_0 = 0x05,
+	MDFLD_DSI_PKG_MCS_SHORT_WRITE_1 = 0x15,
+	MDFLD_DSI_PKG_MCS_LONG_WRITE = 0x39,
+};
+
+enum {
+	MDFLD_DSI_LP_TRANSMISSION,
+	MDFLD_DSI_HS_TRANSMISSION,
+	MDFLD_DSI_DCS,
+};
+
+enum {
+	MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
+};
+
+enum {
+	MDFLD_DSI_PKG_SENDER_FREE = 0x0,
+	MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
+};
+
+enum {
+	MDFLD_DSI_SEND_PACKAGE,
+	MDFLD_DSI_QUEUE_PACKAGE,
+};
+
+struct mdfld_dsi_gen_short_pkg {
+	u8 cmd;
+	u8 param;
+};
+
+struct mdfld_dsi_gen_long_pkg {
+	u32 *data;
+	u32 len;
+};
+
+struct mdfld_dsi_dcs_pkg {
+	u8 cmd;
+	u8 param[MDFLD_MAX_DCS_PARAM];
+	u32 param_num;
+	u8 data_src;
+};
+
+struct mdfld_dsi_pkg {
+	u8 pkg_type;
+	u8 transmission_type;
+
+	union {
+		struct mdfld_dsi_gen_short_pkg short_pkg;
+		struct mdfld_dsi_gen_long_pkg long_pkg;
+		struct mdfld_dsi_dcs_pkg dcs_pkg;
+	} pkg;
+
+	struct list_head entry;
+};
+
+struct mdfld_dsi_pkg_sender {
+	struct drm_device *dev;
+	struct mdfld_dsi_connector *dsi_connector;
+	u32 status;
+
+	u32 panel_mode;
+
+	int pipe;
+
+	spinlock_t lock;
+	struct list_head pkg_list;
+	struct list_head free_list;
+
+	u32 pkg_num;
+
+	int dbi_pkg_support;
+
+	u32 dbi_cb_phy;
+	void *dbi_cb_addr;
+
+	/* Registers */
+	u32 dpll_reg;
+	u32 dspcntr_reg;
+	u32 pipeconf_reg;
+	u32 pipestat_reg;
+	u32 dsplinoff_reg;
+	u32 dspsurf_reg;
+
+	u32 mipi_intr_stat_reg;
+	u32 mipi_lp_gen_data_reg;
+	u32 mipi_hs_gen_data_reg;
+	u32 mipi_lp_gen_ctrl_reg;
+	u32 mipi_hs_gen_ctrl_reg;
+	u32 mipi_gen_fifo_stat_reg;
+	u32 mipi_data_addr_reg;
+	u32 mipi_data_len_reg;
+	u32 mipi_cmd_addr_reg;
+	u32 mipi_cmd_len_reg;
+};
+
+extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
+			int pipe);
+extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender);
+extern int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, u8 dcs,
+			u8 *param, u32 param_num, u8 data_src, int delay);
+extern int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender,
+			u8 cmd, u8 param, u8 param_num, int delay);
+extern int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender,
+			u8 cmd, u8 param, u8 param_num, int delay);
+extern int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender,
+			u32 *data, u32 len, int delay);
+extern int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender,
+			u32 *data, u32 len, int delay);
+extern int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender,
+			u8 param0, u8 param1, u8 param_num, int delay);
+extern int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender,
+			u8 param0, u8 param1, u8 param_num, int delay);
+extern int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender,
+			u32 *data, u32 len, int delay);
+extern int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
+			u32 *data, u32 len, int delay);
+extern void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender);
+
+#endif /* __MDFLD_DSI_PKG_SENDER_H__ */
diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c
new file mode 100644
index 0000000..26d7f80
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_intel_display.c
@@ -0,0 +1,1388 @@
+/*
+ * Copyright © 2006-2011 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#include "psb_fb.h"
+#include "psb_intel_display.h"
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+//#include "mdfld_dsi_output.h"
+#ifdef CONFIG_MDFLD_DSI_DPU
+#include "mdfld_dsi_dbi_dpu.h"
+#endif
+
+#include <linux/pm_runtime.h>
+
+#ifdef MIN
+#undef MIN
+#endif
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+/* Hardcoded currently */
+static int ksel = KSEL_CRYSTAL_19;
+
+extern struct drm_device *gpDrmDevice;
+extern void mdfld_save_display(struct drm_device *dev);
+extern bool gbgfxsuspended;
+
+struct psb_intel_range_t {
+	int min, max;
+};
+
+struct mdfld_limit_t {
+	struct psb_intel_range_t dot, m, p1;
+};
+
+struct mdfld_intel_clock_t {
+	/* given values */
+	int n;
+	int m1, m2;
+	int p1, p2;
+	/* derived values */
+	int dot;
+	int vco;
+	int m;
+	int p;
+};
+
+
+
+#define COUNT_MAX 0x10000000
+
+void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
+{
+	int count, temp;
+	u32 pipeconf_reg = PIPEACONF;
+	
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		pipeconf_reg = PIPEBCONF;
+		break;
+	case 2:
+		pipeconf_reg = PIPECCONF;
+		break;
+	default:
+		DRM_ERROR("Illegal Pipe Number. \n");
+		return;
+	}
+
+	/* FIXME JLIU7_PO */
+	psb_intel_wait_for_vblank(dev);
+	return;
+
+	/* Wait for for the pipe disable to take effect. */
+	for (count = 0; count < COUNT_MAX; count++) {
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_PIPE_STATE) == 0)
+			break;
+	}
+}
+
+void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
+{
+	int count, temp;
+	u32 pipeconf_reg = PIPEACONF;
+	
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		pipeconf_reg = PIPEBCONF;
+		break;
+	case 2:
+		pipeconf_reg = PIPECCONF;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number.\n");
+		return;
+	}
+
+	/* FIXME JLIU7_PO */
+	psb_intel_wait_for_vblank(dev);
+	return;
+
+	/* Wait for for the pipe enable to take effect. */
+	for (count = 0; count < COUNT_MAX; count++) {
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_PIPE_STATE) == 1)
+			break;
+	}
+}
+
+
+static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc,
+				 struct drm_file *file_priv,
+				 uint32_t handle,
+				 uint32_t width, uint32_t height)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	uint32_t control = CURACNTR;
+	uint32_t base = CURABASE;
+	uint32_t temp;
+	size_t addr = 0;
+	struct gtt_range *gt;
+	struct drm_gem_object *obj;
+	int ret;
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		control = CURBCNTR;
+		base = CURBBASE;
+		break;
+	case 2:
+		control = CURCCNTR;
+		base = CURCBASE;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number. \n");
+		return -EINVAL;
+	}
+	
+#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
+	if (pipe != 0)
+		return 0;
+#endif 
+	/* if we want to turn of the cursor ignore width and height */
+	if (!handle) {
+		dev_dbg(dev->dev, "cursor off\n");
+		/* turn off the cursor */
+		temp = 0;
+		temp |= CURSOR_MODE_DISABLE;
+
+		if (gma_power_begin(dev, true)) {
+			REG_WRITE(control, temp);
+			REG_WRITE(base, 0);
+			gma_power_end(dev);
+		}
+		/* Unpin the old GEM object */
+		if (psb_intel_crtc->cursor_obj) {
+			gt = container_of(psb_intel_crtc->cursor_obj,
+							struct gtt_range, gem);
+			psb_gtt_unpin(gt);
+			drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+			psb_intel_crtc->cursor_obj = NULL;
+		}
+		return 0;
+	}
+
+	/* Currently we only support 64x64 cursors */
+	if (width != 64 || height != 64) {
+		DRM_ERROR("we currently only support 64x64 cursors\n");
+		return -EINVAL;
+	}
+
+	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	if (!obj)
+		return -ENOENT;
+
+	if (obj->size < width * height * 4) {
+		dev_dbg(dev->dev, "buffer is to small\n");
+		return -ENOMEM;
+	}
+
+	gt = container_of(obj, struct gtt_range, gem);
+
+	/* Pin the memory into the GTT */
+	ret = psb_gtt_pin(gt);
+	if (ret) {
+		dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
+		return ret;
+	}
+
+
+	addr = gt->offset;	/* Or resource.start ??? */
+
+	psb_intel_crtc->cursor_addr = addr;
+
+	temp = 0;
+	/* set the pipe for the cursor */
+	temp |= (pipe << 28);
+	temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+
+	if (gma_power_begin(dev, true)) {
+		REG_WRITE(control, temp);
+		REG_WRITE(base, addr);
+		gma_power_end(dev);
+	}
+#if 0
+        /* FIXME: COnvert to GEM */
+	/* unpin the old bo */
+	if (psb_intel_crtc->cursor_bo && psb_intel_crtc->cursor_bo != bo) {
+		mode_dev->bo_unpin_for_scanout(dev, psb_intel_crtc->cursor_bo);
+		psb_intel_crtc->cursor_bo = bo;
+	}
+#endif
+	return 0;
+}
+
+static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct drm_device *dev = crtc->dev;
+#ifndef CONFIG_MDFLD_DSI_DPU
+	struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private;
+#else
+	struct psb_drm_dpu_rect rect;
+#endif
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	uint32_t pos = CURAPOS;
+	uint32_t base = CURABASE;
+	uint32_t temp = 0;
+	uint32_t addr;
+
+	switch (pipe) {
+	case 0:
+#ifndef CONFIG_MDFLD_DSI_DPU
+		if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0))
+			mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_0, 0, 0);
+#else /*CONFIG_MDFLD_DSI_DPU*/
+		rect.x = x;
+		rect.y = y;
+		
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect);
+		mdfld_dpu_exit_dsr(dev);
+#endif
+		break;
+	case 1:
+		pos = CURBPOS;
+		base = CURBBASE;
+		break;
+	case 2:
+#ifndef CONFIG_MDFLD_DSI_DPU
+		if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2))
+			mdfld_dsi_dbi_exit_dsr (dev, MDFLD_DSR_CURSOR_2, 0, 0);
+#else /*CONFIG_MDFLD_DSI_DPU*/
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect);
+		mdfld_dpu_exit_dsr(dev);
+#endif
+		pos = CURCPOS;
+		base = CURCBASE;
+		break;
+	default:
+		DRM_ERROR("Illegal Pipe Number. \n");
+		return -EINVAL;
+	}
+		
+#if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */
+	if (pipe != 0)
+		return 0;
+#endif 
+	if (x < 0) {
+		temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+		x = -x;
+	}
+	if (y < 0) {
+		temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+		y = -y;
+	}
+
+	temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
+	temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+
+	addr = psb_intel_crtc->cursor_addr;
+
+	if (gma_power_begin(dev, true)) {
+		REG_WRITE(pos, temp);
+		REG_WRITE(base, addr);
+		gma_power_end(dev);
+	}
+
+	return 0;
+}
+
+const struct drm_crtc_funcs mdfld_intel_crtc_funcs = {
+	.cursor_set = mdfld_intel_crtc_cursor_set,
+	.cursor_move = mdfld_intel_crtc_cursor_move,
+	.gamma_set = psb_intel_crtc_gamma_set,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = psb_intel_crtc_destroy,
+};
+
+static struct drm_device globle_dev;
+
+void mdfld__intel_plane_set_alpha(int enable)
+{
+	struct drm_device *dev = &globle_dev;
+	int dspcntr_reg = DSPACNTR;
+	u32 dspcntr;
+
+	dspcntr = REG_READ(dspcntr_reg);
+
+	if (enable) {
+		dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA;
+		dspcntr |= DISPPLANE_32BPP;
+	} else {
+		dspcntr &= ~DISPPLANE_32BPP;
+		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+	}
+
+	REG_WRITE(dspcntr_reg, dspcntr);
+}
+
+int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	/* struct drm_i915_master_private *master_priv; */
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+	struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
+	int pipe = psb_intel_crtc->pipe;
+	unsigned long start, offset;
+	int dsplinoff = DSPALINOFF;
+	int dspsurf = DSPASURF;
+	int dspstride = DSPASTRIDE;
+	int dspcntr_reg = DSPACNTR;
+	u32 dspcntr;
+	int ret = 0;
+
+	memcpy(&globle_dev, dev, sizeof(struct drm_device));
+
+	if (!gma_power_begin(dev, true))
+		return 0;
+
+	/* no fb bound */
+	if (!crtc->fb) {
+		dev_err(dev->dev, "No FB bound\n");
+		goto psb_intel_pipe_cleaner;
+	}
+
+	switch (pipe) {
+	case 0:
+		dsplinoff = DSPALINOFF;
+		break;
+	case 1:
+		dsplinoff = DSPBLINOFF;
+		dspsurf = DSPBSURF;
+		dspstride = DSPBSTRIDE;
+		dspcntr_reg = DSPBCNTR;
+		break;
+	case 2:
+		dsplinoff = DSPCLINOFF;
+		dspsurf = DSPCSURF;
+		dspstride = DSPCSTRIDE;
+		dspcntr_reg = DSPCCNTR;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number.\n");
+		return -EINVAL;
+	}
+
+	ret = psb_gtt_pin(psbfb->gtt);
+	if (ret < 0)
+	        goto psb_intel_pipe_set_base_exit;
+
+	start = psbfb->gtt->offset;
+	offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+
+	REG_WRITE(dspstride, crtc->fb->pitch);
+	dspcntr = REG_READ(dspcntr_reg);
+	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+
+	switch (crtc->fb->bits_per_pixel) {
+	case 8:
+		dspcntr |= DISPPLANE_8BPP;
+		break;
+	case 16:
+		if (crtc->fb->depth == 15)
+			dspcntr |= DISPPLANE_15_16BPP;
+		else
+			dspcntr |= DISPPLANE_16BPP;
+		break;
+	case 24:
+	case 32:
+		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+		break;
+	default:
+		dev_err(dev->dev, "Unknown color depth\n");
+		ret = -EINVAL;
+		goto psb_intel_pipe_set_base_exit;
+	}
+	REG_WRITE(dspcntr_reg, dspcntr);
+
+	dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n",
+	                                        start, offset, x, y);
+
+	REG_WRITE(dsplinoff, offset);
+	REG_READ(dsplinoff);
+	REG_WRITE(dspsurf, start);
+	REG_READ(dspsurf);
+
+psb_intel_pipe_cleaner:
+	/* If there was a previous display we can now unpin it */
+	if (old_fb)
+		psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
+
+psb_intel_pipe_set_base_exit:
+	gma_power_end(dev);
+	return ret;
+}
+
+/**
+ * Disable the pipe, plane and pll.
+ *
+ */
+void mdfld_disable_crtc (struct drm_device *dev, int pipe)
+{
+	int dpll_reg = MRST_DPLL_A;
+	int dspcntr_reg = DSPACNTR;
+	int dspbase_reg = MRST_DSPABASE;
+	int pipeconf_reg = PIPEACONF;
+	u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
+	u32 temp;
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		dpll_reg = MDFLD_DPLL_B;
+		dspcntr_reg = DSPBCNTR;
+		dspbase_reg = DSPBSURF;
+		pipeconf_reg = PIPEBCONF;
+		break;
+	case 2:
+		dpll_reg = MRST_DPLL_A;
+		dspcntr_reg = DSPCCNTR;
+		dspbase_reg = MDFLD_DSPCBASE;
+		pipeconf_reg = PIPECCONF;
+		gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number. \n");
+		return;
+	}
+
+	if (pipe != 1)
+		mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+	/* Disable display plane */
+	temp = REG_READ(dspcntr_reg);
+	if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+		REG_WRITE(dspcntr_reg,
+			  temp & ~DISPLAY_PLANE_ENABLE);
+		/* Flush the plane changes */
+		REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+		REG_READ(dspbase_reg);
+	}
+
+	/* FIXME_JLIU7 MDFLD_PO revisit */
+	/* Wait for vblank for the disable to take effect */
+// MDFLD_PO_JLIU7		psb_intel_wait_for_vblank(dev);
+
+	/* Next, disable display pipes */
+	temp = REG_READ(pipeconf_reg);
+	if ((temp & PIPEACONF_ENABLE) != 0) {
+		temp &= ~PIPEACONF_ENABLE;
+		temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
+		REG_WRITE(pipeconf_reg, temp);
+		REG_READ(pipeconf_reg);
+
+		/* Wait for for the pipe disable to take effect. */
+		mdfldWaitForPipeDisable(dev, pipe);
+	}
+
+	temp = REG_READ(dpll_reg);
+	if (temp & DPLL_VCO_ENABLE) {
+		if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
+				|| (pipe == 1)){
+			temp &= ~(DPLL_VCO_ENABLE);
+			REG_WRITE(dpll_reg, temp);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to turn off. */
+			/* FIXME_MDFLD PO may need more delay */
+			udelay(500);
+
+			if (!(temp & MDFLD_PWR_GATE_EN)) {
+				/* gating power of DPLL */
+				REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
+				/* FIXME_MDFLD PO - change 500 to 1 after PO */
+				udelay(5000);
+			}
+		}
+	}
+
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	int dpll_reg = MRST_DPLL_A;
+	int dspcntr_reg = DSPACNTR;
+	int dspbase_reg = MRST_DSPABASE;
+	int pipeconf_reg = PIPEACONF;
+	u32 pipestat_reg = PIPEASTAT;
+	u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
+	u32 pipeconf = dev_priv->pipeconf;
+	u32 dspcntr = dev_priv->dspcntr;
+	u32 mipi_enable_reg = MIPIA_DEVICE_READY_REG;
+	u32 temp;
+	bool enabled;
+	int timeout = 0;
+
+	if (!gma_power_begin(dev, true))
+		return;
+
+	 /* Ignore if system is already in DSR and in suspended state. */
+	if(gbgfxsuspended && dev_priv->dispstatus == false && mode == 3){
+	    if(dev_priv->rpm_enabled && pipe == 1){
+	//          dev_priv->is_mipi_on = false;
+	            pm_request_idle(&gpDrmDevice->pdev->dev);
+	    }
+	    return;
+	}else if(mode == 0) {
+		//do not need to set gbdispstatus=true in crtc.
+		//this will be set in encoder such as mdfld_dsi_dbi_dpms
+	    //gbdispstatus = true;
+	}
+
+
+/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
+/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		dpll_reg = DPLL_B;
+		dspcntr_reg = DSPBCNTR;
+		dspbase_reg = MRST_DSPBBASE;
+		pipeconf_reg = PIPEBCONF;
+		pipeconf = dev_priv->pipeconf1;
+		dspcntr = dev_priv->dspcntr1;
+		dpll_reg = MDFLD_DPLL_B;
+		break;
+	case 2:
+		dpll_reg = MRST_DPLL_A;
+		dspcntr_reg = DSPCCNTR;
+		dspbase_reg = MDFLD_DSPCBASE;
+		pipeconf_reg = PIPECCONF;
+		pipestat_reg = PIPECSTAT;
+		pipeconf = dev_priv->pipeconf2;
+		dspcntr = dev_priv->dspcntr2;
+		gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
+		mipi_enable_reg = MIPIA_DEVICE_READY_REG + MIPIC_REG_OFFSET;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number.\n");
+		return;
+	}
+
+	/* XXX: When our outputs are all unaware of DPMS modes other than off
+	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+	 */
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+		/* Enable the DPLL */
+		temp = REG_READ(dpll_reg);
+
+		if ((temp & DPLL_VCO_ENABLE) == 0) {
+			/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+			if (temp & MDFLD_PWR_GATE_EN) {
+				temp &= ~MDFLD_PWR_GATE_EN;
+				REG_WRITE(dpll_reg, temp);
+				/* FIXME_MDFLD PO - change 500 to 1 after PO */
+				udelay(500);
+			}
+
+			REG_WRITE(dpll_reg, temp);
+			REG_READ(dpll_reg);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+			
+			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+
+			/**
+			 * wait for DSI PLL to lock
+			 * NOTE: only need to poll status of pipe 0 and pipe 1,
+			 * since both MIPI pipes share the same PLL.
+			 */
+			while ((pipe != 2) && (timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+				udelay(150);
+				timeout ++;
+			}
+		}
+
+		/* Enable the plane */
+		temp = REG_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+			REG_WRITE(dspcntr_reg,
+				temp | DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+		}
+
+		/* Enable the pipe */
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) == 0) {
+			REG_WRITE(pipeconf_reg, pipeconf);
+
+			/* Wait for for the pipe enable to take effect. */
+			mdfldWaitForPipeEnable(dev, pipe);
+		}
+
+		/*workaround for sighting 3741701 Random X blank display*/
+		/*perform w/a in video mode only on pipe A or C*/
+		if ((pipe == 0 || pipe == 2) &&
+			(mdfld_panel_dpi(dev) == true)) {
+			REG_WRITE(pipestat_reg, REG_READ(pipestat_reg));
+			msleep(100);
+			if(PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) {
+				printk(KERN_ALERT "OK");
+			} else {
+				printk(KERN_ALERT "STUCK!!!!");
+				/*shutdown controller*/
+				temp = REG_READ(dspcntr_reg);
+				REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
+				REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+				/*mdfld_dsi_dpi_shut_down(dev, pipe);*/
+				REG_WRITE(0xb048, 1);
+				msleep(100);
+				temp = REG_READ(pipeconf_reg);
+				temp &= ~PIPEACONF_ENABLE;
+				REG_WRITE(pipeconf_reg, temp);
+				msleep(100); /*wait for pipe disable*/
+			/*printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
+			printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));*/
+				REG_WRITE(mipi_enable_reg, 0);
+				msleep(100);
+			printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
+			printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));
+				REG_WRITE(0xb004, REG_READ(0xb004));
+				/* try to bring the controller back up again*/
+				REG_WRITE(mipi_enable_reg, 1);
+				temp = REG_READ(dspcntr_reg);
+				REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
+				REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+				/*mdfld_dsi_dpi_turn_on(dev, pipe);*/
+				REG_WRITE(0xb048, 2);
+				msleep(100);
+				temp = REG_READ(pipeconf_reg);
+				temp |= PIPEACONF_ENABLE;
+				REG_WRITE(pipeconf_reg, temp);
+			}
+		}
+
+		psb_intel_crtc_load_lut(crtc);
+
+		/* Give the overlay scaler a chance to enable
+		   if it's on this pipe */
+		/* psb_intel_crtc_dpms_video(crtc, true); TODO */
+
+		break;
+	case DRM_MODE_DPMS_OFF:
+		/* Give the overlay scaler a chance to disable
+		 * if it's on this pipe */
+		/* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
+		if (pipe != 1)
+			mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+		/* Disable the VGA plane that we never use */
+		REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+		/* Disable display plane */
+		temp = REG_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+			REG_WRITE(dspcntr_reg,
+				  temp & ~DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+			REG_READ(dspbase_reg);
+		}
+
+		/* FIXME_JLIU7 MDFLD_PO revisit */
+		/* Wait for vblank for the disable to take effect */
+// MDFLD_PO_JLIU7		psb_intel_wait_for_vblank(dev);
+
+		/* Next, disable display pipes */
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+			temp &= ~PIPEACONF_ENABLE;
+			temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
+			REG_WRITE(pipeconf_reg, temp);
+//			REG_WRITE(pipeconf_reg, 0);
+			REG_READ(pipeconf_reg);
+
+			/* Wait for for the pipe disable to take effect. */
+			mdfldWaitForPipeDisable(dev, pipe);
+		}
+
+		temp = REG_READ(dpll_reg);
+		if (temp & DPLL_VCO_ENABLE) {
+			if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
+					|| (pipe == 1)){
+				temp &= ~(DPLL_VCO_ENABLE);
+				REG_WRITE(dpll_reg, temp);
+				REG_READ(dpll_reg);
+				/* Wait for the clocks to turn off. */
+				/* FIXME_MDFLD PO may need more delay */
+				udelay(500);
+#if 0 /* MDFLD_PO_JLIU7 */	
+		if (!(temp & MDFLD_PWR_GATE_EN)) {
+			/* gating power of DPLL */
+			REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(5000);
+		}
+#endif  /* MDFLD_PO_JLIU7 */	
+			}
+		}
+		break;
+	}
+
+	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
+
+#if 0				/* JB: Add vblank support later */
+	if (enabled)
+		dev_priv->vblank_pipe |= (1 << pipe);
+	else
+		dev_priv->vblank_pipe &= ~(1 << pipe);
+#endif
+
+	gma_power_end(dev);
+}
+
+
+#define MDFLD_LIMT_DPLL_19	    0
+#define MDFLD_LIMT_DPLL_25	    1
+#define MDFLD_LIMT_DPLL_83	    2
+#define MDFLD_LIMT_DPLL_100	    3
+#define MDFLD_LIMT_DSIPLL_19	    4
+#define MDFLD_LIMT_DSIPLL_25	    5
+#define MDFLD_LIMT_DSIPLL_83	    6
+#define MDFLD_LIMT_DSIPLL_100	    7
+
+#define MDFLD_DOT_MIN		  19750  /* FIXME_MDFLD JLIU7 need to find out  min & max for MDFLD */
+#define MDFLD_DOT_MAX		  120000
+#define MDFLD_DPLL_M_MIN_19	    113
+#define MDFLD_DPLL_M_MAX_19	    155
+#define MDFLD_DPLL_P1_MIN_19	    2
+#define MDFLD_DPLL_P1_MAX_19	    10
+#define MDFLD_DPLL_M_MIN_25	    101
+#define MDFLD_DPLL_M_MAX_25	    130
+#define MDFLD_DPLL_P1_MIN_25	    2
+#define MDFLD_DPLL_P1_MAX_25	    10
+#define MDFLD_DPLL_M_MIN_83	    64
+#define MDFLD_DPLL_M_MAX_83	    64
+#define MDFLD_DPLL_P1_MIN_83	    2
+#define MDFLD_DPLL_P1_MAX_83	    2
+#define MDFLD_DPLL_M_MIN_100	    64
+#define MDFLD_DPLL_M_MAX_100	    64
+#define MDFLD_DPLL_P1_MIN_100	    2
+#define MDFLD_DPLL_P1_MAX_100	    2
+#define MDFLD_DSIPLL_M_MIN_19	    131
+#define MDFLD_DSIPLL_M_MAX_19	    175
+#define MDFLD_DSIPLL_P1_MIN_19	    3
+#define MDFLD_DSIPLL_P1_MAX_19	    8
+#define MDFLD_DSIPLL_M_MIN_25	    97
+#define MDFLD_DSIPLL_M_MAX_25	    140
+#define MDFLD_DSIPLL_P1_MIN_25	    3
+#define MDFLD_DSIPLL_P1_MAX_25	    9
+#define MDFLD_DSIPLL_M_MIN_83	    33
+#define MDFLD_DSIPLL_M_MAX_83	    92
+#define MDFLD_DSIPLL_P1_MIN_83	    2
+#define MDFLD_DSIPLL_P1_MAX_83	    3
+#define MDFLD_DSIPLL_M_MIN_100	    97
+#define MDFLD_DSIPLL_M_MAX_100	    140
+#define MDFLD_DSIPLL_P1_MIN_100	    3
+#define MDFLD_DSIPLL_P1_MAX_100	    9
+
+static const struct mdfld_limit_t mdfld_limits[] = {
+	{			/* MDFLD_LIMT_DPLL_19 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19},
+	 .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19},
+	 },
+	{			/* MDFLD_LIMT_DPLL_25 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25},
+	 .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25},
+	 },
+	{			/* MDFLD_LIMT_DPLL_83 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83},
+	 .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83},
+	 },
+	{			/* MDFLD_LIMT_DPLL_100 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100},
+	 .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100},
+	 },
+	{			/* MDFLD_LIMT_DSIPLL_19 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19},
+	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19},
+	 },
+	{			/* MDFLD_LIMT_DSIPLL_25 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25},
+	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25},
+	 },
+	{			/* MDFLD_LIMT_DSIPLL_83 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83},
+	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83},
+	 },
+	{			/* MDFLD_LIMT_DSIPLL_100 */
+	 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
+	 .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100},
+	 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100},
+	 },
+};
+
+#define MDFLD_M_MIN	    21
+#define MDFLD_M_MAX	    180
+static const u32 mdfld_m_converts[] = {
+/* M configuration table from 9-bit LFSR table */
+	224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */
+	173, 342, 171, 85, 298, 149, 74, 37, 18, 265,   /* 31 - 40 */
+	388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */
+	83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */
+	341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */
+	461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
+	106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
+	71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */
+	253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */
+	478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */
+	477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */
+	210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */
+	145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */
+	380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */
+	103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */
+	396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */
+};
+
+static const struct mdfld_limit_t *mdfld_limit(struct drm_crtc *crtc)
+{
+	const struct mdfld_limit_t *limit = NULL;
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)
+	    || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) {
+		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
+			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19];
+		else if (ksel == KSEL_BYPASS_25) 
+			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25];
+		else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
+			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83];
+		else if ((ksel == KSEL_BYPASS_83_100) &&
+			 (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
+			limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100];
+	} else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
+		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
+			limit = &mdfld_limits[MDFLD_LIMT_DPLL_19];
+		else if (ksel == KSEL_BYPASS_25) 
+			limit = &mdfld_limits[MDFLD_LIMT_DPLL_25];
+		else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
+			limit = &mdfld_limits[MDFLD_LIMT_DPLL_83];
+		else if ((ksel == KSEL_BYPASS_83_100) &&
+			 (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
+			limit = &mdfld_limits[MDFLD_LIMT_DPLL_100];
+	} else {
+		limit = NULL;
+		dev_err(dev->dev, "mdfld_limit Wrong display type.\n");
+	}
+
+	return limit;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
+static void mdfld_clock(int refclk, struct mdfld_intel_clock_t *clock)
+{
+	clock->dot = (refclk * clock->m) / clock->p1;
+}
+
+/**
+ * Returns a set of divisors for the desired target clock with the given refclk,
+ * or FALSE.  Divisor values are the actual divisors for
+ */
+static bool
+mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
+		struct mdfld_intel_clock_t *best_clock)
+{
+	struct mdfld_intel_clock_t clock;
+	const struct mdfld_limit_t *limit = mdfld_limit(crtc);
+	int err = target;
+
+	memset(best_clock, 0, sizeof(*best_clock));
+
+	for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
+		for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
+		     clock.p1++) {
+			int this_err;
+
+			mdfld_clock(refclk, &clock);
+
+			this_err = abs(clock.dot - target);
+			if (this_err < err) {
+				*best_clock = clock;
+				err = this_err;
+			}
+		}
+	}
+	return err != target;
+}
+
+/**
+ * Return the pipe currently connected to the panel fitter,
+ * or -1 if the panel fitter is not present or not in use
+ */
+static int mdfld_panel_fitter_pipe(struct drm_device *dev)
+{
+	u32 pfit_control;
+
+	pfit_control = REG_READ(PFIT_CONTROL);
+
+	/* See if the panel fitter is in use */
+	if ((pfit_control & PFIT_ENABLE) == 0)
+		return -1;
+	return (pfit_control >> 29) & 3;
+}
+
+static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
+			      struct drm_display_mode *mode,
+			      struct drm_display_mode *adjusted_mode,
+			      int x, int y,
+			      struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int pipe = psb_intel_crtc->pipe;
+	int fp_reg = MRST_FPA0;
+	int dpll_reg = MRST_DPLL_A;
+	int dspcntr_reg = DSPACNTR;
+	int pipeconf_reg = PIPEACONF;
+	int htot_reg = HTOTAL_A;
+	int hblank_reg = HBLANK_A;
+	int hsync_reg = HSYNC_A;
+	int vtot_reg = VTOTAL_A;
+	int vblank_reg = VBLANK_A;
+	int vsync_reg = VSYNC_A;
+	int dspsize_reg = DSPASIZE; 
+	int dsppos_reg = DSPAPOS; 
+	int pipesrc_reg = PIPEASRC;
+	u32 *pipeconf = &dev_priv->pipeconf;
+	u32 *dspcntr = &dev_priv->dspcntr;
+	int refclk = 0;
+	int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, clk_tmp = 0;
+	struct mdfld_intel_clock_t clock;
+	bool ok;
+	u32 dpll = 0, fp = 0;
+	bool is_crt = false, is_lvds = false, is_tv = false;
+	bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct psb_intel_output *psb_intel_output = NULL;
+	uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	int timeout = 0;
+
+	dev_dbg(dev->dev, "pipe = 0x%x \n", pipe);
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		fp_reg = FPB0;
+		dpll_reg = DPLL_B;
+		dspcntr_reg = DSPBCNTR;
+		pipeconf_reg = PIPEBCONF;
+		htot_reg = HTOTAL_B;
+		hblank_reg = HBLANK_B;
+		hsync_reg = HSYNC_B;
+		vtot_reg = VTOTAL_B;
+		vblank_reg = VBLANK_B;
+		vsync_reg = VSYNC_B;
+		dspsize_reg = DSPBSIZE; 
+		dsppos_reg = DSPBPOS; 
+		pipesrc_reg = PIPEBSRC;
+		pipeconf = &dev_priv->pipeconf1;
+		dspcntr = &dev_priv->dspcntr1;
+		fp_reg = MDFLD_DPLL_DIV0;
+		dpll_reg = MDFLD_DPLL_B;
+		break;
+	case 2:
+		dpll_reg = MRST_DPLL_A;
+		dspcntr_reg = DSPCCNTR;
+		pipeconf_reg = PIPECCONF;
+		htot_reg = HTOTAL_C;
+		hblank_reg = HBLANK_C;
+		hsync_reg = HSYNC_C;
+		vtot_reg = VTOTAL_C;
+		vblank_reg = VBLANK_C;
+		vsync_reg = VSYNC_C;
+		dspsize_reg = DSPCSIZE; 
+		dsppos_reg = DSPCPOS; 
+		pipesrc_reg = PIPECSRC;
+		pipeconf = &dev_priv->pipeconf2;
+		dspcntr = &dev_priv->dspcntr2;
+		break;
+	default:
+		DRM_ERROR("Illegal Pipe Number. \n");
+		return 0;
+	}
+
+	dev_dbg(dev->dev, "adjusted_hdisplay = %d\n",
+		 adjusted_mode->hdisplay);
+	dev_dbg(dev->dev, "adjusted_vdisplay = %d\n",
+		 adjusted_mode->vdisplay);
+	dev_dbg(dev->dev, "adjusted_hsync_start = %d\n",
+		 adjusted_mode->hsync_start);
+	dev_dbg(dev->dev, "adjusted_hsync_end = %d\n",
+		 adjusted_mode->hsync_end);
+	dev_dbg(dev->dev, "adjusted_htotal = %d\n",
+		 adjusted_mode->htotal);
+	dev_dbg(dev->dev, "adjusted_vsync_start = %d\n",
+		 adjusted_mode->vsync_start);
+	dev_dbg(dev->dev, "adjusted_vsync_end = %d\n",
+		 adjusted_mode->vsync_end);
+	dev_dbg(dev->dev, "adjusted_vtotal = %d\n",
+		 adjusted_mode->vtotal);
+	dev_dbg(dev->dev, "adjusted_clock = %d\n",
+		 adjusted_mode->clock);
+	dev_dbg(dev->dev, "hdisplay = %d\n",
+		 mode->hdisplay);
+	dev_dbg(dev->dev, "vdisplay = %d\n",
+		 mode->vdisplay);
+
+	if (!gma_power_begin(dev, true))
+		return 0;
+
+	memcpy(&psb_intel_crtc->saved_mode, mode, sizeof(struct drm_display_mode));
+	memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, sizeof(struct drm_display_mode));
+
+	list_for_each_entry(connector, &mode_config->connector_list, head) {
+		if(!connector)
+			continue;
+			
+		encoder = connector->encoder;
+		
+		if(!encoder)
+			continue;
+
+		if (encoder->crtc != crtc)
+			continue;
+
+		psb_intel_output = to_psb_intel_output(connector);
+		
+		dev_dbg(dev->dev, "output->type = 0x%x \n", psb_intel_output->type);
+
+		switch (psb_intel_output->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_TVOUT:
+			is_tv = true;
+			break;
+		case INTEL_OUTPUT_ANALOG:
+			is_crt = true;
+			break;
+		case INTEL_OUTPUT_MIPI:
+			is_mipi = true;
+			break;
+		case INTEL_OUTPUT_MIPI2:
+			is_mipi2 = true;
+			break;
+		case INTEL_OUTPUT_HDMI:
+			is_hdmi = true;
+			break;
+		}
+	}
+
+	/* Disable the VGA plane that we never use */
+	REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+	/* Disable the panel fitter if it was on our pipe */
+	if (mdfld_panel_fitter_pipe(dev) == pipe)
+		REG_WRITE(PFIT_CONTROL, 0);
+
+	/* pipesrc and dspsize control the size that is scaled from,
+	 * which should always be the user's requested size.
+	 */
+	if (pipe == 1) {
+		/* FIXME: To make HDMI display with 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD), set the sprite
+		 * width/height and souce image size registers with the adjusted mode for pipe B. */
+
+		/* The defined sprite rectangle must always be completely contained within the displayable
+		 * area of the screen image (frame buffer). */
+		REG_WRITE(dspsize_reg, ((MIN(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
+				| (MIN(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
+		/* Set the CRTC with encoder mode. */
+		REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16)
+				 | (mode->crtc_vdisplay - 1));
+	} else {
+		REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1));
+		REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
+	}
+
+	REG_WRITE(dsppos_reg, 0);
+
+	if (psb_intel_output)
+		drm_connector_property_get_value(&psb_intel_output->base,
+			dev->mode_config.scaling_mode_property, &scalingType);
+
+	if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
+		/*Moorestown doesn't have register support for centering so we need to
+		  mess with the h/vblank and h/vsync start and ends to get centering*/
+		int offsetX = 0, offsetY = 0;
+
+		offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
+		offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
+
+		REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
+			((adjusted_mode->crtc_htotal - 1) << 16));
+		REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
+			((adjusted_mode->crtc_vtotal - 1) << 16));
+		REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - offsetX - 1) |
+			((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
+		REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - offsetX - 1) |
+			((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
+		REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - offsetY - 1) |
+			((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
+		REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - offsetY - 1) |
+			((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
+	} else {
+		REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+			((adjusted_mode->crtc_htotal - 1) << 16));
+		REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+			((adjusted_mode->crtc_vtotal - 1) << 16));
+		REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+			((adjusted_mode->crtc_hblank_end - 1) << 16));
+		REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+			((adjusted_mode->crtc_hsync_end - 1) << 16));
+		REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+			((adjusted_mode->crtc_vblank_end - 1) << 16));
+		REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+			((adjusted_mode->crtc_vsync_end - 1) << 16));
+	}
+
+	/* Flush the plane changes */
+	{
+		struct drm_crtc_helper_funcs *crtc_funcs =
+		    crtc->helper_private;
+		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+	}
+
+	/* setup pipeconf */
+	*pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
+
+	/* Set up the display plane register */
+ 	*dspcntr = REG_READ(dspcntr_reg);
+	*dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS;
+	*dspcntr |= DISPLAY_PLANE_ENABLE;
+/* MDFLD_PO_JLIU7	dspcntr |= DISPPLANE_BOTTOM; */
+/* MDFLD_PO_JLIU7	dspcntr |= DISPPLANE_GAMMA_ENABLE; */
+
+	if (is_mipi2)
+	{
+		goto mrst_crtc_mode_set_exit;
+	}
+/* FIXME JLIU7 Add MDFLD HDMI supports */
+/* FIXME_MDFLD JLIU7 DSIPLL clock *= 8? */
+/* FIXME_MDFLD JLIU7 need to revist for dual MIPI supports */
+	clk = adjusted_mode->clock;
+
+	if (is_hdmi) {
+		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
+		{
+			refclk = 19200;
+
+			if (is_mipi || is_mipi2)
+			{
+				clk_n = 1, clk_p2 = 8;
+			} else if (is_hdmi) {
+				clk_n = 1, clk_p2 = 10;
+			}
+		} else if (ksel == KSEL_BYPASS_25) { 
+			refclk = 25000;
+
+			if (is_mipi || is_mipi2)
+			{
+				clk_n = 1, clk_p2 = 8;
+			} else if (is_hdmi) {
+				clk_n = 1, clk_p2 = 10;
+			}
+		} else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) {
+			refclk = 83000;
+
+			if (is_mipi || is_mipi2)
+			{
+				clk_n = 4, clk_p2 = 8;
+			} else if (is_hdmi) {
+				clk_n = 4, clk_p2 = 10;
+			}
+		} else if ((ksel == KSEL_BYPASS_83_100) &&
+			   (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) {
+			refclk = 100000;
+			if (is_mipi || is_mipi2)
+			{
+				clk_n = 4, clk_p2 = 8;
+			} else if (is_hdmi) {
+				clk_n = 4, clk_p2 = 10;
+			}
+		}
+
+		if (is_mipi)
+			clk_byte = dev_priv->bpp / 8;
+		else if (is_mipi2)
+			clk_byte = dev_priv->bpp2 / 8;
+	
+		clk_tmp = clk * clk_n * clk_p2 * clk_byte;
+
+		dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2);
+		dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d. \n", adjusted_mode->clock, clk_tmp);
+
+		ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock);
+
+		if (!ok) {
+			dev_err(dev->dev, 
+			   "mdfldFindBestPLL fail in mdfld_crtc_mode_set. \n");
+		} else {
+			m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)];
+
+			dev_dbg(dev->dev, "dot clock = %d,"
+				 "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m,
+				 clock.p1, m_conv);
+		}
+
+		dpll = REG_READ(dpll_reg);
+
+		if (dpll & DPLL_VCO_ENABLE) {
+			dpll &= ~DPLL_VCO_ENABLE;
+			REG_WRITE(dpll_reg, dpll);
+			REG_READ(dpll_reg);
+
+			/* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+
+			/* reset M1, N1 & P1 */
+			REG_WRITE(fp_reg, 0);
+			dpll &= ~MDFLD_P1_MASK;
+			REG_WRITE(dpll_reg, dpll);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+		}
+
+		/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+		if (dpll & MDFLD_PWR_GATE_EN) {
+			dpll &= ~MDFLD_PWR_GATE_EN;
+			REG_WRITE(dpll_reg, dpll);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+		}	
+
+		dpll = 0; 
+
+#if 0 /* FIXME revisit later */
+		if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19) || (ksel == KSEL_BYPASS_25)) {
+			dpll &= ~MDFLD_INPUT_REF_SEL;	
+		} else if (ksel == KSEL_BYPASS_83_100) { 
+			dpll |= MDFLD_INPUT_REF_SEL;	
+		}
+#endif /* FIXME revisit later */
+
+		if (is_hdmi)
+			dpll |= MDFLD_VCO_SEL;	
+
+		fp = (clk_n / 2) << 16;
+		fp |= m_conv; 
+
+		/* compute bitmask from p1 value */
+		dpll |= (1 << (clock.p1 - 2)) << 17;
+
+#if 0 /* 1080p30 & 720p */
+        	dpll = 0x00050000;
+        	fp = 0x000001be;
+#endif 
+#if 0 /* 480p */
+        	dpll = 0x02010000;
+        	fp = 0x000000d2;
+#endif 
+	} else {
+#if 0 /*DBI_TPO_480x864*/
+		dpll = 0x00020000;
+		fp = 0x00000156; 
+#endif /* DBI_TPO_480x864 */ /* get from spec. */
+
+        	dpll = 0x00800000;
+	        fp = 0x000000c1;
+}
+
+	REG_WRITE(fp_reg, fp);
+	REG_WRITE(dpll_reg, dpll);
+	/* FIXME_MDFLD PO - change 500 to 1 after PO */
+	udelay(500);
+
+	dpll |= DPLL_VCO_ENABLE;
+	REG_WRITE(dpll_reg, dpll);
+	REG_READ(dpll_reg);
+
+	/* wait for DSI PLL to lock */
+	while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+		udelay(150);
+		timeout ++;
+	}
+
+	if (is_mipi)
+		goto mrst_crtc_mode_set_exit;
+
+	dev_dbg(dev->dev, "is_mipi = 0x%x \n", is_mipi);
+
+	REG_WRITE(pipeconf_reg, *pipeconf);
+	REG_READ(pipeconf_reg);
+
+	/* Wait for for the pipe enable to take effect. */
+//FIXME_JLIU7 HDMI	mrstWaitForPipeEnable(dev);
+
+	REG_WRITE(dspcntr_reg, *dspcntr);
+	psb_intel_wait_for_vblank(dev);
+
+mrst_crtc_mode_set_exit:
+
+	gma_power_end(dev);
+
+	return 0;
+}
diff --git a/drivers/staging/gma500/mdfld_msic.h b/drivers/staging/gma500/mdfld_msic.h
new file mode 100644
index 0000000..a7ad6547
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_msic.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *	Jim Liu <jim.liu@intel.com>
+ */
+
+#define MSIC_PCI_DEVICE_ID	0x831
+
+int msic_regsiter_driver(void);
+int msic_unregister_driver(void);
+extern void hpd_notify_um(void);
diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c
new file mode 100644
index 0000000..b1fc765
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_output.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#include <linux/init.h>
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+#include "displays/tpo_cmd.h"
+#include "displays/tpo_vid.h"
+#include "displays/tmd_cmd.h"
+#include "displays/tmd_vid.h"
+#include "displays/pyr_cmd.h"
+#include "displays/pyr_vid.h"
+/* #include "displays/hdmi.h" */
+
+/* For now a single type per device is all we cope with */
+int mdfld_get_panel_type(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	return dev_priv->panel_id;
+}
+
+int mdfld_panel_dpi(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	switch (dev_priv->panel_id) {
+	case TMD_VID:
+	case TPO_VID:
+	case PYR_VID:
+		return true;
+	case TMD_CMD:
+	case TPO_CMD:
+	case PYR_CMD:
+	default:
+		return false;
+	}
+}
+
+static void init_panel(struct drm_device *dev, int mipi_pipe, int p_type)
+{
+	struct panel_funcs *p_cmd_funcs;
+	struct panel_funcs *p_vid_funcs;
+
+	/* Oh boy ... FIXME */
+	p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
+	p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
+
+	switch (p_type) {
+	case TPO_CMD:
+		tpo_cmd_init(dev, p_cmd_funcs);
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
+		break;
+	case TPO_VID:
+		tpo_vid_init(dev, p_vid_funcs);
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
+		break;
+	case TMD_CMD:
+		/*tmd_cmd_init(dev, p_cmd_funcs); */
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
+		break;
+	case TMD_VID:
+		tmd_vid_init(dev, p_vid_funcs);
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
+		break;
+	case PYR_CMD:
+		pyr_cmd_init(dev, p_cmd_funcs);
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
+		break;
+	case PYR_VID:
+		/*pyr_vid_init(dev, p_vid_funcs); */
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
+		break;
+	case TPO:	/* TPO panel supports both cmd & vid interfaces */
+		tpo_cmd_init(dev, p_cmd_funcs);
+		tpo_vid_init(dev, p_vid_funcs);
+		mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs,
+				      p_vid_funcs);
+		break;
+	case TMD:
+		break;
+	case PYR:
+		break;
+#if 0
+	case HDMI:
+		dev_dbg(dev->dev, "Initializing HDMI");
+		mdfld_hdmi_init(dev, &dev_priv->mode_dev);
+		break;
+#endif
+	default:
+		dev_err(dev->dev, "Unsupported interface %d", p_type);
+		break;
+	}
+}
+
+void mdfld_output_init(struct drm_device *dev)
+{
+	int type;
+
+	/* MIPI panel 1 */
+	type = mdfld_get_panel_type(dev, 0);
+	dev_info(dev->dev, "panel 1: type is %d\n", type);
+	init_panel(dev, 0, type);
+
+	/* MIPI panel 2 */
+	type = mdfld_get_panel_type(dev, 2);
+	dev_info(dev->dev, "panel 2: type is %d\n", type);
+	init_panel(dev, 2, type);
+}
diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h
new file mode 100644
index 0000000..36f43e1
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_output.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#ifndef MDFLD_OUTPUT_H
+#define MDFLD_OUTPUT_H
+
+#include "psb_drv.h"
+
+/* Panel types */
+enum {
+	TPO_CMD,
+	TPO_VID,
+	TMD_CMD,
+	TMD_VID,
+	PYR_CMD,
+	PYR_VID,
+	TPO,
+	TMD,
+	PYR,
+	HDMI,
+	GCT_DETECT
+};
+
+/* Junk that belongs elsewhere */
+#define TPO_PANEL_WIDTH		84
+#define TPO_PANEL_HEIGHT	46
+#define TMD_PANEL_WIDTH		39
+#define TMD_PANEL_HEIGHT	71
+#define PYR_PANEL_WIDTH		53
+#define PYR_PANEL_HEIGHT	95
+
+/* Panel interface */
+struct panel_info {
+	u32 width_mm;
+	u32 height_mm;
+};
+
+struct mdfld_dsi_dbi_output;
+
+struct panel_funcs {
+	const struct drm_encoder_funcs *encoder_funcs;
+	const struct drm_encoder_helper_funcs *encoder_helper_funcs;
+	struct drm_display_mode *(*get_config_mode) (struct drm_device *);
+	void (*update_fb) (struct mdfld_dsi_dbi_output *, int);
+	int (*get_panel_info) (struct drm_device *, int, struct panel_info *);
+};
+
+void mdfld_output_init(struct drm_device *dev);
+int mdfld_panel_dpi(struct drm_device *dev);
+int mdfld_get_panel_type(struct drm_device *dev, int pipe);
+void mdfld_disable_crtc (struct drm_device *dev, int pipe);
+
+#endif
diff --git a/drivers/staging/gma500/mdfld_pyr_cmd.c b/drivers/staging/gma500/mdfld_pyr_cmd.c
new file mode 100644
index 0000000..0d89384
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_pyr_cmd.c
@@ -0,0 +1,575 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+*/
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "displays/pyr_cmd.h"
+
+static struct drm_display_mode *pyr_cmd_get_config_mode(struct drm_device *dev)
+{
+	struct drm_display_mode *mode;
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode) {
+		dev_err(dev->dev, "Out of memory\n");
+		return NULL;
+	}
+
+	dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
+	dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
+	dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
+	dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
+	dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
+	dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
+	dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
+	dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
+	dev_dbg(dev->dev, "clock is %d\n", mode->clock);
+
+	mode->hdisplay = 480;
+	mode->vdisplay = 864;
+	mode->hsync_start = 487;
+	mode->hsync_end = 490;
+	mode->htotal = 499;
+	mode->vsync_start = 874;
+	mode->vsync_end = 878;
+	mode->vtotal = 886;
+	mode->clock = 25777;
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+static bool pyr_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_display_mode *fixed_mode = pyr_cmd_get_config_mode(dev);
+
+	if (fixed_mode) {
+		adjusted_mode->hdisplay = fixed_mode->hdisplay;
+		adjusted_mode->hsync_start = fixed_mode->hsync_start;
+		adjusted_mode->hsync_end = fixed_mode->hsync_end;
+		adjusted_mode->htotal = fixed_mode->htotal;
+		adjusted_mode->vdisplay = fixed_mode->vdisplay;
+		adjusted_mode->vsync_start = fixed_mode->vsync_start;
+		adjusted_mode->vsync_end = fixed_mode->vsync_end;
+		adjusted_mode->vtotal = fixed_mode->vtotal;
+		adjusted_mode->clock = fixed_mode->clock;
+		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+		kfree(fixed_mode);
+	}
+	return true;
+}
+
+static void pyr_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
+{
+	int ret = 0;
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+				MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 reg_offset = 0;
+	int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
+
+	dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", pipe,
+			on ? "On" : "Off",
+			dbi_output->dbi_panel_on ? "True" : "False");
+
+	if (pipe == 2) {
+		if (on)
+			dev_priv->dual_mipi = true;
+		else
+			dev_priv->dual_mipi = false;
+
+		reg_offset = MIPIC_REG_OFFSET;
+	} else {
+		if (!on)
+			dev_priv->dual_mipi = false;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+
+	if (on) {
+		if (dbi_output->dbi_panel_on)
+			goto out_err;
+
+		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
+		if (ret) {
+			dev_err(dev->dev, "power on error\n");
+			goto out_err;
+		}
+
+		dbi_output->dbi_panel_on = true;
+
+		if (pipe == 2) {
+			dev_priv->dbi_panel_on2 = true;
+		} else {
+			dev_priv->dbi_panel_on = true;
+			mdfld_enable_te(dev, 0);
+		}
+	} else {
+		if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
+			goto out_err;
+
+		dbi_output->dbi_panel_on = false;
+		dbi_output->first_boot = false;
+
+		if (pipe == 2) {
+			dev_priv->dbi_panel_on2 = false;
+			mdfld_disable_te(dev, 2);
+		} else {
+			dev_priv->dbi_panel_on = false;
+			mdfld_disable_te(dev, 0);
+
+			if (dev_priv->dbi_panel_on2)
+				mdfld_enable_te(dev, 2);
+		}
+
+		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
+		if (ret) {
+			dev_err(dev->dev, "power on error\n");
+			goto out_err;
+		}
+	}
+
+out_err:
+	gma_power_end(dev);
+
+	if (ret)
+		dev_err(dev->dev, "failed\n");
+}
+
+static void pyr_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
+								int pipe)
+{
+	struct drm_device *dev = dsi_config->dev;
+	u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
+	int lane_count = dsi_config->lane_count;
+	u32 val = 0;
+
+	dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
+
+	/* In-ready device */
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
+
+	/* Init dsi adapter before kicking off */
+	REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
+
+	/* TODO: figure out how to setup these registers */
+	REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c600F);
+	REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
+								0x000a0014);
+	REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
+	REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
+
+	/* Enable all interrupts */
+	REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
+	/* Max value: 20 clock cycles of txclkesc */
+	REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
+	/* Min 21 txclkesc, max: ffffh */
+	REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
+	/* Min: 7d0 max: 4e20 */
+	REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
+
+	/* Set up func_prg */
+	val |= lane_count;
+	val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
+	val |= DSI_DBI_COLOR_FORMAT_OPTION2;
+	REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
+
+	REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
+	REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
+
+	/* De-assert dbi_stall when half of DBI FIFO is empty */
+	/* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
+
+	REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
+	REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000002);
+	REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
+	REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
+}
+
+static void pyr_dsi_dbi_mode_set(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	int ret = 0;
+	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dsi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct mdfld_dsi_config *dsi_config =
+				mdfld_dsi_encoder_get_config(dsi_encoder);
+	struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
+	int pipe = dsi_connector->pipe;
+	u8 param = 0;
+
+	/* Regs */
+	u32 mipi_reg = MIPI;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 reg_offset = 0;
+
+	/* Values */
+	u32 dspcntr_val = dev_priv->dspcntr;
+	u32 pipeconf_val = dev_priv->pipeconf;
+	u32 h_active_area = mode->hdisplay;
+	u32 v_active_area = mode->vdisplay;
+	u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
+							TE_TRIGGER_GPIO_PIN);
+
+	dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
+
+	dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
+	dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
+
+	if (pipe == 2) {
+		mipi_reg = MIPI_C;
+		dspcntr_reg = DSPCCNTR;
+		pipeconf_reg = PIPECCONF;
+
+		reg_offset = MIPIC_REG_OFFSET;
+
+		dspcntr_val = dev_priv->dspcntr2;
+		pipeconf_val = dev_priv->pipeconf2;
+	} else {
+		mipi_val |= 0x2; /* Two lanes for port A and C respectively */
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	/* Set up pipe related registers */
+	REG_WRITE(mipi_reg, mipi_val);
+	REG_READ(mipi_reg);
+
+	pyr_dsi_controller_dbi_init(dsi_config, pipe);
+
+	msleep(20);
+
+	REG_WRITE(dspcntr_reg, dspcntr_val);
+	REG_READ(dspcntr_reg);
+
+	/* 20ms delay before sending exit_sleep_mode */
+	msleep(20);
+
+	/* Send exit_sleep_mode DCS */
+	ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode, NULL,
+						0, CMD_DATA_SRC_SYSTEM_MEM);
+	if (ret) {
+		dev_err(dev->dev, "sent exit_sleep_mode faild\n");
+		goto out_err;
+	}
+
+	/*send set_tear_on DCS*/
+	ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on,
+					&param, 1, CMD_DATA_SRC_SYSTEM_MEM);
+	if (ret) {
+		dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
+		goto out_err;
+	}
+
+	/* Do some init stuff */
+	mdfld_dsi_brightness_init(dsi_config, pipe);
+	mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset),
+				HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+	REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
+	REG_READ(pipeconf_reg);
+
+	/* TODO: this looks ugly, try to move it to CRTC mode setting */
+	if (pipe == 2)
+		dev_priv->pipeconf2 |= PIPEACONF_DSR;
+	else
+		dev_priv->pipeconf |= PIPEACONF_DSR;
+
+	dev_dbg(dev->dev, "pipeconf %x\n",  REG_READ(pipeconf_reg));
+
+	ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
+				h_active_area - 1, v_active_area - 1);
+	if (ret) {
+		dev_err(dev->dev, "update area failed\n");
+		goto out_err;
+	}
+
+out_err:
+	gma_power_end(dev);
+
+	if (ret)
+		dev_err(dev->dev, "mode set failed\n");
+	else
+		dev_dbg(dev->dev, "mode set done successfully\n");
+}
+
+static void pyr_dsi_dbi_prepare(struct drm_encoder *encoder)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+
+	dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
+	dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
+
+	pyr_dsi_dbi_set_power(encoder, false);
+}
+
+static void pyr_dsi_dbi_commit(struct drm_encoder *encoder)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_drm_dpu_rect rect;
+
+	pyr_dsi_dbi_set_power(encoder, true);
+
+	dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
+
+	rect.x = rect.y = 0;
+	rect.width = 864;
+	rect.height = 480;
+
+	if (dbi_output->channel_num == 1) {
+		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
+#ifdef CONFIG_MDFLD_DSI_DPU
+		/* If DPU enabled report a fullscreen damage */
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
+#endif
+	} else {
+		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
+
+#ifdef CONFIG_MDFLD_DSI_DPU
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
+#endif
+	}
+	dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
+}
+
+static void pyr_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	static bool bdispoff;
+
+	dev_dbg(dev->dev, "%s\n",  (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
+
+	if (mode == DRM_MODE_DPMS_ON) {
+		if (/*gbgfxsuspended && */bdispoff) {
+			bdispoff = false;
+			dev_priv->dispstatus = true;
+			/*gbgfxsuspended = false;
+			*/
+			mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D, 0, 0);
+		}
+		pyr_dsi_dbi_set_power(encoder, true);
+	} else {
+		bdispoff = true;
+		dev_priv->dispstatus = false;
+		pyr_dsi_dbi_set_power(encoder, false);
+	}
+}
+
+/*
+ * Update the DBI MIPI Panel Frame Buffer.
+ */
+static void pyr_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
+								int pipe)
+{
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_crtc *crtc = dbi_output->base.base.crtc;
+	struct psb_intel_crtc *psb_crtc = (crtc) ?
+				to_psb_intel_crtc(crtc) : NULL;
+
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dspsurf_reg = DSPASURF;
+	u32 hs_gen_ctrl_reg = HS_GEN_CTRL_REG;
+	u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG;
+	u32 reg_offset = 0;
+
+	u32 intr_status;
+	u32 fifo_stat_reg_val;
+	u32 dpll_reg_val;
+	u32 dspcntr_reg_val;
+	u32 pipeconf_reg_val;
+
+	/* If mode setting on-going, back off */
+	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
+		!(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
+		return;
+
+	/*
+	 * Look for errors here.  In particular we're checking for whatever
+	 * error status might have appeared during the last frame transmit
+	 * (memory write).
+	 *
+	 * Normally, the bits we're testing here would be set infrequently,
+	 * if at all.  However, one panel (at least) returns at least one
+	 * error bit on most frames.  So we've disabled the kernel message
+	 * for now.
+	 *
+	 * Still clear whatever error bits are set, except don't clear the
+	 * ones that would make the Penwell DSI controller reset if we
+	 * cleared them.
+	 */
+	intr_status = REG_READ(INTR_STAT_REG);
+	if ((intr_status & 0x26FFFFFF) != 0) {
+		/* dev_err(dev->dev, "DSI status: 0x%08X\n", intr_status); */
+		intr_status &= 0x26F3FFFF;
+		REG_WRITE(INTR_STAT_REG, intr_status);
+	}
+
+	if (pipe == 2) {
+		dspcntr_reg = DSPCCNTR;
+		pipeconf_reg = PIPECCONF;
+		dsplinoff_reg = DSPCLINOFF;
+		dspsurf_reg = DSPCSURF;
+
+		hs_gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET;
+		gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET,
+
+		reg_offset = MIPIC_REG_OFFSET;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	fifo_stat_reg_val = REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset);
+	dpll_reg_val = REG_READ(dpll_reg);
+	dspcntr_reg_val = REG_READ(dspcntr_reg);
+	pipeconf_reg_val = REG_READ(pipeconf_reg);
+
+	if (!(fifo_stat_reg_val & (1 << 27)) ||
+		(dpll_reg_val & DPLL_VCO_ENABLE) ||
+		!(dspcntr_reg_val & DISPLAY_PLANE_ENABLE) ||
+		!(pipeconf_reg_val & DISPLAY_PLANE_ENABLE)) {
+		goto update_fb_out0;
+	}
+
+	/* Refresh plane changes */
+	REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
+	REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
+	REG_READ(dspsurf_reg);
+
+	mdfld_dsi_send_dcs(sender,
+			   write_mem_start,
+			   NULL,
+			   0,
+			   CMD_DATA_SRC_PIPE,
+			   MDFLD_DSI_SEND_PACKAGE);
+
+	/*
+	 * The idea here is to transmit a Generic Read command after the
+	 * Write Memory Start/Continue commands finish.  This asks for
+	 * the panel to return an "ACK No Errors," or (if it has errors
+	 * to report) an Error Report.  This allows us to monitor the
+	 * panel's perception of the health of the DSI.
+	 */
+	mdfld_dsi_gen_fifo_ready(dev, gen_fifo_stat_reg,
+				HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+	REG_WRITE(hs_gen_ctrl_reg, (1 << WORD_COUNTS_POS) | GEN_READ_0);
+
+	dbi_output->dsr_fb_update_done = true;
+update_fb_out0:
+	gma_power_end(dev);
+}
+
+/*
+ * TODO: will be removed later, should work out display interfaces for power
+ */
+void pyr_dsi_adapter_init(struct mdfld_dsi_config *dsi_config, int pipe)
+{
+	if (!dsi_config || (pipe != 0 && pipe != 2)) {
+		WARN_ON(1);
+		return;
+	}
+	pyr_dsi_controller_dbi_init(dsi_config, pipe);
+}
+
+static int pyr_cmd_get_panel_info(struct drm_device *dev, int pipe,
+							struct panel_info *pi)
+{
+	if (!dev || !pi)
+		return -EINVAL;
+
+	pi->width_mm = PYR_PANEL_WIDTH;
+	pi->height_mm = PYR_PANEL_HEIGHT;
+
+	return 0;
+}
+
+/* PYR DBI encoder helper funcs */
+static const struct drm_encoder_helper_funcs pyr_dsi_dbi_helper_funcs = {
+	.dpms = pyr_dsi_dbi_dpms,
+	.mode_fixup = pyr_dsi_dbi_mode_fixup,
+	.prepare = pyr_dsi_dbi_prepare,
+	.mode_set = pyr_dsi_dbi_mode_set,
+	.commit = pyr_dsi_dbi_commit,
+};
+
+/* PYR DBI encoder funcs */
+static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
+{
+	p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
+	p_funcs->encoder_helper_funcs = &pyr_dsi_dbi_helper_funcs;
+	p_funcs->get_config_mode = &pyr_cmd_get_config_mode;
+	p_funcs->update_fb = pyr_dsi_dbi_update_fb;
+	p_funcs->get_panel_info = pyr_cmd_get_panel_info;
+}
diff --git a/drivers/staging/gma500/mdfld_tmd_vid.c b/drivers/staging/gma500/mdfld_tmd_vid.c
new file mode 100644
index 0000000..b29c905
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_tmd_vid.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Jim Liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ * Gideon Eaton <eaton.
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "displays/tmd_vid.h"
+
+/* FIXME: static ? */
+struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev)
+{
+	struct drm_display_mode *mode;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+	bool use_gct = false; /*Disable GCT for now*/
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode) {
+		dev_err(dev->dev, "Out of memory\n");
+		return NULL;
+	}
+
+	if (use_gct) {
+		dev_dbg(dev->dev, "gct find MIPI panel.\n");
+
+		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+		mode->hsync_start = mode->hdisplay +
+				((ti->hsync_offset_hi << 8) |
+				ti->hsync_offset_lo);
+		mode->hsync_end = mode->hsync_start +
+				((ti->hsync_pulse_width_hi << 8) |
+				ti->hsync_pulse_width_lo);
+		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) |
+								ti->hblank_lo);
+		mode->vsync_start = \
+			mode->vdisplay + ((ti->vsync_offset_hi << 8) |
+						ti->vsync_offset_lo);
+		mode->vsync_end = \
+			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+						ti->vsync_pulse_width_lo);
+		mode->vtotal = mode->vdisplay +
+				((ti->vblank_hi << 8) | ti->vblank_lo);
+		mode->clock = ti->pixel_clock * 10;
+
+		dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
+		dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
+		dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
+		dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
+		dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
+		dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
+		dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
+		dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
+		dev_dbg(dev->dev, "clock is %d\n", mode->clock);
+	} else {
+		mode->hdisplay = 480;
+		mode->vdisplay = 854;
+		mode->hsync_start = 487;
+		mode->hsync_end = 490;
+		mode->htotal = 499;
+		mode->vsync_start = 861;
+		mode->vsync_end = 865;
+		mode->vtotal = 873;
+		mode->clock = 33264;
+	}
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+static int tmd_vid_get_panel_info(struct drm_device *dev,
+				int pipe,
+				struct panel_info *pi)
+{
+	if (!dev || !pi)
+		return -EINVAL;
+
+	pi->width_mm = TMD_PANEL_WIDTH;
+	pi->height_mm = TMD_PANEL_HEIGHT;
+
+	return 0;
+}
+
+/* TMD DPI encoder helper funcs */
+static const struct drm_encoder_helper_funcs
+					mdfld_tpo_dpi_encoder_helper_funcs = {
+	.dpms = mdfld_dsi_dpi_dpms,
+	.mode_fixup = mdfld_dsi_dpi_mode_fixup,
+	.prepare = mdfld_dsi_dpi_prepare,
+	.mode_set = mdfld_dsi_dpi_mode_set,
+	.commit = mdfld_dsi_dpi_commit,
+};
+
+/* TMD DPI encoder funcs */
+static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs)
+{
+	if (!dev || !p_funcs) {
+		dev_err(dev->dev, "Invalid parameters\n");
+		return;
+	}
+
+	p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
+	p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
+	p_funcs->get_config_mode = &tmd_vid_get_config_mode;
+	p_funcs->update_fb = NULL;
+	p_funcs->get_panel_info = tmd_vid_get_panel_info;
+}
diff --git a/drivers/staging/gma500/mdfld_tpo_cmd.c b/drivers/staging/gma500/mdfld_tpo_cmd.c
new file mode 100644
index 0000000..d2e1818
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_tpo_cmd.c
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c)  2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicensen
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Thomas Eaton <thomas.g.eaton@intel.com>
+ * Scott Rowe <scott.m.rowe@intel.com>
+ */
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "displays/tpo_cmd.h"
+
+static struct drm_display_mode *tpo_cmd_get_config_mode(struct drm_device *dev)
+{
+	struct drm_display_mode *mode;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+	bool use_gct = false;
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode)
+		return NULL;
+
+	if (use_gct) {
+		dev_dbg(dev->dev, "gct find MIPI panel.\n");
+
+		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+		mode->hsync_start = mode->hdisplay + \
+				((ti->hsync_offset_hi << 8) | \
+				ti->hsync_offset_lo);
+		mode->hsync_end = mode->hsync_start + \
+				((ti->hsync_pulse_width_hi << 8) | \
+				ti->hsync_pulse_width_lo);
+		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+								ti->hblank_lo);
+		mode->vsync_start = \
+			mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+						ti->vsync_offset_lo);
+		mode->vsync_end = \
+			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+						ti->vsync_pulse_width_lo);
+		mode->vtotal = mode->vdisplay + \
+				((ti->vblank_hi << 8) | ti->vblank_lo);
+		mode->clock = ti->pixel_clock * 10;
+
+		dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
+		dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
+		dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
+		dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
+		dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
+		dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
+		dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
+		dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
+		dev_dbg(dev->dev, "clock is %d\n", mode->clock);
+	} else {
+		mode->hdisplay = 864;
+		mode->vdisplay = 480;
+		mode->hsync_start = 872;
+		mode->hsync_end = 876;
+		mode->htotal = 884;
+		mode->vsync_start = 482;
+		mode->vsync_end = 494;
+		mode->vtotal = 486;
+		mode->clock = 25777;
+	}
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_display_mode *fixed_mode = tpo_cmd_get_config_mode(dev);
+
+	if (fixed_mode) {
+		adjusted_mode->hdisplay = fixed_mode->hdisplay;
+		adjusted_mode->hsync_start = fixed_mode->hsync_start;
+		adjusted_mode->hsync_end = fixed_mode->hsync_end;
+		adjusted_mode->htotal = fixed_mode->htotal;
+		adjusted_mode->vdisplay = fixed_mode->vdisplay;
+		adjusted_mode->vsync_start = fixed_mode->vsync_start;
+		adjusted_mode->vsync_end = fixed_mode->vsync_end;
+		adjusted_mode->vtotal = fixed_mode->vtotal;
+		adjusted_mode->clock = fixed_mode->clock;
+		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+		kfree(fixed_mode);
+	}
+	return true;
+}
+
+static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
+{
+	int ret = 0;
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+				MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	/*struct drm_device *dev = dbi_output->dev;*/
+	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 reg_offset = 0;
+	int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
+
+	dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n",
+			pipe, on ? "On" : "Off",
+			dbi_output->dbi_panel_on ? "True" : "False");
+
+	if (pipe == 2) {
+		if (on)
+			dev_priv->dual_mipi = true;
+		else
+			dev_priv->dual_mipi = false;
+		reg_offset = MIPIC_REG_OFFSET;
+	} else {
+		if (!on)
+			dev_priv->dual_mipi = false;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	if (on) {
+		if (dbi_output->dbi_panel_on)
+			goto out_err;
+
+		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
+		if (ret) {
+			dev_err(dev->dev, "power on error\n");
+			goto out_err;
+		}
+
+		dbi_output->dbi_panel_on = true;
+
+		if (pipe == 2)
+			dev_priv->dbi_panel_on2 = true;
+		else
+			dev_priv->dbi_panel_on = true;
+		mdfld_enable_te(dev, pipe);
+	} else {
+		if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
+			goto out_err;
+
+		dbi_output->dbi_panel_on = false;
+		dbi_output->first_boot = false;
+
+		if (pipe == 2)
+			dev_priv->dbi_panel_on2 = false;
+		else
+			dev_priv->dbi_panel_on = false;
+
+		mdfld_disable_te(dev, pipe);
+
+		ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
+		if (ret) {
+			dev_err(dev->dev, "power on error\n");
+			goto out_err;
+		}
+	}
+
+out_err:
+	gma_power_end(dev);
+
+	if (ret)
+		dev_err(dev->dev, "failed\n");
+}
+
+
+static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	int ret = 0;
+	struct drm_device *dev = encoder->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dsi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct mdfld_dsi_config *dsi_config =
+				mdfld_dsi_encoder_get_config(dsi_encoder);
+	struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
+	int pipe = dsi_connector->pipe;
+	u8 param = 0;
+
+	/* Regs */
+	u32 mipi_reg = MIPI;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 reg_offset = 0;
+
+	/* Values */
+	u32 dspcntr_val = dev_priv->dspcntr;
+	u32 pipeconf_val = dev_priv->pipeconf;
+	u32 h_active_area = mode->hdisplay;
+	u32 v_active_area = mode->vdisplay;
+	u32 mipi_val;
+
+	mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
+						TE_TRIGGER_GPIO_PIN);
+
+	dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
+
+	dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
+	dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
+
+	if (pipe == 2) {
+		mipi_reg = MIPI_C;
+		dspcntr_reg = DSPCCNTR;
+		pipeconf_reg = PIPECCONF;
+
+		reg_offset = MIPIC_REG_OFFSET;
+
+		dspcntr_val = dev_priv->dspcntr2;
+		pipeconf_val = dev_priv->pipeconf2;
+	} else {
+		mipi_val |= 0x2; /*two lanes for port A and C respectively*/
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	/* Set up pipe related registers */
+	REG_WRITE(mipi_reg, mipi_val);
+	REG_READ(mipi_reg);
+
+	mdfld_dsi_controller_dbi_init(dsi_config, pipe);
+
+	msleep(20);
+
+	REG_WRITE(dspcntr_reg, dspcntr_val);
+	REG_READ(dspcntr_reg);
+
+	/* 20ms delay before sending exit_sleep_mode */
+	msleep(20);
+
+	/* Send exit_sleep_mode DCS */
+	ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode,
+					NULL, 0, CMD_DATA_SRC_SYSTEM_MEM);
+	if (ret) {
+		dev_err(dev->dev, "sent exit_sleep_mode faild\n");
+		goto out_err;
+	}
+
+	/* Send set_tear_on DCS */
+	ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on,
+					&param, 1, CMD_DATA_SRC_SYSTEM_MEM);
+	if (ret) {
+		dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
+		goto out_err;
+	}
+
+	/* Do some init stuff */
+	mdfld_dsi_brightness_init(dsi_config, pipe);
+
+	mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset),
+				HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
+
+	REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
+	REG_READ(pipeconf_reg);
+
+	/* TODO: this looks ugly, try to move it to CRTC mode setting*/
+	if (pipe == 2)
+		dev_priv->pipeconf2 |= PIPEACONF_DSR;
+	else
+		dev_priv->pipeconf |= PIPEACONF_DSR;
+
+	dev_dbg(dev->dev, "pipeconf %x\n",  REG_READ(pipeconf_reg));
+
+	ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
+				h_active_area - 1, v_active_area - 1);
+	if (ret) {
+		dev_err(dev->dev, "update area failed\n");
+		goto out_err;
+	}
+
+out_err:
+	gma_power_end(dev);
+
+	if (ret)
+		dev_err(dev->dev, "mode set failed\n");
+}
+
+static void mdfld_dsi_dbi_prepare(struct drm_encoder *encoder)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output
+				= MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+
+	dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
+	dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
+
+	mdfld_dsi_dbi_set_power(encoder, false);
+}
+
+static void mdfld_dsi_dbi_commit(struct drm_encoder *encoder)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output =
+					MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_drm_dpu_rect rect;
+
+	mdfld_dsi_dbi_set_power(encoder, true);
+	dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
+
+	rect.x = rect.y = 0;
+	rect.width = 864;
+	rect.height = 480;
+
+	if (dbi_output->channel_num == 1) {
+		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
+#ifdef CONFIG_MDFLD_DSI_DPU
+		/*if dpu enabled report a fullscreen damage*/
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
+#endif
+	} else {
+		dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
+#ifdef CONFIG_MDFLD_DSI_DPU
+		mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
+#endif
+	}
+	dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
+}
+
+static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
+	struct mdfld_dsi_dbi_output *dbi_output
+				= MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	static bool bdispoff;
+
+	dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
+
+	if (mode == DRM_MODE_DPMS_ON) {
+		/*
+		 * FIXME: in case I am wrong!
+		 * we don't need to exit dsr here to wake up plane/pipe/pll
+		 * if everything goes right, hw_begin will resume them all
+		 * during set_power.
+		 */
+		if (bdispoff)
+			mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D, 0, 0);
+
+		mdfld_dsi_dbi_set_power(encoder, true);
+		/* FIXME if (gbgfxsuspended)
+			gbgfxsuspended = false; */
+		bdispoff = false;
+		dev_priv->dispstatus = true;
+	} else {
+		/*
+		 * I am not sure whether this is the perfect place to
+		 * turn rpm on since we still have a lot of CRTC turnning
+		 * on work to do.
+		 */
+		mdfld_dsi_dbi_set_power(encoder, false);
+		bdispoff = true;
+		dev_priv->dispstatus = false;
+	}
+}
+
+
+/*
+ * Update the DBI MIPI Panel Frame Buffer.
+ */
+static void mdfld_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
+								int pipe)
+{
+	struct mdfld_dsi_pkg_sender *sender =
+		mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
+	struct drm_device *dev = dbi_output->dev;
+	struct drm_crtc *crtc = dbi_output->base.base.crtc;
+	struct psb_intel_crtc *psb_crtc = (crtc) ?
+					to_psb_intel_crtc(crtc) : NULL;
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dspsurf_reg = DSPASURF;
+	u32 reg_offset = 0;
+
+	/* If mode setting on-going, back off */
+	if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
+		(psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
+		!(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
+		return;
+
+	if (pipe == 2) {
+		dspcntr_reg = DSPCCNTR;
+		pipeconf_reg = PIPECCONF;
+		dsplinoff_reg = DSPCLINOFF;
+		dspsurf_reg = DSPCSURF;
+		reg_offset = MIPIC_REG_OFFSET;
+	}
+
+	if (!gma_power_begin(dev, true)) {
+		dev_err(dev->dev, "hw begin failed\n");
+		return;
+	}
+
+	/* Check DBI FIFO status */
+	if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
+	   !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
+	   !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE))
+		goto update_fb_out0;
+
+	/* Refresh plane changes */
+	REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
+	REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
+	REG_READ(dspsurf_reg);
+
+	mdfld_dsi_send_dcs(sender,
+			   write_mem_start,
+			   NULL,
+			   0,
+			   CMD_DATA_SRC_PIPE,
+			   MDFLD_DSI_SEND_PACKAGE);
+
+	dbi_output->dsr_fb_update_done = true;
+update_fb_out0:
+	gma_power_end(dev);
+}
+
+static int tpo_cmd_get_panel_info(struct drm_device *dev,
+				int pipe,
+				struct panel_info *pi)
+{
+	if (!dev || !pi)
+		return -EINVAL;
+
+	pi->width_mm = TPO_PANEL_WIDTH;
+	pi->height_mm = TPO_PANEL_HEIGHT;
+
+	return 0;
+}
+
+
+/* TPO DBI encoder helper funcs */
+static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
+	.dpms = mdfld_dsi_dbi_dpms,
+	.mode_fixup = mdfld_dsi_dbi_mode_fixup,
+	.prepare = mdfld_dsi_dbi_prepare,
+	.mode_set = mdfld_dsi_dbi_mode_set,
+	.commit = mdfld_dsi_dbi_commit,
+};
+
+/* TPO DBI encoder funcs */
+static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
+{
+	p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
+	p_funcs->encoder_helper_funcs = &mdfld_dsi_dbi_helper_funcs;
+	p_funcs->get_config_mode = &tpo_cmd_get_config_mode;
+	p_funcs->update_fb = mdfld_dsi_dbi_update_fb;
+	p_funcs->get_panel_info = tpo_cmd_get_panel_info;
+}
diff --git a/drivers/staging/gma500/mdfld_tpo_vid.c b/drivers/staging/gma500/mdfld_tpo_vid.c
new file mode 100644
index 0000000..9549017
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_tpo_vid.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * jim liu <jim.liu@intel.com>
+ * Jackie Li<yaodong.li@intel.com>
+ */
+
+#include "mdfld_dsi_dbi.h"
+#include "mdfld_dsi_dpi.h"
+#include "mdfld_dsi_output.h"
+#include "mdfld_output.h"
+
+#include "mdfld_dsi_pkg_sender.h"
+
+#include "displays/tpo_vid.h"
+
+static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev)
+{
+	struct drm_display_mode *mode;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
+	bool use_gct = false;
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode) {
+		dev_err(dev->dev, "out of memory\n");
+		return NULL;
+	}
+
+	if (use_gct) {
+		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
+		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
+		mode->hsync_start = mode->hdisplay + \
+				((ti->hsync_offset_hi << 8) | \
+				ti->hsync_offset_lo);
+		mode->hsync_end = mode->hsync_start + \
+				((ti->hsync_pulse_width_hi << 8) | \
+				ti->hsync_pulse_width_lo);
+		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
+								ti->hblank_lo);
+		mode->vsync_start = \
+			mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
+						ti->vsync_offset_lo);
+		mode->vsync_end = \
+			mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
+						ti->vsync_pulse_width_lo);
+		mode->vtotal = mode->vdisplay + \
+				((ti->vblank_hi << 8) | ti->vblank_lo);
+		mode->clock = ti->pixel_clock * 10;
+
+		dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
+		dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
+		dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
+		dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
+		dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
+		dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
+		dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
+		dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
+		dev_dbg(dev->dev, "clock is %d\n", mode->clock);
+	} else {
+		mode->hdisplay = 864;
+		mode->vdisplay = 480;
+		mode->hsync_start = 873;
+		mode->hsync_end = 876;
+		mode->htotal = 887;
+		mode->vsync_start = 487;
+		mode->vsync_end = 490;
+		mode->vtotal = 499;
+		mode->clock = 33264;
+	}
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+	return mode;
+}
+
+static int tpo_vid_get_panel_info(struct drm_device *dev,
+				int pipe,
+				struct panel_info *pi)
+{
+	if (!dev || !pi)
+		return -EINVAL;
+
+	pi->width_mm = TPO_PANEL_WIDTH;
+	pi->height_mm = TPO_PANEL_HEIGHT;
+
+	return 0;
+}
+
+/*TPO DPI encoder helper funcs*/
+static const struct drm_encoder_helper_funcs
+					mdfld_tpo_dpi_encoder_helper_funcs = {
+	.dpms = mdfld_dsi_dpi_dpms,
+	.mode_fixup = mdfld_dsi_dpi_mode_fixup,
+	.prepare = mdfld_dsi_dpi_prepare,
+	.mode_set = mdfld_dsi_dpi_mode_set,
+	.commit = mdfld_dsi_dpi_commit,
+};
+
+/*TPO DPI encoder funcs*/
+static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs)
+{
+	if (!dev || !p_funcs) {
+		dev_err(dev->dev, "tpo_vid_init: Invalid parameters\n");
+		return;
+	}
+
+	p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs;
+	p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs;
+	p_funcs->get_config_mode = &tpo_vid_get_config_mode;
+	p_funcs->update_fb = NULL;
+	p_funcs->get_panel_info = tpo_vid_get_panel_info;
+}
diff --git a/drivers/staging/gma500/psb_bl.c b/drivers/staging/gma500/psb_bl.c
index 4a00047..c84d261 100644
--- a/drivers/staging/gma500/psb_bl.c
+++ b/drivers/staging/gma500/psb_bl.c
@@ -105,6 +105,46 @@ int mrst_set_brightness(struct backlight_device *bd)
 	return 0;
 }
 
+int mfld_set_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(psb_backlight_device);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int level = bd->props.brightness;
+
+	DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
+
+	/* Percentage 1-100% being valid */
+	if (level < 1)
+		level = 1;
+
+	if (gma_power_begin(dev, 0)) {
+		/* Calculate and set the brightness value */
+		u32 adjusted_level;
+
+		/* Adjust the backlight level with the percent in
+		 * dev_priv->blc_adj2;
+		 */
+		adjusted_level = level * dev_priv->blc_adj2;
+		adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX;
+#if 0
+#ifndef CONFIG_MDFLD_DSI_DPU
+		if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) && 
+			(dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
+			mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0);
+			dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level);
+		}
+#endif
+		mdfld_dsi_brightness_control(dev, 0, adjusted_level);
+
+		if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
+			mdfld_dsi_brightness_control(dev, 2, adjusted_level);
+#endif
+		gma_power_end(dev);
+	}
+	psb_brightness = level;
+	return 0;
+}
+
 int psb_get_brightness(struct backlight_device *bd)
 {
 	/* return locally cached var instead of HW read (due to DPST etc.) */
@@ -118,6 +158,16 @@ static const struct backlight_ops psb_ops = {
 	.update_status  = psb_set_brightness,
 };
 
+static const struct backlight_ops mrst_ops = {
+	.get_brightness = psb_get_brightness,
+	.update_status  = mrst_set_brightness,
+};
+
+static const struct backlight_ops mfld_ops = {
+	.get_brightness = psb_get_brightness,
+	.update_status  = mfld_set_brightness,
+};
+
 static int device_backlight_init(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
@@ -128,7 +178,11 @@ static int device_backlight_init(struct drm_device *dev)
 	uint32_t value;
 	uint32_t blc_pwm_precision_factor;
 
-	if (IS_MRST(dev)) {
+	if (IS_MFLD(dev)) {
+		dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
+		dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
+		return 0;
+	} else if (IS_MRST(dev)) {
 		dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
 		dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
 		bl_max_freq = 256;
@@ -190,8 +244,16 @@ int psb_backlight_init(struct drm_device *dev)
 	props.max_brightness = 100;
 	props.type = BACKLIGHT_PLATFORM;
 
-	psb_backlight_device = backlight_device_register("psb-bl", NULL,
-						(void *)dev, &psb_ops, &props);
+	if (IS_MFLD(dev))
+		psb_backlight_device = backlight_device_register("mfld-bl",
+					NULL, (void *)dev, &mfld_ops, &props);
+	else if (IS_MRST(dev))
+		psb_backlight_device = backlight_device_register("mrst-bl",
+					NULL, (void *)dev, &psb_ops, &props);
+	else
+		psb_backlight_device = backlight_device_register("psb-bl",
+					NULL, (void *)dev, &psb_ops, &props);
+					
 	if (IS_ERR(psb_backlight_device))
 		return PTR_ERR(psb_backlight_device);
 
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
index 8c259b8..c541137 100644
--- a/drivers/staging/gma500/psb_drm.h
+++ b/drivers/staging/gma500/psb_drm.h
@@ -186,4 +186,11 @@ struct drm_psb_get_pipe_from_crtc_id_arg {
 	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;    
+};  
+
 #endif
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 3c2363a..8df9c58 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -58,6 +58,14 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
 	{ 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
 	{ 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
 	{ 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
+	{ 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
+	{ 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
+	{ 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
+	{ 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
+	{ 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
+	{ 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
+	{ 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
+	{ 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
 	{ 0, 0, 0}
 };
 MODULE_DEVICE_TABLE(pci, pciidlist);
@@ -176,7 +184,9 @@ void mrst_get_fuse_settings(struct drm_device *dev)
 	pci_write_config_dword(pci_root, 0xD0, FB_REG06);
 	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
 
-	dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
+	/* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
+	if (IS_MRST(dev))
+		dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
 
 	DRM_INFO("internal display is %s\n",
 		 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
@@ -360,6 +370,7 @@ void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
 		printk(KERN_ERR "Unknown revision of GCT!\n");
 		vbt->size = 0;
 	}
+	/* FIXME: Need to sort out Medfield panel identifiers in future */
 }
 
 static void psb_get_core_freq(struct drm_device *dev)
@@ -539,6 +550,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 
 	if (IS_MRST(dev))
 		dev_priv->num_pipe = 1;
+	else if (IS_MFLD(dev))
+		dev_priv->num_pipe = 3;
 	else
 		dev_priv->num_pipe = 2;
 
@@ -554,7 +567,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	if (!dev_priv->vdc_reg)
 		goto out_err;
 
-	if (IS_MRST(dev))
+	if (IS_MRST(dev) || IS_MFLD(dev))
 		dev_priv->sgx_reg = ioremap(resource_start + MRST_SGX_OFFSET,
 							PSB_SGX_SIZE);
 	else
@@ -564,7 +577,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	if (!dev_priv->sgx_reg)
 		goto out_err;
 
-	if (IS_MRST(dev)) {
+	if (IS_MRST(dev) || IS_MFLD(dev)) {
 		mrst_get_fuse_settings(dev);
 		mrst_get_vbt_data(dev_priv);
 		mid_get_pci_revID(dev_priv);
@@ -706,6 +719,11 @@ static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
 	struct drm_psb_dc_state_arg *arg =
 		(struct drm_psb_dc_state_arg *)data;
 
+
+	/* Double check MRST case */
+	if (IS_MRST(dev) || IS_MFLD(dev))
+		return -EOPNOTSUPP;
+
 	flags = arg->flags;
 	obj_id = arg->obj_id;
 
@@ -954,6 +972,7 @@ static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
 	return 0;
 }
 
+/* FIXME: needs Medfield changes */
 static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
 				 struct drm_file *file_priv)
 {
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index cafbfcd..86abf26 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -34,15 +34,18 @@
 #include "mrst.h"
 
 /* Append new drm mode definition here, align with libdrm definition */
-#define DRM_MODE_SCALE_NO_SCALE   2
+#define DRM_MODE_SCALE_NO_SCALE   	2
+#define DRM_MODE_CONNECTOR_MIPI         15
 
 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
@@ -204,10 +207,25 @@ enum {
 #define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
 #define PSB_LID_DELAY (DRM_HZ / 10)
 
-#define MDFLD_PNW_A0 0x00
 #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
 
@@ -221,6 +239,12 @@ enum {
 #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;
@@ -331,6 +355,7 @@ struct drm_psb_private {
 	int lvds_ssc_freq;
 	bool is_lvds_on;
 	bool is_mipi_on;
+	u32 mipi_ctrl_display;
 
 	unsigned int core_freq;
 	uint32_t iLVDS_enable;
@@ -338,10 +363,19 @@ struct drm_psb_private {
 	/* Runtime PM state */
 	int rpm_enabled;
 
-	/* Moorestown specific */
+	/* MID specific */
 	struct mrst_vbt vbt_data;
 	struct mrst_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 pipe config register value cache */
 	uint32_t pipeconf;
 	uint32_t pipeconf1;
@@ -376,6 +410,7 @@ struct drm_psb_private {
 	uint32_t saveDSPAPOS;
 	uint32_t saveDSPABASE;
 	uint32_t saveDSPASURF;
+	uint32_t saveDSPASTATUS;
 	uint32_t saveFPB0;
 	uint32_t saveFPB1;
 	uint32_t saveDPLL_B;
@@ -391,6 +426,7 @@ struct drm_psb_private {
 	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;
@@ -461,6 +497,77 @@ struct drm_psb_private {
 	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
 	 */
@@ -486,6 +593,22 @@ struct drm_psb_private {
 	uint32_t blc_adj2;
 
 	void *fbdev;
+
+	/* DPST state */
+	uint32_t dsr_idle_count;
+	bool is_in_idle;
+	bool dsr_enable;
+	void (*exit_idle)(struct drm_device *dev, u32 update_src, void *p_surfaceAddr, bool check_hw_on_only);
+
+	/* FIXME: Arrays anyone ? */
+	struct mdfld_dsi_encoder *encoder0;	
+	struct mdfld_dsi_encoder *encoder2;	
+	struct mdfld_dsi_dbi_output * dbi_output;
+	struct mdfld_dsi_dbi_output * dbi_output2;
+	u32 bpp;
+	u32 bpp2;
+	
+	bool dispstatus;
 };
 
 
@@ -567,6 +690,9 @@ 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);
 
+extern int mdfld_enable_te(struct drm_device *dev, int pipe);
+extern void mdfld_disable_te(struct drm_device *dev, int pipe);
+
 /*
  * psb_opregion.c
  */
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index c2d4b23..8377a99 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -38,6 +38,8 @@
 #include "psb_intel_drv.h"
 #include "psb_fb.h"
 
+#include "mdfld_output.h"
+
 static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
 static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
 					      struct drm_file *file_priv,
@@ -270,6 +272,8 @@ static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
 	case 0x12345678:
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
+	        if (IS_MFLD(dev))
+                        return -EOPNOTSUPP;
 		if (get_user(l, p))
 			return -EFAULT;
 		if (l > 32)
@@ -297,6 +301,19 @@ static struct fb_ops psbfb_ops = {
 	.fb_ioctl = psbfb_ioctl,
 };
 
+static struct fb_ops psbfb_mfld_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcolreg = psbfb_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_mmap = psbfb_mmap,
+	.fb_ioctl = psbfb_ioctl,
+};
+
 /**
  *	psb_framebuffer_init	-	initialize a framebuffer
  *	@dev: our DRM device
@@ -346,6 +363,7 @@ static int psb_framebuffer_init(struct drm_device *dev,
  *
  *	TODO: review object references
  */
+
 static struct drm_framebuffer *psb_framebuffer_create
 			(struct drm_device *dev,
 			 struct drm_mode_fb_cmd *mode_cmd,
@@ -468,7 +486,11 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	strcpy(info->fix.id, "psbfb");
 
 	info->flags = FBINFO_DEFAULT;
-	info->fbops = &psbfb_ops;
+	/* No 2D engine */
+	if (IS_MFLD(dev))
+	        info->fbops = &psbfb_mfld_ops;
+        else
+        	info->fbops = &psbfb_ops;
 
 	ret = fb_alloc_cmap(&info->cmap, 256, 0);
 	if (ret) {
@@ -781,7 +803,9 @@ static void psb_setup_outputs(struct drm_device *dev)
 			mrst_lvds_init(dev, &dev_priv->mode_dev);
 		else
 			dev_err(dev->dev, "DSI is not supported\n");
-	} else {
+	} else if (IS_MFLD(dev)) {
+		mdfld_output_init(dev);
+        } else {
 		psb_intel_lvds_init(dev, &dev_priv->mode_dev);
 		psb_intel_sdvo_init(dev, SDVOB);
 	}
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index f28f5d6..ba10849 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2006-2007 Intel Corporation
+ * Copyright © 2006-2011 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -1080,7 +1080,7 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 	return 0;
 }
 
-static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
+void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
 			 u16 *green, u16 *blue, uint32_t type, uint32_t size)
 {
 	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
@@ -1241,7 +1241,7 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
 	return mode;
 }
 
-static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
+void psb_intel_crtc_destroy(struct drm_crtc *crtc)
 {
 	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
 	struct gtt_range *gt;
@@ -1303,7 +1303,14 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 		return;
 	}
 
-	drm_crtc_init(dev, &psb_intel_crtc->base, &psb_intel_crtc_funcs);
+#if 0	/* FIXME */
+	if (IS_MFLD(dev))
+		drm_crtc_init(dev, &psb_intel_crtc->base,
+						&mfld_intel_crtc_funcs);
+	else
+#endif
+        	drm_crtc_init(dev, &psb_intel_crtc->base,
+						&psb_intel_crtc_funcs);
 
 	drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
 	psb_intel_crtc->pipe = pipe;
@@ -1329,6 +1336,9 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 	if (IS_MRST(dev))
 		drm_crtc_helper_add(&psb_intel_crtc->base,
 				    &mrst_helper_funcs);
+/*	else if (IS_MDFLD(dev))
+		drm_crtc_helper_add(&psb_intel_crtc->base,
+				    &mfld_helper_funcs); */
 	else
 		drm_crtc_helper_add(&psb_intel_crtc->base,
 				    &psb_intel_helper_funcs);
diff --git a/drivers/staging/gma500/psb_intel_display.h b/drivers/staging/gma500/psb_intel_display.h
index 3724b97..535b49a 100644
--- a/drivers/staging/gma500/psb_intel_display.h
+++ b/drivers/staging/gma500/psb_intel_display.h
@@ -21,5 +21,8 @@
 #define _INTEL_DISPLAY_H_
 
 bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type);
+void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
+			 u16 *green, u16 *blue, uint32_t type, uint32_t size);
+void psb_intel_crtc_destroy(struct drm_crtc *crtc);
 
 #endif
diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h
index 75a95f7..9d7151a 100644
--- a/drivers/staging/gma500/psb_intel_drv.h
+++ b/drivers/staging/gma500/psb_intel_drv.h
@@ -224,4 +224,7 @@ extern int psb_intel_lvds_set_property(struct drm_connector *connector,
 extern void psb_intel_lvds_destroy(struct drm_connector *connector);
 extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs;
 
+extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe);
+extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe);
+
 #endif				/* __INTEL_DRV_H__ */
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index 1cbc9bc..850d07d 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -388,6 +388,7 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
 	if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
 		panel_fixed_mode = mode_dev->panel_fixed_mode2;
 
+	/* FIXME: review for Medfield */
 	/* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */
 	if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) {
 		printk(KERN_ERR "Can't support LVDS on pipe A\n");
diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c
index 1cbfeb6..3768cf1 100644
--- a/drivers/staging/gma500/psb_irq.c
+++ b/drivers/staging/gma500/psb_irq.c
@@ -27,7 +27,7 @@
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
 #include "psb_powermgmt.h"
-
+#include "mdfld_output.h"
 
 /*
  * inline functions
@@ -455,6 +455,11 @@ int psb_enable_vblank(struct drm_device *dev, int pipe)
 	uint32_t reg_val = 0;
 	uint32_t pipeconf_reg = mid_pipeconf(pipe);
 
+	/* Medfield is different - we should perhaps extract out vblank
+	   and blacklight etc ops */
+	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
+		return mdfld_enable_te(dev, pipe);
+
 	if (gma_power_begin(dev, false)) {
 		reg_val = REG_READ(pipeconf_reg);
 		gma_power_end(dev);
@@ -481,6 +486,8 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	unsigned long irqflags;
 
+	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
+		mdfld_disable_te(dev, pipe);
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	mid_disable_pipe_event(dev_priv, pipe);
@@ -489,6 +496,58 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
 	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
 }
 
+/**
+ *	mdfld_enable_te		-	enable TE events
+ *	@dev: our DRM device
+ *	@pipe: which pipe to work on
+ *
+ *	Enable TE events on a Medfield display pipe. Medfield specific.
+ */
+int mdfld_enable_te(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long flags;
+	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, flags);
+
+	mid_enable_pipe_event(dev_priv, pipe);
+	psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags);
+
+	return 0;
+}
+
+/**
+ *	mdfld_disable_te		-	disable TE events
+ *	@dev: our DRM device
+ *	@pipe: which pipe to work on
+ *
+ *	Disable TE events on a Medfield display pipe. Medfield specific.
+ */
+void mdfld_disable_te(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev_priv->irqmask_lock, flags);
+
+	mid_disable_pipe_event(dev_priv, pipe);
+	psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags);
+}
+
 /* Called from drm generic code, passed a 'crtc', which
  * we use as a pipe index
  */
diff --git a/drivers/staging/gma500/psb_powermgmt.c b/drivers/staging/gma500/psb_powermgmt.c
index 50f2234..f837ab0 100644
--- a/drivers/staging/gma500/psb_powermgmt.c
+++ b/drivers/staging/gma500/psb_powermgmt.c
@@ -31,8 +31,16 @@
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_output.h"
 #include <linux/mutex.h>
 #include <linux/pm_runtime.h>
+#include <asm/intel_scu_ipc.h>
+
+/* IPC message and command defines used to enable/disable mipi panel voltages */
+#define IPC_MSG_PANEL_ON_OFF    0xE9
+#define IPC_CMD_PANEL_ON        1
+#define IPC_CMD_PANEL_OFF       0
 
 static struct mutex power_mutex;
 
@@ -46,6 +54,8 @@ void gma_power_init(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
 
+	/* FIXME: need to sort out fetching apm_reg for both platforms ?? */
+
 	dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
 	dev_priv->ospm_base &= 0xffff;
 
@@ -154,6 +164,521 @@ static int restore_display_registers(struct drm_device *dev)
 }
 
 /**
+ * mdfld_save_display_registers	-	save registers for pipe
+ * @dev: our device
+ * @pipe: pipe to save
+ *
+ * Save the pipe state of the device before we power it off. Keep everything
+ * we need to put it back again
+ */
+static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int i;
+
+	/* register */
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 fp_reg = MRST_FPA0;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 htot_reg = HTOTAL_A;
+	u32 hblank_reg = HBLANK_A;
+	u32 hsync_reg = HSYNC_A;
+	u32 vtot_reg = VTOTAL_A;
+	u32 vblank_reg = VBLANK_A;
+	u32 vsync_reg = VSYNC_A;
+	u32 pipesrc_reg = PIPEASRC;
+	u32 dspstride_reg = DSPASTRIDE;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dsptileoff_reg = DSPATILEOFF;
+	u32 dspsize_reg = DSPASIZE;
+	u32 dsppos_reg = DSPAPOS;
+	u32 dspsurf_reg = DSPASURF;
+	u32 mipi_reg = MIPI;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 dspstatus_reg = PIPEASTAT;
+	u32 palette_reg = PALETTE_A;
+
+	/* pointer to values */
+	u32 *dpll_val = &dev_priv->saveDPLL_A;
+	u32 *fp_val = &dev_priv->saveFPA0;
+	u32 *pipeconf_val = &dev_priv->savePIPEACONF;
+	u32 *htot_val = &dev_priv->saveHTOTAL_A;
+	u32 *hblank_val = &dev_priv->saveHBLANK_A;
+	u32 *hsync_val = &dev_priv->saveHSYNC_A;
+	u32 *vtot_val = &dev_priv->saveVTOTAL_A;
+	u32 *vblank_val = &dev_priv->saveVBLANK_A;
+	u32 *vsync_val = &dev_priv->saveVSYNC_A;
+	u32 *pipesrc_val = &dev_priv->savePIPEASRC;
+	u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
+	u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
+	u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
+	u32 *dspsize_val = &dev_priv->saveDSPASIZE;
+	u32 *dsppos_val = &dev_priv->saveDSPAPOS;
+	u32 *dspsurf_val = &dev_priv->saveDSPASURF;
+	u32 *mipi_val = &dev_priv->saveMIPI;
+	u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
+	u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
+	u32 *palette_val = dev_priv->save_palette_a;
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		/* register */
+		dpll_reg = MDFLD_DPLL_B;
+		fp_reg = MDFLD_DPLL_DIV0;
+		pipeconf_reg = PIPEBCONF;
+		htot_reg = HTOTAL_B;
+		hblank_reg = HBLANK_B;
+		hsync_reg = HSYNC_B;
+		vtot_reg = VTOTAL_B;
+		vblank_reg = VBLANK_B;
+		vsync_reg = VSYNC_B;
+		pipesrc_reg = PIPEBSRC;
+		dspstride_reg = DSPBSTRIDE;
+		dsplinoff_reg = DSPBLINOFF;
+		dsptileoff_reg = DSPBTILEOFF;
+		dspsize_reg = DSPBSIZE;
+		dsppos_reg = DSPBPOS;
+		dspsurf_reg = DSPBSURF;
+		dspcntr_reg = DSPBCNTR;
+		dspstatus_reg = PIPEBSTAT;
+		palette_reg = PALETTE_B;
+
+		/* values */
+		dpll_val = &dev_priv->saveDPLL_B;
+		fp_val = &dev_priv->saveFPB0;
+		pipeconf_val = &dev_priv->savePIPEBCONF;
+		htot_val = &dev_priv->saveHTOTAL_B;
+		hblank_val = &dev_priv->saveHBLANK_B;
+		hsync_val = &dev_priv->saveHSYNC_B;
+		vtot_val = &dev_priv->saveVTOTAL_B;
+		vblank_val = &dev_priv->saveVBLANK_B;
+		vsync_val = &dev_priv->saveVSYNC_B;
+		pipesrc_val = &dev_priv->savePIPEBSRC;
+		dspstride_val = &dev_priv->saveDSPBSTRIDE;
+		dsplinoff_val = &dev_priv->saveDSPBLINOFF;
+		dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
+		dspsize_val = &dev_priv->saveDSPBSIZE;
+		dsppos_val = &dev_priv->saveDSPBPOS;
+		dspsurf_val = &dev_priv->saveDSPBSURF;
+		dspcntr_val = &dev_priv->saveDSPBCNTR;
+		dspstatus_val = &dev_priv->saveDSPBSTATUS;
+		palette_val = dev_priv->save_palette_b;
+		break;
+	case 2:
+		/* register */
+		pipeconf_reg = PIPECCONF;
+		htot_reg = HTOTAL_C;
+		hblank_reg = HBLANK_C;
+		hsync_reg = HSYNC_C;
+		vtot_reg = VTOTAL_C;
+		vblank_reg = VBLANK_C;
+		vsync_reg = VSYNC_C;
+		pipesrc_reg = PIPECSRC;
+		dspstride_reg = DSPCSTRIDE;
+		dsplinoff_reg = DSPCLINOFF;
+		dsptileoff_reg = DSPCTILEOFF;
+		dspsize_reg = DSPCSIZE;
+		dsppos_reg = DSPCPOS;
+		dspsurf_reg = DSPCSURF;
+		mipi_reg = MIPI_C;
+		dspcntr_reg = DSPCCNTR;
+		dspstatus_reg = PIPECSTAT;
+		palette_reg = PALETTE_C;
+
+		/* pointer to values */
+		pipeconf_val = &dev_priv->savePIPECCONF;
+		htot_val = &dev_priv->saveHTOTAL_C;
+		hblank_val = &dev_priv->saveHBLANK_C;
+		hsync_val = &dev_priv->saveHSYNC_C;
+		vtot_val = &dev_priv->saveVTOTAL_C;
+		vblank_val = &dev_priv->saveVBLANK_C;
+		vsync_val = &dev_priv->saveVSYNC_C;
+		pipesrc_val = &dev_priv->savePIPECSRC;
+		dspstride_val = &dev_priv->saveDSPCSTRIDE;
+		dsplinoff_val = &dev_priv->saveDSPCLINOFF;
+		dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
+		dspsize_val = &dev_priv->saveDSPCSIZE;
+		dsppos_val = &dev_priv->saveDSPCPOS;
+		dspsurf_val = &dev_priv->saveDSPCSURF;
+		mipi_val = &dev_priv->saveMIPI_C;
+		dspcntr_val = &dev_priv->saveDSPCCNTR;
+		dspstatus_val = &dev_priv->saveDSPCSTATUS;
+		palette_val = dev_priv->save_palette_c;
+		break;
+	default:
+		DRM_ERROR("%s, invalid pipe number.\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Pipe & plane A info */
+	*dpll_val = PSB_RVDC32(dpll_reg);
+	*fp_val = PSB_RVDC32(fp_reg);
+	*pipeconf_val = PSB_RVDC32(pipeconf_reg);
+	*htot_val = PSB_RVDC32(htot_reg);
+	*hblank_val = PSB_RVDC32(hblank_reg);
+	*hsync_val = PSB_RVDC32(hsync_reg);
+	*vtot_val = PSB_RVDC32(vtot_reg);
+	*vblank_val = PSB_RVDC32(vblank_reg);
+	*vsync_val = PSB_RVDC32(vsync_reg);
+	*pipesrc_val = PSB_RVDC32(pipesrc_reg);
+	*dspstride_val = PSB_RVDC32(dspstride_reg);
+	*dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
+	*dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
+	*dspsize_val = PSB_RVDC32(dspsize_reg);
+	*dsppos_val = PSB_RVDC32(dsppos_reg);
+	*dspsurf_val = PSB_RVDC32(dspsurf_reg);
+	*dspcntr_val = PSB_RVDC32(dspcntr_reg);
+	*dspstatus_val = PSB_RVDC32(dspstatus_reg);
+
+	/*save palette (gamma) */
+	for (i = 0; i < 256; i++)
+		palette_val[i] = PSB_RVDC32(palette_reg + (i<<2));
+
+	if (pipe == 1) {
+		dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
+		dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
+		dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
+		dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
+		return 0;
+	}
+	*mipi_val = PSB_RVDC32(mipi_reg);
+	return 0;
+}
+
+/**
+ * mdfld_save_cursor_overlay_registers	-	save cursor overlay info
+ * @dev: our device
+ *
+ * Save the cursor and overlay register state
+ */
+static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/* Save cursor regs */
+	dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
+	dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
+	dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
+
+	dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
+	dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
+	dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
+
+	dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
+	dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
+	dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
+
+	/* HW overlay */
+	dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
+	dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+	dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+	dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+	dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+	dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+	dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+
+	dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
+
+	return 0;
+}
+/*
+ * mdfld_restore_display_registers	-	restore the state of a pipe
+ * @dev: our device
+ * @pipe: the pipe to restore
+ *
+ * Restore the state of a pipe to that which was saved by the register save
+ * functions.
+ */
+static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
+{
+	/* To get  panel out of ULPS mode */
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_config *dsi_config = NULL;
+	u32 i = 0;
+	u32 dpll = 0;
+	u32 timeout = 0;
+	u32 reg_offset = 0;
+
+	/* register */
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 fp_reg = MRST_FPA0;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 htot_reg = HTOTAL_A;
+	u32 hblank_reg = HBLANK_A;
+	u32 hsync_reg = HSYNC_A;
+	u32 vtot_reg = VTOTAL_A;
+	u32 vblank_reg = VBLANK_A;
+	u32 vsync_reg = VSYNC_A;
+	u32 pipesrc_reg = PIPEASRC;
+	u32 dspstride_reg = DSPASTRIDE;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dsptileoff_reg = DSPATILEOFF;
+	u32 dspsize_reg = DSPASIZE;
+	u32 dsppos_reg = DSPAPOS;
+	u32 dspsurf_reg = DSPASURF;
+	u32 dspstatus_reg = PIPEASTAT;
+	u32 mipi_reg = MIPI;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 palette_reg = PALETTE_A;
+
+	/* values */
+	u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
+	u32 fp_val = dev_priv->saveFPA0;
+	u32 pipeconf_val = dev_priv->savePIPEACONF;
+	u32 htot_val = dev_priv->saveHTOTAL_A;
+	u32 hblank_val = dev_priv->saveHBLANK_A;
+	u32 hsync_val = dev_priv->saveHSYNC_A;
+	u32 vtot_val = dev_priv->saveVTOTAL_A;
+	u32 vblank_val = dev_priv->saveVBLANK_A;
+	u32 vsync_val = dev_priv->saveVSYNC_A;
+	u32 pipesrc_val = dev_priv->savePIPEASRC;
+	u32 dspstride_val = dev_priv->saveDSPASTRIDE;
+	u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
+	u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
+	u32 dspsize_val = dev_priv->saveDSPASIZE;
+	u32 dsppos_val = dev_priv->saveDSPAPOS;
+	u32 dspsurf_val = dev_priv->saveDSPASURF;
+	u32 dspstatus_val = dev_priv->saveDSPASTATUS;
+	u32 mipi_val = dev_priv->saveMIPI;
+	u32 dspcntr_val = dev_priv->saveDSPACNTR;
+	u32 *palette_val = dev_priv->save_palette_a;
+
+	switch (pipe) {
+	case 0:
+		dsi_config = dev_priv->dsi_configs[0];
+		break;
+	case 1:
+		/* register */
+		dpll_reg = MDFLD_DPLL_B;
+		fp_reg = MDFLD_DPLL_DIV0;
+		pipeconf_reg = PIPEBCONF;
+		htot_reg = HTOTAL_B;
+		hblank_reg = HBLANK_B;
+		hsync_reg = HSYNC_B;
+		vtot_reg = VTOTAL_B;
+		vblank_reg = VBLANK_B;
+		vsync_reg = VSYNC_B;
+		pipesrc_reg = PIPEBSRC;
+		dspstride_reg = DSPBSTRIDE;
+		dsplinoff_reg = DSPBLINOFF;
+		dsptileoff_reg = DSPBTILEOFF;
+		dspsize_reg = DSPBSIZE;
+		dsppos_reg = DSPBPOS;
+		dspsurf_reg = DSPBSURF;
+		dspcntr_reg = DSPBCNTR;
+		palette_reg = PALETTE_B;
+		dspstatus_reg = PIPEBSTAT;
+
+		/* values */
+		dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
+		fp_val = dev_priv->saveFPB0;
+		pipeconf_val = dev_priv->savePIPEBCONF;
+		htot_val = dev_priv->saveHTOTAL_B;
+		hblank_val = dev_priv->saveHBLANK_B;
+		hsync_val = dev_priv->saveHSYNC_B;
+		vtot_val = dev_priv->saveVTOTAL_B;
+		vblank_val = dev_priv->saveVBLANK_B;
+		vsync_val = dev_priv->saveVSYNC_B;
+		pipesrc_val = dev_priv->savePIPEBSRC;
+		dspstride_val = dev_priv->saveDSPBSTRIDE;
+		dsplinoff_val = dev_priv->saveDSPBLINOFF;
+		dsptileoff_val = dev_priv->saveDSPBTILEOFF;
+		dspsize_val = dev_priv->saveDSPBSIZE;
+		dsppos_val = dev_priv->saveDSPBPOS;
+		dspsurf_val = dev_priv->saveDSPBSURF;
+		dspcntr_val = dev_priv->saveDSPBCNTR;
+		dspstatus_val = dev_priv->saveDSPBSTATUS;
+		palette_val = dev_priv->save_palette_b;
+		break;
+	case 2:
+		reg_offset = MIPIC_REG_OFFSET;
+
+		/* register */
+		pipeconf_reg = PIPECCONF;
+		htot_reg = HTOTAL_C;
+		hblank_reg = HBLANK_C;
+		hsync_reg = HSYNC_C;
+		vtot_reg = VTOTAL_C;
+		vblank_reg = VBLANK_C;
+		vsync_reg = VSYNC_C;
+		pipesrc_reg = PIPECSRC;
+		dspstride_reg = DSPCSTRIDE;
+		dsplinoff_reg = DSPCLINOFF;
+		dsptileoff_reg = DSPCTILEOFF;
+		dspsize_reg = DSPCSIZE;
+		dsppos_reg = DSPCPOS;
+		dspsurf_reg = DSPCSURF;
+		mipi_reg = MIPI_C;
+		dspcntr_reg = DSPCCNTR;
+		palette_reg = PALETTE_C;
+		dspstatus_reg = PIPECSTAT;
+
+		/* values */
+		pipeconf_val = dev_priv->savePIPECCONF;
+		htot_val = dev_priv->saveHTOTAL_C;
+		hblank_val = dev_priv->saveHBLANK_C;
+		hsync_val = dev_priv->saveHSYNC_C;
+		vtot_val = dev_priv->saveVTOTAL_C;
+		vblank_val = dev_priv->saveVBLANK_C;
+		vsync_val = dev_priv->saveVSYNC_C;
+		pipesrc_val = dev_priv->savePIPECSRC;
+		dspstride_val = dev_priv->saveDSPCSTRIDE;
+		dsplinoff_val = dev_priv->saveDSPCLINOFF;
+		dsptileoff_val = dev_priv->saveDSPCTILEOFF;
+		dspsize_val = dev_priv->saveDSPCSIZE;
+		dsppos_val = dev_priv->saveDSPCPOS;
+		dspsurf_val = dev_priv->saveDSPCSURF;
+		dspstatus_val = dev_priv->saveDSPCSTATUS;
+		mipi_val = dev_priv->saveMIPI_C;
+		dspcntr_val = dev_priv->saveDSPCCNTR;
+		palette_val = dev_priv->save_palette_c;
+
+		dsi_config = dev_priv->dsi_configs[1];
+		break;
+	default:
+		DRM_ERROR("%s, invalid pipe number.\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Make sure VGA plane is off. it initializes to on after reset!*/
+	PSB_WVDC32(0x80000000, VGACNTRL);
+	if (pipe == 1) {
+		PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
+		PSB_RVDC32(dpll_reg);
+
+		PSB_WVDC32(fp_val, fp_reg);
+	} else {
+		dpll = PSB_RVDC32(dpll_reg);
+
+		if (!(dpll & DPLL_VCO_ENABLE)) {
+
+			/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+			if (dpll & MDFLD_PWR_GATE_EN) {
+				dpll &= ~MDFLD_PWR_GATE_EN;
+				PSB_WVDC32(dpll, dpll_reg);
+				udelay(500);	/* FIXME: 1 ? */
+			}
+
+			PSB_WVDC32(fp_val, fp_reg);
+			PSB_WVDC32(dpll_val, dpll_reg);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+
+			dpll_val |= DPLL_VCO_ENABLE;
+			PSB_WVDC32(dpll_val, dpll_reg);
+			PSB_RVDC32(dpll_reg);
+
+			/* wait for DSI PLL to lock */
+			while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+				udelay(150);
+				timeout++;
+			}
+
+			if (timeout == 20000) {
+				DRM_ERROR("%s, can't lock DSIPLL.\n",
+							__func__);
+				return -EINVAL;
+			}
+		}
+	}
+	/* Restore mode */
+	PSB_WVDC32(htot_val, htot_reg);
+	PSB_WVDC32(hblank_val, hblank_reg);
+	PSB_WVDC32(hsync_val, hsync_reg);
+	PSB_WVDC32(vtot_val, vtot_reg);
+	PSB_WVDC32(vblank_val, vblank_reg);
+	PSB_WVDC32(vsync_val, vsync_reg);
+	PSB_WVDC32(pipesrc_val, pipesrc_reg);
+	PSB_WVDC32(dspstatus_val, dspstatus_reg);
+
+	/* Set up the plane */
+	PSB_WVDC32(dspstride_val, dspstride_reg);
+	PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
+	PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
+	PSB_WVDC32(dspsize_val, dspsize_reg);
+	PSB_WVDC32(dsppos_val, dsppos_reg);
+	PSB_WVDC32(dspsurf_val, dspsurf_reg);
+
+	if (pipe == 1) {
+		PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
+		PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
+		PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL);
+		PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL);
+
+	} else {
+		/* Set up pipe related registers */
+		PSB_WVDC32(mipi_val, mipi_reg);
+		/* Setup MIPI adapter + MIPI IP registers */
+		mdfld_dsi_controller_init(dsi_config, pipe);
+		msleep(20);
+	}
+	/* Enable the plane */
+	PSB_WVDC32(dspcntr_val, dspcntr_reg);
+	msleep(20);
+	/* Enable the pipe */
+	PSB_WVDC32(pipeconf_val, pipeconf_reg);
+
+	for (i = 0; i < 256; i++)
+		PSB_WVDC32(palette_val[i], palette_reg + (i<<2));
+	if (pipe == 1)
+		return 0;
+	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
+		mdfld_enable_te(dev, pipe);
+	return 0;
+}
+
+/**
+ * mdfld_restore_cursor_overlay_registers	-	restore cursor
+ * @dev: our device
+ *
+ * Restore the cursor and overlay state that was saved earlier
+ */
+static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/* Enable Cursor A */
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
+
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
+
+	PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
+	PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
+	PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
+
+	/* Restore HW overlay */
+	PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
+
+	PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
+
+	return 0;
+}
+
+/**
  *	power_down	-	power down the display island
  *	@dev: our DRM device
  *
@@ -186,6 +711,10 @@ static void power_down(struct drm_device *dev)
  *	@dev: our DRM device
  *
  *	Suspend the display logic of the graphics interface
+ *
+ *	FIXME: This ought to be replaced by a dev_priv-> ops interface
+ *	where the various platforms register their save/restore methods
+ *	and keep them in their own support files.
  */
 static void gma_suspend_display(struct drm_device *dev)
 {
@@ -195,38 +724,57 @@ static void gma_suspend_display(struct drm_device *dev)
 	if (dev_priv->suspended)
 		return;
 
-	save_display_registers(dev);
-
-	if (dev_priv->iLVDS_enable) {
-		/*shutdown the panel*/
-		PSB_WVDC32(0, PP_CONTROL);
-
-		do {
-			pp_stat = PSB_RVDC32(PP_STATUS);
-		} while (pp_stat & 0x80000000);
-
-		/*turn off the plane*/
-		PSB_WVDC32(0x58000000, DSPACNTR);
-		PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
-		/*wait ~4 ticks*/
-		msleep(4);
-
-		/*turn off pipe*/
-		PSB_WVDC32(0x0, PIPEACONF);
-		/*wait ~8 ticks*/
-		msleep(8);
-
-		/*turn off PLLs*/
-		PSB_WVDC32(0, MRST_DPLL_A);
+	if (IS_MFLD(dev)) {
+		/* FIXME: We need to shut down panels here if using them
+		   and once the right bits are merged */
+		mdfld_save_cursor_overlay_registers(dev);
+		mdfld_save_display_registers(dev, 0);
+		mdfld_save_display_registers(dev, 0);
+		mdfld_save_display_registers(dev, 2);
+		mdfld_save_display_registers(dev, 1);
+		mdfld_disable_crtc(dev, 0);
+		mdfld_disable_crtc(dev, 2);
+		mdfld_disable_crtc(dev, 1);
 	} else {
-		PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
-		PSB_WVDC32(0x0, PIPEACONF);
-		PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
-		while (REG_READ(0x70008) & 0x40000000);
-		while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
-			!= DPI_FIFO_EMPTY);
-		PSB_WVDC32(0, DEVICE_READY_REG);
-			/* turn off panel power */
+		save_display_registers(dev);
+
+		if (dev_priv->iLVDS_enable) {
+			/*shutdown the panel*/
+			PSB_WVDC32(0, PP_CONTROL);
+
+			do {
+				pp_stat = PSB_RVDC32(PP_STATUS);
+			} while (pp_stat & 0x80000000);
+
+			/* Turn off the plane */
+			PSB_WVDC32(0x58000000, DSPACNTR);
+			PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
+			/* Wait ~4 ticks */
+			msleep(4);
+
+			/* Turn off pipe */
+			PSB_WVDC32(0x0, PIPEACONF);
+			/* Wait ~8 ticks */
+			msleep(8);
+
+			/* Turn off PLLs */
+			PSB_WVDC32(0, MRST_DPLL_A);
+		} else {
+			PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
+			PSB_WVDC32(0x0, PIPEACONF);
+			PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
+			while (REG_READ(0x70008) & 0x40000000)
+				cpu_relax();
+			while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
+				!= DPI_FIFO_EMPTY)
+				cpu_relax();
+			PSB_WVDC32(0, DEVICE_READY_REG);
+			/* Turn off panel power */
+#ifdef CONFIG_X86_MRST
+			intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
+							IPC_CMD_PANEL_OFF);
+#endif
+		}
 	}
 	power_down(dev);
 }
@@ -286,7 +834,21 @@ static void gma_resume_display(struct pci_dev *pdev)
 	 * above.
 	 */
 	/*psb_gtt_init(dev_priv->pg, 1);*/
-
+	if (IS_MFLD(dev)) {
+		mdfld_restore_display_registers(dev, 1);
+		mdfld_restore_display_registers(dev, 0);
+		mdfld_restore_display_registers(dev, 2);
+		mdfld_restore_cursor_overlay_registers(dev);
+	} else if (IS_MRST(dev)) {
+		if (!dev_priv->iLVDS_enable) {
+#ifdef CONFIG_X86_MRST
+			intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
+							IPC_CMD_PANEL_ON);
+			/* FIXME: can we avoid this delay ? */
+			msleep(2000); /* wait 2 seconds */
+#endif
+		}
+	}
 	restore_display_registers(dev);
 }
 


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 15/49] gma500: Move our other GEM helper into the bits want to push into GEM
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (13 preceding siblings ...)
  2011-07-05 14:36 ` [PATCH 14/49] gma500: Medfield support Alan Cox
@ 2011-07-05 14:37 ` Alan Cox
  2011-07-05 14:37 ` [PATCH 16/49] gma500: Extract BIOSisy stuff from psb_drv Alan Cox
                   ` (34 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:37 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/gem_glue.c |   54 ++++++++++++++++++++++++++++++++++++
 drivers/staging/gma500/gem_glue.h |    2 +
 drivers/staging/gma500/psb_gem.c  |   56 +------------------------------------
 3 files changed, 56 insertions(+), 56 deletions(-)

diff --git a/drivers/staging/gma500/gem_glue.c b/drivers/staging/gma500/gem_glue.c
index 0817497..0e7364b 100644
--- a/drivers/staging/gma500/gem_glue.c
+++ b/drivers/staging/gma500/gem_glue.c
@@ -45,3 +45,57 @@ void drm_gem_object_release_wrap(struct drm_gem_object *obj)
 	if (obj->filp)
 		drm_gem_object_release(obj);
 }
+
+/**
+ *	gem_create_mmap_offset		-	invent an mmap offset
+ *	@obj: our object
+ *
+ *	Standard implementation of offset generation for mmap as is
+ *	duplicated in several drivers. This belongs in GEM.
+ */
+int gem_create_mmap_offset(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_gem_mm *mm = dev->mm_private;
+	struct drm_map_list *list;
+	struct drm_local_map *map;
+	int ret;
+
+	list = &obj->map_list;
+	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
+	if (list->map == NULL)
+		return -ENOMEM;
+	map = list->map;
+	map->type = _DRM_GEM;
+	map->size = obj->size;
+	map->handle = obj;
+
+	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
+					obj->size / PAGE_SIZE, 0, 0);
+	if (!list->file_offset_node) {
+		dev_err(dev->dev, "failed to allocate offset for bo %d\n",
+								obj->name);
+		ret = -ENOSPC;
+		goto free_it;
+	}
+	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
+					obj->size / PAGE_SIZE, 0);
+	if (!list->file_offset_node) {
+		ret = -ENOMEM;
+		goto free_it;
+	}
+	list->hash.key = list->file_offset_node->start;
+	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
+	if (ret) {
+		dev_err(dev->dev, "failed to add to map hash\n");
+		goto free_mm;
+	}
+	return 0;
+
+free_mm:
+	drm_mm_put_block(list->file_offset_node);
+free_it:
+	kfree(list->map);
+	list->map = NULL;
+	return ret;
+}
diff --git a/drivers/staging/gma500/gem_glue.h b/drivers/staging/gma500/gem_glue.h
index c38285b..a0f2bc4 100644
--- a/drivers/staging/gma500/gem_glue.h
+++ b/drivers/staging/gma500/gem_glue.h
@@ -1,4 +1,4 @@
 extern void drm_gem_object_release_wrap(struct drm_gem_object *obj);
 extern int drm_gem_private_object_init(struct drm_device *dev,
 			struct drm_gem_object *obj, size_t size);
-
+extern int gem_create_mmap_offset(struct drm_gem_object *obj);
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
index 3f658e4..1e7faae 100644
--- a/drivers/staging/gma500/psb_gem.c
+++ b/drivers/staging/gma500/psb_gem.c
@@ -61,60 +61,6 @@ int psb_gem_get_aperture(struct drm_device *dev, void *data,
 }
 
 /**
- *	psb_gem_create_mmap_offset	-	invent an mmap offset
- *	@obj: our object
- *
- *	This is basically doing by hand a pile of ugly crap which should
- *	be done automatically by the GEM library code but isn't
- */
-static int psb_gem_create_mmap_offset(struct drm_gem_object *obj)
-{
-	struct drm_device *dev = obj->dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list;
-	struct drm_local_map *map;
-	int ret;
-
-	list = &obj->map_list;
-	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
-	if (list->map == NULL)
-		return -ENOMEM;
-	map = list->map;
-	map->type = _DRM_GEM;
-	map->size = obj->size;
-	map->handle = obj;
-
-	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
-					obj->size / PAGE_SIZE, 0, 0);
-	if (!list->file_offset_node) {
-		dev_err(dev->dev, "failed to allocate offset for bo %d\n",
-								obj->name);
-		ret = -ENOSPC;
-		goto free_it;
-	}
-	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
-					obj->size / PAGE_SIZE, 0);
-	if (!list->file_offset_node) {
-		ret = -ENOMEM;
-		goto free_it;
-	}
-	list->hash.key = list->file_offset_node->start;
-	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
-	if (ret) {
-		dev_err(dev->dev, "failed to add to map hash\n");
-		goto free_mm;
-	}
-	return 0;
-
-free_mm:
-	drm_mm_put_block(list->file_offset_node);
-free_it:
-	kfree(list->map);
-	list->map = NULL;
-	return ret;
-}
-
-/**
  *	psb_gem_dumb_map_gtt	-	buffer mapping for dumb interface
  *	@file: our drm client file
  *	@dev: drm device
@@ -144,7 +90,7 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
 
 	/* Make it mmapable */
 	if (!obj->map_list.map) {
-		ret = psb_gem_create_mmap_offset(obj);
+		ret = gem_create_mmap_offset(obj);
 		if (ret)
 			goto out;
 	}


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 16/49] gma500: Extract BIOSisy stuff from psb_drv
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (14 preceding siblings ...)
  2011-07-05 14:37 ` [PATCH 15/49] gma500: Move our other GEM helper into the bits want to push into GEM Alan Cox
@ 2011-07-05 14:37 ` Alan Cox
  2011-07-05 14:37 ` [PATCH 17/49] gma500: psb_fb tidy/cleanup pass Alan Cox
                   ` (33 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:37 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

This is too big already so lets rip out more of the device specific crud. It
also means we pull the ugly stuff that needs work out of our main line of
cleanup.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile    |    1 
 drivers/staging/gma500/mrst_bios.c |  236 ++++++++++++++++++++++++++++++++++++
 drivers/staging/gma500/mrst_bios.h |   22 +++
 drivers/staging/gma500/psb_drv.c   |  209 --------------------------------
 4 files changed, 260 insertions(+), 208 deletions(-)
 create mode 100644 drivers/staging/gma500/mrst_bios.c
 create mode 100644 drivers/staging/gma500/mrst_bios.h

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index 4c9c475..fdaac63 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -23,6 +23,7 @@ psb_gfx-y += gem_glue.o \
 	  psb_irq.o \
 	  mrst_crtc.o \
 	  mrst_lvds.o \
+	  mrst_bios.o \
 	  mdfld_output.o \
 	  mdfld_pyr_cmd.o \
 	  mdfld_tmd_vid.o \
diff --git a/drivers/staging/gma500/mrst_bios.c b/drivers/staging/gma500/mrst_bios.c
new file mode 100644
index 0000000..0d944c4
--- /dev/null
+++ b/drivers/staging/gma500/mrst_bios.c
@@ -0,0 +1,236 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+/* TODO
+ * - Split functions by vbt type
+ * - Make them all take drm_device
+ * - Check ioremap failures
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "mrst_bios.h"
+
+void mrst_get_fuse_settings(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	uint32_t fuse_value = 0;
+	uint32_t fuse_value_tmp = 0;
+
+#define FB_REG06 0xD0810600
+#define FB_MIPI_DISABLE  (1 << 11)
+#define FB_REG09 0xD0810900
+#define FB_REG09 0xD0810900
+#define FB_SKU_MASK  0x7000
+#define FB_SKU_SHIFT 12
+#define FB_SKU_100 0
+#define FB_SKU_100L 1
+#define FB_SKU_83 2
+	pci_write_config_dword(pci_root, 0xD0, FB_REG06);
+	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
+
+	/* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
+	if (IS_MRST(dev))
+		dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
+
+	DRM_INFO("internal display is %s\n",
+		 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
+
+	 /* Prevent runtime suspend at start*/
+	 if (dev_priv->iLVDS_enable) {
+		dev_priv->is_lvds_on = true;
+		dev_priv->is_mipi_on = false;
+	} else {
+		dev_priv->is_mipi_on = true;
+		dev_priv->is_lvds_on = false;
+	}
+
+	dev_priv->video_device_fuse = fuse_value;
+
+	pci_write_config_dword(pci_root, 0xD0, FB_REG09);
+	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
+
+	dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value);
+	fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
+
+	dev_priv->fuse_reg_value = fuse_value;
+
+	switch (fuse_value_tmp) {
+	case FB_SKU_100:
+		dev_priv->core_freq = 200;
+		break;
+	case FB_SKU_100L:
+		dev_priv->core_freq = 100;
+		break;
+	case FB_SKU_83:
+		dev_priv->core_freq = 166;
+		break;
+	default:
+		dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n",
+								fuse_value_tmp);
+		dev_priv->core_freq = 0;
+	}
+	dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq);
+	pci_dev_put(pci_root);
+}
+
+/*
+ *	Get the revison ID, B0:D2:F0;0x08
+ */
+void mid_get_pci_revID(struct drm_psb_private *dev_priv)
+{
+	uint32_t platform_rev_id = 0;
+	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+	pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
+	dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
+	pci_dev_put(pci_gfx_root);
+	dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n",
+					dev_priv->platform_rev_id);
+}
+
+void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct mrst_vbt *vbt = &dev_priv->vbt_data;
+	u32 addr;
+	u16 new_size;
+	u8 *vbt_virtual;
+	u8 bpi;
+	u8 number_desc = 0;
+	struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
+	struct gct_r10_timing_info ti;
+	void *pGCT;
+	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+	/* Get the address of the platform config vbt, B0:D2:F0;0xFC */
+	pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
+	pci_dev_put(pci_gfx_root);
+
+	dev_dbg(dev->dev, "drm platform config address is %x\n", addr);
+
+	/* check for platform config address == 0. */
+	/* this means fw doesn't support vbt */
+
+	if (addr == 0) {
+		vbt->size = 0;
+		return;
+	}
+
+	/* get the virtual address of the vbt */
+	vbt_virtual = ioremap(addr, sizeof(*vbt));
+
+	memcpy(vbt, vbt_virtual, sizeof(*vbt));
+	iounmap(vbt_virtual); /* Free virtual address space */
+
+	dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision);
+
+	switch (vbt->revision) {
+	case 0:
+		vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
+					vbt->size - sizeof(*vbt) + 4);
+		pGCT = vbt->mrst_gct;
+		bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
+		dev_priv->gct_data.bpi = bpi;
+		dev_priv->gct_data.pt =
+			((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
+		memcpy(&dev_priv->gct_data.DTD,
+			&((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
+				sizeof(struct mrst_timing_info));
+		dev_priv->gct_data.Panel_Port_Control =
+		  ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+			((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+		break;
+	case 1:
+		vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
+					vbt->size - sizeof(*vbt) + 4);
+		pGCT = vbt->mrst_gct;
+		bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
+		dev_priv->gct_data.bpi = bpi;
+		dev_priv->gct_data.pt =
+			((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
+		memcpy(&dev_priv->gct_data.DTD,
+			&((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
+				sizeof(struct mrst_timing_info));
+		dev_priv->gct_data.Panel_Port_Control =
+		  ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+			((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+		break;
+	case 0x10:
+		/*header definition changed from rev 01 (v2) to rev 10h. */
+		/*so, some values have changed location*/
+		new_size = vbt->checksum; /*checksum contains lo size byte*/
+		/*LSB of mrst_gct contains hi size byte*/
+		new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8;
+
+		vbt->checksum = vbt->size; /*size contains the checksum*/
+		if (new_size > 0xff)
+			vbt->size = 0xff; /*restrict size to 255*/
+		else
+			vbt->size = new_size;
+
+		/* number of descriptors defined in the GCT */
+		number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8;
+		bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16;
+		vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE,
+				GCT_R10_DISPLAY_DESC_SIZE * number_desc);
+		pGCT = vbt->mrst_gct;
+		pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE);
+		dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
+
+		/*copy the GCT display timings into a temp structure*/
+		memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
+
+		/*now copy the temp struct into the dev_priv->gct_data*/
+		dp_ti->pixel_clock = ti.pixel_clock;
+		dp_ti->hactive_hi = ti.hactive_hi;
+		dp_ti->hactive_lo = ti.hactive_lo;
+		dp_ti->hblank_hi = ti.hblank_hi;
+		dp_ti->hblank_lo = ti.hblank_lo;
+		dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
+		dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
+		dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
+		dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
+		dp_ti->vactive_hi = ti.vactive_hi;
+		dp_ti->vactive_lo = ti.vactive_lo;
+		dp_ti->vblank_hi = ti.vblank_hi;
+		dp_ti->vblank_lo = ti.vblank_lo;
+		dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
+		dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
+		dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
+		dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
+
+		/* Move the MIPI_Display_Descriptor data from GCT to dev priv */
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+							*((u8 *)pGCT + 0x0d);
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
+						(*((u8 *)pGCT + 0x0e)) << 8;
+		break;
+	default:
+		dev_err(dev->dev, "Unknown revision of GCT!\n");
+		vbt->size = 0;
+	}
+	/* FIXME: Need to sort out Medfield panel identifiers in future */
+}
+
diff --git a/drivers/staging/gma500/mrst_bios.h b/drivers/staging/gma500/mrst_bios.h
new file mode 100644
index 0000000..a257306
--- /dev/null
+++ b/drivers/staging/gma500/mrst_bios.h
@@ -0,0 +1,22 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+extern void mrst_get_fuse_settings(struct drm_device *dev);
+extern void mid_get_pci_revID(struct drm_psb_private *dev_priv);
+extern void mrst_get_vbt_data(struct drm_psb_private *dev_priv);
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 8df9c58..cbdc02c 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -27,6 +27,7 @@
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
 #include "psb_intel_bios.h"
+#include "mrst_bios.h"
 #include <drm/drm_pciids.h>
 #include "psb_powermgmt.h"
 #include <linux/cpu.h>
@@ -165,214 +166,6 @@ static void psb_do_takedown(struct drm_device *dev)
 	/* FIXME: do we need to clean up the gtt here ? */
 }
 
-void mrst_get_fuse_settings(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-	uint32_t fuse_value = 0;
-	uint32_t fuse_value_tmp = 0;
-
-#define FB_REG06 0xD0810600
-#define FB_MIPI_DISABLE  (1 << 11)
-#define FB_REG09 0xD0810900
-#define FB_REG09 0xD0810900
-#define FB_SKU_MASK  0x7000
-#define FB_SKU_SHIFT 12
-#define FB_SKU_100 0
-#define FB_SKU_100L 1
-#define FB_SKU_83 2
-	pci_write_config_dword(pci_root, 0xD0, FB_REG06);
-	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
-
-	/* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
-	if (IS_MRST(dev))
-		dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
-
-	DRM_INFO("internal display is %s\n",
-		 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
-
-	 /*prevent Runtime suspend at start*/
-	 if (dev_priv->iLVDS_enable) {
-		dev_priv->is_lvds_on = true;
-		dev_priv->is_mipi_on = false;
-	} else {
-		dev_priv->is_mipi_on = true;
-		dev_priv->is_lvds_on = false;
-	}
-
-	dev_priv->video_device_fuse = fuse_value;
-
-	pci_write_config_dword(pci_root, 0xD0, FB_REG09);
-	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
-
-	DRM_INFO("SKU values is 0x%x.\n", fuse_value);
-	fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
-
-	dev_priv->fuse_reg_value = fuse_value;
-
-	switch (fuse_value_tmp) {
-	case FB_SKU_100:
-		dev_priv->core_freq = 200;
-		break;
-	case FB_SKU_100L:
-		dev_priv->core_freq = 100;
-		break;
-	case FB_SKU_83:
-		dev_priv->core_freq = 166;
-		break;
-	default:
-		dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n",
-								fuse_value_tmp);
-		dev_priv->core_freq = 0;
-	}
-	DRM_INFO("LNC core clk is %dMHz.\n", dev_priv->core_freq);
-	pci_dev_put(pci_root);
-}
-
-void mid_get_pci_revID(struct drm_psb_private *dev_priv)
-{
-	uint32_t platform_rev_id = 0;
-	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
-
-	/*get the revison ID, B0:D2:F0;0x08 */
-	pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
-	dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
-	pci_dev_put(pci_gfx_root);
-	dev_info(dev_priv->dev->dev, "platform_rev_id is %x\n",
-					dev_priv->platform_rev_id);
-}
-
-void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
-{
-	struct mrst_vbt *vbt = &dev_priv->vbt_data;
-	u32 platform_config_address;
-	u16 new_size;
-	u8 *vbt_virtual;
-	u8 bpi;
-	u8 number_desc = 0;
-	struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
-	struct gct_r10_timing_info ti;
-	void *pGCT;
-	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
-
-	/*get the address of the platform config vbt, B0:D2:F0;0xFC */
-	pci_read_config_dword(pci_gfx_root, 0xFC, &platform_config_address);
-	pci_dev_put(pci_gfx_root);
-	DRM_INFO("drm platform config address is %x\n",
-			platform_config_address);
-
-	/* check for platform config address == 0. */
-	/* this means fw doesn't support vbt */
-
-	if (platform_config_address == 0) {
-		vbt->size = 0;
-		return;
-	}
-
-	/* get the virtual address of the vbt */
-	vbt_virtual = ioremap(platform_config_address, sizeof(*vbt));
-
-	memcpy(vbt, vbt_virtual, sizeof(*vbt));
-	iounmap(vbt_virtual); /* Free virtual address space */
-
-	printk(KERN_ALERT "GCT revision is %x\n", vbt->revision);
-
-	switch (vbt->revision) {
-	case 0:
-		vbt->mrst_gct = NULL;
-		vbt->mrst_gct = \
-			ioremap(platform_config_address + sizeof(*vbt) - 4,
-					vbt->size - sizeof(*vbt) + 4);
-		pGCT = vbt->mrst_gct;
-		bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
-		dev_priv->gct_data.bpi = bpi;
-		dev_priv->gct_data.pt =
-			((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
-		memcpy(&dev_priv->gct_data.DTD,
-			&((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
-				sizeof(struct mrst_timing_info));
-		dev_priv->gct_data.Panel_Port_Control =
-		  ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-			((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
-		break;
-	case 1:
-		vbt->mrst_gct = NULL;
-		vbt->mrst_gct = \
-			ioremap(platform_config_address + sizeof(*vbt) - 4,
-					vbt->size - sizeof(*vbt) + 4);
-		pGCT = vbt->mrst_gct;
-		bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
-		dev_priv->gct_data.bpi = bpi;
-		dev_priv->gct_data.pt =
-			((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
-		memcpy(&dev_priv->gct_data.DTD,
-			&((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
-				sizeof(struct mrst_timing_info));
-		dev_priv->gct_data.Panel_Port_Control =
-		  ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-			((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
-		break;
-	case 0x10:
-		/*header definition changed from rev 01 (v2) to rev 10h. */
-		/*so, some values have changed location*/
-		new_size = vbt->checksum; /*checksum contains lo size byte*/
-		/*LSB of mrst_gct contains hi size byte*/
-		new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8;
-
-		vbt->checksum = vbt->size; /*size contains the checksum*/
-		if (new_size > 0xff)
-			vbt->size = 0xff; /*restrict size to 255*/
-		else
-			vbt->size = new_size;
-
-		/* number of descriptors defined in the GCT */
-		number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8;
-		bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16;
-		vbt->mrst_gct = NULL;
-		vbt->mrst_gct = \
-			ioremap(platform_config_address + GCT_R10_HEADER_SIZE,
-				GCT_R10_DISPLAY_DESC_SIZE * number_desc);
-		pGCT = vbt->mrst_gct;
-		pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE);
-		dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
-
-		/*copy the GCT display timings into a temp structure*/
-		memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
-
-		/*now copy the temp struct into the dev_priv->gct_data*/
-		dp_ti->pixel_clock = ti.pixel_clock;
-		dp_ti->hactive_hi = ti.hactive_hi;
-		dp_ti->hactive_lo = ti.hactive_lo;
-		dp_ti->hblank_hi = ti.hblank_hi;
-		dp_ti->hblank_lo = ti.hblank_lo;
-		dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
-		dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
-		dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
-		dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
-		dp_ti->vactive_hi = ti.vactive_hi;
-		dp_ti->vactive_lo = ti.vactive_lo;
-		dp_ti->vblank_hi = ti.vblank_hi;
-		dp_ti->vblank_lo = ti.vblank_lo;
-		dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
-		dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
-		dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
-		dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
-
-		/*mov the MIPI_Display_Descriptor data from GCT to dev priv*/
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-							*((u8 *)pGCT + 0x0d);
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
-						(*((u8 *)pGCT + 0x0e)) << 8;
-		break;
-	default:
-		printk(KERN_ERR "Unknown revision of GCT!\n");
-		vbt->size = 0;
-	}
-	/* FIXME: Need to sort out Medfield panel identifiers in future */
-}
-
 static void psb_get_core_freq(struct drm_device *dev)
 {
 	uint32_t clock;


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 17/49] gma500: psb_fb tidy/cleanup pass
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (15 preceding siblings ...)
  2011-07-05 14:37 ` [PATCH 16/49] gma500: Extract BIOSisy stuff from psb_drv Alan Cox
@ 2011-07-05 14:37 ` Alan Cox
  2011-07-05 14:37 ` [PATCH 18/49] gma500: Update the GEM todo Alan Cox
                   ` (32 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:37 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Eliminate unused stuff and clean up the code ordering.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_drm.h |    4 -
 drivers/staging/gma500/psb_drv.c |    9 ---
 drivers/staging/gma500/psb_drv.h |    6 --
 drivers/staging/gma500/psb_fb.c  |  135 ++++++++------------------------------
 4 files changed, 29 insertions(+), 125 deletions(-)

diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
index c541137..5dcf045 100644
--- a/drivers/staging/gma500/psb_drm.h
+++ b/drivers/staging/gma500/psb_drm.h
@@ -145,8 +145,6 @@ struct drm_psb_register_rw_arg {
 
 /* Controlling the kernel modesetting buffers */
 
-#define DRM_PSB_KMS_OFF		0x00
-#define DRM_PSB_KMS_ON		0x01
 #define DRM_PSB_SIZES           0x07
 #define DRM_PSB_FUSE_REG	0x08
 #define DRM_PSB_DC_STATE	0x0A
@@ -155,7 +153,7 @@ struct drm_psb_register_rw_arg {
 #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
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index cbdc02c..0d65f75 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -75,10 +75,6 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
  * Standard IOCTLs.
  */
 
-#define DRM_IOCTL_PSB_KMS_OFF	\
-		DRM_IO(DRM_PSB_KMS_OFF + DRM_COMMAND_BASE)
-#define DRM_IOCTL_PSB_KMS_ON	\
-		DRM_IO(DRM_PSB_KMS_ON + DRM_COMMAND_BASE)
 #define DRM_IOCTL_PSB_SIZES	\
 		DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
 			struct drm_psb_sizes_arg)
@@ -134,11 +130,6 @@ static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
 	[DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
 
 static struct drm_ioctl_desc psb_ioctls[] = {
-	PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_OFF, psbfb_kms_off_ioctl,
-		      DRM_ROOT_ONLY),
-	PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_ON,
-			psbfb_kms_on_ioctl,
-			DRM_ROOT_ONLY),
 	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),
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 86abf26..3b2ee08 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -704,12 +704,6 @@ extern int psb_intel_opregion_init(struct drm_device *dev);
 extern int psbfb_probed(struct drm_device *dev);
 extern int psbfb_remove(struct drm_device *dev,
 			struct drm_framebuffer *fb);
-extern int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
-			       struct drm_file *file_priv);
-extern int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
-			      struct drm_file *file_priv);
-extern void *psbfb_vdc_reg(struct drm_device* dev);
-
 /*
  * psb_2d.c
  */
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 8377a99..83095fc 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -52,13 +52,6 @@ static const struct drm_framebuffer_funcs psb_fb_funcs = {
 
 #define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
 
-void *psbfb_vdc_reg(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv;
-	dev_priv = (struct drm_psb_private *) dev->dev_private;
-	return dev_priv->vdc_reg;
-}
-
 static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 			   unsigned blue, unsigned transp,
 			   struct fb_info *info)
@@ -98,108 +91,60 @@ static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 	return 0;
 }
 
-static int psbfb_kms_off(struct drm_device *dev, int suspend)
+
+void psbfb_suspend(struct drm_device *dev)
 {
 	struct drm_framebuffer *fb = 0;
 	struct psb_framebuffer *psbfb = to_psb_fb(fb);
 
+	console_lock();
 	mutex_lock(&dev->mode_config.mutex);
 	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
 		struct fb_info *info = psbfb->fbdev;
-
-		if (suspend) {
-			fb_set_suspend(info, 1);
-			drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
-		}
+		fb_set_suspend(info, 1);
+		drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
 	}
 	mutex_unlock(&dev->mode_config.mutex);
-	return 0;
-}
-
-int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file_priv)
-{
-	int ret;
-
-	if (drm_psb_no_fb)
-		return 0;
-	console_lock();
-	ret = psbfb_kms_off(dev, 0);
 	console_unlock();
-
-	return ret;
 }
 
-static int psbfb_kms_on(struct drm_device *dev, int resume)
+void psbfb_resume(struct drm_device *dev)
 {
 	struct drm_framebuffer *fb = 0;
 	struct psb_framebuffer *psbfb = to_psb_fb(fb);
 
+	console_lock();
 	mutex_lock(&dev->mode_config.mutex);
 	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
 		struct fb_info *info = psbfb->fbdev;
-
-		if (resume) {
-			fb_set_suspend(info, 0);
-			drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
-		}
+		fb_set_suspend(info, 0);
+		drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
 	}
 	mutex_unlock(&dev->mode_config.mutex);
-
-	return 0;
-}
-
-int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
-{
-	int ret;
-
-	if (drm_psb_no_fb)
-		return 0;
-	console_lock();
-	ret = psbfb_kms_on(dev, 0);
-	console_unlock();
-	drm_helper_disable_unused_functions(dev);
-	return ret;
-}
-
-void psbfb_suspend(struct drm_device *dev)
-{
-	console_lock();
-	psbfb_kms_off(dev, 1);
-	console_unlock();
-}
-
-void psbfb_resume(struct drm_device *dev)
-{
-	console_lock();
-	psbfb_kms_on(dev, 1);
 	console_unlock();
 	drm_helper_disable_unused_functions(dev);
 }
 
 static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
-	int page_num = 0;
-	int i;
-	unsigned long address = 0;
-	int ret;
-	unsigned long pfn;
 	struct psb_framebuffer *psbfb = vma->vm_private_data;
 	struct drm_device *dev = psbfb->base.dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
-
+	int page_num;
+	int i;
+	unsigned long address;
+	int ret;
+	unsigned long pfn;
 	/* FIXME: assumes fb at stolen base which may not be true */
 	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
 
 	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-
 	address = (unsigned long)vmf->virtual_address;
 
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
 	for (i = 0; i < page_num; i++) {
-		pfn = (phys_addr >> PAGE_SHIFT); /* phys_to_pfn(phys_addr); */
+		pfn = (phys_addr >> PAGE_SHIFT);
 
 		ret = vm_insert_mixed(vma, address, pfn);
 		if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
@@ -208,11 +153,9 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 			ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
 			return ret;
 		}
-
 		address += PAGE_SIZE;
 		phys_addr += PAGE_SIZE;
 	}
-
 	return VM_FAULT_NOPAGE;
 }
 
@@ -234,7 +177,6 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
 	struct psb_fbdev *fbdev = info->par;
 	struct psb_framebuffer *psbfb = &fbdev->pfb;
-	char *fb_screen_base = NULL;
 
 	if (vma->vm_pgoff != 0)
 		return -EINVAL;
@@ -243,9 +185,6 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 
 	if (!psbfb->addr_space)
 		psbfb->addr_space = vma->vm_file->f_mapping;
-
-	fb_screen_base = (char *)info->screen_base;
-
 	/*
 	 * If this is a GEM object then info->screen_base is the virtual
 	 * kernel remapping of the object. FIXME: Review if this is
@@ -272,8 +211,8 @@ static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
 	case 0x12345678:
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
-	        if (IS_MFLD(dev))
-                        return -EOPNOTSUPP;
+		if (IS_MFLD(dev))
+			return -EOPNOTSUPP;
 		if (get_user(l, p))
 			return -EFAULT;
 		if (l > 32)
@@ -488,9 +427,9 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	info->flags = FBINFO_DEFAULT;
 	/* No 2D engine */
 	if (IS_MFLD(dev))
-	        info->fbops = &psbfb_mfld_ops;
-        else
-        	info->fbops = &psbfb_ops;
+		info->fbops = &psbfb_mfld_ops;
+	else
+		info->fbops = &psbfb_ops;
 
 	ret = fb_alloc_cmap(&info->cmap, 256, 0);
 	if (ret) {
@@ -518,7 +457,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 		psbfb->vm_map = 1;
 	}
 	info->screen_size = size;
-/*	memset(info->screen_base, 0, size); */
 
 	if (dev_priv->pg->stolen_size) {
 		info->apertures = alloc_apertures(1);
@@ -644,15 +582,8 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
 	drm_fb_helper_fini(&fbdev->psb_fb_helper);
 	drm_framebuffer_cleanup(&psbfb->base);
 
-	if (psbfb->gtt) {
-		/* FIXME: this is a bit more inside knowledge than I'd like
-		   but I don't see how to make a fake GEM object of the
-		   stolen space nicely */
-		if (psbfb->gtt->stolen)
-			psb_gtt_free_range(dev, psbfb->gtt);
-		else
-			drm_gem_object_unreference(&psbfb->gtt->gem);
-	}
+	if (psbfb->gtt)
+		drm_gem_object_unreference(&psbfb->gtt->gem);
 	return 0;
 }
 
@@ -671,6 +602,7 @@ int psb_fbdev_init(struct drm_device *dev)
 	dev_priv->fbdev = fbdev;
 	fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
 
+	/* FIXME: check Medfield */
 	num_crtc = 2;
 
 	drm_fb_helper_init(dev, &fbdev->psb_fb_helper, num_crtc,
@@ -769,17 +701,14 @@ static const struct drm_mode_config_funcs psb_mode_funcs = {
 
 static int psb_create_backlight_property(struct drm_device *dev)
 {
-	struct drm_psb_private *dev_priv
-				= (struct drm_psb_private *) dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 	struct drm_property *backlight;
 
 	if (dev_priv->backlight_property)
 		return 0;
 
-	backlight = drm_property_create(dev,
-					DRM_MODE_PROP_RANGE,
-					"backlight",
-					2);
+	backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE,
+							"backlight", 2);
 	backlight->values[0] = 0;
 	backlight->values[1] = 100;
 
@@ -790,12 +719,10 @@ static int psb_create_backlight_property(struct drm_device *dev)
 
 static void psb_setup_outputs(struct drm_device *dev)
 {
-	struct drm_psb_private *dev_priv =
-	    (struct drm_psb_private *) dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 	struct drm_connector *connector;
 
 	drm_mode_create_scaling_mode_property(dev);
-
 	psb_create_backlight_property(dev);
 
 	if (IS_MRST(dev)) {
@@ -805,7 +732,7 @@ static void psb_setup_outputs(struct drm_device *dev)
 			dev_err(dev->dev, "DSI is not supported\n");
 	} else if (IS_MFLD(dev)) {
 		mdfld_output_init(dev);
-        } else {
+	} else {
 		psb_intel_lvds_init(dev, &dev_priv->mode_dev);
 		psb_intel_sdvo_init(dev, SDVOB);
 	}
@@ -843,11 +770,9 @@ static void psb_setup_outputs(struct drm_device *dev)
 			clone_mask = (1 << INTEL_OUTPUT_HDMI);
 			break;
 		}
-
 		encoder->possible_crtcs = crtc_mask;
 		encoder->possible_clones =
 		    psb_intel_connector_clones(dev, clone_mask);
-
 	}
 }
 
@@ -878,9 +803,6 @@ void psb_modeset_init(struct drm_device *dev)
 	dev->mode_config.max_height = 2048;
 
 	psb_setup_outputs(dev);
-
-	/* setup fbs */
-	/* drm_initial_config(dev); */
 }
 
 void psb_modeset_cleanup(struct drm_device *dev)
@@ -889,7 +811,6 @@ void psb_modeset_cleanup(struct drm_device *dev)
 
 	drm_kms_helper_poll_fini(dev);
 	psb_fbdev_fini(dev);
-
 	drm_mode_config_cleanup(dev);
 
 	mutex_unlock(&dev->struct_mutex);


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 18/49] gma500: Update the GEM todo
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (16 preceding siblings ...)
  2011-07-05 14:37 ` [PATCH 17/49] gma500: psb_fb tidy/cleanup pass Alan Cox
@ 2011-07-05 14:37 ` Alan Cox
  2011-07-05 14:38 ` [PATCH 19/49] gma500: Only fiddle with clock gating on PSB Alan Cox
                   ` (31 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:37 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We also pull out the undo side of the mmap offset processing so we can later
push it into GEM where it belongs

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/gem_glue.c |    9 +++++++++
 drivers/staging/gma500/psb_gem.c  |   15 +--------------
 2 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/drivers/staging/gma500/gem_glue.c b/drivers/staging/gma500/gem_glue.c
index 0e7364b..779ac1a 100644
--- a/drivers/staging/gma500/gem_glue.c
+++ b/drivers/staging/gma500/gem_glue.c
@@ -42,6 +42,15 @@ int drm_gem_private_object_init(struct drm_device *dev,
 
 void drm_gem_object_release_wrap(struct drm_gem_object *obj)
 {
+	/* Remove the list map if one is present */
+	if (obj->map_list.map) {
+		struct drm_gem_mm *mm = obj->dev->mm_private;
+		struct drm_map_list *list = &obj->map_list;
+		drm_ht_remove_item(&mm->offset_hash, &list->hash);
+		drm_mm_put_block(list->file_offset_node);
+		kfree(list->map);
+		list->map = NULL;
+	}
 	if (obj->filp)
 		drm_gem_object_release(obj);
 }
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
index 1e7faae..a63ad9e 100644
--- a/drivers/staging/gma500/psb_gem.c
+++ b/drivers/staging/gma500/psb_gem.c
@@ -19,12 +19,8 @@
  * Authors: Alan Cox
  *
  * TODO:
- *	-	we don't actually put GEM objects into the GART yet
- *	-	we need to work out if the MMU is relevant as well (eg for
+ *	-	we need to work out if the MMU is relevant (eg for
  *		accelerated operations on a GEM object)
- *	-	cache coherency
- *
- * ie this is just an initial framework to get us going.
  */
 
 #include <drm/drmP.h>
@@ -40,15 +36,6 @@ int psb_gem_init_object(struct drm_gem_object *obj)
 void psb_gem_free_object(struct drm_gem_object *obj)
 {
 	struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
-	if (obj->map_list.map) {
-		/* Do things GEM should do for us */
-		struct drm_gem_mm *mm = obj->dev->mm_private;
-		struct drm_map_list *list = &obj->map_list;
-		drm_ht_remove_item(&mm->offset_hash, &list->hash);
-		drm_mm_put_block(list->file_offset_node);
-		kfree(list->map);
-		list->map = NULL;
-	}
 	drm_gem_object_release_wrap(obj);
 	/* This must occur last as it frees up the memory of the GEM object */
 	psb_gtt_free_range(obj->dev, gtt);


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 19/49] gma500: Only fiddle with clock gating on PSB
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (17 preceding siblings ...)
  2011-07-05 14:37 ` [PATCH 18/49] gma500: Update the GEM todo Alan Cox
@ 2011-07-05 14:38 ` Alan Cox
  2011-07-05 14:38 ` [PATCH 20/49] gma500: being abstracting out devices a bit more Alan Cox
                   ` (30 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:38 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_powermgmt.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/gma500/psb_powermgmt.c b/drivers/staging/gma500/psb_powermgmt.c
index f837ab0..2253ecb 100644
--- a/drivers/staging/gma500/psb_powermgmt.c
+++ b/drivers/staging/gma500/psb_powermgmt.c
@@ -64,7 +64,7 @@ void gma_power_init(struct drm_device *dev)
 	dev_priv->suspended = false;	/* And not suspended */
 	mutex_init(&power_mutex);
 
-	if (!IS_MRST(dev)) {
+	if (!IS_MRST(dev) && !IS_MFLD(dev)) {
 		/* FIXME: wants further review */
 		u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
 		/* Disable 2D clock gating */


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 20/49] gma500: being abstracting out devices a bit more
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (18 preceding siblings ...)
  2011-07-05 14:38 ` [PATCH 19/49] gma500: Only fiddle with clock gating on PSB Alan Cox
@ 2011-07-05 14:38 ` Alan Cox
  2011-07-05 14:38 ` [PATCH 21/49] gma500: continue abstracting platform specific code Alan Cox
                   ` (29 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:38 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We really want to move towards a completely abstracted interface rather
than having tons of per chip junk in the same files.

Begin with the power code which is probably the worst offender. Add a set
of methods, initialise a dev_priv->ops pointer and rip the chip specifics
out of the power code. While we are it pick up the display init bits.

So we know it's now chip specifics clean remove the psb_ naming from it.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile        |    5 
 drivers/staging/gma500/mdfld_device.c  |  610 +++++++++++++++++++
 drivers/staging/gma500/mdfld_output.c  |   15 
 drivers/staging/gma500/mdfld_output.h  |    2 
 drivers/staging/gma500/mrst_device.c   |  230 +++++++
 drivers/staging/gma500/power.c         |  320 ++++++++++
 drivers/staging/gma500/psb_device.c    |  174 +++++
 drivers/staging/gma500/psb_drv.c       |   47 +
 drivers/staging/gma500/psb_drv.h       |   29 +
 drivers/staging/gma500/psb_fb.c        |   12 
 drivers/staging/gma500/psb_powermgmt.c | 1051 --------------------------------
 11 files changed, 1402 insertions(+), 1093 deletions(-)
 create mode 100644 drivers/staging/gma500/mdfld_device.c
 create mode 100644 drivers/staging/gma500/mrst_device.c
 create mode 100644 drivers/staging/gma500/power.c
 create mode 100644 drivers/staging/gma500/psb_device.c
 delete mode 100644 drivers/staging/gma500/psb_powermgmt.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index fdaac63..e93cbe3 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -4,6 +4,7 @@
 ccflags-y += -Iinclude/drm
 
 psb_gfx-y += gem_glue.o \
+	  power.o \
 	  psb_bl.o \
 	  psb_drv.o \
 	  psb_gem.o \
@@ -19,11 +20,13 @@ psb_gfx-y += gem_glue.o \
 	  psb_intel_sdvo.o \
 	  psb_lid.o \
 	  psb_mmu.o \
-	  psb_powermgmt.o \
 	  psb_irq.o \
+	  psb_device.o \
+	  mrst_device.o \
 	  mrst_crtc.o \
 	  mrst_lvds.o \
 	  mrst_bios.o \
+	  mdfld_device.o \
 	  mdfld_output.o \
 	  mdfld_pyr_cmd.o \
 	  mdfld_tmd_vid.o \
diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
new file mode 100644
index 0000000..7caa7cd
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_device.c
@@ -0,0 +1,610 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "mdfld_output.h"
+#include "mdfld_dsi_output.h"
+
+/*
+ *	Provide the Medfield specific chip logic and low level methods
+ */
+
+static void mdfld_init_pm(struct drm_device *dev)
+{
+	/* No work needed here yet */
+}
+
+/**
+ * mdfld_save_display_registers	-	save registers for pipe
+ * @dev: our device
+ * @pipe: pipe to save
+ *
+ * Save the pipe state of the device before we power it off. Keep everything
+ * we need to put it back again
+ */
+static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int i;
+
+	/* register */
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 fp_reg = MRST_FPA0;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 htot_reg = HTOTAL_A;
+	u32 hblank_reg = HBLANK_A;
+	u32 hsync_reg = HSYNC_A;
+	u32 vtot_reg = VTOTAL_A;
+	u32 vblank_reg = VBLANK_A;
+	u32 vsync_reg = VSYNC_A;
+	u32 pipesrc_reg = PIPEASRC;
+	u32 dspstride_reg = DSPASTRIDE;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dsptileoff_reg = DSPATILEOFF;
+	u32 dspsize_reg = DSPASIZE;
+	u32 dsppos_reg = DSPAPOS;
+	u32 dspsurf_reg = DSPASURF;
+	u32 mipi_reg = MIPI;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 dspstatus_reg = PIPEASTAT;
+	u32 palette_reg = PALETTE_A;
+
+	/* pointer to values */
+	u32 *dpll_val = &dev_priv->saveDPLL_A;
+	u32 *fp_val = &dev_priv->saveFPA0;
+	u32 *pipeconf_val = &dev_priv->savePIPEACONF;
+	u32 *htot_val = &dev_priv->saveHTOTAL_A;
+	u32 *hblank_val = &dev_priv->saveHBLANK_A;
+	u32 *hsync_val = &dev_priv->saveHSYNC_A;
+	u32 *vtot_val = &dev_priv->saveVTOTAL_A;
+	u32 *vblank_val = &dev_priv->saveVBLANK_A;
+	u32 *vsync_val = &dev_priv->saveVSYNC_A;
+	u32 *pipesrc_val = &dev_priv->savePIPEASRC;
+	u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
+	u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
+	u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
+	u32 *dspsize_val = &dev_priv->saveDSPASIZE;
+	u32 *dsppos_val = &dev_priv->saveDSPAPOS;
+	u32 *dspsurf_val = &dev_priv->saveDSPASURF;
+	u32 *mipi_val = &dev_priv->saveMIPI;
+	u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
+	u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
+	u32 *palette_val = dev_priv->save_palette_a;
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		/* register */
+		dpll_reg = MDFLD_DPLL_B;
+		fp_reg = MDFLD_DPLL_DIV0;
+		pipeconf_reg = PIPEBCONF;
+		htot_reg = HTOTAL_B;
+		hblank_reg = HBLANK_B;
+		hsync_reg = HSYNC_B;
+		vtot_reg = VTOTAL_B;
+		vblank_reg = VBLANK_B;
+		vsync_reg = VSYNC_B;
+		pipesrc_reg = PIPEBSRC;
+		dspstride_reg = DSPBSTRIDE;
+		dsplinoff_reg = DSPBLINOFF;
+		dsptileoff_reg = DSPBTILEOFF;
+		dspsize_reg = DSPBSIZE;
+		dsppos_reg = DSPBPOS;
+		dspsurf_reg = DSPBSURF;
+		dspcntr_reg = DSPBCNTR;
+		dspstatus_reg = PIPEBSTAT;
+		palette_reg = PALETTE_B;
+
+		/* values */
+		dpll_val = &dev_priv->saveDPLL_B;
+		fp_val = &dev_priv->saveFPB0;
+		pipeconf_val = &dev_priv->savePIPEBCONF;
+		htot_val = &dev_priv->saveHTOTAL_B;
+		hblank_val = &dev_priv->saveHBLANK_B;
+		hsync_val = &dev_priv->saveHSYNC_B;
+		vtot_val = &dev_priv->saveVTOTAL_B;
+		vblank_val = &dev_priv->saveVBLANK_B;
+		vsync_val = &dev_priv->saveVSYNC_B;
+		pipesrc_val = &dev_priv->savePIPEBSRC;
+		dspstride_val = &dev_priv->saveDSPBSTRIDE;
+		dsplinoff_val = &dev_priv->saveDSPBLINOFF;
+		dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
+		dspsize_val = &dev_priv->saveDSPBSIZE;
+		dsppos_val = &dev_priv->saveDSPBPOS;
+		dspsurf_val = &dev_priv->saveDSPBSURF;
+		dspcntr_val = &dev_priv->saveDSPBCNTR;
+		dspstatus_val = &dev_priv->saveDSPBSTATUS;
+		palette_val = dev_priv->save_palette_b;
+		break;
+	case 2:
+		/* register */
+		pipeconf_reg = PIPECCONF;
+		htot_reg = HTOTAL_C;
+		hblank_reg = HBLANK_C;
+		hsync_reg = HSYNC_C;
+		vtot_reg = VTOTAL_C;
+		vblank_reg = VBLANK_C;
+		vsync_reg = VSYNC_C;
+		pipesrc_reg = PIPECSRC;
+		dspstride_reg = DSPCSTRIDE;
+		dsplinoff_reg = DSPCLINOFF;
+		dsptileoff_reg = DSPCTILEOFF;
+		dspsize_reg = DSPCSIZE;
+		dsppos_reg = DSPCPOS;
+		dspsurf_reg = DSPCSURF;
+		mipi_reg = MIPI_C;
+		dspcntr_reg = DSPCCNTR;
+		dspstatus_reg = PIPECSTAT;
+		palette_reg = PALETTE_C;
+
+		/* pointer to values */
+		pipeconf_val = &dev_priv->savePIPECCONF;
+		htot_val = &dev_priv->saveHTOTAL_C;
+		hblank_val = &dev_priv->saveHBLANK_C;
+		hsync_val = &dev_priv->saveHSYNC_C;
+		vtot_val = &dev_priv->saveVTOTAL_C;
+		vblank_val = &dev_priv->saveVBLANK_C;
+		vsync_val = &dev_priv->saveVSYNC_C;
+		pipesrc_val = &dev_priv->savePIPECSRC;
+		dspstride_val = &dev_priv->saveDSPCSTRIDE;
+		dsplinoff_val = &dev_priv->saveDSPCLINOFF;
+		dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
+		dspsize_val = &dev_priv->saveDSPCSIZE;
+		dsppos_val = &dev_priv->saveDSPCPOS;
+		dspsurf_val = &dev_priv->saveDSPCSURF;
+		mipi_val = &dev_priv->saveMIPI_C;
+		dspcntr_val = &dev_priv->saveDSPCCNTR;
+		dspstatus_val = &dev_priv->saveDSPCSTATUS;
+		palette_val = dev_priv->save_palette_c;
+		break;
+	default:
+		DRM_ERROR("%s, invalid pipe number.\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Pipe & plane A info */
+	*dpll_val = PSB_RVDC32(dpll_reg);
+	*fp_val = PSB_RVDC32(fp_reg);
+	*pipeconf_val = PSB_RVDC32(pipeconf_reg);
+	*htot_val = PSB_RVDC32(htot_reg);
+	*hblank_val = PSB_RVDC32(hblank_reg);
+	*hsync_val = PSB_RVDC32(hsync_reg);
+	*vtot_val = PSB_RVDC32(vtot_reg);
+	*vblank_val = PSB_RVDC32(vblank_reg);
+	*vsync_val = PSB_RVDC32(vsync_reg);
+	*pipesrc_val = PSB_RVDC32(pipesrc_reg);
+	*dspstride_val = PSB_RVDC32(dspstride_reg);
+	*dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
+	*dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
+	*dspsize_val = PSB_RVDC32(dspsize_reg);
+	*dsppos_val = PSB_RVDC32(dsppos_reg);
+	*dspsurf_val = PSB_RVDC32(dspsurf_reg);
+	*dspcntr_val = PSB_RVDC32(dspcntr_reg);
+	*dspstatus_val = PSB_RVDC32(dspstatus_reg);
+
+	/*save palette (gamma) */
+	for (i = 0; i < 256; i++)
+		palette_val[i] = PSB_RVDC32(palette_reg + (i<<2));
+
+	if (pipe == 1) {
+		dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
+		dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
+		dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
+		dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
+		return 0;
+	}
+	*mipi_val = PSB_RVDC32(mipi_reg);
+	return 0;
+}
+
+/**
+ * mdfld_save_cursor_overlay_registers	-	save cursor overlay info
+ * @dev: our device
+ *
+ * Save the cursor and overlay register state
+ */
+static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/* Save cursor regs */
+	dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
+	dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
+	dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
+
+	dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
+	dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
+	dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
+
+	dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
+	dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
+	dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
+
+	/* HW overlay */
+	dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
+	dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+	dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+	dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+	dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+	dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+	dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+
+	dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
+	dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
+
+	return 0;
+}
+/*
+ * mdfld_restore_display_registers	-	restore the state of a pipe
+ * @dev: our device
+ * @pipe: the pipe to restore
+ *
+ * Restore the state of a pipe to that which was saved by the register save
+ * functions.
+ */
+static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
+{
+	/* To get  panel out of ULPS mode */
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct mdfld_dsi_config *dsi_config = NULL;
+	u32 i = 0;
+	u32 dpll = 0;
+	u32 timeout = 0;
+	u32 reg_offset = 0;
+
+	/* register */
+	u32 dpll_reg = MRST_DPLL_A;
+	u32 fp_reg = MRST_FPA0;
+	u32 pipeconf_reg = PIPEACONF;
+	u32 htot_reg = HTOTAL_A;
+	u32 hblank_reg = HBLANK_A;
+	u32 hsync_reg = HSYNC_A;
+	u32 vtot_reg = VTOTAL_A;
+	u32 vblank_reg = VBLANK_A;
+	u32 vsync_reg = VSYNC_A;
+	u32 pipesrc_reg = PIPEASRC;
+	u32 dspstride_reg = DSPASTRIDE;
+	u32 dsplinoff_reg = DSPALINOFF;
+	u32 dsptileoff_reg = DSPATILEOFF;
+	u32 dspsize_reg = DSPASIZE;
+	u32 dsppos_reg = DSPAPOS;
+	u32 dspsurf_reg = DSPASURF;
+	u32 dspstatus_reg = PIPEASTAT;
+	u32 mipi_reg = MIPI;
+	u32 dspcntr_reg = DSPACNTR;
+	u32 palette_reg = PALETTE_A;
+
+	/* values */
+	u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
+	u32 fp_val = dev_priv->saveFPA0;
+	u32 pipeconf_val = dev_priv->savePIPEACONF;
+	u32 htot_val = dev_priv->saveHTOTAL_A;
+	u32 hblank_val = dev_priv->saveHBLANK_A;
+	u32 hsync_val = dev_priv->saveHSYNC_A;
+	u32 vtot_val = dev_priv->saveVTOTAL_A;
+	u32 vblank_val = dev_priv->saveVBLANK_A;
+	u32 vsync_val = dev_priv->saveVSYNC_A;
+	u32 pipesrc_val = dev_priv->savePIPEASRC;
+	u32 dspstride_val = dev_priv->saveDSPASTRIDE;
+	u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
+	u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
+	u32 dspsize_val = dev_priv->saveDSPASIZE;
+	u32 dsppos_val = dev_priv->saveDSPAPOS;
+	u32 dspsurf_val = dev_priv->saveDSPASURF;
+	u32 dspstatus_val = dev_priv->saveDSPASTATUS;
+	u32 mipi_val = dev_priv->saveMIPI;
+	u32 dspcntr_val = dev_priv->saveDSPACNTR;
+	u32 *palette_val = dev_priv->save_palette_a;
+
+	switch (pipe) {
+	case 0:
+		dsi_config = dev_priv->dsi_configs[0];
+		break;
+	case 1:
+		/* register */
+		dpll_reg = MDFLD_DPLL_B;
+		fp_reg = MDFLD_DPLL_DIV0;
+		pipeconf_reg = PIPEBCONF;
+		htot_reg = HTOTAL_B;
+		hblank_reg = HBLANK_B;
+		hsync_reg = HSYNC_B;
+		vtot_reg = VTOTAL_B;
+		vblank_reg = VBLANK_B;
+		vsync_reg = VSYNC_B;
+		pipesrc_reg = PIPEBSRC;
+		dspstride_reg = DSPBSTRIDE;
+		dsplinoff_reg = DSPBLINOFF;
+		dsptileoff_reg = DSPBTILEOFF;
+		dspsize_reg = DSPBSIZE;
+		dsppos_reg = DSPBPOS;
+		dspsurf_reg = DSPBSURF;
+		dspcntr_reg = DSPBCNTR;
+		palette_reg = PALETTE_B;
+		dspstatus_reg = PIPEBSTAT;
+
+		/* values */
+		dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
+		fp_val = dev_priv->saveFPB0;
+		pipeconf_val = dev_priv->savePIPEBCONF;
+		htot_val = dev_priv->saveHTOTAL_B;
+		hblank_val = dev_priv->saveHBLANK_B;
+		hsync_val = dev_priv->saveHSYNC_B;
+		vtot_val = dev_priv->saveVTOTAL_B;
+		vblank_val = dev_priv->saveVBLANK_B;
+		vsync_val = dev_priv->saveVSYNC_B;
+		pipesrc_val = dev_priv->savePIPEBSRC;
+		dspstride_val = dev_priv->saveDSPBSTRIDE;
+		dsplinoff_val = dev_priv->saveDSPBLINOFF;
+		dsptileoff_val = dev_priv->saveDSPBTILEOFF;
+		dspsize_val = dev_priv->saveDSPBSIZE;
+		dsppos_val = dev_priv->saveDSPBPOS;
+		dspsurf_val = dev_priv->saveDSPBSURF;
+		dspcntr_val = dev_priv->saveDSPBCNTR;
+		dspstatus_val = dev_priv->saveDSPBSTATUS;
+		palette_val = dev_priv->save_palette_b;
+		break;
+	case 2:
+		reg_offset = MIPIC_REG_OFFSET;
+
+		/* register */
+		pipeconf_reg = PIPECCONF;
+		htot_reg = HTOTAL_C;
+		hblank_reg = HBLANK_C;
+		hsync_reg = HSYNC_C;
+		vtot_reg = VTOTAL_C;
+		vblank_reg = VBLANK_C;
+		vsync_reg = VSYNC_C;
+		pipesrc_reg = PIPECSRC;
+		dspstride_reg = DSPCSTRIDE;
+		dsplinoff_reg = DSPCLINOFF;
+		dsptileoff_reg = DSPCTILEOFF;
+		dspsize_reg = DSPCSIZE;
+		dsppos_reg = DSPCPOS;
+		dspsurf_reg = DSPCSURF;
+		mipi_reg = MIPI_C;
+		dspcntr_reg = DSPCCNTR;
+		palette_reg = PALETTE_C;
+		dspstatus_reg = PIPECSTAT;
+
+		/* values */
+		pipeconf_val = dev_priv->savePIPECCONF;
+		htot_val = dev_priv->saveHTOTAL_C;
+		hblank_val = dev_priv->saveHBLANK_C;
+		hsync_val = dev_priv->saveHSYNC_C;
+		vtot_val = dev_priv->saveVTOTAL_C;
+		vblank_val = dev_priv->saveVBLANK_C;
+		vsync_val = dev_priv->saveVSYNC_C;
+		pipesrc_val = dev_priv->savePIPECSRC;
+		dspstride_val = dev_priv->saveDSPCSTRIDE;
+		dsplinoff_val = dev_priv->saveDSPCLINOFF;
+		dsptileoff_val = dev_priv->saveDSPCTILEOFF;
+		dspsize_val = dev_priv->saveDSPCSIZE;
+		dsppos_val = dev_priv->saveDSPCPOS;
+		dspsurf_val = dev_priv->saveDSPCSURF;
+		dspstatus_val = dev_priv->saveDSPCSTATUS;
+		mipi_val = dev_priv->saveMIPI_C;
+		dspcntr_val = dev_priv->saveDSPCCNTR;
+		palette_val = dev_priv->save_palette_c;
+
+		dsi_config = dev_priv->dsi_configs[1];
+		break;
+	default:
+		DRM_ERROR("%s, invalid pipe number.\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Make sure VGA plane is off. it initializes to on after reset!*/
+	PSB_WVDC32(0x80000000, VGACNTRL);
+	if (pipe == 1) {
+		PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
+		PSB_RVDC32(dpll_reg);
+
+		PSB_WVDC32(fp_val, fp_reg);
+	} else {
+		dpll = PSB_RVDC32(dpll_reg);
+
+		if (!(dpll & DPLL_VCO_ENABLE)) {
+
+			/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
+			if (dpll & MDFLD_PWR_GATE_EN) {
+				dpll &= ~MDFLD_PWR_GATE_EN;
+				PSB_WVDC32(dpll, dpll_reg);
+				udelay(500);	/* FIXME: 1 ? */
+			}
+
+			PSB_WVDC32(fp_val, fp_reg);
+			PSB_WVDC32(dpll_val, dpll_reg);
+			/* FIXME_MDFLD PO - change 500 to 1 after PO */
+			udelay(500);
+
+			dpll_val |= DPLL_VCO_ENABLE;
+			PSB_WVDC32(dpll_val, dpll_reg);
+			PSB_RVDC32(dpll_reg);
+
+			/* wait for DSI PLL to lock */
+			while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
+				udelay(150);
+				timeout++;
+			}
+
+			if (timeout == 20000) {
+				DRM_ERROR("%s, can't lock DSIPLL.\n",
+							__func__);
+				return -EINVAL;
+			}
+		}
+	}
+	/* Restore mode */
+	PSB_WVDC32(htot_val, htot_reg);
+	PSB_WVDC32(hblank_val, hblank_reg);
+	PSB_WVDC32(hsync_val, hsync_reg);
+	PSB_WVDC32(vtot_val, vtot_reg);
+	PSB_WVDC32(vblank_val, vblank_reg);
+	PSB_WVDC32(vsync_val, vsync_reg);
+	PSB_WVDC32(pipesrc_val, pipesrc_reg);
+	PSB_WVDC32(dspstatus_val, dspstatus_reg);
+
+	/* Set up the plane */
+	PSB_WVDC32(dspstride_val, dspstride_reg);
+	PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
+	PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
+	PSB_WVDC32(dspsize_val, dspsize_reg);
+	PSB_WVDC32(dsppos_val, dsppos_reg);
+	PSB_WVDC32(dspsurf_val, dspsurf_reg);
+
+	if (pipe == 1) {
+		PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
+		PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
+		PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL);
+		PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL);
+
+	} else {
+		/* Set up pipe related registers */
+		PSB_WVDC32(mipi_val, mipi_reg);
+		/* Setup MIPI adapter + MIPI IP registers */
+		mdfld_dsi_controller_init(dsi_config, pipe);
+		msleep(20);
+	}
+	/* Enable the plane */
+	PSB_WVDC32(dspcntr_val, dspcntr_reg);
+	msleep(20);
+	/* Enable the pipe */
+	PSB_WVDC32(pipeconf_val, pipeconf_reg);
+
+	for (i = 0; i < 256; i++)
+		PSB_WVDC32(palette_val[i], palette_reg + (i<<2));
+	if (pipe == 1)
+		return 0;
+	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
+		mdfld_enable_te(dev, pipe);
+	return 0;
+}
+
+/**
+ * mdfld_restore_cursor_overlay_registers	-	restore cursor
+ * @dev: our device
+ *
+ * Restore the cursor and overlay state that was saved earlier
+ */
+static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/* Enable Cursor A */
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
+	PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
+
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
+	PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
+
+	PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
+	PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
+	PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
+
+	/* Restore HW overlay */
+	PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
+
+	PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
+	PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
+
+	return 0;
+}
+
+/**
+ *	mdfld_save_display_registers	-	save registers lost on suspend
+ *	@dev: our DRM device
+ *
+ *	Save the state we need in order to be able to restore the interface
+ *	upon resume from suspend
+ */
+static int mdfld_save_registers(struct drm_device *dev)
+{
+	/* FIXME: We need to shut down panels here if using them
+	   and once the right bits are merged */
+	mdfld_save_cursor_overlay_registers(dev);
+	mdfld_save_display_registers(dev, 0);
+	mdfld_save_display_registers(dev, 0);
+	mdfld_save_display_registers(dev, 2);
+	mdfld_save_display_registers(dev, 1);
+	mdfld_disable_crtc(dev, 0);
+	mdfld_disable_crtc(dev, 2);
+	mdfld_disable_crtc(dev, 1);
+	return 0;
+}
+
+/**
+ *	mdfld_restore_display_registers	-	restore lost register state
+ *	@dev: our DRM device
+ *
+ *	Restore register state that was lost during suspend and resume.
+ */
+static int mdfld_restore_registers(struct drm_device *dev)
+{
+	mdfld_restore_display_registers(dev, 1);
+	mdfld_restore_display_registers(dev, 0);
+	mdfld_restore_display_registers(dev, 2);
+	mdfld_restore_cursor_overlay_registers(dev);
+	return 0;
+}
+
+static int mdfld_power_down(struct drm_device *dev)
+{
+	/* FIXME */
+	return 0;
+}
+
+static int mdfld_power_up(struct drm_device *dev)
+{
+	/* FIXME */
+	return 0;
+}
+
+const struct psb_ops mdfld_chip_ops = {
+	.output_init = mdfld_output_init,
+	.init_pm = mdfld_init_pm,
+	.save_regs = mdfld_save_registers,
+	.restore_regs = mdfld_restore_registers,
+	.power_down = mdfld_power_down,
+	.power_up = mdfld_power_up,
+};
+
diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c
index b1fc765..7e11401 100644
--- a/drivers/staging/gma500/mdfld_output.c
+++ b/drivers/staging/gma500/mdfld_output.c
@@ -63,14 +63,20 @@ int mdfld_panel_dpi(struct drm_device *dev)
 	}
 }
 
-static void init_panel(struct drm_device *dev, int mipi_pipe, int p_type)
+static int init_panel(struct drm_device *dev, int mipi_pipe, int p_type)
 {
 	struct panel_funcs *p_cmd_funcs;
 	struct panel_funcs *p_vid_funcs;
 
 	/* Oh boy ... FIXME */
 	p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
+	if (p_cmd_funcs == NULL)
+		return -ENODEV;
 	p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
+	if (p_vid_funcs == NULL) {
+		kfree(p_cmd_funcs);
+		return -ENODEV;
+	}
 
 	switch (p_type) {
 	case TPO_CMD:
@@ -115,11 +121,12 @@ static void init_panel(struct drm_device *dev, int mipi_pipe, int p_type)
 #endif
 	default:
 		dev_err(dev->dev, "Unsupported interface %d", p_type);
-		break;
+		return -ENODEV;
 	}
+	return 0;
 }
 
-void mdfld_output_init(struct drm_device *dev)
+int mdfld_output_init(struct drm_device *dev)
 {
 	int type;
 
@@ -132,4 +139,6 @@ void mdfld_output_init(struct drm_device *dev)
 	type = mdfld_get_panel_type(dev, 2);
 	dev_info(dev->dev, "panel 2: type is %d\n", type);
 	init_panel(dev, 2, type);
+
+	return 0;
 }
diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h
index 36f43e1..53b57db 100644
--- a/drivers/staging/gma500/mdfld_output.h
+++ b/drivers/staging/gma500/mdfld_output.h
@@ -69,7 +69,7 @@ struct panel_funcs {
 	int (*get_panel_info) (struct drm_device *, int, struct panel_info *);
 };
 
-void mdfld_output_init(struct drm_device *dev);
+int mdfld_output_init(struct drm_device *dev);
 int mdfld_panel_dpi(struct drm_device *dev);
 int mdfld_get_panel_type(struct drm_device *dev, int pipe);
 void mdfld_disable_crtc (struct drm_device *dev, int pipe);
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
new file mode 100644
index 0000000..5cd8283
--- /dev/null
+++ b/drivers/staging/gma500/mrst_device.c
@@ -0,0 +1,230 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include <asm/intel_scu_ipc.h>
+
+/* IPC message and command defines used to enable/disable mipi panel voltages */
+#define IPC_MSG_PANEL_ON_OFF    0xE9
+#define IPC_CMD_PANEL_ON        1
+#define IPC_CMD_PANEL_OFF       0
+
+static int mrst_output_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	if (dev_priv->iLVDS_enable) {
+		mrst_lvds_init(dev, &dev_priv->mode_dev);
+		return 0;
+	}
+	dev_err(dev->dev, "DSI is not supported\n");
+	return -ENODEV;
+}
+
+/*
+ *	Provide the Moorestown specific chip logic and low level methods
+ */
+
+static void mrst_init_pm(struct drm_device *dev)
+{
+}
+
+/**
+ *	mrst_save_display_registers	-	save registers lost on suspend
+ *	@dev: our DRM device
+ *
+ *	Save the state we need in order to be able to restore the interface
+ *	upon resume from suspend
+ */
+static int mrst_save_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+
+	/* Display arbitration control + watermarks */
+	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+	/* Save crtc and output state */
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (drm_helper_crtc_in_use(crtc))
+			crtc->funcs->save(crtc);
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		connector->funcs->save(connector);
+
+	mutex_unlock(&dev->mode_config.mutex);
+	return 0;
+}
+
+/**
+ *	mrst_restore_display_registers	-	restore lost register state
+ *	@dev: our DRM device
+ *
+ *	Restore register state that was lost during suspend and resume.
+ */
+static int mrst_restore_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+	int pp_stat;
+
+	if (!dev_priv->iLVDS_enable) {
+#ifdef CONFIG_X86_MRST
+		intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
+							IPC_CMD_PANEL_ON);
+		/* FIXME: can we avoid this delay ? */
+		msleep(2000); /* wait 2 seconds */
+#endif
+	}
+
+	/* Display arbitration + watermarks */
+	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+	/*make sure VGA plane is off. it initializes to on after reset!*/
+	PSB_WVDC32(0x80000000, VGACNTRL);
+
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		if (drm_helper_crtc_in_use(crtc))
+			crtc->funcs->restore(crtc);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		connector->funcs->restore(connector);
+
+	mutex_unlock(&dev->mode_config.mutex);
+
+	if (dev_priv->iLVDS_enable) {
+		/*shutdown the panel*/
+		PSB_WVDC32(0, PP_CONTROL);
+		do {
+			pp_stat = PSB_RVDC32(PP_STATUS);
+		} while (pp_stat & 0x80000000);
+
+		/* Turn off the plane */
+		PSB_WVDC32(0x58000000, DSPACNTR);
+		PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
+		/* Wait ~4 ticks */
+		msleep(4);
+		/* Turn off pipe */
+		PSB_WVDC32(0x0, PIPEACONF);
+		/* Wait ~8 ticks */
+		msleep(8);
+
+		/* Turn off PLLs */
+		PSB_WVDC32(0, MRST_DPLL_A);
+	} else {
+		PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
+		PSB_WVDC32(0x0, PIPEACONF);
+		PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
+		while (REG_READ(0x70008) & 0x40000000)
+			cpu_relax();
+		while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
+			!= DPI_FIFO_EMPTY)
+			cpu_relax();
+		PSB_WVDC32(0, DEVICE_READY_REG);
+		/* Turn off panel power */
+#ifdef CONFIG_X86_MRST	/* FIXME: kill define once modular */
+		intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
+							IPC_CMD_PANEL_OFF);
+#endif
+	}
+	return 0;
+}
+
+/**
+ *	mrst_power_down	-	power down the display island
+ *	@dev: our DRM device
+ *
+ *	Power down the display interface of our device
+ */
+static int mrst_power_down(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 pwr_mask ;
+	u32 pwr_sts;
+
+	pwr_mask = PSB_PWRGT_DISPLAY_MASK;
+	outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
+
+	while (true) {
+		pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+		if ((pwr_sts & pwr_mask) == pwr_mask)
+			break;
+		else
+			udelay(10);
+	}
+	return 0;
+}
+
+/*
+ * mrst_power_up
+ *
+ * Restore power to the specified island(s) (powergating)
+ */
+static int mrst_power_up(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
+	u32 pwr_sts, pwr_cnt;
+
+	pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
+	pwr_cnt &= ~pwr_mask;
+	outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
+
+	while (true) {
+		pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+		if ((pwr_sts & pwr_mask) == 0)
+			break;
+		else
+			udelay(10);
+	}
+	return 0;
+}
+
+const struct psb_ops mrst_chip_ops = {
+	.output_init = mrst_output_init,
+	.init_pm = mrst_init_pm,
+	.save_regs = mrst_save_display_registers,
+	.restore_regs = mrst_restore_display_registers,
+	.power_down = mrst_power_down,
+	.power_up = mrst_power_up,
+};
+
diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
new file mode 100644
index 0000000..fc2324e
--- /dev/null
+++ b/drivers/staging/gma500/power.c
@@ -0,0 +1,320 @@
+/**************************************************************************
+ * Copyright (c) 2009-2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ * Massively reworked
+ *    Alan Cox <alan@linux.intel.com>
+ */
+#include "psb_powermgmt.h"
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+
+static struct mutex power_mutex;
+
+/**
+ *	gma_power_init		-	initialise power manager
+ *	@dev: our device
+ *
+ *	Set up for power management tracking of our hardware.
+ */
+void gma_power_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/* FIXME: need to sort out fetching apm_reg for both platforms ?? */
+
+	dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
+	dev_priv->ospm_base &= 0xffff;
+
+	dev_priv->display_power = true;	/* We start active */
+	dev_priv->display_count = 0;	/* Currently no users */
+	dev_priv->suspended = false;	/* And not suspended */
+	mutex_init(&power_mutex);
+
+	dev_priv->ops->init_pm(dev);
+}
+
+/**
+ *	gma_power_uninit	-	end power manager
+ *	@dev: device to end for
+ *
+ *	Undo the effects of gma_power_init
+ */
+void gma_power_uninit(struct drm_device *dev)
+{
+	mutex_destroy(&power_mutex);
+	pm_runtime_disable(&dev->pdev->dev);
+	pm_runtime_set_suspended(&dev->pdev->dev);
+}
+
+
+
+
+/**
+ *	gma_suspend_display	-	suspend the display logic
+ *	@dev: our DRM device
+ *
+ *	Suspend the display logic of the graphics interface
+ *
+ *	FIXME: This ought to be replaced by a dev_priv-> ops interface
+ *	where the various platforms register their save/restore methods
+ *	and keep them in their own support files.
+ */
+static void gma_suspend_display(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->suspended)
+		return;
+	dev_priv->ops->save_regs(dev);
+	dev_priv->ops->power_down(dev);
+	dev_priv->display_power = false;
+}
+
+/**
+ *	gma_resume_display	-	resume display side logic
+ *
+ *	Resume the display hardware restoring state and enabling
+ *	as necessary.
+ */
+static void gma_resume_display(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->suspended == false)
+		return;
+
+	/* turn on the display power island */
+	dev_priv->ops->power_up(dev);
+	dev_priv->suspended = false;
+	dev_priv->display_power = true;
+
+	PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+	pci_write_config_word(pdev, PSB_GMCH_CTRL,
+			dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
+	dev_priv->ops->restore_regs(dev);
+}
+
+/**
+ *	gma_suspend_pci		-	suspend PCI side
+ *	@pdev: PCI device
+ *
+ *	Perform the suspend processing on our PCI device state
+ */
+static void gma_suspend_pci(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int bsm, vbt;
+
+	if (dev_priv->suspended)
+		return;
+
+	pci_save_state(pdev);
+	pci_read_config_dword(pdev, 0x5C, &bsm);
+	dev_priv->saveBSM = bsm;
+	pci_read_config_dword(pdev, 0xFC, &vbt);
+	dev_priv->saveVBT = vbt;
+	pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
+	pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
+
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	dev_priv->suspended = true;
+}
+
+/**
+ *	gma_resume_pci		-	resume helper
+ *	@dev: our PCI device
+ *
+ *	Perform the resume processing on our PCI device state - rewrite
+ *	register state and re-enable the PCI device
+ */
+static bool gma_resume_pci(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret;
+
+	if (!dev_priv->suspended)
+		return true;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
+	pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
+	/* restoring MSI address and data in PCIx space */
+	pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
+	pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
+	ret = pci_enable_device(pdev);
+
+	if (ret != 0)
+		dev_err(&pdev->dev, "pci_enable failed: %d\n", ret);
+	else
+		dev_priv->suspended = false;
+	return !dev_priv->suspended;
+}
+
+/**
+ *	gma_power_suspend		-	bus callback for suspend
+ *	@pdev: our PCI device
+ *	@state: suspend type
+ *
+ *	Called back by the PCI layer during a suspend of the system. We
+ *	perform the necessary shut down steps and save enough state that
+ *	we can undo this when resume is called.
+ */
+int gma_power_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&power_mutex);
+	if (!dev_priv->suspended) {
+		if (dev_priv->display_count) {
+			mutex_unlock(&power_mutex);
+			return -EBUSY;
+		}
+		psb_irq_uninstall(dev);
+		gma_suspend_display(dev);
+		gma_suspend_pci(pdev);
+	}
+	mutex_unlock(&power_mutex);
+	return 0;
+}
+
+
+/**
+ *	gma_power_resume		-	resume power
+ *	@pdev: PCI device
+ *
+ *	Resume the PCI side of the graphics and then the displays
+ */
+int gma_power_resume(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	mutex_lock(&power_mutex);
+	gma_resume_pci(pdev);
+	gma_resume_display(pdev);
+	psb_irq_preinstall(dev);
+	psb_irq_postinstall(dev);
+	mutex_unlock(&power_mutex);
+	return 0;
+}
+
+
+
+/**
+ *	gma_power_is_on		-	returne true if power is on
+ *	@dev: our DRM device
+ *
+ *	Returns true if the display island power is on at this moment
+ */
+bool gma_power_is_on(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	return dev_priv->display_power;
+}
+
+
+/**
+ *	gma_power_begin		-	begin requiring power
+ *	@dev: our DRM device
+ *	@force_on: true to force power on
+ *
+ *	Begin an action that requires the display power island is enabled.
+ *	We refcount the islands.
+ *
+ *	FIXME: locking
+ */
+bool gma_power_begin(struct drm_device *dev, bool force_on)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret;
+
+	/* Power already on ? */
+	if (dev_priv->display_power) {
+		dev_priv->display_count++;
+		pm_runtime_get(&dev->pdev->dev);
+		return true;
+	}
+	if (force_on == false)
+		return false;
+
+	/* Ok power up needed */
+	ret = gma_resume_pci(dev->pdev);
+	if (ret == 0) {
+		psb_irq_preinstall(dev);
+		psb_irq_postinstall(dev);
+		pm_runtime_get(&dev->pdev->dev);
+		dev_priv->display_count++;
+		return true;
+	}
+	return false;
+}
+
+
+/**
+ *	gma_power_end		-	end use of power
+ *	@dev: Our DRM device
+ *
+ *	Indicate that one of our gma_power_begin() requested periods when
+ *	the diplay island power is needed has completed.
+ */
+void gma_power_end(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	dev_priv->display_count--;
+	WARN_ON(dev_priv->display_count < 0);
+	pm_runtime_put(&dev->pdev->dev);
+}
+
+int psb_runtime_suspend(struct device *dev)
+{
+	static pm_message_t dummy;
+	return gma_power_suspend(to_pci_dev(dev), dummy);
+}
+
+int psb_runtime_resume(struct device *dev)
+{
+	return 0;
+}
+
+int psb_runtime_idle(struct device *dev)
+{
+	struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev));
+	struct drm_psb_private *dev_priv = drmdev->dev_private;
+	if (dev_priv->display_count)
+		return 0;
+	else
+		return 1;
+}
+
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
new file mode 100644
index 0000000..97e25ab
--- /dev/null
+++ b/drivers/staging/gma500/psb_device.c
@@ -0,0 +1,174 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+
+static int psb_output_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	psb_intel_lvds_init(dev, &dev_priv->mode_dev);
+	psb_intel_sdvo_init(dev, SDVOB);
+	return 0;
+}
+
+/*
+ *	Provide the Poulsbo specific chip logic and low level methods
+ */
+
+static void psb_init_pm(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
+	gating &= ~3;	/* Disable 2D clock gating */
+	gating |= 1;
+	PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
+	PSB_RSGX32(PSB_CR_CLKGATECTL);
+}
+
+/**
+ *	psb_save_display_registers	-	save registers lost on suspend
+ *	@dev: our DRM device
+ *
+ *	Save the state we need in order to be able to restore the interface
+ *	upon resume from suspend
+ */
+static int psb_save_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+
+	/* Display arbitration control + watermarks */
+	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+	/* Save crtc and output state */
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (drm_helper_crtc_in_use(crtc))
+			crtc->funcs->save(crtc);
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		connector->funcs->save(connector);
+
+	mutex_unlock(&dev->mode_config.mutex);
+	return 0;
+}
+
+/**
+ *	psb_restore_display_registers	-	restore lost register state
+ *	@dev: our DRM device
+ *
+ *	Restore register state that was lost during suspend and resume.
+ */
+static int psb_restore_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+	int pp_stat;
+
+	/* Display arbitration + watermarks */
+	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+	/*make sure VGA plane is off. it initializes to on after reset!*/
+	PSB_WVDC32(0x80000000, VGACNTRL);
+
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		if (drm_helper_crtc_in_use(crtc))
+			crtc->funcs->restore(crtc);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		connector->funcs->restore(connector);
+
+	mutex_unlock(&dev->mode_config.mutex);
+
+	if (dev_priv->iLVDS_enable) {
+		/*shutdown the panel*/
+		PSB_WVDC32(0, PP_CONTROL);
+		do {
+			pp_stat = PSB_RVDC32(PP_STATUS);
+		} while (pp_stat & 0x80000000);
+
+		/* Turn off the plane */
+		PSB_WVDC32(0x58000000, DSPACNTR);
+		PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
+		/* Wait ~4 ticks */
+		msleep(4);
+		/* Turn off pipe */
+		PSB_WVDC32(0x0, PIPEACONF);
+		/* Wait ~8 ticks */
+		msleep(8);
+
+		/* Turn off PLLs */
+		PSB_WVDC32(0, MRST_DPLL_A);
+	} else {
+		PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
+		PSB_WVDC32(0x0, PIPEACONF);
+		PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
+		while (REG_READ(0x70008) & 0x40000000)
+			cpu_relax();
+		while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
+			!= DPI_FIFO_EMPTY)
+			cpu_relax();
+		PSB_WVDC32(0, DEVICE_READY_REG);
+	}
+	return 0;
+}
+
+int psb_power_down(struct drm_device *dev)
+{
+	return 0;
+}
+
+int psb_power_up(struct drm_device *dev)
+{
+	return 0;
+}
+
+const struct psb_ops psb_chip_ops = {
+	.output_init = psb_output_init,
+	.init_pm = psb_init_pm,
+	.save_regs = psb_save_display_registers,
+	.restore_regs = psb_restore_display_registers,
+	.power_down = psb_power_down,
+	.power_up = psb_power_up,
+};
+
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 0d65f75..6c57234 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -49,24 +49,24 @@ module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
 
 
 static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
-	{ 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8108 },
-	{ 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8109 },
-	{ 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MRST_4100},
-	{ 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
-	{ 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
-	{ 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
-	{ 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
-	{ 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
-	{ 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
-	{ 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
-	{ 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_MFLD_0130},
+	{ 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
+	{ 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
+	{ 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+	{ 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
 	{ 0, 0, 0}
 };
 MODULE_DEVICE_TABLE(pci, pciidlist);
@@ -257,8 +257,7 @@ out_err:
 
 static int psb_driver_unload(struct drm_device *dev)
 {
-	struct drm_psb_private *dev_priv =
-	    (struct drm_psb_private *) dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 
 	/* Kill vblank etc here */
 
@@ -332,6 +331,10 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	if (dev_priv == NULL)
 		return -ENOMEM;
 
+	dev_priv->ops = (struct psb_ops *)chipset;
+	dev_priv->dev = dev;
+	dev->dev_private = (void *) dev_priv;
+
 	if (IS_MRST(dev))
 		dev_priv->num_pipe = 1;
 	else if (IS_MFLD(dev))
@@ -339,10 +342,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	else
 		dev_priv->num_pipe = 2;
 
-	dev_priv->dev = dev;
-
-	dev->dev_private = (void *) dev_priv;
-	dev_priv->chipset = chipset;
 
 	resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
 
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 3b2ee08..d1c49e7 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -258,11 +258,11 @@ struct psb_intel_opregion {
 	int enabled;
 };
 
+struct psb_ops;
 
 struct drm_psb_private {
 	struct drm_device *dev;
-
-	unsigned long chipset;
+	const struct psb_ops *ops;
 
 	struct psb_gtt *pg;
 
@@ -612,6 +612,23 @@ struct drm_psb_private {
 };
 
 
+/*
+ *	Operations for each board type
+ */
+ 
+struct psb_ops {
+	/* Display management hooks */
+	int (*output_init)(struct drm_device *dev);
+	/* Power management hooks */
+	void (*init_pm)(struct drm_device *dev);
+	int (*save_regs)(struct drm_device *dev);
+	int (*restore_regs)(struct drm_device *dev);
+	int (*power_up)(struct drm_device *dev);
+	int (*power_down)(struct drm_device *dev);
+};
+
+
+
 struct psb_mmu_driver;
 
 extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
@@ -761,6 +778,14 @@ extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
 			 uint32_t handle, uint64_t *offset);
 extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 
+/* psb_device.c */
+extern const struct psb_ops psb_chip_ops;
+
+/* mrst_device.c */
+extern const struct psb_ops mrst_chip_ops;
+
+/* mdfld_device.c */
+extern const struct psb_ops mdfld_chip_ops;
 
 /*
  * Debug print bits setting
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 83095fc..32d9016 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -725,17 +725,7 @@ static void psb_setup_outputs(struct drm_device *dev)
 	drm_mode_create_scaling_mode_property(dev);
 	psb_create_backlight_property(dev);
 
-	if (IS_MRST(dev)) {
-		if (dev_priv->iLVDS_enable)
-			mrst_lvds_init(dev, &dev_priv->mode_dev);
-		else
-			dev_err(dev->dev, "DSI is not supported\n");
-	} else if (IS_MFLD(dev)) {
-		mdfld_output_init(dev);
-	} else {
-		psb_intel_lvds_init(dev, &dev_priv->mode_dev);
-		psb_intel_sdvo_init(dev, SDVOB);
-	}
+	dev_priv->ops->output_init(dev);
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list,
 			    head) {
diff --git a/drivers/staging/gma500/psb_powermgmt.c b/drivers/staging/gma500/psb_powermgmt.c
deleted file mode 100644
index 2253ecb..0000000
--- a/drivers/staging/gma500/psb_powermgmt.c
+++ /dev/null
@@ -1,1051 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2009-2011, Intel Corporation.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *    Benjamin Defnet <benjamin.r.defnet@intel.com>
- *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
- * Massively reworked
- *    Alan Cox <alan@linux.intel.com>
- */
-#include "psb_powermgmt.h"
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "psb_intel_reg.h"
-#include "mdfld_output.h"
-#include "mdfld_dsi_output.h"
-#include <linux/mutex.h>
-#include <linux/pm_runtime.h>
-#include <asm/intel_scu_ipc.h>
-
-/* IPC message and command defines used to enable/disable mipi panel voltages */
-#define IPC_MSG_PANEL_ON_OFF    0xE9
-#define IPC_CMD_PANEL_ON        1
-#define IPC_CMD_PANEL_OFF       0
-
-static struct mutex power_mutex;
-
-/**
- *	gma_power_init		-	initialise power manager
- *	@dev: our device
- *
- *	Set up for power management tracking of our hardware.
- */
-void gma_power_init(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	/* FIXME: need to sort out fetching apm_reg for both platforms ?? */
-
-	dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
-	dev_priv->ospm_base &= 0xffff;
-
-	dev_priv->display_power = true;	/* We start active */
-	dev_priv->display_count = 0;	/* Currently no users */
-	dev_priv->suspended = false;	/* And not suspended */
-	mutex_init(&power_mutex);
-
-	if (!IS_MRST(dev) && !IS_MFLD(dev)) {
-		/* FIXME: wants further review */
-		u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
-		/* Disable 2D clock gating */
-		gating &= ~3;
-		gating |= 1;
-		PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
-		PSB_RSGX32(PSB_CR_CLKGATECTL);
-	}
-}
-
-/**
- *	gma_power_uninit	-	end power manager
- *	@dev: device to end for
- *
- *	Undo the effects of gma_power_init
- */
-void gma_power_uninit(struct drm_device *dev)
-{
-	mutex_destroy(&power_mutex);
-	pm_runtime_disable(&dev->pdev->dev);
-	pm_runtime_set_suspended(&dev->pdev->dev);
-}
-
-
-/**
- *	save_display_registers	-	save registers lost on suspend
- *	@dev: our DRM device
- *
- *	Save the state we need in order to be able to restore the interface
- *	upon resume from suspend
- */
-static int save_display_registers(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	struct drm_connector *connector;
-
-	/* Display arbitration control + watermarks */
-	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
-	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
-	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
-	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
-	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
-	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
-	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
-	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
-
-	/* Save crtc and output state */
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		if (drm_helper_crtc_in_use(crtc))
-			crtc->funcs->save(crtc);
-	}
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-		connector->funcs->save(connector);
-
-	mutex_unlock(&dev->mode_config.mutex);
-	return 0;
-}
-
-/**
- *	restore_display_registers	-	restore lost register state
- *	@dev: our DRM device
- *
- *	Restore register state that was lost during suspend and resume.
- */
-static int restore_display_registers(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	struct drm_connector *connector;
-
-	/* Display arbitration + watermarks */
-	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
-	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
-	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
-	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
-	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
-	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
-	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
-	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
-
-	/*make sure VGA plane is off. it initializes to on after reset!*/
-	PSB_WVDC32(0x80000000, VGACNTRL);
-
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-		if (drm_helper_crtc_in_use(crtc))
-			crtc->funcs->restore(crtc);
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-		connector->funcs->restore(connector);
-
-	mutex_unlock(&dev->mode_config.mutex);
-	return 0;
-}
-
-/**
- * mdfld_save_display_registers	-	save registers for pipe
- * @dev: our device
- * @pipe: pipe to save
- *
- * Save the pipe state of the device before we power it off. Keep everything
- * we need to put it back again
- */
-static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int i;
-
-	/* register */
-	u32 dpll_reg = MRST_DPLL_A;
-	u32 fp_reg = MRST_FPA0;
-	u32 pipeconf_reg = PIPEACONF;
-	u32 htot_reg = HTOTAL_A;
-	u32 hblank_reg = HBLANK_A;
-	u32 hsync_reg = HSYNC_A;
-	u32 vtot_reg = VTOTAL_A;
-	u32 vblank_reg = VBLANK_A;
-	u32 vsync_reg = VSYNC_A;
-	u32 pipesrc_reg = PIPEASRC;
-	u32 dspstride_reg = DSPASTRIDE;
-	u32 dsplinoff_reg = DSPALINOFF;
-	u32 dsptileoff_reg = DSPATILEOFF;
-	u32 dspsize_reg = DSPASIZE;
-	u32 dsppos_reg = DSPAPOS;
-	u32 dspsurf_reg = DSPASURF;
-	u32 mipi_reg = MIPI;
-	u32 dspcntr_reg = DSPACNTR;
-	u32 dspstatus_reg = PIPEASTAT;
-	u32 palette_reg = PALETTE_A;
-
-	/* pointer to values */
-	u32 *dpll_val = &dev_priv->saveDPLL_A;
-	u32 *fp_val = &dev_priv->saveFPA0;
-	u32 *pipeconf_val = &dev_priv->savePIPEACONF;
-	u32 *htot_val = &dev_priv->saveHTOTAL_A;
-	u32 *hblank_val = &dev_priv->saveHBLANK_A;
-	u32 *hsync_val = &dev_priv->saveHSYNC_A;
-	u32 *vtot_val = &dev_priv->saveVTOTAL_A;
-	u32 *vblank_val = &dev_priv->saveVBLANK_A;
-	u32 *vsync_val = &dev_priv->saveVSYNC_A;
-	u32 *pipesrc_val = &dev_priv->savePIPEASRC;
-	u32 *dspstride_val = &dev_priv->saveDSPASTRIDE;
-	u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF;
-	u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF;
-	u32 *dspsize_val = &dev_priv->saveDSPASIZE;
-	u32 *dsppos_val = &dev_priv->saveDSPAPOS;
-	u32 *dspsurf_val = &dev_priv->saveDSPASURF;
-	u32 *mipi_val = &dev_priv->saveMIPI;
-	u32 *dspcntr_val = &dev_priv->saveDSPACNTR;
-	u32 *dspstatus_val = &dev_priv->saveDSPASTATUS;
-	u32 *palette_val = dev_priv->save_palette_a;
-
-	switch (pipe) {
-	case 0:
-		break;
-	case 1:
-		/* register */
-		dpll_reg = MDFLD_DPLL_B;
-		fp_reg = MDFLD_DPLL_DIV0;
-		pipeconf_reg = PIPEBCONF;
-		htot_reg = HTOTAL_B;
-		hblank_reg = HBLANK_B;
-		hsync_reg = HSYNC_B;
-		vtot_reg = VTOTAL_B;
-		vblank_reg = VBLANK_B;
-		vsync_reg = VSYNC_B;
-		pipesrc_reg = PIPEBSRC;
-		dspstride_reg = DSPBSTRIDE;
-		dsplinoff_reg = DSPBLINOFF;
-		dsptileoff_reg = DSPBTILEOFF;
-		dspsize_reg = DSPBSIZE;
-		dsppos_reg = DSPBPOS;
-		dspsurf_reg = DSPBSURF;
-		dspcntr_reg = DSPBCNTR;
-		dspstatus_reg = PIPEBSTAT;
-		palette_reg = PALETTE_B;
-
-		/* values */
-		dpll_val = &dev_priv->saveDPLL_B;
-		fp_val = &dev_priv->saveFPB0;
-		pipeconf_val = &dev_priv->savePIPEBCONF;
-		htot_val = &dev_priv->saveHTOTAL_B;
-		hblank_val = &dev_priv->saveHBLANK_B;
-		hsync_val = &dev_priv->saveHSYNC_B;
-		vtot_val = &dev_priv->saveVTOTAL_B;
-		vblank_val = &dev_priv->saveVBLANK_B;
-		vsync_val = &dev_priv->saveVSYNC_B;
-		pipesrc_val = &dev_priv->savePIPEBSRC;
-		dspstride_val = &dev_priv->saveDSPBSTRIDE;
-		dsplinoff_val = &dev_priv->saveDSPBLINOFF;
-		dsptileoff_val = &dev_priv->saveDSPBTILEOFF;
-		dspsize_val = &dev_priv->saveDSPBSIZE;
-		dsppos_val = &dev_priv->saveDSPBPOS;
-		dspsurf_val = &dev_priv->saveDSPBSURF;
-		dspcntr_val = &dev_priv->saveDSPBCNTR;
-		dspstatus_val = &dev_priv->saveDSPBSTATUS;
-		palette_val = dev_priv->save_palette_b;
-		break;
-	case 2:
-		/* register */
-		pipeconf_reg = PIPECCONF;
-		htot_reg = HTOTAL_C;
-		hblank_reg = HBLANK_C;
-		hsync_reg = HSYNC_C;
-		vtot_reg = VTOTAL_C;
-		vblank_reg = VBLANK_C;
-		vsync_reg = VSYNC_C;
-		pipesrc_reg = PIPECSRC;
-		dspstride_reg = DSPCSTRIDE;
-		dsplinoff_reg = DSPCLINOFF;
-		dsptileoff_reg = DSPCTILEOFF;
-		dspsize_reg = DSPCSIZE;
-		dsppos_reg = DSPCPOS;
-		dspsurf_reg = DSPCSURF;
-		mipi_reg = MIPI_C;
-		dspcntr_reg = DSPCCNTR;
-		dspstatus_reg = PIPECSTAT;
-		palette_reg = PALETTE_C;
-
-		/* pointer to values */
-		pipeconf_val = &dev_priv->savePIPECCONF;
-		htot_val = &dev_priv->saveHTOTAL_C;
-		hblank_val = &dev_priv->saveHBLANK_C;
-		hsync_val = &dev_priv->saveHSYNC_C;
-		vtot_val = &dev_priv->saveVTOTAL_C;
-		vblank_val = &dev_priv->saveVBLANK_C;
-		vsync_val = &dev_priv->saveVSYNC_C;
-		pipesrc_val = &dev_priv->savePIPECSRC;
-		dspstride_val = &dev_priv->saveDSPCSTRIDE;
-		dsplinoff_val = &dev_priv->saveDSPCLINOFF;
-		dsptileoff_val = &dev_priv->saveDSPCTILEOFF;
-		dspsize_val = &dev_priv->saveDSPCSIZE;
-		dsppos_val = &dev_priv->saveDSPCPOS;
-		dspsurf_val = &dev_priv->saveDSPCSURF;
-		mipi_val = &dev_priv->saveMIPI_C;
-		dspcntr_val = &dev_priv->saveDSPCCNTR;
-		dspstatus_val = &dev_priv->saveDSPCSTATUS;
-		palette_val = dev_priv->save_palette_c;
-		break;
-	default:
-		DRM_ERROR("%s, invalid pipe number.\n", __func__);
-		return -EINVAL;
-	}
-
-	/* Pipe & plane A info */
-	*dpll_val = PSB_RVDC32(dpll_reg);
-	*fp_val = PSB_RVDC32(fp_reg);
-	*pipeconf_val = PSB_RVDC32(pipeconf_reg);
-	*htot_val = PSB_RVDC32(htot_reg);
-	*hblank_val = PSB_RVDC32(hblank_reg);
-	*hsync_val = PSB_RVDC32(hsync_reg);
-	*vtot_val = PSB_RVDC32(vtot_reg);
-	*vblank_val = PSB_RVDC32(vblank_reg);
-	*vsync_val = PSB_RVDC32(vsync_reg);
-	*pipesrc_val = PSB_RVDC32(pipesrc_reg);
-	*dspstride_val = PSB_RVDC32(dspstride_reg);
-	*dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
-	*dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
-	*dspsize_val = PSB_RVDC32(dspsize_reg);
-	*dsppos_val = PSB_RVDC32(dsppos_reg);
-	*dspsurf_val = PSB_RVDC32(dspsurf_reg);
-	*dspcntr_val = PSB_RVDC32(dspcntr_reg);
-	*dspstatus_val = PSB_RVDC32(dspstatus_reg);
-
-	/*save palette (gamma) */
-	for (i = 0; i < 256; i++)
-		palette_val[i] = PSB_RVDC32(palette_reg + (i<<2));
-
-	if (pipe == 1) {
-		dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
-		dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
-		dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
-		dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
-		return 0;
-	}
-	*mipi_val = PSB_RVDC32(mipi_reg);
-	return 0;
-}
-
-/**
- * mdfld_save_cursor_overlay_registers	-	save cursor overlay info
- * @dev: our device
- *
- * Save the cursor and overlay register state
- */
-static int mdfld_save_cursor_overlay_registers(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	/* Save cursor regs */
-	dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
-	dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
-	dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
-
-	dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
-	dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
-	dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
-
-	dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR);
-	dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE);
-	dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS);
-
-	/* HW overlay */
-	dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
-	dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
-	dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
-	dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
-	dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
-	dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
-	dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
-
-	dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET);
-	dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET);
-	dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET);
-	dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET);
-	dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET);
-	dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET);
-	dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET);
-
-	return 0;
-}
-/*
- * mdfld_restore_display_registers	-	restore the state of a pipe
- * @dev: our device
- * @pipe: the pipe to restore
- *
- * Restore the state of a pipe to that which was saved by the register save
- * functions.
- */
-static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
-{
-	/* To get  panel out of ULPS mode */
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct mdfld_dsi_config *dsi_config = NULL;
-	u32 i = 0;
-	u32 dpll = 0;
-	u32 timeout = 0;
-	u32 reg_offset = 0;
-
-	/* register */
-	u32 dpll_reg = MRST_DPLL_A;
-	u32 fp_reg = MRST_FPA0;
-	u32 pipeconf_reg = PIPEACONF;
-	u32 htot_reg = HTOTAL_A;
-	u32 hblank_reg = HBLANK_A;
-	u32 hsync_reg = HSYNC_A;
-	u32 vtot_reg = VTOTAL_A;
-	u32 vblank_reg = VBLANK_A;
-	u32 vsync_reg = VSYNC_A;
-	u32 pipesrc_reg = PIPEASRC;
-	u32 dspstride_reg = DSPASTRIDE;
-	u32 dsplinoff_reg = DSPALINOFF;
-	u32 dsptileoff_reg = DSPATILEOFF;
-	u32 dspsize_reg = DSPASIZE;
-	u32 dsppos_reg = DSPAPOS;
-	u32 dspsurf_reg = DSPASURF;
-	u32 dspstatus_reg = PIPEASTAT;
-	u32 mipi_reg = MIPI;
-	u32 dspcntr_reg = DSPACNTR;
-	u32 palette_reg = PALETTE_A;
-
-	/* values */
-	u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE;
-	u32 fp_val = dev_priv->saveFPA0;
-	u32 pipeconf_val = dev_priv->savePIPEACONF;
-	u32 htot_val = dev_priv->saveHTOTAL_A;
-	u32 hblank_val = dev_priv->saveHBLANK_A;
-	u32 hsync_val = dev_priv->saveHSYNC_A;
-	u32 vtot_val = dev_priv->saveVTOTAL_A;
-	u32 vblank_val = dev_priv->saveVBLANK_A;
-	u32 vsync_val = dev_priv->saveVSYNC_A;
-	u32 pipesrc_val = dev_priv->savePIPEASRC;
-	u32 dspstride_val = dev_priv->saveDSPASTRIDE;
-	u32 dsplinoff_val = dev_priv->saveDSPALINOFF;
-	u32 dsptileoff_val = dev_priv->saveDSPATILEOFF;
-	u32 dspsize_val = dev_priv->saveDSPASIZE;
-	u32 dsppos_val = dev_priv->saveDSPAPOS;
-	u32 dspsurf_val = dev_priv->saveDSPASURF;
-	u32 dspstatus_val = dev_priv->saveDSPASTATUS;
-	u32 mipi_val = dev_priv->saveMIPI;
-	u32 dspcntr_val = dev_priv->saveDSPACNTR;
-	u32 *palette_val = dev_priv->save_palette_a;
-
-	switch (pipe) {
-	case 0:
-		dsi_config = dev_priv->dsi_configs[0];
-		break;
-	case 1:
-		/* register */
-		dpll_reg = MDFLD_DPLL_B;
-		fp_reg = MDFLD_DPLL_DIV0;
-		pipeconf_reg = PIPEBCONF;
-		htot_reg = HTOTAL_B;
-		hblank_reg = HBLANK_B;
-		hsync_reg = HSYNC_B;
-		vtot_reg = VTOTAL_B;
-		vblank_reg = VBLANK_B;
-		vsync_reg = VSYNC_B;
-		pipesrc_reg = PIPEBSRC;
-		dspstride_reg = DSPBSTRIDE;
-		dsplinoff_reg = DSPBLINOFF;
-		dsptileoff_reg = DSPBTILEOFF;
-		dspsize_reg = DSPBSIZE;
-		dsppos_reg = DSPBPOS;
-		dspsurf_reg = DSPBSURF;
-		dspcntr_reg = DSPBCNTR;
-		palette_reg = PALETTE_B;
-		dspstatus_reg = PIPEBSTAT;
-
-		/* values */
-		dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE;
-		fp_val = dev_priv->saveFPB0;
-		pipeconf_val = dev_priv->savePIPEBCONF;
-		htot_val = dev_priv->saveHTOTAL_B;
-		hblank_val = dev_priv->saveHBLANK_B;
-		hsync_val = dev_priv->saveHSYNC_B;
-		vtot_val = dev_priv->saveVTOTAL_B;
-		vblank_val = dev_priv->saveVBLANK_B;
-		vsync_val = dev_priv->saveVSYNC_B;
-		pipesrc_val = dev_priv->savePIPEBSRC;
-		dspstride_val = dev_priv->saveDSPBSTRIDE;
-		dsplinoff_val = dev_priv->saveDSPBLINOFF;
-		dsptileoff_val = dev_priv->saveDSPBTILEOFF;
-		dspsize_val = dev_priv->saveDSPBSIZE;
-		dsppos_val = dev_priv->saveDSPBPOS;
-		dspsurf_val = dev_priv->saveDSPBSURF;
-		dspcntr_val = dev_priv->saveDSPBCNTR;
-		dspstatus_val = dev_priv->saveDSPBSTATUS;
-		palette_val = dev_priv->save_palette_b;
-		break;
-	case 2:
-		reg_offset = MIPIC_REG_OFFSET;
-
-		/* register */
-		pipeconf_reg = PIPECCONF;
-		htot_reg = HTOTAL_C;
-		hblank_reg = HBLANK_C;
-		hsync_reg = HSYNC_C;
-		vtot_reg = VTOTAL_C;
-		vblank_reg = VBLANK_C;
-		vsync_reg = VSYNC_C;
-		pipesrc_reg = PIPECSRC;
-		dspstride_reg = DSPCSTRIDE;
-		dsplinoff_reg = DSPCLINOFF;
-		dsptileoff_reg = DSPCTILEOFF;
-		dspsize_reg = DSPCSIZE;
-		dsppos_reg = DSPCPOS;
-		dspsurf_reg = DSPCSURF;
-		mipi_reg = MIPI_C;
-		dspcntr_reg = DSPCCNTR;
-		palette_reg = PALETTE_C;
-		dspstatus_reg = PIPECSTAT;
-
-		/* values */
-		pipeconf_val = dev_priv->savePIPECCONF;
-		htot_val = dev_priv->saveHTOTAL_C;
-		hblank_val = dev_priv->saveHBLANK_C;
-		hsync_val = dev_priv->saveHSYNC_C;
-		vtot_val = dev_priv->saveVTOTAL_C;
-		vblank_val = dev_priv->saveVBLANK_C;
-		vsync_val = dev_priv->saveVSYNC_C;
-		pipesrc_val = dev_priv->savePIPECSRC;
-		dspstride_val = dev_priv->saveDSPCSTRIDE;
-		dsplinoff_val = dev_priv->saveDSPCLINOFF;
-		dsptileoff_val = dev_priv->saveDSPCTILEOFF;
-		dspsize_val = dev_priv->saveDSPCSIZE;
-		dsppos_val = dev_priv->saveDSPCPOS;
-		dspsurf_val = dev_priv->saveDSPCSURF;
-		dspstatus_val = dev_priv->saveDSPCSTATUS;
-		mipi_val = dev_priv->saveMIPI_C;
-		dspcntr_val = dev_priv->saveDSPCCNTR;
-		palette_val = dev_priv->save_palette_c;
-
-		dsi_config = dev_priv->dsi_configs[1];
-		break;
-	default:
-		DRM_ERROR("%s, invalid pipe number.\n", __func__);
-		return -EINVAL;
-	}
-
-	/* Make sure VGA plane is off. it initializes to on after reset!*/
-	PSB_WVDC32(0x80000000, VGACNTRL);
-	if (pipe == 1) {
-		PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
-		PSB_RVDC32(dpll_reg);
-
-		PSB_WVDC32(fp_val, fp_reg);
-	} else {
-		dpll = PSB_RVDC32(dpll_reg);
-
-		if (!(dpll & DPLL_VCO_ENABLE)) {
-
-			/* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
-			if (dpll & MDFLD_PWR_GATE_EN) {
-				dpll &= ~MDFLD_PWR_GATE_EN;
-				PSB_WVDC32(dpll, dpll_reg);
-				udelay(500);	/* FIXME: 1 ? */
-			}
-
-			PSB_WVDC32(fp_val, fp_reg);
-			PSB_WVDC32(dpll_val, dpll_reg);
-			/* FIXME_MDFLD PO - change 500 to 1 after PO */
-			udelay(500);
-
-			dpll_val |= DPLL_VCO_ENABLE;
-			PSB_WVDC32(dpll_val, dpll_reg);
-			PSB_RVDC32(dpll_reg);
-
-			/* wait for DSI PLL to lock */
-			while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
-				udelay(150);
-				timeout++;
-			}
-
-			if (timeout == 20000) {
-				DRM_ERROR("%s, can't lock DSIPLL.\n",
-							__func__);
-				return -EINVAL;
-			}
-		}
-	}
-	/* Restore mode */
-	PSB_WVDC32(htot_val, htot_reg);
-	PSB_WVDC32(hblank_val, hblank_reg);
-	PSB_WVDC32(hsync_val, hsync_reg);
-	PSB_WVDC32(vtot_val, vtot_reg);
-	PSB_WVDC32(vblank_val, vblank_reg);
-	PSB_WVDC32(vsync_val, vsync_reg);
-	PSB_WVDC32(pipesrc_val, pipesrc_reg);
-	PSB_WVDC32(dspstatus_val, dspstatus_reg);
-
-	/* Set up the plane */
-	PSB_WVDC32(dspstride_val, dspstride_reg);
-	PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
-	PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
-	PSB_WVDC32(dspsize_val, dspsize_reg);
-	PSB_WVDC32(dsppos_val, dsppos_reg);
-	PSB_WVDC32(dspsurf_val, dspsurf_reg);
-
-	if (pipe == 1) {
-		PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
-		PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
-		PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL);
-		PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL);
-
-	} else {
-		/* Set up pipe related registers */
-		PSB_WVDC32(mipi_val, mipi_reg);
-		/* Setup MIPI adapter + MIPI IP registers */
-		mdfld_dsi_controller_init(dsi_config, pipe);
-		msleep(20);
-	}
-	/* Enable the plane */
-	PSB_WVDC32(dspcntr_val, dspcntr_reg);
-	msleep(20);
-	/* Enable the pipe */
-	PSB_WVDC32(pipeconf_val, pipeconf_reg);
-
-	for (i = 0; i < 256; i++)
-		PSB_WVDC32(palette_val[i], palette_reg + (i<<2));
-	if (pipe == 1)
-		return 0;
-	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
-		mdfld_enable_te(dev, pipe);
-	return 0;
-}
-
-/**
- * mdfld_restore_cursor_overlay_registers	-	restore cursor
- * @dev: our device
- *
- * Restore the cursor and overlay state that was saved earlier
- */
-static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	/* Enable Cursor A */
-	PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
-	PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
-	PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
-
-	PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
-	PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
-	PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
-
-	PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR);
-	PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS);
-	PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE);
-
-	/* Restore HW overlay */
-	PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
-
-	PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET);
-	PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET);
-
-	return 0;
-}
-
-/**
- *	power_down	-	power down the display island
- *	@dev: our DRM device
- *
- *	Power down the display interface of our device
- */
-static void power_down(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 pwr_mask ;
-	u32 pwr_sts;
-
-	if (IS_MRST(dev)) {
-		pwr_mask = PSB_PWRGT_DISPLAY_MASK;
-		outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
-
-		while (true) {
-			pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
-			if ((pwr_sts & pwr_mask) == pwr_mask)
-				break;
-			else
-				udelay(10);
-		}
-		dev_priv->display_power = false;
-	}
-}
-
-
-/**
- *	gma_suspend_display	-	suspend the display logic
- *	@dev: our DRM device
- *
- *	Suspend the display logic of the graphics interface
- *
- *	FIXME: This ought to be replaced by a dev_priv-> ops interface
- *	where the various platforms register their save/restore methods
- *	and keep them in their own support files.
- */
-static void gma_suspend_display(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int pp_stat;
-
-	if (dev_priv->suspended)
-		return;
-
-	if (IS_MFLD(dev)) {
-		/* FIXME: We need to shut down panels here if using them
-		   and once the right bits are merged */
-		mdfld_save_cursor_overlay_registers(dev);
-		mdfld_save_display_registers(dev, 0);
-		mdfld_save_display_registers(dev, 0);
-		mdfld_save_display_registers(dev, 2);
-		mdfld_save_display_registers(dev, 1);
-		mdfld_disable_crtc(dev, 0);
-		mdfld_disable_crtc(dev, 2);
-		mdfld_disable_crtc(dev, 1);
-	} else {
-		save_display_registers(dev);
-
-		if (dev_priv->iLVDS_enable) {
-			/*shutdown the panel*/
-			PSB_WVDC32(0, PP_CONTROL);
-
-			do {
-				pp_stat = PSB_RVDC32(PP_STATUS);
-			} while (pp_stat & 0x80000000);
-
-			/* Turn off the plane */
-			PSB_WVDC32(0x58000000, DSPACNTR);
-			PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
-			/* Wait ~4 ticks */
-			msleep(4);
-
-			/* Turn off pipe */
-			PSB_WVDC32(0x0, PIPEACONF);
-			/* Wait ~8 ticks */
-			msleep(8);
-
-			/* Turn off PLLs */
-			PSB_WVDC32(0, MRST_DPLL_A);
-		} else {
-			PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
-			PSB_WVDC32(0x0, PIPEACONF);
-			PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
-			while (REG_READ(0x70008) & 0x40000000)
-				cpu_relax();
-			while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
-				!= DPI_FIFO_EMPTY)
-				cpu_relax();
-			PSB_WVDC32(0, DEVICE_READY_REG);
-			/* Turn off panel power */
-#ifdef CONFIG_X86_MRST
-			intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
-							IPC_CMD_PANEL_OFF);
-#endif
-		}
-	}
-	power_down(dev);
-}
-
-/*
- * power_up
- *
- * Description: Restore power to the specified island(s) (powergating)
- */
-static void power_up(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
-	u32 pwr_sts, pwr_cnt;
-
-	if (IS_MRST(dev)) {
-		pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
-		pwr_cnt &= ~pwr_mask;
-		outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
-
-		while (true) {
-			pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
-			if ((pwr_sts & pwr_mask) == 0)
-				break;
-			else
-				udelay(10);
-		}
-	}
-	dev_priv->suspended = false;
-	dev_priv->display_power = true;
-}
-
-/**
- *	gma_resume_display	-	resume display side logic
- *
- *	Resume the display hardware restoring state and enabling
- *	as necessary.
- */
-static void gma_resume_display(struct pci_dev *pdev)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	if (dev_priv->suspended == false)
-		return;
-
-	/* turn on the display power island */
-	power_up(dev);
-
-	PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
-	pci_write_config_word(pdev, PSB_GMCH_CTRL,
-			dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
-
-	/* Don't reinitialize the GTT as it is unnecessary.  The gtt is
-	 * stored in memory so it will automatically be restored.  All
-	 * we need to do is restore the PGETBL_CTL which we already do
-	 * above.
-	 */
-	/*psb_gtt_init(dev_priv->pg, 1);*/
-	if (IS_MFLD(dev)) {
-		mdfld_restore_display_registers(dev, 1);
-		mdfld_restore_display_registers(dev, 0);
-		mdfld_restore_display_registers(dev, 2);
-		mdfld_restore_cursor_overlay_registers(dev);
-	} else if (IS_MRST(dev)) {
-		if (!dev_priv->iLVDS_enable) {
-#ifdef CONFIG_X86_MRST
-			intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
-							IPC_CMD_PANEL_ON);
-			/* FIXME: can we avoid this delay ? */
-			msleep(2000); /* wait 2 seconds */
-#endif
-		}
-	}
-	restore_display_registers(dev);
-}
-
-/**
- *	gma_suspend_pci		-	suspend PCI side
- *	@pdev: PCI device
- *
- *	Perform the suspend processing on our PCI device state
- */
-static void gma_suspend_pci(struct pci_dev *pdev)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int bsm, vbt;
-
-	if (dev_priv->suspended)
-		return;
-
-	pci_save_state(pdev);
-	pci_read_config_dword(pdev, 0x5C, &bsm);
-	dev_priv->saveBSM = bsm;
-	pci_read_config_dword(pdev, 0xFC, &vbt);
-	dev_priv->saveVBT = vbt;
-	pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
-	pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
-
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	dev_priv->suspended = true;
-}
-
-/**
- *	gma_resume_pci		-	resume helper
- *	@dev: our PCI device
- *
- *	Perform the resume processing on our PCI device state - rewrite
- *	register state and re-enable the PCI device
- */
-static bool gma_resume_pci(struct pci_dev *pdev)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int ret;
-
-	if (!dev_priv->suspended)
-		return true;
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
-	pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
-	/* retoring MSI address and data in PCIx space */
-	pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
-	pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
-	ret = pci_enable_device(pdev);
-
-	if (ret != 0)
-		dev_err(&pdev->dev, "pci_enable failed: %d\n", ret);
-	else
-		dev_priv->suspended = false;
-	return !dev_priv->suspended;
-}
-
-/**
- *	gma_power_suspend		-	bus callback for suspend
- *	@pdev: our PCI device
- *	@state: suspend type
- *
- *	Called back by the PCI layer during a suspend of the system. We
- *	perform the necessary shut down steps and save enough state that
- *	we can undo this when resume is called.
- */
-int gma_power_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	mutex_lock(&power_mutex);
-	if (!dev_priv->suspended) {
-		if (dev_priv->display_count) {
-			mutex_unlock(&power_mutex);
-			return -EBUSY;
-		}
-		psb_irq_uninstall(dev);
-		gma_suspend_display(dev);
-		gma_suspend_pci(pdev);
-	}
-	mutex_unlock(&power_mutex);
-	return 0;
-}
-
-
-/**
- *	gma_power_resume		-	resume power
- *	@pdev: PCI device
- *
- *	Resume the PCI side of the graphics and then the displays
- */
-int gma_power_resume(struct pci_dev *pdev)
-{
-	struct drm_device *dev = pci_get_drvdata(pdev);
-
-	mutex_lock(&power_mutex);
-	gma_resume_pci(pdev);
-	gma_resume_display(pdev);
-	psb_irq_preinstall(dev);
-	psb_irq_postinstall(dev);
-	mutex_unlock(&power_mutex);
-	return 0;
-}
-
-
-
-/**
- *	gma_power_is_on		-	returne true if power is on
- *	@dev: our DRM device
- *
- *	Returns true if the display island power is on at this moment
- */
-bool gma_power_is_on(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	return dev_priv->display_power;
-}
-
-
-/**
- *	gma_power_begin		-	begin requiring power
- *	@dev: our DRM device
- *	@force_on: true to force power on
- *
- *	Begin an action that requires the display power island is enabled.
- *	We refcount the islands.
- *
- *	FIXME: locking
- */
-bool gma_power_begin(struct drm_device *dev, bool force_on)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int ret;
-
-	/* Power already on ? */
-	if (dev_priv->display_power) {
-		dev_priv->display_count++;
-		pm_runtime_get(&dev->pdev->dev);
-		return true;
-	}
-	if (force_on == false)
-		return false;
-
-	/* Ok power up needed */
-	ret = gma_resume_pci(dev->pdev);
-	if (ret == 0) {
-		psb_irq_preinstall(dev);
-		psb_irq_postinstall(dev);
-		pm_runtime_get(&dev->pdev->dev);
-		dev_priv->display_count++;
-		return true;
-	}
-	return false;
-}
-
-
-/**
- *	gma_power_end		-	end use of power
- *	@dev: Our DRM device
- *
- *	Indicate that one of our gma_power_begin() requested periods when
- *	the diplay island power is needed has completed.
- */
-void gma_power_end(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	dev_priv->display_count--;
-	WARN_ON(dev_priv->display_count < 0);
-	pm_runtime_put(&dev->pdev->dev);
-}
-
-int psb_runtime_suspend(struct device *dev)
-{
-	static pm_message_t dummy;
-	return gma_power_suspend(to_pci_dev(dev), dummy);
-}
-
-int psb_runtime_resume(struct device *dev)
-{
-	return 0;
-}
-
-int psb_runtime_idle(struct device *dev)
-{
-	struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev));
-	struct drm_psb_private *dev_priv = drmdev->dev_private;
-	if (dev_priv->display_count)
-		return 0;
-	else
-		return 1;
-}
-


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 21/49] gma500: continue abstracting platform specific code
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (19 preceding siblings ...)
  2011-07-05 14:38 ` [PATCH 20/49] gma500: being abstracting out devices a bit more Alan Cox
@ 2011-07-05 14:38 ` Alan Cox
  2011-07-05 14:38 ` [PATCH 22/49] gma500: Fix early Medfield crash Alan Cox
                   ` (28 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:38 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Next obvious target - backlight support

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile           |    2 
 drivers/staging/gma500/backlight.c        |   46 +++++
 drivers/staging/gma500/mdfld_device.c     |   94 ++++++++++
 drivers/staging/gma500/mdfld_dsi_output.c |   11 +
 drivers/staging/gma500/mrst_device.c      |  137 ++++++++++++++
 drivers/staging/gma500/psb_bl.c           |  283 -----------------------------
 drivers/staging/gma500/psb_device.c       |  125 +++++++++++++
 drivers/staging/gma500/psb_drv.c          |   20 +-
 drivers/staging/gma500/psb_drv.h          |   15 +-
 drivers/staging/gma500/psb_intel_lvds.c   |   31 ++-
 10 files changed, 445 insertions(+), 319 deletions(-)
 create mode 100644 drivers/staging/gma500/backlight.c
 delete mode 100644 drivers/staging/gma500/psb_bl.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index e93cbe3..dc02b2f 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -4,8 +4,8 @@
 ccflags-y += -Iinclude/drm
 
 psb_gfx-y += gem_glue.o \
+	  backlight.o \
 	  power.o \
-	  psb_bl.o \
 	  psb_drv.o \
 	  psb_gem.o \
 	  psb_fb.o \
diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c
new file mode 100644
index 0000000..47681c9
--- /dev/null
+++ b/drivers/staging/gma500/backlight.c
@@ -0,0 +1,46 @@
+/*
+ * GMA500 Backlight Interface
+ *
+ * Copyright (c) 2009-2011, Intel Corporation.
+ *
+ * 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: Eric Knopp
+ *
+ */
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_bios.h"
+#include "psb_powermgmt.h"
+
+int gma_backlight_init(struct drm_device *dev)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	return dev_priv->ops->backlight_init(dev);
+#endif
+}
+
+void gma_backlight_exit(struct drm_device *dev)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	dev_priv->backlight_device->props.brightness = 0;
+	backlight_update_status(dev_priv->backlight_device);
+	if (dev_priv->backlight_device)
+		backlight_device_unregister(dev_priv->backlight_device);
+#endif
+}
diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
index 7caa7cd..e86e476 100644
--- a/drivers/staging/gma500/mdfld_device.c
+++ b/drivers/staging/gma500/mdfld_device.c
@@ -17,6 +17,7 @@
  *
  **************************************************************************/
 
+#include <linux/backlight.h>
 #include <drm/drmP.h>
 #include <drm/drm.h>
 #include "psb_reg.h"
@@ -27,7 +28,93 @@
 #include "mdfld_dsi_output.h"
 
 /*
- *	Provide the Medfield specific chip logic and low level methods
+ *	Provide the Medfield specific backlight management
+ */
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+static int mdfld_brightness;
+struct backlight_device *mdfld_backlight_device;
+
+static int mfld_set_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(mdfld_backlight_device);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int level = bd->props.brightness;
+
+	/* Percentage 1-100% being valid */
+	if (level < 1)
+		level = 1;
+
+	if (gma_power_begin(dev, 0)) {
+		/* Calculate and set the brightness value */
+		u32 adjusted_level;
+
+		/* Adjust the backlight level with the percent in
+		 * dev_priv->blc_adj2;
+		 */
+		adjusted_level = level * dev_priv->blc_adj2;
+		adjusted_level = adjusted_level / 100;
+#if 0
+#ifndef CONFIG_MDFLD_DSI_DPU
+		if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) && 
+			(dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
+			mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0);
+			dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level);
+		}
+#endif
+		mdfld_dsi_brightness_control(dev, 0, adjusted_level);
+
+		if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
+			mdfld_dsi_brightness_control(dev, 2, adjusted_level);
+#endif
+		gma_power_end(dev);
+	}
+	mdfld_brightness = level;
+	return 0;
+}
+
+int psb_get_brightness(struct backlight_device *bd)
+{
+	/* return locally cached var instead of HW read (due to DPST etc.) */
+	/* FIXME: ideally return actual value in case firmware fiddled with
+	   it */
+	return mdfld_brightness;
+}
+
+static const struct backlight_ops mfld_ops = {
+	.get_brightness = psb_get_brightness,
+	.update_status  = mfld_set_brightness,
+};
+
+static int mdfld_backlight_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct backlight_properties props;
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = 100;
+	props.type = BACKLIGHT_PLATFORM;
+
+	mdfld_backlight_device = backlight_device_register("mfld-bl",
+					NULL, (void *)dev, &mfld_ops, &props);
+					
+	if (IS_ERR(mdfld_backlight_device))
+		return PTR_ERR(mdfld_backlight_device);
+
+	dev_priv->blc_adj1 = 100;
+	dev_priv->blc_adj2 = 100;
+	mdfld_backlight_device->props.brightness = 100;
+	mdfld_backlight_device->props.max_brightness = 100;
+	backlight_update_status(mdfld_backlight_device);
+	dev_priv->backlight_device = mdfld_backlight_device;
+	return 0;
+}
+
+#endif
+
+/*
+ *	Provide the Medfield specific chip logic and low level methods for
+ *	power management.
  */
 
 static void mdfld_init_pm(struct drm_device *dev)
@@ -601,6 +688,11 @@ static int mdfld_power_up(struct drm_device *dev)
 
 const struct psb_ops mdfld_chip_ops = {
 	.output_init = mdfld_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	.backlight_init = mdfld_backlight_init,
+#endif
+
 	.init_pm = mdfld_init_pm,
 	.save_regs = mdfld_save_registers,
 	.restore_regs = mdfld_restore_registers,
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
index 44ee3f6..b88dfc2 100644
--- a/drivers/staging/gma500/mdfld_dsi_output.c
+++ b/drivers/staging/gma500/mdfld_dsi_output.c
@@ -468,6 +468,7 @@ static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
 {
 	struct drm_encoder * encoder = connector->encoder;
 	struct backlight_device * psb_bd;
+	struct drm_psb_private * dev_priv = encoder->dev->dev_private;
 
 	if (!strcmp(property->name, "scaling mode") && encoder) {
 		struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
@@ -512,6 +513,7 @@ static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
 						     &psb_crtc->saved_adjusted_mode);
 			}
 		}
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
 	} else if (!strcmp(property->name, "backlight") && encoder) {
 		dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value);
 		if (drm_connector_property_set_value(connector, property, value))
@@ -519,20 +521,21 @@ static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
 		else {
 			dev_dbg(encoder->dev->dev,
 			                "set brightness to %d", (int)value);
-			psb_bd = psb_get_backlight_device();
-			if(psb_bd) {
+			psb_bd = dev_priv->backlight_device;
+			if (psb_bd) {
 				psb_bd->props.brightness = value;
-				psb_set_brightness(psb_bd);
+				backlight_update_status(psb_bd);
 			}
 		}
 	} 
+#endif
 set_prop_done:
     return 0;
 set_prop_error:
     return -1;
 }
 
-static void mdfld_dsi_connector_destroy(struct drm_connector * connector)
+static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
 {
 	struct psb_intel_output * psb_output = to_psb_intel_output(connector);
 	struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
index 5cd8283..daeeb18 100644
--- a/drivers/staging/gma500/mrst_device.c
+++ b/drivers/staging/gma500/mrst_device.c
@@ -17,6 +17,7 @@
  *
  **************************************************************************/
 
+#include <linux/backlight.h>
 #include <drm/drmP.h>
 #include <drm/drm.h>
 #include "psb_drm.h"
@@ -42,7 +43,138 @@ static int mrst_output_init(struct drm_device *dev)
 }
 
 /*
+ *	Provide the low level interfaces for the Moorestown backlight
+ */
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+#define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF
+#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
+#define BLC_PWM_FREQ_CALC_CONSTANT 32
+#define MHz 1000000
+#define BLC_ADJUSTMENT_MAX 100
+
+static struct backlight_device *mrst_backlight_device;
+static int mrst_brightness;
+
+static int mrst_set_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(mrst_backlight_device);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int level = bd->props.brightness;
+	u32 blc_pwm_ctl;
+	u32 max_pwm_blc;
+
+	/* Percentage 1-100% being valid */
+	if (level < 1)
+		level = 1;
+
+	if (gma_power_begin(dev, 0)) {
+		/* Calculate and set the brightness value */
+		max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
+		blc_pwm_ctl = level * max_pwm_blc / 100;
+
+		/* Adjust the backlight level with the percent in
+		 * dev_priv->blc_adj1;
+		 */
+		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
+		blc_pwm_ctl = blc_pwm_ctl / 100;
+
+		/* Adjust the backlight level with the percent in
+		 * dev_priv->blc_adj2;
+		 */
+		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
+		blc_pwm_ctl = blc_pwm_ctl / 100;
+
+		/* force PWM bit on */
+		REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
+		REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
+		gma_power_end(dev);
+	}
+	mrst_brightness = level;
+	return 0;
+}
+
+static int mrst_get_brightness(struct backlight_device *bd)
+{
+	/* return locally cached var instead of HW read (due to DPST etc.) */
+	/* FIXME: ideally return actual value in case firmware fiddled with
+	   it */
+	return mrst_brightness;
+}
+
+static int device_backlight_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long core_clock;
+	u16 bl_max_freq;
+	uint32_t value;
+	uint32_t blc_pwm_precision_factor;
+
+	dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
+	dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
+	bl_max_freq = 256;
+	/* this needs to be set elsewhere */
+	blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
+
+	core_clock = dev_priv->core_freq;
+
+	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
+	value *= blc_pwm_precision_factor;
+	value /= bl_max_freq;
+	value /= blc_pwm_precision_factor;
+
+	if (gma_power_begin(dev, false)) {
+		if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
+				return -ERANGE;
+		else {
+			REG_WRITE(BLC_PWM_CTL2,
+					(0x80000000 | REG_READ(BLC_PWM_CTL2)));
+			REG_WRITE(BLC_PWM_CTL, value | (value << 16));
+		}
+		gma_power_end(dev);
+	}
+	return 0;
+}
+
+static const struct backlight_ops mrst_ops = {
+	.get_brightness = mrst_get_brightness,
+	.update_status  = mrst_set_brightness,
+};
+
+int mrst_backlight_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret;
+	struct backlight_properties props;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = 100;
+	props.type = BACKLIGHT_PLATFORM;
+
+	mrst_backlight_device = backlight_device_register("mrst-bl",
+					NULL, (void *)dev, &mrst_ops, &props);
+					
+	if (IS_ERR(mrst_backlight_device))
+		return PTR_ERR(mrst_backlight_device);
+
+	ret = device_backlight_init(dev);
+	if (ret < 0) {
+		backlight_device_unregister(mrst_backlight_device);
+		return ret;
+	}
+	mrst_backlight_device->props.brightness = 100;
+	mrst_backlight_device->props.max_brightness = 100;
+	backlight_update_status(mrst_backlight_device);
+	dev_priv->backlight_device = mrst_backlight_device;
+	return 0;
+}
+
+#endif
+
+/*
  *	Provide the Moorestown specific chip logic and low level methods
+ *	for power management
  */
 
 static void mrst_init_pm(struct drm_device *dev)
@@ -221,6 +353,11 @@ static int mrst_power_up(struct drm_device *dev)
 
 const struct psb_ops mrst_chip_ops = {
 	.output_init = mrst_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	.backlight_init = mrst_backlight_init,
+#endif
+	
 	.init_pm = mrst_init_pm,
 	.save_regs = mrst_save_display_registers,
 	.restore_regs = mrst_restore_display_registers,
diff --git a/drivers/staging/gma500/psb_bl.c b/drivers/staging/gma500/psb_bl.c
deleted file mode 100644
index c84d261..0000000
--- a/drivers/staging/gma500/psb_bl.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * GMA500 Backlight Interface
- *
- * Copyright (c) 2009-2011, Intel Corporation.
- *
- * 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: Eric Knopp
- *
- */
-
-#include <linux/backlight.h>
-#include <linux/version.h>
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_bios.h"
-#include "psb_powermgmt.h"
-
-#define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF
-#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
-#define BLC_PWM_FREQ_CALC_CONSTANT 32
-#define MHz 1000000
-#define BRIGHTNESS_MIN_LEVEL 1
-#define BRIGHTNESS_MASK	0xFF
-#define BLC_POLARITY_NORMAL 0
-#define BLC_POLARITY_INVERSE 1
-#define BLC_ADJUSTMENT_MAX 100
-
-#define PSB_BLC_PWM_PRECISION_FACTOR    10
-#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
-#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
-
-#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
-#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
-
-static int psb_brightness;
-static struct backlight_device *psb_backlight_device;
-static u8 blc_brightnesscmd;
-static u8 blc_pol;
-static u8 blc_type;
-
-int psb_set_brightness(struct backlight_device *bd)
-{
-	struct drm_device *dev = bl_get_data(psb_backlight_device);
-	int level = bd->props.brightness;
-
-	/* Percentage 1-100% being valid */
-	if (level < 1)
-		level = 1;
-
-	psb_intel_lvds_set_brightness(dev, level);
-	psb_brightness = level;
-	return 0;
-}
-
-int mrst_set_brightness(struct backlight_device *bd)
-{
-	struct drm_device *dev = bl_get_data(psb_backlight_device);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int level = bd->props.brightness;
-	u32 blc_pwm_ctl;
-	u32 max_pwm_blc;
-
-	/* Percentage 1-100% being valid */
-	if (level < 1)
-		level = 1;
-
-	if (gma_power_begin(dev, 0)) {
-		/* Calculate and set the brightness value */
-		max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16;
-		blc_pwm_ctl = level * max_pwm_blc / 100;
-
-		/* Adjust the backlight level with the percent in
-		 * dev_priv->blc_adj1;
-		 */
-		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1;
-		blc_pwm_ctl = blc_pwm_ctl / 100;
-
-		/* Adjust the backlight level with the percent in
-		 * dev_priv->blc_adj2;
-		 */
-		blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2;
-		blc_pwm_ctl = blc_pwm_ctl / 100;
-
-		if (blc_pol == BLC_POLARITY_INVERSE)
-			blc_pwm_ctl = max_pwm_blc - blc_pwm_ctl;
-		/* force PWM bit on */
-		REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2)));
-		REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl);
-		gma_power_end(dev);
-	}
-	psb_brightness = level;
-	return 0;
-}
-
-int mfld_set_brightness(struct backlight_device *bd)
-{
-	struct drm_device *dev = bl_get_data(psb_backlight_device);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int level = bd->props.brightness;
-
-	DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
-
-	/* Percentage 1-100% being valid */
-	if (level < 1)
-		level = 1;
-
-	if (gma_power_begin(dev, 0)) {
-		/* Calculate and set the brightness value */
-		u32 adjusted_level;
-
-		/* Adjust the backlight level with the percent in
-		 * dev_priv->blc_adj2;
-		 */
-		adjusted_level = level * dev_priv->blc_adj2;
-		adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX;
-#if 0
-#ifndef CONFIG_MDFLD_DSI_DPU
-		if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) && 
-			(dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){
-			mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0);
-			dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level);
-		}
-#endif
-		mdfld_dsi_brightness_control(dev, 0, adjusted_level);
-
-		if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2))
-			mdfld_dsi_brightness_control(dev, 2, adjusted_level);
-#endif
-		gma_power_end(dev);
-	}
-	psb_brightness = level;
-	return 0;
-}
-
-int psb_get_brightness(struct backlight_device *bd)
-{
-	/* return locally cached var instead of HW read (due to DPST etc.) */
-	/* FIXME: ideally return actual value in case firmware fiddled with
-	   it */
-	return psb_brightness;
-}
-
-static const struct backlight_ops psb_ops = {
-	.get_brightness = psb_get_brightness,
-	.update_status  = psb_set_brightness,
-};
-
-static const struct backlight_ops mrst_ops = {
-	.get_brightness = psb_get_brightness,
-	.update_status  = mrst_set_brightness,
-};
-
-static const struct backlight_ops mfld_ops = {
-	.get_brightness = psb_get_brightness,
-	.update_status  = mfld_set_brightness,
-};
-
-static int device_backlight_init(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	unsigned long core_clock;
-	/* u32 bl_max_freq; */
-	/* unsigned long value; */
-	u16 bl_max_freq;
-	uint32_t value;
-	uint32_t blc_pwm_precision_factor;
-
-	if (IS_MFLD(dev)) {
-		dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
-		dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
-		return 0;
-	} else if (IS_MRST(dev)) {
-		dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
-		dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
-		bl_max_freq = 256;
-		/* this needs to be set elsewhere */
-		blc_pol = BLC_POLARITY_NORMAL;
-		blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR;
-	} else {
-		/* get bl_max_freq and pol from dev_priv*/
-		if (!dev_priv->lvds_bl) {
-			dev_err(dev->dev, "Has no valid LVDS backlight info\n");
-			return 1;
-		}
-		bl_max_freq = dev_priv->lvds_bl->freq;
-		blc_pol = dev_priv->lvds_bl->pol;
-		blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
-		blc_brightnesscmd = dev_priv->lvds_bl->brightnesscmd;
-		blc_type = dev_priv->lvds_bl->type;
-	}
-
-	core_clock = dev_priv->core_freq;
-
-	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
-	value *= blc_pwm_precision_factor;
-	value /= bl_max_freq;
-	value /= blc_pwm_precision_factor;
-
-	if (gma_power_begin(dev, false)) {
-		if (IS_MRST(dev)) {
-			if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ)
-				return 2;
-			else {
-				REG_WRITE(BLC_PWM_CTL2,
-					(0x80000000 | REG_READ(BLC_PWM_CTL2)));
-				REG_WRITE(BLC_PWM_CTL, value | (value << 16));
-			}
-		} else {
-			if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
-			 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
-				return 2;
-			else {
-				value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
-				REG_WRITE(BLC_PWM_CTL,
-					(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
-					(value));
-			}
-		}
-		gma_power_end(dev);
-	}
-	return 0;
-}
-
-int psb_backlight_init(struct drm_device *dev)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-	int ret = 0;
-
-	struct backlight_properties props;
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.max_brightness = 100;
-	props.type = BACKLIGHT_PLATFORM;
-
-	if (IS_MFLD(dev))
-		psb_backlight_device = backlight_device_register("mfld-bl",
-					NULL, (void *)dev, &mfld_ops, &props);
-	else if (IS_MRST(dev))
-		psb_backlight_device = backlight_device_register("mrst-bl",
-					NULL, (void *)dev, &psb_ops, &props);
-	else
-		psb_backlight_device = backlight_device_register("psb-bl",
-					NULL, (void *)dev, &psb_ops, &props);
-					
-	if (IS_ERR(psb_backlight_device))
-		return PTR_ERR(psb_backlight_device);
-
-	ret = device_backlight_init(dev);
-	if (ret < 0)
-		return ret;
-
-	psb_backlight_device->props.brightness = 100;
-	psb_backlight_device->props.max_brightness = 100;
-	backlight_update_status(psb_backlight_device);
-#endif
-	return 0;
-}
-
-void psb_backlight_exit(void)
-{
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-	psb_backlight_device->props.brightness = 0;
-	backlight_update_status(psb_backlight_device);
-	backlight_device_unregister(psb_backlight_device);
-#endif
-}
-
-struct backlight_device *psb_get_backlight_device(void)
-{
-	return psb_backlight_device;
-}
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
index 97e25ab..4a3c516 100644
--- a/drivers/staging/gma500/psb_device.c
+++ b/drivers/staging/gma500/psb_device.c
@@ -17,12 +17,15 @@
  *
  **************************************************************************/
 
+#include <linux/backlight.h>
 #include <drm/drmP.h>
 #include <drm/drm.h>
 #include "psb_drm.h"
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
+#include "psb_intel_bios.h"
+
 
 static int psb_output_init(struct drm_device *dev)
 {
@@ -32,8 +35,123 @@ static int psb_output_init(struct drm_device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+/*
+ *	Poulsbo Backlight Interfaces
+ */
+
+#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
+#define BLC_PWM_FREQ_CALC_CONSTANT 32
+#define MHz 1000000
+
+#define PSB_BLC_PWM_PRECISION_FACTOR    10
+#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
+#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
+
+#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
+#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
+
+static int psb_brightness;
+static struct backlight_device *psb_backlight_device;
+
+static int psb_get_brightness(struct backlight_device *bd)
+{
+	/* return locally cached var instead of HW read (due to DPST etc.) */
+	/* FIXME: ideally return actual value in case firmware fiddled with
+	   it */
+	return psb_brightness;
+}
+
+
+static int psb_backlight_setup(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long core_clock;
+	/* u32 bl_max_freq; */
+	/* unsigned long value; */
+	u16 bl_max_freq;
+	uint32_t value;
+	uint32_t blc_pwm_precision_factor;
+
+	/* get bl_max_freq and pol from dev_priv*/
+	if (!dev_priv->lvds_bl) {
+		dev_err(dev->dev, "Has no valid LVDS backlight info\n");
+		return -ENOENT;
+	}
+	bl_max_freq = dev_priv->lvds_bl->freq;
+	blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
+
+	core_clock = dev_priv->core_freq;
+
+	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
+	value *= blc_pwm_precision_factor;
+	value /= bl_max_freq;
+	value /= blc_pwm_precision_factor;
+
+	if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
+		 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
+				return -ERANGE;
+	else {
+		value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
+		REG_WRITE(BLC_PWM_CTL,
+			(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value));
+	}
+	return 0;
+}
+
+static int psb_set_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(psb_backlight_device);
+	int level = bd->props.brightness;
+
+	/* Percentage 1-100% being valid */
+	if (level < 1)
+		level = 1;
+
+	psb_intel_lvds_set_brightness(dev, level);
+	psb_brightness = level;
+	return 0;
+}
+
+static const struct backlight_ops psb_ops = {
+	.get_brightness = psb_get_brightness,
+	.update_status  = psb_set_brightness,
+};
+
+static int psb_backlight_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret;
+	struct backlight_properties props;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = 100;
+	props.type = BACKLIGHT_PLATFORM;
+
+	psb_backlight_device = backlight_device_register("psb-bl",
+					NULL, (void *)dev, &psb_ops, &props);
+	if (IS_ERR(psb_backlight_device))
+		return PTR_ERR(psb_backlight_device);
+
+	ret = psb_backlight_setup(dev);
+	if (ret < 0) {
+		backlight_device_unregister(psb_backlight_device);
+		psb_backlight_device = NULL;
+		return ret;
+	}
+	psb_backlight_device->props.brightness = 100;
+	psb_backlight_device->props.max_brightness = 100;
+	backlight_update_status(psb_backlight_device);
+	dev_priv->backlight_device = psb_backlight_device;
+	return 0;
+}
+
+#endif
+
 /*
  *	Provide the Poulsbo specific chip logic and low level methods
+ *	for power management
  */
 
 static void psb_init_pm(struct drm_device *dev)
@@ -165,10 +283,15 @@ int psb_power_up(struct drm_device *dev)
 
 const struct psb_ops psb_chip_ops = {
 	.output_init = psb_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	.backlight_init = psb_backlight_init,
+#endif
+
 	.init_pm = psb_init_pm,
 	.save_regs = psb_save_display_registers,
 	.restore_regs = psb_restore_display_registers,
 	.power_down = psb_power_down,
-	.power_up = psb_power_up,
+	.power_up = psb_power_up,	
 };
 
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 6c57234..bb6b68f 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -261,7 +261,7 @@ static int psb_driver_unload(struct drm_device *dev)
 
 	/* Kill vblank etc here */
 
-	psb_backlight_exit(); /*writes minimum value to backlight HW reg */
+	gma_backlight_exit(dev);
 
 	if (drm_psb_no_fb == 0)
 		psb_modeset_cleanup(dev);
@@ -455,7 +455,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 
 		switch (psb_intel_output->type) {
 		case INTEL_OUTPUT_LVDS:
-			ret = psb_backlight_init(dev);
+			ret = gma_backlight_init(dev);
 			break;
 		}
 	}
@@ -554,12 +554,14 @@ static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_psb_private *dev_priv = psb_priv(dev);
 	uint32_t *arg = data;
-	struct backlight_device bd;
+	struct backlight_device *bd = dev_priv->backlight_device;
 	dev_priv->blc_adj2 = *arg;
 
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-	bd.props.brightness = psb_get_brightness(&bd);
-	psb_set_brightness(&bd);
+	if (bd) {
+		bd->props.brightness = bd->ops->get_brightness(bd);
+		backlight_update_status(bd);
+	}
 #endif
 	return 0;
 }
@@ -569,12 +571,14 @@ static int psb_adb_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_psb_private *dev_priv = psb_priv(dev);
 	uint32_t *arg = data;
-	struct backlight_device bd;
+	struct backlight_device *bd = dev_priv->backlight_device;
 	dev_priv->blc_adj1 = *arg;
 
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-	bd.props.brightness = psb_get_brightness(&bd);
-	psb_set_brightness(&bd);
+	if (bd) {
+		bd->props.brightness = bd->ops->get_brightness(bd);
+		backlight_update_status(bd);
+	}
 #endif
 	return 0;
 }
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index d1c49e7..b0908f2 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -588,12 +588,12 @@ struct drm_psb_private {
 	 * 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;
-
 	/* DPST state */
 	uint32_t dsr_idle_count;
 	bool is_in_idle;
@@ -625,6 +625,10 @@ struct psb_ops {
 	int (*restore_regs)(struct drm_device *dev);
 	int (*power_up)(struct drm_device *dev);
 	int (*power_down)(struct drm_device *dev);
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	/* Backlight */
+	int (*backlight_init)(struct drm_device *dev);
+#endif
 };
 
 
@@ -744,12 +748,9 @@ 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);
 
-/* psb_bl.c */
-int psb_backlight_init(struct drm_device *dev);
-void psb_backlight_exit(void);
-int psb_set_brightness(struct backlight_device *bd);
-int psb_get_brightness(struct backlight_device *bd);
-struct backlight_device *psb_get_backlight_device(void);
+/* backlight.c */
+int gma_backlight_init(struct drm_device *dev);
+void gma_backlight_exit(struct drm_device *dev);
 
 /* mrst_crtc.c */
 extern const struct drm_crtc_helper_funcs mrst_helper_funcs;
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index 850d07d..41b96d2 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -575,11 +575,12 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
 				       struct drm_property *property,
 				       uint64_t value)
 {
-	struct drm_encoder *pEncoder = connector->encoder;
+	struct drm_encoder *encoder = connector->encoder;
+	struct drm_psb_private *dev_priv = encoder->dev->dev_private;
 
-	if (!strcmp(property->name, "scaling mode") && pEncoder) {
+	if (!strcmp(property->name, "scaling mode") && encoder) {
 		struct psb_intel_crtc *pPsbCrtc =
-					to_psb_intel_crtc(pEncoder->crtc);
+					to_psb_intel_crtc(encoder->crtc);
 		uint64_t curValue;
 
 		if (!pPsbCrtc)
@@ -611,29 +612,31 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
 
 		if (pPsbCrtc->saved_mode.hdisplay != 0 &&
 		    pPsbCrtc->saved_mode.vdisplay != 0) {
-			if (!drm_crtc_helper_set_mode(pEncoder->crtc,
+			if (!drm_crtc_helper_set_mode(encoder->crtc,
 						      &pPsbCrtc->saved_mode,
-						      pEncoder->crtc->x,
-						      pEncoder->crtc->y,
-						      pEncoder->crtc->fb))
+						      encoder->crtc->x,
+						      encoder->crtc->y,
+						      encoder->crtc->fb))
 				goto set_prop_error;
 		}
-	} else if (!strcmp(property->name, "backlight") && pEncoder) {
+	} else if (!strcmp(property->name, "backlight") && encoder) {
 		if (drm_connector_property_set_value(connector,
 							property,
 							value))
 			goto set_prop_error;
 		else {
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-			struct backlight_device bd;
-			bd.props.brightness = value;
-			psb_set_brightness(&bd);
+			struct backlight_device *bd = dev_priv->backlight_device;
+			if (bd) {
+        			bd->props.brightness = value;
+	        		backlight_update_status(bd);
+                        }
 #endif
 		}
-	} else if (!strcmp(property->name, "DPMS") && pEncoder) {
+	} else if (!strcmp(property->name, "DPMS") && encoder) {
 		struct drm_encoder_helper_funcs *pEncHFuncs
-						= pEncoder->helper_private;
-		pEncHFuncs->dpms(pEncoder, value);
+						= encoder->helper_private;
+		pEncHFuncs->dpms(encoder, value);
 	}
 
 set_prop_done:


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 22/49] gma500: Fix early Medfield crash
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (20 preceding siblings ...)
  2011-07-05 14:38 ` [PATCH 21/49] gma500: continue abstracting platform specific code Alan Cox
@ 2011-07-05 14:38 ` Alan Cox
  2011-07-05 14:39 ` [PATCH 23/49] gma500: Read the GCT panel type information for Medfield Alan Cox
                   ` (27 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:38 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We need to initialise the DBI interface and the code for it got missed in
the original merge as it's in a daft place. This will need moving but lets
get it added first.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_drv.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index bb6b68f..dfb3f3a 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -28,6 +28,7 @@
 #include "psb_intel_reg.h"
 #include "psb_intel_bios.h"
 #include "mrst_bios.h"
+#include "mdfld_dsi_dbi.h"
 #include <drm/drm_pciids.h>
 #include "psb_powermgmt.h"
 #include <linux/cpu.h>
@@ -442,6 +443,17 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 
 	dev->driver->get_vblank_counter = psb_get_vblank_counter;
 
+	/* FIXME: this is not the right place for this stuff ! */
+	if (IS_MFLD(dev)) {
+#ifdef CONFIG_MDFLD_DSI_DPU
+		/*init dpu info*/
+		mdfld_dbi_dpu_init(dev);
+#else 
+		mdfld_dbi_dsr_init(dev);
+#endif /*CONFIG_MDFLD_DSI_DPU*/
+		/* INIT_WORK(&dev_priv->te_work, mdfld_te_handler_work);*/
+	}
+
 	if (drm_psb_no_fb == 0) {
 		psb_modeset_init(dev);
 		psb_fbdev_init(dev);


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 23/49] gma500: Read the GCT panel type information for Medfield
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (21 preceding siblings ...)
  2011-07-05 14:38 ` [PATCH 22/49] gma500: Fix early Medfield crash Alan Cox
@ 2011-07-05 14:39 ` Alan Cox
  2011-07-05 14:39 ` [PATCH 24/49] gma500: enable Medfield CRTC support Alan Cox
                   ` (26 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:39 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Missed in the original merge work

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/mrst_bios.c |   29 ++++++++++++++++++++++++++++-
 1 files changed, 28 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/gma500/mrst_bios.c b/drivers/staging/gma500/mrst_bios.c
index 0d944c4..103777b 100644
--- a/drivers/staging/gma500/mrst_bios.c
+++ b/drivers/staging/gma500/mrst_bios.c
@@ -28,6 +28,12 @@
 #include "psb_drm.h"
 #include "psb_drv.h"
 #include "mrst_bios.h"
+#include "mdfld_output.h"
+
+static int panel_id;
+module_param_named(panel_id, panel_id, int, 0600);
+MODULE_PARM_DESC(panel_id, "Panel Identifier");
+
 
 void mrst_get_fuse_settings(struct drm_device *dev)
 {
@@ -231,6 +237,27 @@ void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
 		dev_err(dev->dev, "Unknown revision of GCT!\n");
 		vbt->size = 0;
 	}
-	/* FIXME: Need to sort out Medfield panel identifiers in future */
+	if (IS_MDFLD(dev_priv->dev)){
+		if (panel_id == GCT_DETECT) {
+			if (dev_priv->gct_data.bpi == 2) {
+				dev_info(dev->dev, "[GFX] PYR Panel Detected\n");
+				dev_priv->panel_id = PYR_CMD;
+				panel_id = PYR_CMD;
+			}
+			else if(dev_priv->gct_data.bpi == 0) {
+				dev_info(dev->dev, "[GFX] TMD Panel Detected.\n");
+				dev_priv->panel_id = TMD_VID;
+				panel_id = TMD_VID;
+			}
+			else {
+				dev_info(dev->dev, "[GFX] Default Panel (TPO)\n");
+				dev_priv->panel_id = TPO_CMD;
+				panel_id = TPO_CMD;
+			}
+		} else {
+			dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n");
+			dev_priv->panel_id = panel_id;
+		}
+	}
 }
 


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 24/49] gma500: enable Medfield CRTC support
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (22 preceding siblings ...)
  2011-07-05 14:39 ` [PATCH 23/49] gma500: Read the GCT panel type information for Medfield Alan Cox
@ 2011-07-05 14:39 ` Alan Cox
  2011-07-05 14:39 ` [PATCH 25/49] commit ee12661199b82934552c7636b10217a9aa42958a Alan Cox
                   ` (25 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:39 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/mdfld_intel_display.c |   33 ++++++++++++++++++++++++--
 drivers/staging/gma500/mdfld_output.h        |    3 ++
 drivers/staging/gma500/mrst_bios.c           |    4 ++-
 drivers/staging/gma500/psb_intel_display.c   |    9 +++----
 4 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c
index 26d7f80..0b619b6 100644
--- a/drivers/staging/gma500/mdfld_intel_display.c
+++ b/drivers/staging/gma500/mdfld_intel_display.c
@@ -44,7 +44,6 @@
 /* Hardcoded currently */
 static int ksel = KSEL_CRYSTAL_19;
 
-extern struct drm_device *gpDrmDevice;
 extern void mdfld_save_display(struct drm_device *dev);
 extern bool gbgfxsuspended;
 
@@ -561,10 +560,10 @@ static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
 		return;
 
 	 /* Ignore if system is already in DSR and in suspended state. */
-	if(gbgfxsuspended && dev_priv->dispstatus == false && mode == 3){
+	if(/*gbgfxsuspended */0 && dev_priv->dispstatus == false && mode == 3){
 	    if(dev_priv->rpm_enabled && pipe == 1){
 	//          dev_priv->is_mipi_on = false;
-	            pm_request_idle(&gpDrmDevice->pdev->dev);
+	          pm_request_idle(&dev->pdev->dev);
 	    }
 	    return;
 	}else if(mode == 0) {
@@ -1386,3 +1385,31 @@ mrst_crtc_mode_set_exit:
 
 	return 0;
 }
+
+static void mdfld_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void mdfld_crtc_commit(struct drm_crtc *crtc)
+{
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+static bool mdfld_crtc_mode_fixup(struct drm_crtc *crtc,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
+	.dpms = mdfld_crtc_dpms,
+	.mode_fixup = mdfld_crtc_mode_fixup,
+	.mode_set = mdfld_crtc_mode_set,
+	.mode_set_base = mdfld__intel_pipe_set_base,
+	.prepare = mdfld_crtc_prepare,
+	.commit = mdfld_crtc_commit,
+};
diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h
index 53b57db..70f2302a 100644
--- a/drivers/staging/gma500/mdfld_output.h
+++ b/drivers/staging/gma500/mdfld_output.h
@@ -74,4 +74,7 @@ int mdfld_panel_dpi(struct drm_device *dev);
 int mdfld_get_panel_type(struct drm_device *dev, int pipe);
 void mdfld_disable_crtc (struct drm_device *dev, int pipe);
 
+extern const struct drm_crtc_helper_funcs mdfld_helper_funcs;
+extern const struct drm_crtc_funcs mdfld_intel_crtc_funcs;
+
 #endif
diff --git a/drivers/staging/gma500/mrst_bios.c b/drivers/staging/gma500/mrst_bios.c
index 103777b..c3707f4 100644
--- a/drivers/staging/gma500/mrst_bios.c
+++ b/drivers/staging/gma500/mrst_bios.c
@@ -30,7 +30,7 @@
 #include "mrst_bios.h"
 #include "mdfld_output.h"
 
-static int panel_id;
+static int panel_id = GCT_DETECT;
 module_param_named(panel_id, panel_id, int, 0600);
 MODULE_PARM_DESC(panel_id, "Panel Identifier");
 
@@ -237,7 +237,7 @@ void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
 		dev_err(dev->dev, "Unknown revision of GCT!\n");
 		vbt->size = 0;
 	}
-	if (IS_MDFLD(dev_priv->dev)){
+	if (IS_MFLD(dev_priv->dev)){
 		if (panel_id == GCT_DETECT) {
 			if (dev_priv->gct_data.bpi == 2) {
 				dev_info(dev->dev, "[GFX] PYR Panel Detected\n");
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index ba10849..0e9758a 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -29,6 +29,7 @@
 #include "psb_intel_display.h"
 #include "psb_powermgmt.h"
 
+#include "mdfld_output.h"
 
 struct psb_intel_clock_t {
 	/* given values */
@@ -1303,12 +1304,10 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 		return;
 	}
 
-#if 0	/* FIXME */
 	if (IS_MFLD(dev))
 		drm_crtc_init(dev, &psb_intel_crtc->base,
-						&mfld_intel_crtc_funcs);
+						&mdfld_intel_crtc_funcs);
 	else
-#endif
         	drm_crtc_init(dev, &psb_intel_crtc->base,
 						&psb_intel_crtc_funcs);
 
@@ -1336,9 +1335,9 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 	if (IS_MRST(dev))
 		drm_crtc_helper_add(&psb_intel_crtc->base,
 				    &mrst_helper_funcs);
-/*	else if (IS_MDFLD(dev))
+	else if (IS_MFLD(dev))
 		drm_crtc_helper_add(&psb_intel_crtc->base,
-				    &mfld_helper_funcs); */
+				    &mdfld_helper_funcs);
 	else
 		drm_crtc_helper_add(&psb_intel_crtc->base,
 				    &psb_intel_helper_funcs);


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 25/49] commit ee12661199b82934552c7636b10217a9aa42958a
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (23 preceding siblings ...)
  2011-07-05 14:39 ` [PATCH 24/49] gma500: enable Medfield CRTC support Alan Cox
@ 2011-07-05 14:39 ` Alan Cox
  2011-07-05 15:55   ` Greg KH
  2011-07-05 14:39 ` [PATCH 26/49] gma500: add more ops Alan Cox
                   ` (24 subsequent siblings)
  49 siblings, 1 reply; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:39 UTC (permalink / raw)
  To: greg, linux-kernel

From: Jani Nikula <jani.nikula@intel.com>

gma500: fix build without backlight device support

    Fix unmatched curly brackets when CONFIG_BACKLIGHT_CLASS_DEVICE is not
    defined.

    Signed-off-by: Jani Nikula <jani.nikula@intel.com>
    Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/mdfld_dsi_output.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c
index b88dfc2..e911ef2 100644
--- a/drivers/staging/gma500/mdfld_dsi_output.c
+++ b/drivers/staging/gma500/mdfld_dsi_output.c
@@ -527,8 +527,8 @@ static int mdfld_dsi_connector_set_property(struct drm_connector * connector,
 				backlight_update_status(psb_bd);
 			}
 		}
-	} 
 #endif
+	}
 set_prop_done:
     return 0;
 set_prop_error:


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 26/49] gma500: add more ops
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (24 preceding siblings ...)
  2011-07-05 14:39 ` [PATCH 25/49] commit ee12661199b82934552c7636b10217a9aa42958a Alan Cox
@ 2011-07-05 14:39 ` Alan Cox
  2011-07-05 14:40 ` [PATCH 27/49] gma500: remove an un-needed check Alan Cox
                   ` (23 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:39 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Split the 2d properties, name, and various function vectors out so that we
can get rid of more conditional gloop in favour of a per device structure.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/mdfld_device.c      |    5 +++++
 drivers/staging/gma500/mrst_device.c       |    5 +++++
 drivers/staging/gma500/psb_device.c        |    5 +++++
 drivers/staging/gma500/psb_drv.h           |   11 +++++++++++
 drivers/staging/gma500/psb_fb.c            |    8 ++++----
 drivers/staging/gma500/psb_intel_display.c |   21 +++++----------------
 6 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
index e86e476..3955448 100644
--- a/drivers/staging/gma500/mdfld_device.c
+++ b/drivers/staging/gma500/mdfld_device.c
@@ -687,6 +687,11 @@ static int mdfld_power_up(struct drm_device *dev)
 }
 
 const struct psb_ops mdfld_chip_ops = {
+	.name = "Medfield",
+	.accel_2d = 0,
+	.crtc_helper = &mdfld_helper_funcs,
+	.crtc_funcs = &mdfld_intel_crtc_funcs,
+
 	.output_init = mdfld_output_init,
 
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
index daeeb18..79cd784 100644
--- a/drivers/staging/gma500/mrst_device.c
+++ b/drivers/staging/gma500/mrst_device.c
@@ -352,6 +352,11 @@ static int mrst_power_up(struct drm_device *dev)
 }
 
 const struct psb_ops mrst_chip_ops = {
+	.name = "Moorestown",
+	.accel_2d = 1,
+	.crtc_helper = &mrst_helper_funcs,
+	.crtc_funcs = &psb_intel_crtc_funcs,
+
 	.output_init = mrst_output_init,
 
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
index 4a3c516..0402171 100644
--- a/drivers/staging/gma500/psb_device.c
+++ b/drivers/staging/gma500/psb_device.c
@@ -282,6 +282,11 @@ int psb_power_up(struct drm_device *dev)
 }
 
 const struct psb_ops psb_chip_ops = {
+	.name = "Poulsbo",
+	.accel_2d = 1,
+	.crtc_helper = &psb_intel_helper_funcs,
+	.crtc_funcs = &psb_intel_crtc_funcs,
+
 	.output_init = psb_output_init,
 
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index b0908f2..4bc5e8d 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -617,6 +617,13 @@ struct drm_psb_private {
  */
  
 struct psb_ops {
+	const char *name;
+	unsigned int accel_2d:1;
+
+	/* Sub functions */
+	struct drm_crtc_helper_funcs const *crtc_helper;
+	struct drm_crtc_funcs const *crtc_funcs;
+
 	/* Display management hooks */
 	int (*output_init)(struct drm_device *dev);
 	/* Power management hooks */
@@ -759,6 +766,10 @@ extern const struct drm_crtc_helper_funcs mrst_helper_funcs;
 extern void mrst_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 void psb_intel_lvds_prepare(struct drm_encoder *encoder);
 extern void psb_intel_lvds_commit(struct drm_encoder *encoder);
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 32d9016..349fff8 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -211,7 +211,7 @@ static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
 	case 0x12345678:
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
-		if (IS_MFLD(dev))
+		if (!dev_priv->ops->accel_2d)
 			return -EOPNOTSUPP;
 		if (get_user(l, p))
 			return -EFAULT;
@@ -240,7 +240,7 @@ static struct fb_ops psbfb_ops = {
 	.fb_ioctl = psbfb_ioctl,
 };
 
-static struct fb_ops psbfb_mfld_ops = {
+static struct fb_ops psbfb_unaccel_ops = {
 	.owner = THIS_MODULE,
 	.fb_check_var = drm_fb_helper_check_var,
 	.fb_set_par = drm_fb_helper_set_par,
@@ -426,8 +426,8 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 
 	info->flags = FBINFO_DEFAULT;
 	/* No 2D engine */
-	if (IS_MFLD(dev))
-		info->fbops = &psbfb_mfld_ops;
+	if (!dev_priv->ops->accel_2d)
+		info->fbops = &psbfb_unaccel_ops;
 	else
 		info->fbops = &psbfb_ops;
 
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 0e9758a..c38e819 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -1260,7 +1260,7 @@ void psb_intel_crtc_destroy(struct drm_crtc *crtc)
 	kfree(psb_intel_crtc);
 }
 
-static const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
+const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
 	.dpms = psb_intel_crtc_dpms,
 	.mode_fixup = psb_intel_crtc_mode_fixup,
 	.mode_set = psb_intel_crtc_mode_set,
@@ -1304,12 +1304,8 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 		return;
 	}
 
-	if (IS_MFLD(dev))
-		drm_crtc_init(dev, &psb_intel_crtc->base,
-						&mdfld_intel_crtc_funcs);
-	else
-        	drm_crtc_init(dev, &psb_intel_crtc->base,
-						&psb_intel_crtc_funcs);
+	/* Set the CRTC operations from the chip specific data */
+	drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs);
 
 	drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
 	psb_intel_crtc->pipe = pipe;
@@ -1332,15 +1328,8 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 	psb_intel_crtc->mode_dev = mode_dev;
 	psb_intel_crtc->cursor_addr = 0;
 
-	if (IS_MRST(dev))
-		drm_crtc_helper_add(&psb_intel_crtc->base,
-				    &mrst_helper_funcs);
-	else if (IS_MFLD(dev))
-		drm_crtc_helper_add(&psb_intel_crtc->base,
-				    &mdfld_helper_funcs);
-	else
-		drm_crtc_helper_add(&psb_intel_crtc->base,
-				    &psb_intel_helper_funcs);
+	drm_crtc_helper_add(&psb_intel_crtc->base,
+	                                dev_priv->ops->crtc_helper);
 
 	/* Setup the array of drm_connector pointer array */
 	psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base;


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 27/49] gma500: remove an un-needed check
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (25 preceding siblings ...)
  2011-07-05 14:39 ` [PATCH 26/49] gma500: add more ops Alan Cox
@ 2011-07-05 14:40 ` Alan Cox
  2011-07-05 14:40 ` [PATCH 28/49] gma500: move configuration bits into the psb_ops structure Alan Cox
                   ` (22 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:40 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

This is a Medfield only path

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/mdfld_device.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
index 3955448..e66d04a 100644
--- a/drivers/staging/gma500/mdfld_device.c
+++ b/drivers/staging/gma500/mdfld_device.c
@@ -589,7 +589,7 @@ static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
 		PSB_WVDC32(palette_val[i], palette_reg + (i<<2));
 	if (pipe == 1)
 		return 0;
-	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
+	if (!mdfld_panel_dpi(dev))
 		mdfld_enable_te(dev, pipe);
 	return 0;
 }


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 28/49] gma500: move configuration bits into the psb_ops structure
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (26 preceding siblings ...)
  2011-07-05 14:40 ` [PATCH 27/49] gma500: remove an un-needed check Alan Cox
@ 2011-07-05 14:40 ` Alan Cox
  2011-07-05 14:40 ` [PATCH 29/49] gma500: Add the beginnings of Cedarview support Alan Cox
                   ` (21 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:40 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We can stuff things like the number of pipes and the SGX offset away in
here as well and clean up more conditional code.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/mdfld_device.c |    6 +++
 drivers/staging/gma500/mrst_bios.c    |   14 ++++++-
 drivers/staging/gma500/mrst_bios.h    |    5 +--
 drivers/staging/gma500/mrst_device.c  |    5 +++
 drivers/staging/gma500/psb_device.c   |   54 ++++++++++++++++++++++++++-
 drivers/staging/gma500/psb_drv.c      |   65 +++------------------------------
 drivers/staging/gma500/psb_drv.h      |    5 +++
 7 files changed, 86 insertions(+), 68 deletions(-)

diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
index e66d04a..daa9487 100644
--- a/drivers/staging/gma500/mdfld_device.c
+++ b/drivers/staging/gma500/mdfld_device.c
@@ -26,6 +26,7 @@
 #include "psb_drv.h"
 #include "mdfld_output.h"
 #include "mdfld_dsi_output.h"
+#include "mrst_bios.h"
 
 /*
  *	Provide the Medfield specific backlight management
@@ -689,6 +690,11 @@ static int mdfld_power_up(struct drm_device *dev)
 const struct psb_ops mdfld_chip_ops = {
 	.name = "Medfield",
 	.accel_2d = 0,
+	.pipes = 3,
+	.sgx_offset = MRST_SGX_OFFSET,
+
+	.chip_setup = mid_chip_setup,
+
 	.crtc_helper = &mdfld_helper_funcs,
 	.crtc_funcs = &mdfld_intel_crtc_funcs,
 
diff --git a/drivers/staging/gma500/mrst_bios.c b/drivers/staging/gma500/mrst_bios.c
index c3707f4..cf015df 100644
--- a/drivers/staging/gma500/mrst_bios.c
+++ b/drivers/staging/gma500/mrst_bios.c
@@ -35,7 +35,7 @@ module_param_named(panel_id, panel_id, int, 0600);
 MODULE_PARM_DESC(panel_id, "Panel Identifier");
 
 
-void mrst_get_fuse_settings(struct drm_device *dev)
+static void mid_get_fuse_settings(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
@@ -102,7 +102,7 @@ void mrst_get_fuse_settings(struct drm_device *dev)
 /*
  *	Get the revison ID, B0:D2:F0;0x08
  */
-void mid_get_pci_revID(struct drm_psb_private *dev_priv)
+static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
 {
 	uint32_t platform_rev_id = 0;
 	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
@@ -114,7 +114,7 @@ void mid_get_pci_revID(struct drm_psb_private *dev_priv)
 					dev_priv->platform_rev_id);
 }
 
-void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
+static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
 	struct mrst_vbt *vbt = &dev_priv->vbt_data;
@@ -261,3 +261,11 @@ void mrst_get_vbt_data(struct drm_psb_private *dev_priv)
 	}
 }
 
+int mid_chip_setup(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	mid_get_fuse_settings(dev);
+	mid_get_vbt_data(dev_priv);
+	mid_get_pci_revID(dev_priv);
+	return 0;
+}
\ No newline at end of file
diff --git a/drivers/staging/gma500/mrst_bios.h b/drivers/staging/gma500/mrst_bios.h
index a257306..00e7d56 100644
--- a/drivers/staging/gma500/mrst_bios.h
+++ b/drivers/staging/gma500/mrst_bios.h
@@ -17,6 +17,5 @@
  *
  **************************************************************************/
 
-extern void mrst_get_fuse_settings(struct drm_device *dev);
-extern void mid_get_pci_revID(struct drm_psb_private *dev_priv);
-extern void mrst_get_vbt_data(struct drm_psb_private *dev_priv);
+extern int mid_chip_setup(struct drm_device *dev);
+
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
index 79cd784..d71e8d3 100644
--- a/drivers/staging/gma500/mrst_device.c
+++ b/drivers/staging/gma500/mrst_device.c
@@ -25,6 +25,7 @@
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
 #include <asm/intel_scu_ipc.h>
+#include "mrst_bios.h"
 
 /* IPC message and command defines used to enable/disable mipi panel voltages */
 #define IPC_MSG_PANEL_ON_OFF    0xE9
@@ -354,6 +355,10 @@ static int mrst_power_up(struct drm_device *dev)
 const struct psb_ops mrst_chip_ops = {
 	.name = "Moorestown",
 	.accel_2d = 1,
+	.pipes = 1,
+	.sgx_offset = MRST_SGX_OFFSET,
+
+	.chip_setup = mid_chip_setup,
 	.crtc_helper = &mrst_helper_funcs,
 	.crtc_funcs = &psb_intel_crtc_funcs,
 
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
index 0402171..1be6434 100644
--- a/drivers/staging/gma500/psb_device.c
+++ b/drivers/staging/gma500/psb_device.c
@@ -271,19 +271,69 @@ static int psb_restore_display_registers(struct drm_device *dev)
 	return 0;
 }
 
-int psb_power_down(struct drm_device *dev)
+static int psb_power_down(struct drm_device *dev)
 {
 	return 0;
 }
 
-int psb_power_up(struct drm_device *dev)
+static int psb_power_up(struct drm_device *dev)
 {
 	return 0;
 }
 
+static void psb_get_core_freq(struct drm_device *dev)
+{
+	uint32_t clock;
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
+	/*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
+
+	pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
+	pci_read_config_dword(pci_root, 0xD4, &clock);
+	pci_dev_put(pci_root);
+
+	switch (clock & 0x07) {
+	case 0:
+		dev_priv->core_freq = 100;
+		break;
+	case 1:
+		dev_priv->core_freq = 133;
+		break;
+	case 2:
+		dev_priv->core_freq = 150;
+		break;
+	case 3:
+		dev_priv->core_freq = 178;
+		break;
+	case 4:
+		dev_priv->core_freq = 200;
+		break;
+	case 5:
+	case 6:
+	case 7:
+		dev_priv->core_freq = 266;
+	default:
+		dev_priv->core_freq = 0;
+	}
+}
+
+static int psb_chip_setup(struct drm_device *dev)
+{
+	psb_get_core_freq(dev);
+	psb_intel_opregion_init(dev);
+	psb_intel_init_bios(dev);
+	return 0;
+}
+
 const struct psb_ops psb_chip_ops = {
 	.name = "Poulsbo",
 	.accel_2d = 1,
+	.pipes = 2,
+	.sgx_offset = PSB_SGX_OFFSET,
+	.chip_setup = psb_chip_setup,
+
 	.crtc_helper = &psb_intel_helper_funcs,
 	.crtc_funcs = &psb_intel_crtc_funcs,
 
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index dfb3f3a..b95d0a6 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -158,44 +158,6 @@ static void psb_do_takedown(struct drm_device *dev)
 	/* FIXME: do we need to clean up the gtt here ? */
 }
 
-static void psb_get_core_freq(struct drm_device *dev)
-{
-	uint32_t clock;
-	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	/*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
-	/*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
-
-	pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
-	pci_read_config_dword(pci_root, 0xD4, &clock);
-	pci_dev_put(pci_root);
-
-	switch (clock & 0x07) {
-	case 0:
-		dev_priv->core_freq = 100;
-		break;
-	case 1:
-		dev_priv->core_freq = 133;
-		break;
-	case 2:
-		dev_priv->core_freq = 150;
-		break;
-	case 3:
-		dev_priv->core_freq = 178;
-		break;
-	case 4:
-		dev_priv->core_freq = 200;
-		break;
-	case 5:
-	case 6:
-	case 7:
-		dev_priv->core_freq = 266;
-	default:
-		dev_priv->core_freq = 0;
-	}
-}
-
 static int psb_do_init(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv =
@@ -336,13 +298,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	dev_priv->dev = dev;
 	dev->dev_private = (void *) dev_priv;
 
-	if (IS_MRST(dev))
-		dev_priv->num_pipe = 1;
-	else if (IS_MFLD(dev))
-		dev_priv->num_pipe = 3;
-	else
-		dev_priv->num_pipe = 2;
-
+	dev_priv->num_pipe = dev_priv->ops->pipes;
 
 	resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
 
@@ -351,25 +307,14 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	if (!dev_priv->vdc_reg)
 		goto out_err;
 
-	if (IS_MRST(dev) || IS_MFLD(dev))
-		dev_priv->sgx_reg = ioremap(resource_start + MRST_SGX_OFFSET,
+	dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset,
 							PSB_SGX_SIZE);
-	else
-		dev_priv->sgx_reg = ioremap(resource_start + PSB_SGX_OFFSET,
-							PSB_SGX_SIZE);
-
 	if (!dev_priv->sgx_reg)
 		goto out_err;
 
-	if (IS_MRST(dev) || IS_MFLD(dev)) {
-		mrst_get_fuse_settings(dev);
-		mrst_get_vbt_data(dev_priv);
-		mid_get_pci_revID(dev_priv);
-	} else {
-		psb_get_core_freq(dev);
-		psb_intel_opregion_init(dev);
-		psb_intel_init_bios(dev);
-	}
+	ret = dev_priv->ops->chip_setup(dev);
+	if (ret)
+		goto out_err;
 
 	/* Init OSPM support */
 	gma_power_init(dev);
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 4bc5e8d..7e6f178 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -619,11 +619,16 @@ struct drm_psb_private {
 struct psb_ops {
 	const char *name;
 	unsigned int accel_2d:1;
+	int pipes;		/* Number of output pipes */
+	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);
+
 	/* Display management hooks */
 	int (*output_init)(struct drm_device *dev);
 	/* Power management hooks */


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 29/49] gma500: Add the beginnings of Cedarview support
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (27 preceding siblings ...)
  2011-07-05 14:40 ` [PATCH 28/49] gma500: move configuration bits into the psb_ops structure Alan Cox
@ 2011-07-05 14:40 ` Alan Cox
  2011-07-05 14:40 ` [PATCH 30/49] gma500: the 'mrst' BIOS is actually MID generic Alan Cox
                   ` (20 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:40 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile     |    1 
 drivers/staging/gma500/cdv_device.c |  353 +++++++++++++++++++++++++++++++++++
 drivers/staging/gma500/psb_drv.c    |    8 +
 drivers/staging/gma500/psb_drv.h    |    3 
 4 files changed, 365 insertions(+), 0 deletions(-)
 create mode 100644 drivers/staging/gma500/cdv_device.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index dc02b2f..1b525ac 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -22,6 +22,7 @@ psb_gfx-y += gem_glue.o \
 	  psb_mmu.o \
 	  psb_irq.o \
 	  psb_device.o \
+	  cdv_device.o \
 	  mrst_device.o \
 	  mrst_crtc.o \
 	  mrst_lvds.o \
diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c
new file mode 100644
index 0000000..bb0b3f9
--- /dev/null
+++ b/drivers/staging/gma500/cdv_device.c
@@ -0,0 +1,353 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <linux/backlight.h>
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_bios.h"
+
+
+static int cdv_output_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	psb_intel_lvds_init(dev, &dev_priv->mode_dev);
+	psb_intel_sdvo_init(dev, SDVOB);
+	return 0;
+}
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+/*
+ *	Poulsbo Backlight Interfaces
+ */
+
+#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
+#define BLC_PWM_FREQ_CALC_CONSTANT 32
+#define MHz 1000000
+
+#define PSB_BLC_PWM_PRECISION_FACTOR    10
+#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
+#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
+
+#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
+#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
+
+static int cdv_brightness;
+static struct backlight_device *cdv_backlight_device;
+
+static int cdv_get_brightness(struct backlight_device *bd)
+{
+	/* return locally cached var instead of HW read (due to DPST etc.) */
+	/* FIXME: ideally return actual value in case firmware fiddled with
+	   it */
+	return cdv_brightness;
+}
+
+
+static int cdv_backlight_setup(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long core_clock;
+	/* u32 bl_max_freq; */
+	/* unsigned long value; */
+	u16 bl_max_freq;
+	uint32_t value;
+	uint32_t blc_pwm_precision_factor;
+
+	/* get bl_max_freq and pol from dev_priv*/
+	if (!dev_priv->lvds_bl) {
+		dev_err(dev->dev, "Has no valid LVDS backlight info\n");
+		return -ENOENT;
+	}
+	bl_max_freq = dev_priv->lvds_bl->freq;
+	blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
+
+	core_clock = dev_priv->core_freq;
+
+	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
+	value *= blc_pwm_precision_factor;
+	value /= bl_max_freq;
+	value /= blc_pwm_precision_factor;
+
+	if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
+		 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
+				return -ERANGE;
+	else {
+		/* FIXME */
+	}
+	return 0;
+}
+
+static int cdv_set_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(cdv_backlight_device);
+	int level = bd->props.brightness;
+
+	/* Percentage 1-100% being valid */
+	if (level < 1)
+		level = 1;
+
+	/*cdv_intel_lvds_set_brightness(dev, level); FIXME */
+	cdv_brightness = level;
+	return 0;
+}
+
+static const struct backlight_ops cdv_ops = {
+	.get_brightness = cdv_get_brightness,
+	.update_status  = cdv_set_brightness,
+};
+
+static int cdv_backlight_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret;
+	struct backlight_properties props;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = 100;
+	props.type = BACKLIGHT_PLATFORM;
+
+	cdv_backlight_device = backlight_device_register("psb-bl",
+					NULL, (void *)dev, &cdv_ops, &props);
+	if (IS_ERR(cdv_backlight_device))
+		return PTR_ERR(cdv_backlight_device);
+
+	ret = cdv_backlight_setup(dev);
+	if (ret < 0) {
+		backlight_device_unregister(cdv_backlight_device);
+		cdv_backlight_device = NULL;
+		return ret;
+	}
+	cdv_backlight_device->props.brightness = 100;
+	cdv_backlight_device->props.max_brightness = 100;
+	backlight_update_status(cdv_backlight_device);
+	dev_priv->backlight_device = cdv_backlight_device;
+	return 0;
+}
+
+#endif
+
+/*
+ *	Provide the Poulsbo specific chip logic and low level methods
+ *	for power management
+ */
+
+static void cdv_init_pm(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
+	gating &= ~3;	/* Disable 2D clock gating */
+	gating |= 1;
+	PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
+	PSB_RSGX32(PSB_CR_CLKGATECTL);
+}
+
+/**
+ *	cdv_save_display_registers	-	save registers lost on suspend
+ *	@dev: our DRM device
+ *
+ *	Save the state we need in order to be able to restore the interface
+ *	upon resume from suspend
+ */
+static int cdv_save_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+
+	/* Display arbitration control + watermarks */
+	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+	/* Save crtc and output state */
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (drm_helper_crtc_in_use(crtc))
+			crtc->funcs->save(crtc);
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		connector->funcs->save(connector);
+
+	mutex_unlock(&dev->mode_config.mutex);
+	return 0;
+}
+
+/**
+ *	cdv_restore_display_registers	-	restore lost register state
+ *	@dev: our DRM device
+ *
+ *	Restore register state that was lost during suspend and resume.
+ */
+static int cdv_restore_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+	int pp_stat;
+
+	/* Display arbitration + watermarks */
+	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+	/*make sure VGA plane is off. it initializes to on after reset!*/
+	PSB_WVDC32(0x80000000, VGACNTRL);
+
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		if (drm_helper_crtc_in_use(crtc))
+			crtc->funcs->restore(crtc);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		connector->funcs->restore(connector);
+
+	mutex_unlock(&dev->mode_config.mutex);
+
+	if (dev_priv->iLVDS_enable) {
+		/*shutdown the panel*/
+		PSB_WVDC32(0, PP_CONTROL);
+		do {
+			pp_stat = PSB_RVDC32(PP_STATUS);
+		} while (pp_stat & 0x80000000);
+
+		/* Turn off the plane */
+		PSB_WVDC32(0x58000000, DSPACNTR);
+		PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
+		/* Wait ~4 ticks */
+		msleep(4);
+		/* Turn off pipe */
+		PSB_WVDC32(0x0, PIPEACONF);
+		/* Wait ~8 ticks */
+		msleep(8);
+
+		/* Turn off PLLs */
+		PSB_WVDC32(0, MRST_DPLL_A);
+	} else {
+		PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
+		PSB_WVDC32(0x0, PIPEACONF);
+		PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
+		while (REG_READ(0x70008) & 0x40000000)
+			cpu_relax();
+		while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
+			!= DPI_FIFO_EMPTY)
+			cpu_relax();
+		PSB_WVDC32(0, DEVICE_READY_REG);
+	}
+	return 0;
+}
+
+static int cdv_power_down(struct drm_device *dev)
+{
+	return 0;
+}
+
+static int cdv_power_up(struct drm_device *dev)
+{
+	return 0;
+}
+
+/* FIXME ? - shared with Poulsbo */
+static void cdv_get_core_freq(struct drm_device *dev)
+{
+	uint32_t clock;
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
+	/*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
+
+	pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
+	pci_read_config_dword(pci_root, 0xD4, &clock);
+	pci_dev_put(pci_root);
+
+	switch (clock & 0x07) {
+	case 0:
+		dev_priv->core_freq = 100;
+		break;
+	case 1:
+		dev_priv->core_freq = 133;
+		break;
+	case 2:
+		dev_priv->core_freq = 150;
+		break;
+	case 3:
+		dev_priv->core_freq = 178;
+		break;
+	case 4:
+		dev_priv->core_freq = 200;
+		break;
+	case 5:
+	case 6:
+	case 7:
+		dev_priv->core_freq = 266;
+	default:
+		dev_priv->core_freq = 0;
+	}
+}
+
+static int cdv_chip_setup(struct drm_device *dev)
+{
+	cdv_get_core_freq(dev);
+	psb_intel_opregion_init(dev);
+	psb_intel_init_bios(dev);
+	return 0;
+}
+
+/* CDV is much like Poulsbo but has MID like SGX offsets */
+
+const struct psb_ops cdv_chip_ops = {
+	.name = "Cedartrail",
+	.accel_2d = 0,
+	.pipes = 2,
+	.sgx_offset = MRST_SGX_OFFSET,
+	.chip_setup = cdv_chip_setup,
+
+	.crtc_helper = &psb_intel_helper_funcs,
+	.crtc_funcs = &psb_intel_crtc_funcs,
+
+	.output_init = cdv_output_init,
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	.backlight_init = cdv_backlight_init,
+#endif
+
+	.init_pm = cdv_init_pm,
+	.save_regs = cdv_save_display_registers,
+	.restore_regs = cdv_restore_display_registers,
+	.power_down = cdv_power_down,
+	.power_up = cdv_power_up,	
+};
+
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index b95d0a6..cf5fe91 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -68,6 +68,14 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
 	{ 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
 	{ 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
 	{ 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+	{ 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},
 	{ 0, 0, 0}
 };
 MODULE_DEVICE_TABLE(pci, pciidlist);
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 7e6f178..45035ec 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -804,6 +804,9 @@ extern const struct psb_ops mrst_chip_ops;
 /* mdfld_device.c */
 extern const struct psb_ops mdfld_chip_ops;
 
+/* cdv_device.c */
+extern const struct psb_ops cdv_chip_ops;
+
 /*
  * Debug print bits setting
  */


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 30/49] gma500: the 'mrst' BIOS is actually MID generic
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (28 preceding siblings ...)
  2011-07-05 14:40 ` [PATCH 29/49] gma500: Add the beginnings of Cedarview support Alan Cox
@ 2011-07-05 14:40 ` Alan Cox
  2011-07-05 14:40 ` [PATCH 31/49] gma500: tidy the framebuffer fixme and oddments Alan Cox
                   ` (19 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:40 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Shuffle the naming so this reflects better and we can try and build some
sort of ordering to the naming scheme.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile       |    2 
 drivers/staging/gma500/mdfld_device.c |    2 
 drivers/staging/gma500/mid_bios.c     |  271 +++++++++++++++++++++++++++++++++
 drivers/staging/gma500/mid_bios.h     |   21 +++
 drivers/staging/gma500/mrst_bios.c    |  271 ---------------------------------
 drivers/staging/gma500/mrst_bios.h    |   21 ---
 drivers/staging/gma500/mrst_device.c  |    2 
 drivers/staging/gma500/psb_drv.c      |    2 
 8 files changed, 296 insertions(+), 296 deletions(-)
 create mode 100644 drivers/staging/gma500/mid_bios.c
 create mode 100644 drivers/staging/gma500/mid_bios.h
 delete mode 100644 drivers/staging/gma500/mrst_bios.c
 delete mode 100644 drivers/staging/gma500/mrst_bios.h

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index 1b525ac..2ad6b1c 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -23,10 +23,10 @@ psb_gfx-y += gem_glue.o \
 	  psb_irq.o \
 	  psb_device.o \
 	  cdv_device.o \
+	  mid_bios.o \
 	  mrst_device.o \
 	  mrst_crtc.o \
 	  mrst_lvds.o \
-	  mrst_bios.o \
 	  mdfld_device.o \
 	  mdfld_output.o \
 	  mdfld_pyr_cmd.o \
diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
index daa9487..f258b06 100644
--- a/drivers/staging/gma500/mdfld_device.c
+++ b/drivers/staging/gma500/mdfld_device.c
@@ -26,7 +26,7 @@
 #include "psb_drv.h"
 #include "mdfld_output.h"
 #include "mdfld_dsi_output.h"
-#include "mrst_bios.h"
+#include "mid_bios.h"
 
 /*
  *	Provide the Medfield specific backlight management
diff --git a/drivers/staging/gma500/mid_bios.c b/drivers/staging/gma500/mid_bios.c
new file mode 100644
index 0000000..9a7731c
--- /dev/null
+++ b/drivers/staging/gma500/mid_bios.c
@@ -0,0 +1,271 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+/* TODO
+ * - Split functions by vbt type
+ * - Make them all take drm_device
+ * - Check ioremap failures
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "mid_bios.h"
+#include "mdfld_output.h"
+
+static int panel_id = GCT_DETECT;
+module_param_named(panel_id, panel_id, int, 0600);
+MODULE_PARM_DESC(panel_id, "Panel Identifier");
+
+
+static void mid_get_fuse_settings(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	uint32_t fuse_value = 0;
+	uint32_t fuse_value_tmp = 0;
+
+#define FB_REG06 0xD0810600
+#define FB_MIPI_DISABLE  (1 << 11)
+#define FB_REG09 0xD0810900
+#define FB_REG09 0xD0810900
+#define FB_SKU_MASK  0x7000
+#define FB_SKU_SHIFT 12
+#define FB_SKU_100 0
+#define FB_SKU_100L 1
+#define FB_SKU_83 2
+	pci_write_config_dword(pci_root, 0xD0, FB_REG06);
+	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
+
+	/* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
+	if (IS_MRST(dev))
+		dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
+
+	DRM_INFO("internal display is %s\n",
+		 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
+
+	 /* Prevent runtime suspend at start*/
+	 if (dev_priv->iLVDS_enable) {
+		dev_priv->is_lvds_on = true;
+		dev_priv->is_mipi_on = false;
+	} else {
+		dev_priv->is_mipi_on = true;
+		dev_priv->is_lvds_on = false;
+	}
+
+	dev_priv->video_device_fuse = fuse_value;
+
+	pci_write_config_dword(pci_root, 0xD0, FB_REG09);
+	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
+
+	dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value);
+	fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
+
+	dev_priv->fuse_reg_value = fuse_value;
+
+	switch (fuse_value_tmp) {
+	case FB_SKU_100:
+		dev_priv->core_freq = 200;
+		break;
+	case FB_SKU_100L:
+		dev_priv->core_freq = 100;
+		break;
+	case FB_SKU_83:
+		dev_priv->core_freq = 166;
+		break;
+	default:
+		dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n",
+								fuse_value_tmp);
+		dev_priv->core_freq = 0;
+	}
+	dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq);
+	pci_dev_put(pci_root);
+}
+
+/*
+ *	Get the revison ID, B0:D2:F0;0x08
+ */
+static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
+{
+	uint32_t platform_rev_id = 0;
+	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+	pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
+	dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
+	pci_dev_put(pci_gfx_root);
+	dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n",
+					dev_priv->platform_rev_id);
+}
+
+static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct mrst_vbt *vbt = &dev_priv->vbt_data;
+	u32 addr;
+	u16 new_size;
+	u8 *vbt_virtual;
+	u8 bpi;
+	u8 number_desc = 0;
+	struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
+	struct gct_r10_timing_info ti;
+	void *pGCT;
+	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+	/* Get the address of the platform config vbt, B0:D2:F0;0xFC */
+	pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
+	pci_dev_put(pci_gfx_root);
+
+	dev_dbg(dev->dev, "drm platform config address is %x\n", addr);
+
+	/* check for platform config address == 0. */
+	/* this means fw doesn't support vbt */
+
+	if (addr == 0) {
+		vbt->size = 0;
+		return;
+	}
+
+	/* get the virtual address of the vbt */
+	vbt_virtual = ioremap(addr, sizeof(*vbt));
+
+	memcpy(vbt, vbt_virtual, sizeof(*vbt));
+	iounmap(vbt_virtual); /* Free virtual address space */
+
+	dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision);
+
+	switch (vbt->revision) {
+	case 0:
+		vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
+					vbt->size - sizeof(*vbt) + 4);
+		pGCT = vbt->mrst_gct;
+		bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
+		dev_priv->gct_data.bpi = bpi;
+		dev_priv->gct_data.pt =
+			((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
+		memcpy(&dev_priv->gct_data.DTD,
+			&((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
+				sizeof(struct mrst_timing_info));
+		dev_priv->gct_data.Panel_Port_Control =
+		  ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+			((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+		break;
+	case 1:
+		vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
+					vbt->size - sizeof(*vbt) + 4);
+		pGCT = vbt->mrst_gct;
+		bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
+		dev_priv->gct_data.bpi = bpi;
+		dev_priv->gct_data.pt =
+			((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
+		memcpy(&dev_priv->gct_data.DTD,
+			&((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
+				sizeof(struct mrst_timing_info));
+		dev_priv->gct_data.Panel_Port_Control =
+		  ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+			((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
+		break;
+	case 0x10:
+		/*header definition changed from rev 01 (v2) to rev 10h. */
+		/*so, some values have changed location*/
+		new_size = vbt->checksum; /*checksum contains lo size byte*/
+		/*LSB of mrst_gct contains hi size byte*/
+		new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8;
+
+		vbt->checksum = vbt->size; /*size contains the checksum*/
+		if (new_size > 0xff)
+			vbt->size = 0xff; /*restrict size to 255*/
+		else
+			vbt->size = new_size;
+
+		/* number of descriptors defined in the GCT */
+		number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8;
+		bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16;
+		vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE,
+				GCT_R10_DISPLAY_DESC_SIZE * number_desc);
+		pGCT = vbt->mrst_gct;
+		pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE);
+		dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
+
+		/*copy the GCT display timings into a temp structure*/
+		memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
+
+		/*now copy the temp struct into the dev_priv->gct_data*/
+		dp_ti->pixel_clock = ti.pixel_clock;
+		dp_ti->hactive_hi = ti.hactive_hi;
+		dp_ti->hactive_lo = ti.hactive_lo;
+		dp_ti->hblank_hi = ti.hblank_hi;
+		dp_ti->hblank_lo = ti.hblank_lo;
+		dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
+		dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
+		dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
+		dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
+		dp_ti->vactive_hi = ti.vactive_hi;
+		dp_ti->vactive_lo = ti.vactive_lo;
+		dp_ti->vblank_hi = ti.vblank_hi;
+		dp_ti->vblank_lo = ti.vblank_lo;
+		dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
+		dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
+		dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
+		dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
+
+		/* Move the MIPI_Display_Descriptor data from GCT to dev priv */
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
+							*((u8 *)pGCT + 0x0d);
+		dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
+						(*((u8 *)pGCT + 0x0e)) << 8;
+		break;
+	default:
+		dev_err(dev->dev, "Unknown revision of GCT!\n");
+		vbt->size = 0;
+	}
+	if (IS_MFLD(dev_priv->dev)){
+		if (panel_id == GCT_DETECT) {
+			if (dev_priv->gct_data.bpi == 2) {
+				dev_info(dev->dev, "[GFX] PYR Panel Detected\n");
+				dev_priv->panel_id = PYR_CMD;
+				panel_id = PYR_CMD;
+			}
+			else if(dev_priv->gct_data.bpi == 0) {
+				dev_info(dev->dev, "[GFX] TMD Panel Detected.\n");
+				dev_priv->panel_id = TMD_VID;
+				panel_id = TMD_VID;
+			}
+			else {
+				dev_info(dev->dev, "[GFX] Default Panel (TPO)\n");
+				dev_priv->panel_id = TPO_CMD;
+				panel_id = TPO_CMD;
+			}
+		} else {
+			dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n");
+			dev_priv->panel_id = panel_id;
+		}
+	}
+}
+
+int mid_chip_setup(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	mid_get_fuse_settings(dev);
+	mid_get_vbt_data(dev_priv);
+	mid_get_pci_revID(dev_priv);
+	return 0;
+}
\ No newline at end of file
diff --git a/drivers/staging/gma500/mid_bios.h b/drivers/staging/gma500/mid_bios.h
new file mode 100644
index 0000000..00e7d56
--- /dev/null
+++ b/drivers/staging/gma500/mid_bios.h
@@ -0,0 +1,21 @@
+/**************************************************************************
+ * Copyright (c) 2011, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+extern int mid_chip_setup(struct drm_device *dev);
+
diff --git a/drivers/staging/gma500/mrst_bios.c b/drivers/staging/gma500/mrst_bios.c
deleted file mode 100644
index cf015df..0000000
--- a/drivers/staging/gma500/mrst_bios.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-/* TODO
- * - Split functions by vbt type
- * - Make them all take drm_device
- * - Check ioremap failures
- */
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "mrst_bios.h"
-#include "mdfld_output.h"
-
-static int panel_id = GCT_DETECT;
-module_param_named(panel_id, panel_id, int, 0600);
-MODULE_PARM_DESC(panel_id, "Panel Identifier");
-
-
-static void mid_get_fuse_settings(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
-	uint32_t fuse_value = 0;
-	uint32_t fuse_value_tmp = 0;
-
-#define FB_REG06 0xD0810600
-#define FB_MIPI_DISABLE  (1 << 11)
-#define FB_REG09 0xD0810900
-#define FB_REG09 0xD0810900
-#define FB_SKU_MASK  0x7000
-#define FB_SKU_SHIFT 12
-#define FB_SKU_100 0
-#define FB_SKU_100L 1
-#define FB_SKU_83 2
-	pci_write_config_dword(pci_root, 0xD0, FB_REG06);
-	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
-
-	/* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
-	if (IS_MRST(dev))
-		dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
-
-	DRM_INFO("internal display is %s\n",
-		 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
-
-	 /* Prevent runtime suspend at start*/
-	 if (dev_priv->iLVDS_enable) {
-		dev_priv->is_lvds_on = true;
-		dev_priv->is_mipi_on = false;
-	} else {
-		dev_priv->is_mipi_on = true;
-		dev_priv->is_lvds_on = false;
-	}
-
-	dev_priv->video_device_fuse = fuse_value;
-
-	pci_write_config_dword(pci_root, 0xD0, FB_REG09);
-	pci_read_config_dword(pci_root, 0xD4, &fuse_value);
-
-	dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value);
-	fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
-
-	dev_priv->fuse_reg_value = fuse_value;
-
-	switch (fuse_value_tmp) {
-	case FB_SKU_100:
-		dev_priv->core_freq = 200;
-		break;
-	case FB_SKU_100L:
-		dev_priv->core_freq = 100;
-		break;
-	case FB_SKU_83:
-		dev_priv->core_freq = 166;
-		break;
-	default:
-		dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n",
-								fuse_value_tmp);
-		dev_priv->core_freq = 0;
-	}
-	dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq);
-	pci_dev_put(pci_root);
-}
-
-/*
- *	Get the revison ID, B0:D2:F0;0x08
- */
-static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
-{
-	uint32_t platform_rev_id = 0;
-	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
-
-	pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
-	dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
-	pci_dev_put(pci_gfx_root);
-	dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n",
-					dev_priv->platform_rev_id);
-}
-
-static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
-{
-	struct drm_device *dev = dev_priv->dev;
-	struct mrst_vbt *vbt = &dev_priv->vbt_data;
-	u32 addr;
-	u16 new_size;
-	u8 *vbt_virtual;
-	u8 bpi;
-	u8 number_desc = 0;
-	struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
-	struct gct_r10_timing_info ti;
-	void *pGCT;
-	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
-
-	/* Get the address of the platform config vbt, B0:D2:F0;0xFC */
-	pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
-	pci_dev_put(pci_gfx_root);
-
-	dev_dbg(dev->dev, "drm platform config address is %x\n", addr);
-
-	/* check for platform config address == 0. */
-	/* this means fw doesn't support vbt */
-
-	if (addr == 0) {
-		vbt->size = 0;
-		return;
-	}
-
-	/* get the virtual address of the vbt */
-	vbt_virtual = ioremap(addr, sizeof(*vbt));
-
-	memcpy(vbt, vbt_virtual, sizeof(*vbt));
-	iounmap(vbt_virtual); /* Free virtual address space */
-
-	dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision);
-
-	switch (vbt->revision) {
-	case 0:
-		vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
-					vbt->size - sizeof(*vbt) + 4);
-		pGCT = vbt->mrst_gct;
-		bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
-		dev_priv->gct_data.bpi = bpi;
-		dev_priv->gct_data.pt =
-			((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
-		memcpy(&dev_priv->gct_data.DTD,
-			&((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
-				sizeof(struct mrst_timing_info));
-		dev_priv->gct_data.Panel_Port_Control =
-		  ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-			((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
-		break;
-	case 1:
-		vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
-					vbt->size - sizeof(*vbt) + 4);
-		pGCT = vbt->mrst_gct;
-		bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
-		dev_priv->gct_data.bpi = bpi;
-		dev_priv->gct_data.pt =
-			((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
-		memcpy(&dev_priv->gct_data.DTD,
-			&((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
-				sizeof(struct mrst_timing_info));
-		dev_priv->gct_data.Panel_Port_Control =
-		  ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-			((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
-		break;
-	case 0x10:
-		/*header definition changed from rev 01 (v2) to rev 10h. */
-		/*so, some values have changed location*/
-		new_size = vbt->checksum; /*checksum contains lo size byte*/
-		/*LSB of mrst_gct contains hi size byte*/
-		new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8;
-
-		vbt->checksum = vbt->size; /*size contains the checksum*/
-		if (new_size > 0xff)
-			vbt->size = 0xff; /*restrict size to 255*/
-		else
-			vbt->size = new_size;
-
-		/* number of descriptors defined in the GCT */
-		number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8;
-		bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16;
-		vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE,
-				GCT_R10_DISPLAY_DESC_SIZE * number_desc);
-		pGCT = vbt->mrst_gct;
-		pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE);
-		dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
-
-		/*copy the GCT display timings into a temp structure*/
-		memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
-
-		/*now copy the temp struct into the dev_priv->gct_data*/
-		dp_ti->pixel_clock = ti.pixel_clock;
-		dp_ti->hactive_hi = ti.hactive_hi;
-		dp_ti->hactive_lo = ti.hactive_lo;
-		dp_ti->hblank_hi = ti.hblank_hi;
-		dp_ti->hblank_lo = ti.hblank_lo;
-		dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
-		dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
-		dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
-		dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
-		dp_ti->vactive_hi = ti.vactive_hi;
-		dp_ti->vactive_lo = ti.vactive_lo;
-		dp_ti->vblank_hi = ti.vblank_hi;
-		dp_ti->vblank_lo = ti.vblank_lo;
-		dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
-		dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
-		dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
-		dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
-
-		/* Move the MIPI_Display_Descriptor data from GCT to dev priv */
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
-							*((u8 *)pGCT + 0x0d);
-		dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
-						(*((u8 *)pGCT + 0x0e)) << 8;
-		break;
-	default:
-		dev_err(dev->dev, "Unknown revision of GCT!\n");
-		vbt->size = 0;
-	}
-	if (IS_MFLD(dev_priv->dev)){
-		if (panel_id == GCT_DETECT) {
-			if (dev_priv->gct_data.bpi == 2) {
-				dev_info(dev->dev, "[GFX] PYR Panel Detected\n");
-				dev_priv->panel_id = PYR_CMD;
-				panel_id = PYR_CMD;
-			}
-			else if(dev_priv->gct_data.bpi == 0) {
-				dev_info(dev->dev, "[GFX] TMD Panel Detected.\n");
-				dev_priv->panel_id = TMD_VID;
-				panel_id = TMD_VID;
-			}
-			else {
-				dev_info(dev->dev, "[GFX] Default Panel (TPO)\n");
-				dev_priv->panel_id = TPO_CMD;
-				panel_id = TPO_CMD;
-			}
-		} else {
-			dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n");
-			dev_priv->panel_id = panel_id;
-		}
-	}
-}
-
-int mid_chip_setup(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	mid_get_fuse_settings(dev);
-	mid_get_vbt_data(dev_priv);
-	mid_get_pci_revID(dev_priv);
-	return 0;
-}
\ No newline at end of file
diff --git a/drivers/staging/gma500/mrst_bios.h b/drivers/staging/gma500/mrst_bios.h
deleted file mode 100644
index 00e7d56..0000000
--- a/drivers/staging/gma500/mrst_bios.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-extern int mid_chip_setup(struct drm_device *dev);
-
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
index d71e8d3..195a25b 100644
--- a/drivers/staging/gma500/mrst_device.c
+++ b/drivers/staging/gma500/mrst_device.c
@@ -25,7 +25,7 @@
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
 #include <asm/intel_scu_ipc.h>
-#include "mrst_bios.h"
+#include "mid_bios.h"
 
 /* IPC message and command defines used to enable/disable mipi panel voltages */
 #define IPC_MSG_PANEL_ON_OFF    0xE9
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index cf5fe91..ba47178 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -27,7 +27,7 @@
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
 #include "psb_intel_bios.h"
-#include "mrst_bios.h"
+#include "mid_bios.h"
 #include "mdfld_dsi_dbi.h"
 #include <drm/drm_pciids.h>
 #include "psb_powermgmt.h"


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 31/49] gma500: tidy the framebuffer fixme and oddments
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (29 preceding siblings ...)
  2011-07-05 14:40 ` [PATCH 30/49] gma500: the 'mrst' BIOS is actually MID generic Alan Cox
@ 2011-07-05 14:40 ` Alan Cox
  2011-07-05 14:41 ` [PATCH 32/49] gma500: move framebuffer file Alan Cox
                   ` (18 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:40 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_fb.c |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
index 349fff8..17c3cf6 100644
--- a/drivers/staging/gma500/psb_fb.c
+++ b/drivers/staging/gma500/psb_fb.c
@@ -591,7 +591,6 @@ int psb_fbdev_init(struct drm_device *dev)
 {
 	struct psb_fbdev *fbdev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	int num_crtc;
 
 	fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
 	if (!fbdev) {
@@ -602,10 +601,7 @@ int psb_fbdev_init(struct drm_device *dev)
 	dev_priv->fbdev = fbdev;
 	fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
 
-	/* FIXME: check Medfield */
-	num_crtc = 2;
-
-	drm_fb_helper_init(dev, &fbdev->psb_fb_helper, num_crtc,
+	drm_fb_helper_init(dev, &fbdev->psb_fb_helper, 2,
 							INTELFB_CONN_LIMIT);
 
 	drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 32/49] gma500: move framebuffer file
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (30 preceding siblings ...)
  2011-07-05 14:40 ` [PATCH 31/49] gma500: tidy the framebuffer fixme and oddments Alan Cox
@ 2011-07-05 14:41 ` Alan Cox
  2011-07-05 14:41 ` [PATCH 33/49] gma500: The 2D code is now also device independent Alan Cox
                   ` (17 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:41 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

The framebuffer code is now clean of device specific code, and passes
checkpatch. Move it to its new name

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile              |    2 
 drivers/staging/gma500/framebuffer.c         |  803 ++++++++++++++++++++++++++
 drivers/staging/gma500/framebuffer.h         |   49 ++
 drivers/staging/gma500/mdfld_intel_display.c |    2 
 drivers/staging/gma500/mrst_crtc.c           |    2 
 drivers/staging/gma500/psb_2d.c              |    3 
 drivers/staging/gma500/psb_drv.c             |    2 
 drivers/staging/gma500/psb_fb.c              |  803 --------------------------
 drivers/staging/gma500/psb_fb.h              |   49 --
 drivers/staging/gma500/psb_intel_display.c   |    2 
 10 files changed, 858 insertions(+), 859 deletions(-)
 create mode 100644 drivers/staging/gma500/framebuffer.c
 create mode 100644 drivers/staging/gma500/framebuffer.h
 delete mode 100644 drivers/staging/gma500/psb_fb.c
 delete mode 100644 drivers/staging/gma500/psb_fb.h

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index 2ad6b1c..fb6040f0 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -6,9 +6,9 @@ ccflags-y += -Iinclude/drm
 psb_gfx-y += gem_glue.o \
 	  backlight.o \
 	  power.o \
+	  framebuffer.o \
 	  psb_drv.o \
 	  psb_gem.o \
-	  psb_fb.o \
 	  psb_2d.o \
 	  psb_gtt.o \
 	  psb_intel_bios.o \
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
new file mode 100644
index 0000000..716a7b9
--- /dev/null
+++ b/drivers/staging/gma500/framebuffer.c
@@ -0,0 +1,803 @@
+/**************************************************************************
+ * 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.
+ *
+ **************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_drv.h"
+#include "framebuffer.h"
+
+#include "mdfld_output.h"
+
+static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
+static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+					      struct drm_file *file_priv,
+					      unsigned int *handle);
+
+static const struct drm_framebuffer_funcs psb_fb_funcs = {
+	.destroy = psb_user_framebuffer_destroy,
+	.create_handle = psb_user_framebuffer_create_handle,
+};
+
+#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
+
+static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
+	uint32_t v;
+
+	if (!fb)
+		return -ENOMEM;
+
+	if (regno > 255)
+		return 1;
+
+	red = CMAP_TOHW(red, info->var.red.length);
+	blue = CMAP_TOHW(blue, info->var.blue.length);
+	green = CMAP_TOHW(green, info->var.green.length);
+	transp = CMAP_TOHW(transp, info->var.transp.length);
+
+	v = (red << info->var.red.offset) |
+	    (green << info->var.green.offset) |
+	    (blue << info->var.blue.offset) |
+	    (transp << info->var.transp.offset);
+
+	if (regno < 16) {
+		switch (fb->bits_per_pixel) {
+		case 16:
+			((uint32_t *) info->pseudo_palette)[regno] = v;
+			break;
+		case 24:
+		case 32:
+			((uint32_t *) info->pseudo_palette)[regno] = v;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+
+void psbfb_suspend(struct drm_device *dev)
+{
+	struct drm_framebuffer *fb = 0;
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+
+	console_lock();
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+		struct fb_info *info = psbfb->fbdev;
+		fb_set_suspend(info, 1);
+		drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+	console_unlock();
+}
+
+void psbfb_resume(struct drm_device *dev)
+{
+	struct drm_framebuffer *fb = 0;
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+
+	console_lock();
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+		struct fb_info *info = psbfb->fbdev;
+		fb_set_suspend(info, 0);
+		drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+	console_unlock();
+	drm_helper_disable_unused_functions(dev);
+}
+
+static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct psb_framebuffer *psbfb = vma->vm_private_data;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int page_num;
+	int i;
+	unsigned long address;
+	int ret;
+	unsigned long pfn;
+	/* FIXME: assumes fb at stolen base which may not be true */
+	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
+
+	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+	address = (unsigned long)vmf->virtual_address;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	for (i = 0; i < page_num; i++) {
+		pfn = (phys_addr >> PAGE_SHIFT);
+
+		ret = vm_insert_mixed(vma, address, pfn);
+		if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
+			break;
+		else if (unlikely(ret != 0)) {
+			ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
+			return ret;
+		}
+		address += PAGE_SIZE;
+		phys_addr += PAGE_SIZE;
+	}
+	return VM_FAULT_NOPAGE;
+}
+
+static void psbfb_vm_open(struct vm_area_struct *vma)
+{
+}
+
+static void psbfb_vm_close(struct vm_area_struct *vma)
+{
+}
+
+static struct vm_operations_struct psbfb_vm_ops = {
+	.fault	= psbfb_vm_fault,
+	.open	= psbfb_vm_open,
+	.close	= psbfb_vm_close
+};
+
+static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+
+	if (vma->vm_pgoff != 0)
+		return -EINVAL;
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+
+	if (!psbfb->addr_space)
+		psbfb->addr_space = vma->vm_file->f_mapping;
+	/*
+	 * If this is a GEM object then info->screen_base is the virtual
+	 * kernel remapping of the object. FIXME: Review if this is
+	 * suitable for our mmap work
+	 */
+	vma->vm_ops = &psbfb_vm_ops;
+	vma->vm_private_data = (void *)psbfb;
+	vma->vm_flags |= VM_RESERVED | VM_IO |
+					VM_MIXEDMAP | VM_DONTEXPAND;
+	return 0;
+}
+
+static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
+						unsigned long arg)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 __user *p = (u32 __user *)arg;
+	u32 l;
+	u32 buf[32];
+	switch (cmd) {
+	case 0x12345678:
+		if (!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+		if (!dev_priv->ops->accel_2d)
+			return -EOPNOTSUPP;
+		if (get_user(l, p))
+			return -EFAULT;
+		if (l > 32)
+			return -EMSGSIZE;
+		if (copy_from_user(buf, p + 1, l * sizeof(u32)))
+			return -EFAULT;
+		psbfb_2d_submit(dev_priv, buf, l);
+		return 0;
+	default:
+		return -ENOTTY;
+	}
+}
+
+static struct fb_ops psbfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcolreg = psbfb_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = psbfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_mmap = psbfb_mmap,
+	.fb_sync = psbfb_sync,
+	.fb_ioctl = psbfb_ioctl,
+};
+
+static struct fb_ops psbfb_unaccel_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcolreg = psbfb_setcolreg,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_mmap = psbfb_mmap,
+	.fb_ioctl = psbfb_ioctl,
+};
+
+/**
+ *	psb_framebuffer_init	-	initialize a framebuffer
+ *	@dev: our DRM device
+ *	@fb: framebuffer to set up
+ *	@mode_cmd: mode description
+ *	@gt: backing object
+ *
+ *	Configure and fill in the boilerplate for our frame buffer. Return
+ *	0 on success or an error code if we fail.
+ */
+static int psb_framebuffer_init(struct drm_device *dev,
+					struct psb_framebuffer *fb,
+					struct drm_mode_fb_cmd *mode_cmd,
+					struct gtt_range *gt)
+{
+	int ret;
+
+	if (mode_cmd->pitch & 63)
+		return -EINVAL;
+	switch (mode_cmd->bpp) {
+	case 8:
+	case 16:
+	case 24:
+	case 32:
+		break;
+	default:
+		return -EINVAL;
+	}
+	ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
+	if (ret) {
+		dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
+		return ret;
+	}
+	drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
+	fb->gtt = gt;
+	return 0;
+}
+
+/**
+ *	psb_framebuffer_create	-	create a framebuffer backed by gt
+ *	@dev: our DRM device
+ *	@mode_cmd: the description of the requested mode
+ *	@gt: the backing object
+ *
+ *	Create a framebuffer object backed by the gt, and fill in the
+ *	boilerplate required
+ *
+ *	TODO: review object references
+ */
+
+static struct drm_framebuffer *psb_framebuffer_create
+			(struct drm_device *dev,
+			 struct drm_mode_fb_cmd *mode_cmd,
+			 struct gtt_range *gt)
+{
+	struct psb_framebuffer *fb;
+	int ret;
+
+	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+	if (!fb)
+		return ERR_PTR(-ENOMEM);
+
+	ret = psb_framebuffer_init(dev, fb, mode_cmd, gt);
+	if (ret) {
+		kfree(fb);
+		return ERR_PTR(ret);
+	}
+	return &fb->base;
+}
+
+/**
+ *	psbfb_alloc		-	allocate frame buffer memory
+ *	@dev: the DRM device
+ *	@aligned_size: space needed
+ *
+ *	Allocate the frame buffer. In the usual case we get a GTT range that
+ *	is stolen memory backed and life is simple. If there isn't sufficient
+ *	stolen memory or the system has no stolen memory we allocate a range
+ *	and back it with a GEM object.
+ *
+ *	In this case the GEM object has no handle.
+ *
+ *	FIXME: console speed up - allocate twice the space if room and use
+ *	hardware scrolling for acceleration.
+ */
+static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
+{
+	struct gtt_range *backing;
+	/* Begin by trying to use stolen memory backing */
+	backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
+	if (backing) {
+		if (drm_gem_private_object_init(dev,
+					&backing->gem, aligned_size) == 0)
+			return backing;
+		psb_gtt_free_range(dev, backing);
+	}
+	/* Next try using GEM host memory */
+	backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
+	if (backing == NULL)
+		return NULL;
+
+	/* Now back it with an object */
+	if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) {
+		psb_gtt_free_range(dev, backing);
+		return NULL;
+	}
+	return backing;
+}
+
+/**
+ *	psbfb_create		-	create a framebuffer
+ *	@fbdev: the framebuffer device
+ *	@sizes: specification of the layout
+ *
+ *	Create a framebuffer to the specifications provided
+ */
+static int psbfb_create(struct psb_fbdev *fbdev,
+				struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_device *dev = fbdev->psb_fb_helper.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct fb_info *info;
+	struct drm_framebuffer *fb;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+	struct drm_mode_fb_cmd mode_cmd;
+	struct device *device = &dev->pdev->dev;
+	int size;
+	int ret;
+	struct gtt_range *backing;
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.bpp = sizes->surface_bpp;
+
+	/* No 24bit packed */
+	if (mode_cmd.bpp == 24)
+		mode_cmd.bpp = 32;
+
+	/* HW requires pitch to be 64 byte aligned */
+	mode_cmd.pitch =  ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
+	mode_cmd.depth = sizes->surface_depth;
+
+	size = mode_cmd.pitch * mode_cmd.height;
+	size = ALIGN(size, PAGE_SIZE);
+
+	/* Allocate the framebuffer in the GTT with stolen page backing */
+	backing = psbfb_alloc(dev, size);
+	if (backing == NULL)
+		return -ENOMEM;
+
+	mutex_lock(&dev->struct_mutex);
+
+	info = framebuffer_alloc(0, device);
+	if (!info) {
+		ret = -ENOMEM;
+		goto out_err1;
+	}
+	info->par = fbdev;
+
+	ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
+	if (ret)
+		goto out_unref;
+
+	fb = &psbfb->base;
+	psbfb->fbdev = info;
+
+	fbdev->psb_fb_helper.fb = fb;
+	fbdev->psb_fb_helper.fbdev = info;
+
+	strcpy(info->fix.id, "psbfb");
+
+	info->flags = FBINFO_DEFAULT;
+	/* No 2D engine */
+	if (!dev_priv->ops->accel_2d)
+		info->fbops = &psbfb_unaccel_ops;
+	else
+		info->fbops = &psbfb_ops;
+
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret) {
+		ret = -ENOMEM;
+		goto out_unref;
+	}
+
+	info->fix.smem_start = dev->mode_config.fb_base;
+	info->fix.smem_len = size;
+
+	if (backing->stolen) {
+		/* Accessed stolen memory directly */
+		info->screen_base = (char *)dev_priv->vram_addr +
+							backing->offset;
+	} else {
+		/* Pin the pages into the GTT and create a mapping to them */
+		psb_gtt_pin(backing);
+		info->screen_base = vm_map_ram(backing->pages, backing->npage,
+				-1, PAGE_KERNEL);
+		if (info->screen_base == NULL) {
+			psb_gtt_unpin(backing);
+			ret = -ENOMEM;
+			goto out_unref;
+		}
+		psbfb->vm_map = 1;
+	}
+	info->screen_size = size;
+
+	if (dev_priv->pg->stolen_size) {
+		info->apertures = alloc_apertures(1);
+		if (!info->apertures) {
+			ret = -ENOMEM;
+			goto out_unref;
+		}
+		info->apertures->ranges[0].base = dev->mode_config.fb_base;
+		info->apertures->ranges[0].size = dev_priv->pg->stolen_size;
+	}
+
+	drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+	drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
+				sizes->fb_width, sizes->fb_height);
+
+	info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
+	info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
+
+	info->pixmap.size = 64 * 1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 1;
+
+	dev_info(dev->dev, "allocated %dx%d fb\n",
+					psbfb->base.width, psbfb->base.height);
+
+	mutex_unlock(&dev->struct_mutex);
+	return 0;
+out_unref:
+	if (backing->stolen)
+		psb_gtt_free_range(dev, backing);
+	else {
+		if (psbfb->vm_map)
+			vm_unmap_ram(info->screen_base, backing->npage);
+		drm_gem_object_unreference(&backing->gem);
+	}
+out_err1:
+	mutex_unlock(&dev->struct_mutex);
+	psb_gtt_free_range(dev, backing);
+	return ret;
+}
+
+/**
+ *	psb_user_framebuffer_create	-	create framebuffer
+ *	@dev: our DRM device
+ *	@filp: client file
+ *	@cmd: mode request
+ *
+ *	Create a new framebuffer backed by a userspace GEM object
+ */
+static struct drm_framebuffer *psb_user_framebuffer_create
+			(struct drm_device *dev, struct drm_file *filp,
+			 struct drm_mode_fb_cmd *cmd)
+{
+	struct gtt_range *r;
+	struct drm_gem_object *obj;
+
+	/*
+	 *	Find the GEM object and thus the gtt range object that is
+	 *	to back this space
+	 */
+	obj = drm_gem_object_lookup(dev, filp, cmd->handle);
+	if (obj == NULL)
+		return ERR_PTR(-ENOENT);
+
+	/* Let the core code do all the work */
+	r = container_of(obj, struct gtt_range, gem);
+	return psb_framebuffer_create(dev, cmd, r);
+}
+
+static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+							u16 blue, int regno)
+{
+}
+
+static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
+					u16 *green, u16 *blue, int regno)
+{
+}
+
+static int psbfb_probe(struct drm_fb_helper *helper,
+				struct drm_fb_helper_surface_size *sizes)
+{
+	struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
+	int new_fb = 0;
+	int ret;
+
+	if (!helper->fb) {
+		ret = psbfb_create(psb_fbdev, sizes);
+		if (ret)
+			return ret;
+		new_fb = 1;
+	}
+	return new_fb;
+}
+
+struct drm_fb_helper_funcs psb_fb_helper_funcs = {
+	.gamma_set = psbfb_gamma_set,
+	.gamma_get = psbfb_gamma_get,
+	.fb_probe = psbfb_probe,
+};
+
+int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
+{
+	struct fb_info *info;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+
+	if (fbdev->psb_fb_helper.fbdev) {
+		info = fbdev->psb_fb_helper.fbdev;
+
+		/* If this is our base framebuffer then kill any virtual map
+		   for the framebuffer layer and unpin it */
+		if (psbfb->vm_map) {
+			vm_unmap_ram(info->screen_base, psbfb->gtt->npage);
+			psb_gtt_unpin(psbfb->gtt);
+		}
+		unregister_framebuffer(info);
+		if (info->cmap.len)
+			fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	drm_fb_helper_fini(&fbdev->psb_fb_helper);
+	drm_framebuffer_cleanup(&psbfb->base);
+
+	if (psbfb->gtt)
+		drm_gem_object_unreference(&psbfb->gtt->gem);
+	return 0;
+}
+
+int psb_fbdev_init(struct drm_device *dev)
+{
+	struct psb_fbdev *fbdev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
+	if (!fbdev) {
+		dev_err(dev->dev, "no memory\n");
+		return -ENOMEM;
+	}
+
+	dev_priv->fbdev = fbdev;
+	fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
+
+	drm_fb_helper_init(dev, &fbdev->psb_fb_helper, 2,
+							INTELFB_CONN_LIMIT);
+
+	drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
+	drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
+	return 0;
+}
+
+void psb_fbdev_fini(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (!dev_priv->fbdev)
+		return;
+
+	psb_fbdev_destroy(dev, dev_priv->fbdev);
+	kfree(dev_priv->fbdev);
+	dev_priv->fbdev = NULL;
+}
+
+static void psbfb_output_poll_changed(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
+	drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
+}
+
+/**
+ *	psb_user_framebuffer_create_handle - add hamdle to a framebuffer
+ *	@fb: framebuffer
+ *	@file_priv: our DRM file
+ *	@handle: returned handle
+ *
+ *	Our framebuffer object is a GTT range which also contains a GEM
+ *	object. We need to turn it into a handle for userspace. GEM will do
+ *	the work for us
+ */
+static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+					      struct drm_file *file_priv,
+					      unsigned int *handle)
+{
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+	struct gtt_range *r = psbfb->gtt;
+	return drm_gem_handle_create(file_priv, &r->gem, handle);
+}
+
+/**
+ *	psb_user_framebuffer_destroy	-	destruct user created fb
+ *	@fb: framebuffer
+ *
+ *	User framebuffers are backed by GEM objects so all we have to do is
+ *	clean up a bit and drop the reference, GEM will handle the fallout
+ */
+static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+	struct gtt_range *r = psbfb->gtt;
+	struct drm_device *dev = fb->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_fbdev *fbdev = dev_priv->fbdev;
+	struct drm_crtc *crtc;
+	int reset = 0;
+
+	/* Should never get stolen memory for a user fb */
+	WARN_ON(r->stolen);
+
+	/* Check if we are erroneously live */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		if (crtc->fb == fb)
+			reset = 1;
+
+	if (reset)
+		/*
+		 * Now force a sane response before we permit the DRM CRTC
+		 * layer to do stupid things like blank the display. Instead
+		 * we reset this framebuffer as if the user had forced a reset.
+		 * We must do this before the cleanup so that the DRM layer
+		 * doesn't get a chance to stick its oar in where it isn't
+		 * wanted.
+		 */
+		drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
+
+	/* Let DRM do its clean up */
+	drm_framebuffer_cleanup(fb);
+	/*  We are no longer using the resource in GEM */
+	drm_gem_object_unreference_unlocked(&r->gem);
+	kfree(fb);
+}
+
+static const struct drm_mode_config_funcs psb_mode_funcs = {
+	.fb_create = psb_user_framebuffer_create,
+	.output_poll_changed = psbfb_output_poll_changed,
+};
+
+static int psb_create_backlight_property(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_property *backlight;
+
+	if (dev_priv->backlight_property)
+		return 0;
+
+	backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE,
+							"backlight", 2);
+	backlight->values[0] = 0;
+	backlight->values[1] = 100;
+
+	dev_priv->backlight_property = backlight;
+
+	return 0;
+}
+
+static void psb_setup_outputs(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_connector *connector;
+
+	drm_mode_create_scaling_mode_property(dev);
+	psb_create_backlight_property(dev);
+
+	dev_priv->ops->output_init(dev);
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    head) {
+		struct psb_intel_output *psb_intel_output =
+		    to_psb_intel_output(connector);
+		struct drm_encoder *encoder = &psb_intel_output->enc;
+		int crtc_mask = 0, clone_mask = 0;
+
+		/* valid crtcs */
+		switch (psb_intel_output->type) {
+		case INTEL_OUTPUT_SDVO:
+			crtc_mask = ((1 << 0) | (1 << 1));
+			clone_mask = (1 << INTEL_OUTPUT_SDVO);
+			break;
+		case INTEL_OUTPUT_LVDS:
+			if (IS_MRST(dev))
+				crtc_mask = (1 << 0);
+			else
+				crtc_mask = (1 << 1);
+			clone_mask = (1 << INTEL_OUTPUT_LVDS);
+			break;
+		case INTEL_OUTPUT_MIPI:
+			crtc_mask = (1 << 0);
+			clone_mask = (1 << INTEL_OUTPUT_MIPI);
+			break;
+		case INTEL_OUTPUT_MIPI2:
+			crtc_mask = (1 << 2);
+			clone_mask = (1 << INTEL_OUTPUT_MIPI2);
+			break;
+		case INTEL_OUTPUT_HDMI:
+			crtc_mask = (1 << 1);
+			clone_mask = (1 << INTEL_OUTPUT_HDMI);
+			break;
+		}
+		encoder->possible_crtcs = crtc_mask;
+		encoder->possible_clones =
+		    psb_intel_connector_clones(dev, clone_mask);
+	}
+}
+
+void psb_modeset_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
+	int i;
+
+	drm_mode_config_init(dev);
+
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+
+	dev->mode_config.funcs = (void *) &psb_mode_funcs;
+
+	/* set memory base */
+	/* MRST and PSB should use BAR 2*/
+	pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
+					&(dev->mode_config.fb_base));
+
+	/* num pipes is 2 for PSB but 1 for Mrst */
+	for (i = 0; i < dev_priv->num_pipe; i++)
+		psb_intel_crtc_init(dev, i, mode_dev);
+
+	dev->mode_config.max_width = 2048;
+	dev->mode_config.max_height = 2048;
+
+	psb_setup_outputs(dev);
+}
+
+void psb_modeset_cleanup(struct drm_device *dev)
+{
+	mutex_lock(&dev->struct_mutex);
+
+	drm_kms_helper_poll_fini(dev);
+	psb_fbdev_fini(dev);
+	drm_mode_config_cleanup(dev);
+
+	mutex_unlock(&dev->struct_mutex);
+}
diff --git a/drivers/staging/gma500/framebuffer.h b/drivers/staging/gma500/framebuffer.h
new file mode 100644
index 0000000..9416a21
--- /dev/null
+++ b/drivers/staging/gma500/framebuffer.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2008-2011, Intel Corporation
+ *
+ * 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:
+ *      Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _FRAMEBUFFER_H_
+#define _FRAMEBUFFER_H_
+
+#include <linux/version.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+
+#include "psb_drv.h"
+
+struct psb_framebuffer {
+	struct drm_framebuffer base;
+	struct address_space *addr_space;
+	struct fb_info *fbdev;
+	struct gtt_range *gtt;
+	bool vm_map;		/* True if we must undo a vm_map_ram */
+};
+
+struct psb_fbdev {
+	struct drm_fb_helper psb_fb_helper;
+	struct psb_framebuffer pfb;
+};
+
+#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
+
+extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
+
+#endif
+
diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c
index 0b619b6..1447a5b 100644
--- a/drivers/staging/gma500/mdfld_intel_display.c
+++ b/drivers/staging/gma500/mdfld_intel_display.c
@@ -24,7 +24,7 @@
  *	Eric Anholt <eric@anholt.net>
  */
 
-#include "psb_fb.h"
+#include "framebuffer.h"
 #include "psb_intel_display.h"
 #include "mdfld_dsi_dbi.h"
 #include "mdfld_dsi_dpi.h"
diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c
index fb9f2a2..d12d1a6 100644
--- a/drivers/staging/gma500/mrst_crtc.c
+++ b/drivers/staging/gma500/mrst_crtc.c
@@ -19,7 +19,7 @@
 #include <linux/pm_runtime.h>
 
 #include <drm/drmP.h>
-#include "psb_fb.h"
+#include "framebuffer.h"
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c
index df4c519..5ca4c42 100644
--- a/drivers/staging/gma500/psb_2d.c
+++ b/drivers/staging/gma500/psb_2d.c
@@ -38,8 +38,7 @@
 
 #include "psb_drv.h"
 #include "psb_reg.h"
-#include "psb_drv.h"
-#include "psb_fb.h"
+#include "framebuffer.h"
 
 /**
  *	psb_spank		-	reset the 2D engine
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index ba47178..4114ffd 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -23,7 +23,7 @@
 #include <drm/drm.h>
 #include "psb_drm.h"
 #include "psb_drv.h"
-#include "psb_fb.h"
+#include "framebuffer.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
 #include "psb_intel_bios.h"
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
deleted file mode 100644
index 17c3cf6..0000000
--- a/drivers/staging/gma500/psb_fb.c
+++ /dev/null
@@ -1,803 +0,0 @@
-/**************************************************************************
- * 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.
- *
- **************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_drv.h"
-#include "psb_fb.h"
-
-#include "mdfld_output.h"
-
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
-					      struct drm_file *file_priv,
-					      unsigned int *handle);
-
-static const struct drm_framebuffer_funcs psb_fb_funcs = {
-	.destroy = psb_user_framebuffer_destroy,
-	.create_handle = psb_user_framebuffer_create_handle,
-};
-
-#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
-
-static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
-	uint32_t v;
-
-	if (!fb)
-		return -ENOMEM;
-
-	if (regno > 255)
-		return 1;
-
-	red = CMAP_TOHW(red, info->var.red.length);
-	blue = CMAP_TOHW(blue, info->var.blue.length);
-	green = CMAP_TOHW(green, info->var.green.length);
-	transp = CMAP_TOHW(transp, info->var.transp.length);
-
-	v = (red << info->var.red.offset) |
-	    (green << info->var.green.offset) |
-	    (blue << info->var.blue.offset) |
-	    (transp << info->var.transp.offset);
-
-	if (regno < 16) {
-		switch (fb->bits_per_pixel) {
-		case 16:
-			((uint32_t *) info->pseudo_palette)[regno] = v;
-			break;
-		case 24:
-		case 32:
-			((uint32_t *) info->pseudo_palette)[regno] = v;
-			break;
-		}
-	}
-
-	return 0;
-}
-
-
-void psbfb_suspend(struct drm_device *dev)
-{
-	struct drm_framebuffer *fb = 0;
-	struct psb_framebuffer *psbfb = to_psb_fb(fb);
-
-	console_lock();
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
-		struct fb_info *info = psbfb->fbdev;
-		fb_set_suspend(info, 1);
-		drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
-	}
-	mutex_unlock(&dev->mode_config.mutex);
-	console_unlock();
-}
-
-void psbfb_resume(struct drm_device *dev)
-{
-	struct drm_framebuffer *fb = 0;
-	struct psb_framebuffer *psbfb = to_psb_fb(fb);
-
-	console_lock();
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
-		struct fb_info *info = psbfb->fbdev;
-		fb_set_suspend(info, 0);
-		drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
-	}
-	mutex_unlock(&dev->mode_config.mutex);
-	console_unlock();
-	drm_helper_disable_unused_functions(dev);
-}
-
-static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-	struct psb_framebuffer *psbfb = vma->vm_private_data;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	int page_num;
-	int i;
-	unsigned long address;
-	int ret;
-	unsigned long pfn;
-	/* FIXME: assumes fb at stolen base which may not be true */
-	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
-
-	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-	address = (unsigned long)vmf->virtual_address;
-
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-	for (i = 0; i < page_num; i++) {
-		pfn = (phys_addr >> PAGE_SHIFT);
-
-		ret = vm_insert_mixed(vma, address, pfn);
-		if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
-			break;
-		else if (unlikely(ret != 0)) {
-			ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
-			return ret;
-		}
-		address += PAGE_SIZE;
-		phys_addr += PAGE_SIZE;
-	}
-	return VM_FAULT_NOPAGE;
-}
-
-static void psbfb_vm_open(struct vm_area_struct *vma)
-{
-}
-
-static void psbfb_vm_close(struct vm_area_struct *vma)
-{
-}
-
-static struct vm_operations_struct psbfb_vm_ops = {
-	.fault	= psbfb_vm_fault,
-	.open	= psbfb_vm_open,
-	.close	= psbfb_vm_close
-};
-
-static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = &fbdev->pfb;
-
-	if (vma->vm_pgoff != 0)
-		return -EINVAL;
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-		return -EINVAL;
-
-	if (!psbfb->addr_space)
-		psbfb->addr_space = vma->vm_file->f_mapping;
-	/*
-	 * If this is a GEM object then info->screen_base is the virtual
-	 * kernel remapping of the object. FIXME: Review if this is
-	 * suitable for our mmap work
-	 */
-	vma->vm_ops = &psbfb_vm_ops;
-	vma->vm_private_data = (void *)psbfb;
-	vma->vm_flags |= VM_RESERVED | VM_IO |
-					VM_MIXEDMAP | VM_DONTEXPAND;
-	return 0;
-}
-
-static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
-						unsigned long arg)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = &fbdev->pfb;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 __user *p = (u32 __user *)arg;
-	u32 l;
-	u32 buf[32];
-	switch (cmd) {
-	case 0x12345678:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		if (!dev_priv->ops->accel_2d)
-			return -EOPNOTSUPP;
-		if (get_user(l, p))
-			return -EFAULT;
-		if (l > 32)
-			return -EMSGSIZE;
-		if (copy_from_user(buf, p + 1, l * sizeof(u32)))
-			return -EFAULT;
-		psbfb_2d_submit(dev_priv, buf, l);
-		return 0;
-	default:
-		return -ENOTTY;
-	}
-}
-
-static struct fb_ops psbfb_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcolreg = psbfb_setcolreg,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = psbfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_mmap = psbfb_mmap,
-	.fb_sync = psbfb_sync,
-	.fb_ioctl = psbfb_ioctl,
-};
-
-static struct fb_ops psbfb_unaccel_ops = {
-	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcolreg = psbfb_setcolreg,
-	.fb_fillrect = cfb_fillrect,
-	.fb_copyarea = cfb_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_mmap = psbfb_mmap,
-	.fb_ioctl = psbfb_ioctl,
-};
-
-/**
- *	psb_framebuffer_init	-	initialize a framebuffer
- *	@dev: our DRM device
- *	@fb: framebuffer to set up
- *	@mode_cmd: mode description
- *	@gt: backing object
- *
- *	Configure and fill in the boilerplate for our frame buffer. Return
- *	0 on success or an error code if we fail.
- */
-static int psb_framebuffer_init(struct drm_device *dev,
-					struct psb_framebuffer *fb,
-					struct drm_mode_fb_cmd *mode_cmd,
-					struct gtt_range *gt)
-{
-	int ret;
-
-	if (mode_cmd->pitch & 63)
-		return -EINVAL;
-	switch (mode_cmd->bpp) {
-	case 8:
-	case 16:
-	case 24:
-	case 32:
-		break;
-	default:
-		return -EINVAL;
-	}
-	ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
-	if (ret) {
-		dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
-		return ret;
-	}
-	drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
-	fb->gtt = gt;
-	return 0;
-}
-
-/**
- *	psb_framebuffer_create	-	create a framebuffer backed by gt
- *	@dev: our DRM device
- *	@mode_cmd: the description of the requested mode
- *	@gt: the backing object
- *
- *	Create a framebuffer object backed by the gt, and fill in the
- *	boilerplate required
- *
- *	TODO: review object references
- */
-
-static struct drm_framebuffer *psb_framebuffer_create
-			(struct drm_device *dev,
-			 struct drm_mode_fb_cmd *mode_cmd,
-			 struct gtt_range *gt)
-{
-	struct psb_framebuffer *fb;
-	int ret;
-
-	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
-	if (!fb)
-		return ERR_PTR(-ENOMEM);
-
-	ret = psb_framebuffer_init(dev, fb, mode_cmd, gt);
-	if (ret) {
-		kfree(fb);
-		return ERR_PTR(ret);
-	}
-	return &fb->base;
-}
-
-/**
- *	psbfb_alloc		-	allocate frame buffer memory
- *	@dev: the DRM device
- *	@aligned_size: space needed
- *
- *	Allocate the frame buffer. In the usual case we get a GTT range that
- *	is stolen memory backed and life is simple. If there isn't sufficient
- *	stolen memory or the system has no stolen memory we allocate a range
- *	and back it with a GEM object.
- *
- *	In this case the GEM object has no handle.
- *
- *	FIXME: console speed up - allocate twice the space if room and use
- *	hardware scrolling for acceleration.
- */
-static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
-{
-	struct gtt_range *backing;
-	/* Begin by trying to use stolen memory backing */
-	backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
-	if (backing) {
-		if (drm_gem_private_object_init(dev,
-					&backing->gem, aligned_size) == 0)
-			return backing;
-		psb_gtt_free_range(dev, backing);
-	}
-	/* Next try using GEM host memory */
-	backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
-	if (backing == NULL)
-		return NULL;
-
-	/* Now back it with an object */
-	if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) {
-		psb_gtt_free_range(dev, backing);
-		return NULL;
-	}
-	return backing;
-}
-
-/**
- *	psbfb_create		-	create a framebuffer
- *	@fbdev: the framebuffer device
- *	@sizes: specification of the layout
- *
- *	Create a framebuffer to the specifications provided
- */
-static int psbfb_create(struct psb_fbdev *fbdev,
-				struct drm_fb_helper_surface_size *sizes)
-{
-	struct drm_device *dev = fbdev->psb_fb_helper.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct fb_info *info;
-	struct drm_framebuffer *fb;
-	struct psb_framebuffer *psbfb = &fbdev->pfb;
-	struct drm_mode_fb_cmd mode_cmd;
-	struct device *device = &dev->pdev->dev;
-	int size;
-	int ret;
-	struct gtt_range *backing;
-
-	mode_cmd.width = sizes->surface_width;
-	mode_cmd.height = sizes->surface_height;
-	mode_cmd.bpp = sizes->surface_bpp;
-
-	/* No 24bit packed */
-	if (mode_cmd.bpp == 24)
-		mode_cmd.bpp = 32;
-
-	/* HW requires pitch to be 64 byte aligned */
-	mode_cmd.pitch =  ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
-	mode_cmd.depth = sizes->surface_depth;
-
-	size = mode_cmd.pitch * mode_cmd.height;
-	size = ALIGN(size, PAGE_SIZE);
-
-	/* Allocate the framebuffer in the GTT with stolen page backing */
-	backing = psbfb_alloc(dev, size);
-	if (backing == NULL)
-		return -ENOMEM;
-
-	mutex_lock(&dev->struct_mutex);
-
-	info = framebuffer_alloc(0, device);
-	if (!info) {
-		ret = -ENOMEM;
-		goto out_err1;
-	}
-	info->par = fbdev;
-
-	ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
-	if (ret)
-		goto out_unref;
-
-	fb = &psbfb->base;
-	psbfb->fbdev = info;
-
-	fbdev->psb_fb_helper.fb = fb;
-	fbdev->psb_fb_helper.fbdev = info;
-
-	strcpy(info->fix.id, "psbfb");
-
-	info->flags = FBINFO_DEFAULT;
-	/* No 2D engine */
-	if (!dev_priv->ops->accel_2d)
-		info->fbops = &psbfb_unaccel_ops;
-	else
-		info->fbops = &psbfb_ops;
-
-	ret = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (ret) {
-		ret = -ENOMEM;
-		goto out_unref;
-	}
-
-	info->fix.smem_start = dev->mode_config.fb_base;
-	info->fix.smem_len = size;
-
-	if (backing->stolen) {
-		/* Accessed stolen memory directly */
-		info->screen_base = (char *)dev_priv->vram_addr +
-							backing->offset;
-	} else {
-		/* Pin the pages into the GTT and create a mapping to them */
-		psb_gtt_pin(backing);
-		info->screen_base = vm_map_ram(backing->pages, backing->npage,
-				-1, PAGE_KERNEL);
-		if (info->screen_base == NULL) {
-			psb_gtt_unpin(backing);
-			ret = -ENOMEM;
-			goto out_unref;
-		}
-		psbfb->vm_map = 1;
-	}
-	info->screen_size = size;
-
-	if (dev_priv->pg->stolen_size) {
-		info->apertures = alloc_apertures(1);
-		if (!info->apertures) {
-			ret = -ENOMEM;
-			goto out_unref;
-		}
-		info->apertures->ranges[0].base = dev->mode_config.fb_base;
-		info->apertures->ranges[0].size = dev_priv->pg->stolen_size;
-	}
-
-	drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
-	drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
-				sizes->fb_width, sizes->fb_height);
-
-	info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
-	info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
-
-	info->pixmap.size = 64 * 1024;
-	info->pixmap.buf_align = 8;
-	info->pixmap.access_align = 32;
-	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-	info->pixmap.scan_align = 1;
-
-	dev_info(dev->dev, "allocated %dx%d fb\n",
-					psbfb->base.width, psbfb->base.height);
-
-	mutex_unlock(&dev->struct_mutex);
-	return 0;
-out_unref:
-	if (backing->stolen)
-		psb_gtt_free_range(dev, backing);
-	else {
-		if (psbfb->vm_map)
-			vm_unmap_ram(info->screen_base, backing->npage);
-		drm_gem_object_unreference(&backing->gem);
-	}
-out_err1:
-	mutex_unlock(&dev->struct_mutex);
-	psb_gtt_free_range(dev, backing);
-	return ret;
-}
-
-/**
- *	psb_user_framebuffer_create	-	create framebuffer
- *	@dev: our DRM device
- *	@filp: client file
- *	@cmd: mode request
- *
- *	Create a new framebuffer backed by a userspace GEM object
- */
-static struct drm_framebuffer *psb_user_framebuffer_create
-			(struct drm_device *dev, struct drm_file *filp,
-			 struct drm_mode_fb_cmd *cmd)
-{
-	struct gtt_range *r;
-	struct drm_gem_object *obj;
-
-	/*
-	 *	Find the GEM object and thus the gtt range object that is
-	 *	to back this space
-	 */
-	obj = drm_gem_object_lookup(dev, filp, cmd->handle);
-	if (obj == NULL)
-		return ERR_PTR(-ENOENT);
-
-	/* Let the core code do all the work */
-	r = container_of(obj, struct gtt_range, gem);
-	return psb_framebuffer_create(dev, cmd, r);
-}
-
-static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
-							u16 blue, int regno)
-{
-}
-
-static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
-					u16 *green, u16 *blue, int regno)
-{
-}
-
-static int psbfb_probe(struct drm_fb_helper *helper,
-				struct drm_fb_helper_surface_size *sizes)
-{
-	struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
-	int new_fb = 0;
-	int ret;
-
-	if (!helper->fb) {
-		ret = psbfb_create(psb_fbdev, sizes);
-		if (ret)
-			return ret;
-		new_fb = 1;
-	}
-	return new_fb;
-}
-
-struct drm_fb_helper_funcs psb_fb_helper_funcs = {
-	.gamma_set = psbfb_gamma_set,
-	.gamma_get = psbfb_gamma_get,
-	.fb_probe = psbfb_probe,
-};
-
-int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
-{
-	struct fb_info *info;
-	struct psb_framebuffer *psbfb = &fbdev->pfb;
-
-	if (fbdev->psb_fb_helper.fbdev) {
-		info = fbdev->psb_fb_helper.fbdev;
-
-		/* If this is our base framebuffer then kill any virtual map
-		   for the framebuffer layer and unpin it */
-		if (psbfb->vm_map) {
-			vm_unmap_ram(info->screen_base, psbfb->gtt->npage);
-			psb_gtt_unpin(psbfb->gtt);
-		}
-		unregister_framebuffer(info);
-		if (info->cmap.len)
-			fb_dealloc_cmap(&info->cmap);
-		framebuffer_release(info);
-	}
-	drm_fb_helper_fini(&fbdev->psb_fb_helper);
-	drm_framebuffer_cleanup(&psbfb->base);
-
-	if (psbfb->gtt)
-		drm_gem_object_unreference(&psbfb->gtt->gem);
-	return 0;
-}
-
-int psb_fbdev_init(struct drm_device *dev)
-{
-	struct psb_fbdev *fbdev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
-	if (!fbdev) {
-		dev_err(dev->dev, "no memory\n");
-		return -ENOMEM;
-	}
-
-	dev_priv->fbdev = fbdev;
-	fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
-
-	drm_fb_helper_init(dev, &fbdev->psb_fb_helper, 2,
-							INTELFB_CONN_LIMIT);
-
-	drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
-	drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
-	return 0;
-}
-
-void psb_fbdev_fini(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	if (!dev_priv->fbdev)
-		return;
-
-	psb_fbdev_destroy(dev, dev_priv->fbdev);
-	kfree(dev_priv->fbdev);
-	dev_priv->fbdev = NULL;
-}
-
-static void psbfb_output_poll_changed(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
-	drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
-}
-
-/**
- *	psb_user_framebuffer_create_handle - add hamdle to a framebuffer
- *	@fb: framebuffer
- *	@file_priv: our DRM file
- *	@handle: returned handle
- *
- *	Our framebuffer object is a GTT range which also contains a GEM
- *	object. We need to turn it into a handle for userspace. GEM will do
- *	the work for us
- */
-static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
-					      struct drm_file *file_priv,
-					      unsigned int *handle)
-{
-	struct psb_framebuffer *psbfb = to_psb_fb(fb);
-	struct gtt_range *r = psbfb->gtt;
-	return drm_gem_handle_create(file_priv, &r->gem, handle);
-}
-
-/**
- *	psb_user_framebuffer_destroy	-	destruct user created fb
- *	@fb: framebuffer
- *
- *	User framebuffers are backed by GEM objects so all we have to do is
- *	clean up a bit and drop the reference, GEM will handle the fallout
- */
-static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
-{
-	struct psb_framebuffer *psbfb = to_psb_fb(fb);
-	struct gtt_range *r = psbfb->gtt;
-	struct drm_device *dev = fb->dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct psb_fbdev *fbdev = dev_priv->fbdev;
-	struct drm_crtc *crtc;
-	int reset = 0;
-
-	/* Should never get stolen memory for a user fb */
-	WARN_ON(r->stolen);
-
-	/* Check if we are erroneously live */
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-		if (crtc->fb == fb)
-			reset = 1;
-
-	if (reset)
-		/*
-		 * Now force a sane response before we permit the DRM CRTC
-		 * layer to do stupid things like blank the display. Instead
-		 * we reset this framebuffer as if the user had forced a reset.
-		 * We must do this before the cleanup so that the DRM layer
-		 * doesn't get a chance to stick its oar in where it isn't
-		 * wanted.
-		 */
-		drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
-
-	/* Let DRM do its clean up */
-	drm_framebuffer_cleanup(fb);
-	/*  We are no longer using the resource in GEM */
-	drm_gem_object_unreference_unlocked(&r->gem);
-	kfree(fb);
-}
-
-static const struct drm_mode_config_funcs psb_mode_funcs = {
-	.fb_create = psb_user_framebuffer_create,
-	.output_poll_changed = psbfb_output_poll_changed,
-};
-
-static int psb_create_backlight_property(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct drm_property *backlight;
-
-	if (dev_priv->backlight_property)
-		return 0;
-
-	backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE,
-							"backlight", 2);
-	backlight->values[0] = 0;
-	backlight->values[1] = 100;
-
-	dev_priv->backlight_property = backlight;
-
-	return 0;
-}
-
-static void psb_setup_outputs(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct drm_connector *connector;
-
-	drm_mode_create_scaling_mode_property(dev);
-	psb_create_backlight_property(dev);
-
-	dev_priv->ops->output_init(dev);
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list,
-			    head) {
-		struct psb_intel_output *psb_intel_output =
-		    to_psb_intel_output(connector);
-		struct drm_encoder *encoder = &psb_intel_output->enc;
-		int crtc_mask = 0, clone_mask = 0;
-
-		/* valid crtcs */
-		switch (psb_intel_output->type) {
-		case INTEL_OUTPUT_SDVO:
-			crtc_mask = ((1 << 0) | (1 << 1));
-			clone_mask = (1 << INTEL_OUTPUT_SDVO);
-			break;
-		case INTEL_OUTPUT_LVDS:
-			if (IS_MRST(dev))
-				crtc_mask = (1 << 0);
-			else
-				crtc_mask = (1 << 1);
-			clone_mask = (1 << INTEL_OUTPUT_LVDS);
-			break;
-		case INTEL_OUTPUT_MIPI:
-			crtc_mask = (1 << 0);
-			clone_mask = (1 << INTEL_OUTPUT_MIPI);
-			break;
-		case INTEL_OUTPUT_MIPI2:
-			crtc_mask = (1 << 2);
-			clone_mask = (1 << INTEL_OUTPUT_MIPI2);
-			break;
-		case INTEL_OUTPUT_HDMI:
-			crtc_mask = (1 << 1);
-			clone_mask = (1 << INTEL_OUTPUT_HDMI);
-			break;
-		}
-		encoder->possible_crtcs = crtc_mask;
-		encoder->possible_clones =
-		    psb_intel_connector_clones(dev, clone_mask);
-	}
-}
-
-void psb_modeset_init(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv =
-	    (struct drm_psb_private *) dev->dev_private;
-	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
-	int i;
-
-	drm_mode_config_init(dev);
-
-	dev->mode_config.min_width = 0;
-	dev->mode_config.min_height = 0;
-
-	dev->mode_config.funcs = (void *) &psb_mode_funcs;
-
-	/* set memory base */
-	/* MRST and PSB should use BAR 2*/
-	pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
-					&(dev->mode_config.fb_base));
-
-	/* num pipes is 2 for PSB but 1 for Mrst */
-	for (i = 0; i < dev_priv->num_pipe; i++)
-		psb_intel_crtc_init(dev, i, mode_dev);
-
-	dev->mode_config.max_width = 2048;
-	dev->mode_config.max_height = 2048;
-
-	psb_setup_outputs(dev);
-}
-
-void psb_modeset_cleanup(struct drm_device *dev)
-{
-	mutex_lock(&dev->struct_mutex);
-
-	drm_kms_helper_poll_fini(dev);
-	psb_fbdev_fini(dev);
-	drm_mode_config_cleanup(dev);
-
-	mutex_unlock(&dev->struct_mutex);
-}
diff --git a/drivers/staging/gma500/psb_fb.h b/drivers/staging/gma500/psb_fb.h
deleted file mode 100644
index ed6e856..0000000
--- a/drivers/staging/gma500/psb_fb.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2008-2011, Intel Corporation
- *
- * 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:
- *      Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifndef _PSB_FB_H_
-#define _PSB_FB_H_
-
-#include <linux/version.h>
-#include <drm/drmP.h>
-#include <drm/drm_fb_helper.h>
-
-#include "psb_drv.h"
-
-struct psb_framebuffer {
-	struct drm_framebuffer base;
-	struct address_space *addr_space;
-	struct fb_info *fbdev;
-	struct gtt_range *gtt;
-	bool vm_map;		/* True if we must undo a vm_map_ram */
-};
-
-struct psb_fbdev {
-	struct drm_fb_helper psb_fb_helper;
-	struct psb_framebuffer pfb;
-};
-
-#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
-
-extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
-
-#endif
-
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index c38e819..0b650a0 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -22,7 +22,7 @@
 #include <linux/pm_runtime.h>
 
 #include <drm/drmP.h>
-#include "psb_fb.h"
+#include "framebuffer.h"
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 33/49] gma500: The 2D code is now also device independent
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (31 preceding siblings ...)
  2011-07-05 14:41 ` [PATCH 32/49] gma500: move framebuffer file Alan Cox
@ 2011-07-05 14:41 ` Alan Cox
  2011-07-05 14:41 ` [PATCH 34/49] gma500: the GEM and GTT code is device independant Alan Cox
                   ` (16 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:41 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Rename

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile   |    2 
 drivers/staging/gma500/accel_2d.c |  358 +++++++++++++++++++++++++++++++++++++
 drivers/staging/gma500/psb_2d.c   |  358 -------------------------------------
 drivers/staging/gma500/psb_drv.h  |    4 
 4 files changed, 361 insertions(+), 361 deletions(-)
 create mode 100644 drivers/staging/gma500/accel_2d.c
 delete mode 100644 drivers/staging/gma500/psb_2d.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index fb6040f0..d2c0887 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -4,12 +4,12 @@
 ccflags-y += -Iinclude/drm
 
 psb_gfx-y += gem_glue.o \
+	  accel_2d.o \
 	  backlight.o \
 	  power.o \
 	  framebuffer.o \
 	  psb_drv.o \
 	  psb_gem.o \
-	  psb_2d.o \
 	  psb_gtt.o \
 	  psb_intel_bios.o \
 	  psb_intel_opregion.o \
diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c
new file mode 100644
index 0000000..5ca4c42
--- /dev/null
+++ b/drivers/staging/gma500/accel_2d.c
@@ -0,0 +1,358 @@
+/**************************************************************************
+ * 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.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ **************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "framebuffer.h"
+
+/**
+ *	psb_spank		-	reset the 2D engine
+ *	@dev_priv: our PSB DRM device
+ *
+ *	Soft reset the graphics engine and then reload the necessary registers.
+ *	We use this at initialisation time but it will become relevant for
+ *	accelerated X later
+ */
+void psb_spank(struct drm_psb_private *dev_priv)
+{
+	PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
+		_PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET |
+		_PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET |
+		_PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET);
+	PSB_RSGX32(PSB_CR_SOFT_RESET);
+
+	msleep(1);
+
+	PSB_WSGX32(0, PSB_CR_SOFT_RESET);
+	wmb();
+	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT,
+		   PSB_CR_BIF_CTRL);
+	wmb();
+	(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
+
+	msleep(1);
+	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT,
+		   PSB_CR_BIF_CTRL);
+	(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
+	PSB_WSGX32(dev_priv->pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
+}
+
+/**
+ *	psb2_2d_wait_available	-	wait for FIFO room
+ *	@dev_priv: our DRM device
+ *	@size: size (in dwords) of the command we want to issue
+ *
+ *	Wait until there is room to load the FIFO with our data. If the
+ *	device is not responding then reset it
+ */
+static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
+			  unsigned size)
+{
+	uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
+	unsigned long t = jiffies + HZ;
+
+	while (avail < size) {
+		avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
+		if (time_after(jiffies, t)) {
+			psb_spank(dev_priv);
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+/**
+ *	psb_2d_submit		-	submit a 2D command
+ *	@dev_priv: our DRM device
+ *	@cmdbuf: command to issue
+ *	@size: length (in dwords)
+ *
+ *	Issue one or more 2D commands to the accelerator. This needs to be
+ *	serialized later when we add the GEM interfaces for acceleration
+ */
+int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
+								unsigned size)
+{
+	int ret = 0;
+	int i;
+	unsigned submit_size;
+
+	while (size > 0) {
+		submit_size = (size < 0x60) ? size : 0x60;
+		size -= submit_size;
+		ret = psb_2d_wait_available(dev_priv, submit_size);
+		if (ret)
+			return ret;
+
+		submit_size <<= 2;
+
+		for (i = 0; i < submit_size; i += 4)
+			PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
+
+		(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
+	}
+	return 0;
+}
+
+
+/**
+ *	psb_accel_2d_copy_direction	-	compute blit order
+ *	@xdir: X direction of move
+ *	@ydir: Y direction of move
+ *
+ *	Compute the correct order setings to ensure that an overlapping blit
+ *	correctly copies all the pixels.
+ */
+static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
+{
+	if (xdir < 0)
+		return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
+						PSB_2D_COPYORDER_TR2BL;
+	else
+		return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
+						PSB_2D_COPYORDER_TL2BR;
+}
+
+/**
+ *	psb_accel_2d_copy		-	accelerated 2D copy
+ *	@dev_priv: our DRM device
+ *	@src_offset in bytes
+ *	@src_stride in bytes
+ *	@src_format psb 2D format defines
+ *	@dst_offset in bytes
+ *	@dst_stride in bytes
+ *	@dst_format psb 2D format defines
+ *	@src_x offset in pixels
+ *	@src_y offset in pixels
+ *	@dst_x offset in pixels
+ *	@dst_y offset in pixels
+ *	@size_x of the copied area
+ *	@size_y of the copied area
+ *
+ *	Format and issue a 2D accelerated copy command.
+ */
+static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
+			     uint32_t src_offset, uint32_t src_stride,
+			     uint32_t src_format, uint32_t dst_offset,
+			     uint32_t dst_stride, uint32_t dst_format,
+			     uint16_t src_x, uint16_t src_y,
+			     uint16_t dst_x, uint16_t dst_y,
+			     uint16_t size_x, uint16_t size_y)
+{
+	uint32_t blit_cmd;
+	uint32_t buffer[10];
+	uint32_t *buf;
+	uint32_t direction;
+
+	buf = buffer;
+
+	direction =
+	    psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y);
+
+	if (direction == PSB_2D_COPYORDER_BR2TL ||
+	    direction == PSB_2D_COPYORDER_TR2BL) {
+		src_x += size_x - 1;
+		dst_x += size_x - 1;
+	}
+	if (direction == PSB_2D_COPYORDER_BR2TL ||
+	    direction == PSB_2D_COPYORDER_BL2TR) {
+		src_y += size_y - 1;
+		dst_y += size_y - 1;
+	}
+
+	blit_cmd =
+	    PSB_2D_BLIT_BH |
+	    PSB_2D_ROT_NONE |
+	    PSB_2D_DSTCK_DISABLE |
+	    PSB_2D_SRCCK_DISABLE |
+	    PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction;
+
+	*buf++ = PSB_2D_FENCE_BH;
+	*buf++ =
+	    PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
+					       PSB_2D_DST_STRIDE_SHIFT);
+	*buf++ = dst_offset;
+	*buf++ =
+	    PSB_2D_SRC_SURF_BH | src_format | (src_stride <<
+					       PSB_2D_SRC_STRIDE_SHIFT);
+	*buf++ = src_offset;
+	*buf++ =
+	    PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) |
+	    (src_y << PSB_2D_SRCOFF_YSTART_SHIFT);
+	*buf++ = blit_cmd;
+	*buf++ =
+	    (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
+						  PSB_2D_DST_YSTART_SHIFT);
+	*buf++ =
+	    (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
+						  PSB_2D_DST_YSIZE_SHIFT);
+	*buf++ = PSB_2D_FLUSH_BH;
+
+	return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
+}
+
+/**
+ *	psbfb_copyarea_accel	-	copyarea acceleration for /dev/fb
+ *	@info: our framebuffer
+ *	@a: copyarea parameters from the framebuffer core
+ *
+ *	Perform a 2D copy via the accelerator
+ */
+static void psbfb_copyarea_accel(struct fb_info *info,
+				 const struct fb_copyarea *a)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	uint32_t offset;
+	uint32_t stride;
+	uint32_t src_format;
+	uint32_t dst_format;
+
+	if (!fb)
+		return;
+
+	offset = psbfb->gtt->offset;
+	stride = fb->pitch;
+
+	switch (fb->depth) {
+	case 8:
+		src_format = PSB_2D_SRC_332RGB;
+		dst_format = PSB_2D_DST_332RGB;
+		break;
+	case 15:
+		src_format = PSB_2D_SRC_555RGB;
+		dst_format = PSB_2D_DST_555RGB;
+		break;
+	case 16:
+		src_format = PSB_2D_SRC_565RGB;
+		dst_format = PSB_2D_DST_565RGB;
+		break;
+	case 24:
+	case 32:
+		/* this is wrong but since we don't do blending its okay */
+		src_format = PSB_2D_SRC_8888ARGB;
+		dst_format = PSB_2D_DST_8888ARGB;
+		break;
+	default:
+		/* software fallback */
+		cfb_copyarea(info, a);
+		return;
+	}
+
+	if (!gma_power_begin(dev, false)) {
+		cfb_copyarea(info, a);
+		return;
+	}
+	psb_accel_2d_copy(dev_priv,
+			  offset, stride, src_format,
+			  offset, stride, dst_format,
+			  a->sx, a->sy, a->dx, a->dy, a->width, a->height);
+	gma_power_end(dev);
+}
+
+/**
+ *	psbfb_copyarea	-	2D copy interface
+ *	@info: our framebuffer
+ *	@region: region to copy
+ *
+ *	Copy an area of the framebuffer console either by the accelerator
+ *	or directly using the cfb helpers according to the request
+ */
+void psbfb_copyarea(struct fb_info *info,
+			   const struct fb_copyarea *region)
+{
+	if (unlikely(info->state != FBINFO_STATE_RUNNING))
+		return;
+
+	/* Avoid the 8 pixel erratum */
+	if (region->width == 8 || region->height == 8 ||
+		(info->flags & FBINFO_HWACCEL_DISABLED))
+		return cfb_copyarea(info, region);
+
+	psbfb_copyarea_accel(info, region);
+}
+
+/**
+ *	psbfb_sync	-	synchronize 2D
+ *	@info: our framebuffer
+ *
+ *	Wait for the 2D engine to quiesce so that we can do CPU
+ *	access to the framebuffer again
+ */
+int psbfb_sync(struct fb_info *info)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long _end = jiffies + DRM_HZ;
+	int busy = 0;
+
+	/*
+	 * First idle the 2D engine.
+	 */
+
+	if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
+	    ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
+		goto out;
+
+	do {
+		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
+		cpu_relax();
+	} while (busy && !time_after_eq(jiffies, _end));
+
+	if (busy)
+		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
+	if (busy)
+		goto out;
+
+	do {
+		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
+						_PSB_C2B_STATUS_BUSY) != 0);
+		cpu_relax();
+	} while (busy && !time_after_eq(jiffies, _end));
+	if (busy)
+		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
+					_PSB_C2B_STATUS_BUSY) != 0);
+
+out:
+	return (busy) ? -EBUSY : 0;
+}
diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c
deleted file mode 100644
index 5ca4c42..0000000
--- a/drivers/staging/gma500/psb_2d.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/**************************************************************************
- * 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.
- *
- * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
- * develop this driver.
- *
- **************************************************************************/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include <drm/drm_crtc.h>
-
-#include "psb_drv.h"
-#include "psb_reg.h"
-#include "framebuffer.h"
-
-/**
- *	psb_spank		-	reset the 2D engine
- *	@dev_priv: our PSB DRM device
- *
- *	Soft reset the graphics engine and then reload the necessary registers.
- *	We use this at initialisation time but it will become relevant for
- *	accelerated X later
- */
-void psb_spank(struct drm_psb_private *dev_priv)
-{
-	PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
-		_PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET |
-		_PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET |
-		_PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET);
-	PSB_RSGX32(PSB_CR_SOFT_RESET);
-
-	msleep(1);
-
-	PSB_WSGX32(0, PSB_CR_SOFT_RESET);
-	wmb();
-	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT,
-		   PSB_CR_BIF_CTRL);
-	wmb();
-	(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
-
-	msleep(1);
-	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT,
-		   PSB_CR_BIF_CTRL);
-	(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
-	PSB_WSGX32(dev_priv->pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
-}
-
-/**
- *	psb2_2d_wait_available	-	wait for FIFO room
- *	@dev_priv: our DRM device
- *	@size: size (in dwords) of the command we want to issue
- *
- *	Wait until there is room to load the FIFO with our data. If the
- *	device is not responding then reset it
- */
-static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
-			  unsigned size)
-{
-	uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
-	unsigned long t = jiffies + HZ;
-
-	while (avail < size) {
-		avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
-		if (time_after(jiffies, t)) {
-			psb_spank(dev_priv);
-			return -EIO;
-		}
-	}
-	return 0;
-}
-
-/**
- *	psb_2d_submit		-	submit a 2D command
- *	@dev_priv: our DRM device
- *	@cmdbuf: command to issue
- *	@size: length (in dwords)
- *
- *	Issue one or more 2D commands to the accelerator. This needs to be
- *	serialized later when we add the GEM interfaces for acceleration
- */
-int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
-								unsigned size)
-{
-	int ret = 0;
-	int i;
-	unsigned submit_size;
-
-	while (size > 0) {
-		submit_size = (size < 0x60) ? size : 0x60;
-		size -= submit_size;
-		ret = psb_2d_wait_available(dev_priv, submit_size);
-		if (ret)
-			return ret;
-
-		submit_size <<= 2;
-
-		for (i = 0; i < submit_size; i += 4)
-			PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
-
-		(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
-	}
-	return 0;
-}
-
-
-/**
- *	psb_accel_2d_copy_direction	-	compute blit order
- *	@xdir: X direction of move
- *	@ydir: Y direction of move
- *
- *	Compute the correct order setings to ensure that an overlapping blit
- *	correctly copies all the pixels.
- */
-static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
-{
-	if (xdir < 0)
-		return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
-						PSB_2D_COPYORDER_TR2BL;
-	else
-		return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
-						PSB_2D_COPYORDER_TL2BR;
-}
-
-/**
- *	psb_accel_2d_copy		-	accelerated 2D copy
- *	@dev_priv: our DRM device
- *	@src_offset in bytes
- *	@src_stride in bytes
- *	@src_format psb 2D format defines
- *	@dst_offset in bytes
- *	@dst_stride in bytes
- *	@dst_format psb 2D format defines
- *	@src_x offset in pixels
- *	@src_y offset in pixels
- *	@dst_x offset in pixels
- *	@dst_y offset in pixels
- *	@size_x of the copied area
- *	@size_y of the copied area
- *
- *	Format and issue a 2D accelerated copy command.
- */
-static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
-			     uint32_t src_offset, uint32_t src_stride,
-			     uint32_t src_format, uint32_t dst_offset,
-			     uint32_t dst_stride, uint32_t dst_format,
-			     uint16_t src_x, uint16_t src_y,
-			     uint16_t dst_x, uint16_t dst_y,
-			     uint16_t size_x, uint16_t size_y)
-{
-	uint32_t blit_cmd;
-	uint32_t buffer[10];
-	uint32_t *buf;
-	uint32_t direction;
-
-	buf = buffer;
-
-	direction =
-	    psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y);
-
-	if (direction == PSB_2D_COPYORDER_BR2TL ||
-	    direction == PSB_2D_COPYORDER_TR2BL) {
-		src_x += size_x - 1;
-		dst_x += size_x - 1;
-	}
-	if (direction == PSB_2D_COPYORDER_BR2TL ||
-	    direction == PSB_2D_COPYORDER_BL2TR) {
-		src_y += size_y - 1;
-		dst_y += size_y - 1;
-	}
-
-	blit_cmd =
-	    PSB_2D_BLIT_BH |
-	    PSB_2D_ROT_NONE |
-	    PSB_2D_DSTCK_DISABLE |
-	    PSB_2D_SRCCK_DISABLE |
-	    PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction;
-
-	*buf++ = PSB_2D_FENCE_BH;
-	*buf++ =
-	    PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
-					       PSB_2D_DST_STRIDE_SHIFT);
-	*buf++ = dst_offset;
-	*buf++ =
-	    PSB_2D_SRC_SURF_BH | src_format | (src_stride <<
-					       PSB_2D_SRC_STRIDE_SHIFT);
-	*buf++ = src_offset;
-	*buf++ =
-	    PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) |
-	    (src_y << PSB_2D_SRCOFF_YSTART_SHIFT);
-	*buf++ = blit_cmd;
-	*buf++ =
-	    (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
-						  PSB_2D_DST_YSTART_SHIFT);
-	*buf++ =
-	    (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
-						  PSB_2D_DST_YSIZE_SHIFT);
-	*buf++ = PSB_2D_FLUSH_BH;
-
-	return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
-}
-
-/**
- *	psbfb_copyarea_accel	-	copyarea acceleration for /dev/fb
- *	@info: our framebuffer
- *	@a: copyarea parameters from the framebuffer core
- *
- *	Perform a 2D copy via the accelerator
- */
-static void psbfb_copyarea_accel(struct fb_info *info,
-				 const struct fb_copyarea *a)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = &fbdev->pfb;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	uint32_t offset;
-	uint32_t stride;
-	uint32_t src_format;
-	uint32_t dst_format;
-
-	if (!fb)
-		return;
-
-	offset = psbfb->gtt->offset;
-	stride = fb->pitch;
-
-	switch (fb->depth) {
-	case 8:
-		src_format = PSB_2D_SRC_332RGB;
-		dst_format = PSB_2D_DST_332RGB;
-		break;
-	case 15:
-		src_format = PSB_2D_SRC_555RGB;
-		dst_format = PSB_2D_DST_555RGB;
-		break;
-	case 16:
-		src_format = PSB_2D_SRC_565RGB;
-		dst_format = PSB_2D_DST_565RGB;
-		break;
-	case 24:
-	case 32:
-		/* this is wrong but since we don't do blending its okay */
-		src_format = PSB_2D_SRC_8888ARGB;
-		dst_format = PSB_2D_DST_8888ARGB;
-		break;
-	default:
-		/* software fallback */
-		cfb_copyarea(info, a);
-		return;
-	}
-
-	if (!gma_power_begin(dev, false)) {
-		cfb_copyarea(info, a);
-		return;
-	}
-	psb_accel_2d_copy(dev_priv,
-			  offset, stride, src_format,
-			  offset, stride, dst_format,
-			  a->sx, a->sy, a->dx, a->dy, a->width, a->height);
-	gma_power_end(dev);
-}
-
-/**
- *	psbfb_copyarea	-	2D copy interface
- *	@info: our framebuffer
- *	@region: region to copy
- *
- *	Copy an area of the framebuffer console either by the accelerator
- *	or directly using the cfb helpers according to the request
- */
-void psbfb_copyarea(struct fb_info *info,
-			   const struct fb_copyarea *region)
-{
-	if (unlikely(info->state != FBINFO_STATE_RUNNING))
-		return;
-
-	/* Avoid the 8 pixel erratum */
-	if (region->width == 8 || region->height == 8 ||
-		(info->flags & FBINFO_HWACCEL_DISABLED))
-		return cfb_copyarea(info, region);
-
-	psbfb_copyarea_accel(info, region);
-}
-
-/**
- *	psbfb_sync	-	synchronize 2D
- *	@info: our framebuffer
- *
- *	Wait for the 2D engine to quiesce so that we can do CPU
- *	access to the framebuffer again
- */
-int psbfb_sync(struct fb_info *info)
-{
-	struct psb_fbdev *fbdev = info->par;
-	struct psb_framebuffer *psbfb = &fbdev->pfb;
-	struct drm_device *dev = psbfb->base.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	unsigned long _end = jiffies + DRM_HZ;
-	int busy = 0;
-
-	/*
-	 * First idle the 2D engine.
-	 */
-
-	if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
-	    ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
-		goto out;
-
-	do {
-		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
-		cpu_relax();
-	} while (busy && !time_after_eq(jiffies, _end));
-
-	if (busy)
-		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
-	if (busy)
-		goto out;
-
-	do {
-		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
-						_PSB_C2B_STATUS_BUSY) != 0);
-		cpu_relax();
-	} while (busy && !time_after_eq(jiffies, _end));
-	if (busy)
-		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
-					_PSB_C2B_STATUS_BUSY) != 0);
-
-out:
-	return (busy) ? -EBUSY : 0;
-}
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 45035ec..9c6aba5 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -732,13 +732,13 @@ extern void mdfld_disable_te(struct drm_device *dev, int pipe);
 extern int psb_intel_opregion_init(struct drm_device *dev);
 
 /*
- *psb_fb.c
+ * framebuffer.c
  */
 extern int psbfb_probed(struct drm_device *dev);
 extern int psbfb_remove(struct drm_device *dev,
 			struct drm_framebuffer *fb);
 /*
- * psb_2d.c
+ * accel_2d.c
  */
 extern void psbfb_copyarea(struct fb_info *info,
 					const struct fb_copyarea *region);


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (32 preceding siblings ...)
  2011-07-05 14:41 ` [PATCH 33/49] gma500: The 2D code is now also device independent Alan Cox
@ 2011-07-05 14:41 ` Alan Cox
  2011-07-08  1:14   ` Hugh Dickins
  2011-07-05 14:41 ` [PATCH 35/49] gma500: begin the config based split Alan Cox
                   ` (15 subsequent siblings)
  49 siblings, 1 reply; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:41 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Rename the gem and gtt files accordingly.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile  |    6 
 drivers/staging/gma500/gem.c     |  252 ++++++++++++++++++++
 drivers/staging/gma500/gtt.c     |  487 ++++++++++++++++++++++++++++++++++++++
 drivers/staging/gma500/gtt.h     |   62 +++++
 drivers/staging/gma500/psb_drv.h |    2 
 drivers/staging/gma500/psb_gem.c |  252 --------------------
 drivers/staging/gma500/psb_gtt.c |  487 --------------------------------------
 drivers/staging/gma500/psb_gtt.h |   62 -----
 8 files changed, 805 insertions(+), 805 deletions(-)
 create mode 100644 drivers/staging/gma500/gem.c
 create mode 100644 drivers/staging/gma500/gtt.c
 create mode 100644 drivers/staging/gma500/gtt.h
 delete mode 100644 drivers/staging/gma500/psb_gem.c
 delete mode 100644 drivers/staging/gma500/psb_gtt.c
 delete mode 100644 drivers/staging/gma500/psb_gtt.h

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index d2c0887..0603949 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -6,11 +6,11 @@ ccflags-y += -Iinclude/drm
 psb_gfx-y += gem_glue.o \
 	  accel_2d.o \
 	  backlight.o \
-	  power.o \
 	  framebuffer.o \
+	  gem.o \
+	  gtt.o \
+	  power.o \
 	  psb_drv.o \
-	  psb_gem.o \
-	  psb_gtt.o \
 	  psb_intel_bios.o \
 	  psb_intel_opregion.o \
 	  psb_intel_display.o \
diff --git a/drivers/staging/gma500/gem.c b/drivers/staging/gma500/gem.c
new file mode 100644
index 0000000..a63ad9e
--- /dev/null
+++ b/drivers/staging/gma500/gem.c
@@ -0,0 +1,252 @@
+/*
+ *  psb GEM interface
+ *
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * 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: Alan Cox
+ *
+ * TODO:
+ *	-	we need to work out if the MMU is relevant (eg for
+ *		accelerated operations on a GEM object)
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+
+int psb_gem_init_object(struct drm_gem_object *obj)
+{
+	return -EINVAL;
+}
+
+void psb_gem_free_object(struct drm_gem_object *obj)
+{
+	struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
+	drm_gem_object_release_wrap(obj);
+	/* This must occur last as it frees up the memory of the GEM object */
+	psb_gtt_free_range(obj->dev, gtt);
+}
+
+int psb_gem_get_aperture(struct drm_device *dev, void *data,
+				struct drm_file *file)
+{
+	return -EINVAL;
+}
+
+/**
+ *	psb_gem_dumb_map_gtt	-	buffer mapping for dumb interface
+ *	@file: our drm client file
+ *	@dev: drm device
+ *	@handle: GEM handle to the object (from dumb_create)
+ *
+ *	Do the necessary setup to allow the mapping of the frame buffer
+ *	into user memory. We don't have to do much here at the moment.
+ */
+int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
+			 uint32_t handle, uint64_t *offset)
+{
+	int ret = 0;
+	struct drm_gem_object *obj;
+
+	if (!(dev->driver->driver_features & DRIVER_GEM))
+		return -ENODEV;
+
+	mutex_lock(&dev->struct_mutex);
+
+	/* GEM does all our handle to object mapping */
+	obj = drm_gem_object_lookup(dev, file, handle);
+	if (obj == NULL) {
+		ret = -ENOENT;
+		goto unlock;
+	}
+	/* What validation is needed here ? */
+
+	/* Make it mmapable */
+	if (!obj->map_list.map) {
+		ret = gem_create_mmap_offset(obj);
+		if (ret)
+			goto out;
+	}
+	/* GEM should really work out the hash offsets for us */
+	*offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
+out:
+	drm_gem_object_unreference(obj);
+unlock:
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+/**
+ *	psb_gem_create		-	create a mappable object
+ *	@file: the DRM file of the client
+ *	@dev: our device
+ *	@size: the size requested
+ *	@handlep: returned handle (opaque number)
+ *
+ *	Create a GEM object, fill in the boilerplate and attach a handle to
+ *	it so that userspace can speak about it. This does the core work
+ *	for the various methods that do/will create GEM objects for things
+ */
+static int psb_gem_create(struct drm_file *file,
+	struct drm_device *dev, uint64_t size, uint32_t *handlep)
+{
+	struct gtt_range *r;
+	int ret;
+	u32 handle;
+
+	size = roundup(size, PAGE_SIZE);
+
+	/* Allocate our object - for now a direct gtt range which is not
+	   stolen memory backed */
+	r = psb_gtt_alloc_range(dev, size, "gem", 0);
+	if (r == NULL) {
+		dev_err(dev->dev, "no memory for %lld byte GEM object\n", size);
+		return -ENOSPC;
+	}
+	/* Initialize the extra goodies GEM needs to do all the hard work */
+	if (drm_gem_object_init(dev, &r->gem, size) != 0) {
+		psb_gtt_free_range(dev, r);
+		/* GEM doesn't give an error code and we don't have an
+		   EGEMSUCKS so make something up for now - FIXME */
+		dev_err(dev->dev, "GEM init failed for %lld\n", size);
+		return -ENOMEM;
+	}
+	/* Give the object a handle so we can carry it more easily */
+	ret = drm_gem_handle_create(file, &r->gem, &handle);
+	if (ret) {
+		dev_err(dev->dev, "GEM handle failed for %p, %lld\n",
+							&r->gem, size);
+		drm_gem_object_release(&r->gem);
+		psb_gtt_free_range(dev, r);
+		return ret;
+	}
+	/* We have the initial and handle reference but need only one now */
+	drm_gem_object_unreference(&r->gem);
+	*handlep = handle;
+	return 0;
+}
+
+/**
+ *	psb_gem_dumb_create	-	create a dumb buffer
+ *	@drm_file: our client file
+ *	@dev: our device
+ *	@args: the requested arguments copied from userspace
+ *
+ *	Allocate a buffer suitable for use for a frame buffer of the
+ *	form described by user space. Give userspace a handle by which
+ *	to reference it.
+ */
+int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
+			struct drm_mode_create_dumb *args)
+{
+	args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
+	args->size = args->pitch * args->height;
+	return psb_gem_create(file, dev, args->size, &args->handle);
+}
+
+/**
+ *	psb_gem_dumb_destroy	-	destroy a dumb buffer
+ *	@file: client file
+ *	@dev: our DRM device
+ *	@handle: the object handle
+ *
+ *	Destroy a handle that was created via psb_gem_dumb_create, at least
+ *	we hope it was created that way. i915 seems to assume the caller
+ *	does the checking but that might be worth review ! FIXME
+ */
+int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
+			uint32_t handle)
+{
+	/* No special work needed, drop the reference and see what falls out */
+	return drm_gem_handle_delete(file, handle);
+}
+
+/**
+ *	psb_gem_fault		-	pagefault handler for GEM objects
+ *	@vma: the VMA of the GEM object
+ *	@vmf: fault detail
+ *
+ *	Invoked when a fault occurs on an mmap of a GEM managed area. GEM
+ *	does most of the work for us including the actual map/unmap calls
+ *	but we need to do the actual page work.
+ *
+ *	This code eventually needs to handle faulting objects in and out
+ *	of the GTT and repacking it when we run out of space. We can put
+ *	that off for now and for our simple uses
+ *
+ *	The VMA was set up by GEM. In doing so it also ensured that the
+ *	vma->vm_private_data points to the GEM object that is backing this
+ *	mapping.
+ *
+ *	FIXME
+ */
+int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct drm_gem_object *obj;
+	struct gtt_range *r;
+	int ret;
+	unsigned long pfn;
+	pgoff_t page_offset;
+	struct drm_device *dev;
+	struct drm_psb_private *dev_priv;
+
+	obj = vma->vm_private_data;	/* GEM object */
+	dev = obj->dev;
+	dev_priv = dev->dev_private;
+
+	r = container_of(obj, struct gtt_range, gem);	/* Get the gtt range */
+
+	/* Make sure we don't parallel update on a fault, nor move or remove
+	   something from beneath our feet */
+	mutex_lock(&dev->struct_mutex);
+
+	/* For now the mmap pins the object and it stays pinned. As things
+	   stand that will do us no harm */
+	if (r->mmapping == 0) {
+		ret = psb_gtt_pin(r);
+		if (ret < 0) {
+			dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
+			goto fail;
+		}
+		r->mmapping = 1;
+	}
+
+	/* Page relative to the VMA start - we must calculate this ourselves
+	   because vmf->pgoff is the fake GEM offset */
+	page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
+				>> PAGE_SHIFT;
+
+	/* CPU view of the page, don't go via the GART for CPU writes */
+	if (r->stolen)
+		pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT;
+	else
+		pfn = page_to_pfn(r->pages[page_offset]);
+	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+
+fail:
+	mutex_unlock(&dev->struct_mutex);
+	switch (ret) {
+	case 0:
+	case -ERESTARTSYS:
+	case -EINTR:
+		return VM_FAULT_NOPAGE;
+	case -ENOMEM:
+		return VM_FAULT_OOM;
+	default:
+		return VM_FAULT_SIGBUS;
+	}
+}
diff --git a/drivers/staging/gma500/gtt.c b/drivers/staging/gma500/gtt.c
new file mode 100644
index 0000000..6cfa59b
--- /dev/null
+++ b/drivers/staging/gma500/gtt.c
@@ -0,0 +1,487 @@
+/*
+ * 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.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ *	    Alan Cox <alan@linux.intel.com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+
+
+/*
+ *	GTT resource allocator - manage page mappings in GTT space
+ */
+
+/**
+ *	psb_gtt_mask_pte	-	generate GTT pte entry
+ *	@pfn: page number to encode
+ *	@type: type of memory in the GTT
+ *
+ *	Set the GTT entry for the appropriate memory type.
+ */
+static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
+{
+	uint32_t mask = PSB_PTE_VALID;
+
+	if (type & PSB_MMU_CACHED_MEMORY)
+		mask |= PSB_PTE_CACHED;
+	if (type & PSB_MMU_RO_MEMORY)
+		mask |= PSB_PTE_RO;
+	if (type & PSB_MMU_WO_MEMORY)
+		mask |= PSB_PTE_WO;
+
+	return (pfn << PAGE_SHIFT) | mask;
+}
+
+/**
+ *	psb_gtt_entry		-	find the GTT entries for a gtt_range
+ *	@dev: our DRM device
+ *	@r: our GTT range
+ *
+ *	Given a gtt_range object return the GTT offset of the page table
+ *	entries for this gtt_range
+ */
+u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long offset;
+
+	offset = r->resource.start - dev_priv->gtt_mem->start;
+
+	return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
+}
+
+/**
+ *	psb_gtt_insert	-	put an object into the GTT
+ *	@dev: our DRM device
+ *	@r: our GTT range
+ *
+ *	Take our preallocated GTT range and insert the GEM object into
+ *	the GTT.
+ *
+ *	FIXME: gtt lock ?
+ */
+static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
+{
+	u32 *gtt_slot, pte;
+	struct page **pages;
+	int i;
+
+	if (r->pages == NULL) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	WARN_ON(r->stolen);	/* refcount these maybe ? */
+
+	gtt_slot = psb_gtt_entry(dev, r);
+	pages = r->pages;
+
+	/* Make sure changes are visible to the GPU */
+	set_pages_array_uc(pages, r->npage);
+
+	/* Write our page entries into the GTT itself */
+	for (i = 0; i < r->npage; i++) {
+		pte = psb_gtt_mask_pte(page_to_pfn(*pages++), 0/*type*/);
+		iowrite32(pte, gtt_slot++);
+	}
+	/* Make sure all the entries are set before we return */
+	ioread32(gtt_slot - 1);
+	return 0;
+}
+
+/**
+ *	psb_gtt_remove	-	remove an object from the GTT
+ *	@dev: our DRM device
+ *	@r: our GTT range
+ *
+ *	Remove a preallocated GTT range from the GTT. Overwrite all the
+ *	page table entries with the dummy page
+ */
+
+static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 *gtt_slot, pte;
+	int i;
+
+	WARN_ON(r->stolen);
+
+	gtt_slot = psb_gtt_entry(dev, r);
+	pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
+
+	for (i = 0; i < r->npage; i++)
+		iowrite32(pte, gtt_slot++);
+	ioread32(gtt_slot - 1);
+	set_pages_array_wb(r->pages, r->npage);
+}
+
+/**
+ *	psb_gtt_attach_pages	-	attach and pin GEM pages
+ *	@gt: the gtt range
+ *
+ *	Pin and build an in kernel list of the pages that back our GEM object.
+ *	While we hold this the pages cannot be swapped out
+ */
+static int psb_gtt_attach_pages(struct gtt_range *gt)
+{
+	struct inode *inode;
+	struct address_space *mapping;
+	int i;
+	struct page *p;
+	int pages = gt->gem.size / PAGE_SIZE;
+
+	WARN_ON(gt->pages);
+
+	/* This is the shared memory object that backs the GEM resource */
+	inode = gt->gem.filp->f_path.dentry->d_inode;
+	mapping = inode->i_mapping;
+
+	gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
+	if (gt->pages == NULL)
+		return -ENOMEM;
+	gt->npage = pages;
+
+	for (i = 0; i < pages; i++) {
+		/* FIXME: review flags later */
+		p = read_cache_page_gfp(mapping, i,
+					__GFP_COLD | GFP_KERNEL);
+		if (IS_ERR(p))
+			goto err;
+		gt->pages[i] = p;
+	}
+	return 0;
+
+err:
+	while (i--)
+		page_cache_release(gt->pages[i]);
+	kfree(gt->pages);
+	gt->pages = NULL;
+	return PTR_ERR(p);
+}
+
+/**
+ *	psb_gtt_detach_pages	-	attach and pin GEM pages
+ *	@gt: the gtt range
+ *
+ *	Undo the effect of psb_gtt_attach_pages. At this point the pages
+ *	must have been removed from the GTT as they could now be paged out
+ *	and move bus address.
+ */
+static void psb_gtt_detach_pages(struct gtt_range *gt)
+{
+	int i;
+	for (i = 0; i < gt->npage; i++) {
+		/* FIXME: do we need to force dirty */
+		set_page_dirty(gt->pages[i]);
+		page_cache_release(gt->pages[i]);
+	}
+	kfree(gt->pages);
+	gt->pages = NULL;
+}
+
+/**
+ *	psb_gtt_pin		-	pin pages into the GTT
+ *	@gt: range to pin
+ *
+ *	Pin a set of pages into the GTT. The pins are refcounted so that
+ *	multiple pins need multiple unpins to undo.
+ *
+ *	Non GEM backed objects treat this as a no-op as they are always GTT
+ *	backed objects.
+ */
+int psb_gtt_pin(struct gtt_range *gt)
+{
+	int ret = 0;
+	struct drm_device *dev = gt->gem.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&dev_priv->gtt_mutex);
+
+	if (gt->in_gart == 0 && gt->stolen == 0) {
+		ret = psb_gtt_attach_pages(gt);
+		if (ret < 0)
+			goto out;
+		ret = psb_gtt_insert(dev, gt);
+		if (ret < 0) {
+			psb_gtt_detach_pages(gt);
+			goto out;
+		}
+	}
+	gt->in_gart++;
+out:
+	mutex_unlock(&dev_priv->gtt_mutex);
+	return ret;
+}
+
+/**
+ *	psb_gtt_unpin		-	Drop a GTT pin requirement
+ *	@gt: range to pin
+ *
+ *	Undoes the effect of psb_gtt_pin. On the last drop the GEM object
+ *	will be removed from the GTT which will also drop the page references
+ *	and allow the VM to clean up or page stuff.
+ *
+ *	Non GEM backed objects treat this as a no-op as they are always GTT
+ *	backed objects.
+ */
+void psb_gtt_unpin(struct gtt_range *gt)
+{
+	struct drm_device *dev = gt->gem.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	mutex_lock(&dev_priv->gtt_mutex);
+
+	WARN_ON(!gt->in_gart);
+
+	gt->in_gart--;
+	if (gt->in_gart == 0 && gt->stolen == 0) {
+		psb_gtt_remove(dev, gt);
+		psb_gtt_detach_pages(gt);
+	}
+	mutex_unlock(&dev_priv->gtt_mutex);
+}
+
+/*
+ *	GTT resource allocator - allocate and manage GTT address space
+ */
+
+/**
+ *	psb_gtt_alloc_range	-	allocate GTT address space
+ *	@dev: Our DRM device
+ *	@len: length (bytes) of address space required
+ *	@name: resource name
+ *	@backed: resource should be backed by stolen pages
+ *
+ *	Ask the kernel core to find us a suitable range of addresses
+ *	to use for a GTT mapping.
+ *
+ *	Returns a gtt_range structure describing the object, or NULL on
+ *	error. On successful return the resource is both allocated and marked
+ *	as in use.
+ */
+struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
+						const char *name, int backed)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct gtt_range *gt;
+	struct resource *r = dev_priv->gtt_mem;
+	int ret;
+	unsigned long start, end;
+
+	if (backed) {
+		/* The start of the GTT is the stolen pages */
+		start = r->start;
+		end = r->start + dev_priv->pg->stolen_size - 1;
+	} else {
+		/* The rest we will use for GEM backed objects */
+		start = r->start + dev_priv->pg->stolen_size;
+		end = r->end;
+	}
+
+	gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
+	if (gt == NULL)
+		return NULL;
+	gt->resource.name = name;
+	gt->stolen = backed;
+	gt->in_gart = backed;
+	/* Ensure this is set for non GEM objects */
+	gt->gem.dev = dev;
+	ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
+				len, start, end, PAGE_SIZE, NULL, NULL);
+	if (ret == 0) {
+		gt->offset = gt->resource.start - r->start;
+		return gt;
+	}
+	kfree(gt);
+	return NULL;
+}
+
+/**
+ *	psb_gtt_free_range	-	release GTT address space
+ *	@dev: our DRM device
+ *	@gt: a mapping created with psb_gtt_alloc_range
+ *
+ *	Release a resource that was allocated with psb_gtt_alloc_range. If the
+ *	object has been pinned by mmap users we clean this up here currently.
+ */
+void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
+{
+	/* Undo the mmap pin if we are destroying the object */
+	if (gt->mmapping) {
+		psb_gtt_unpin(gt);
+		gt->mmapping = 0;
+	}
+	WARN_ON(gt->in_gart && !gt->stolen);
+	release_resource(&gt->resource);
+	kfree(gt);
+}
+
+struct psb_gtt *psb_gtt_alloc(struct drm_device *dev)
+{
+	struct psb_gtt *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+
+	if (!tmp)
+		return NULL;
+
+	init_rwsem(&tmp->sem);
+	tmp->dev = dev;
+
+	return tmp;
+}
+
+void psb_gtt_takedown(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->gtt_map) {
+		iounmap(dev_priv->gtt_map);
+		dev_priv->gtt_map = NULL;
+	}
+	if (dev_priv->gtt_initialized) {
+		pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+				      dev_priv->gmch_ctrl);
+		PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
+		(void) PSB_RVDC32(PSB_PGETBL_CTL);
+	}
+	if (dev_priv->vram_addr)
+		iounmap(dev_priv->gtt_map);
+	kfree(dev_priv->pg);
+	dev_priv->pg = NULL;
+}
+
+int psb_gtt_init(struct drm_device *dev, int resume)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned gtt_pages;
+	unsigned long stolen_size, vram_stolen_size;
+	unsigned i, num_pages;
+	unsigned pfn_base;
+	uint32_t vram_pages;
+	uint32_t dvmt_mode = 0;
+	struct psb_gtt *pg;
+
+	int ret = 0;
+	uint32_t pte;
+
+	mutex_init(&dev_priv->gtt_mutex);
+
+	dev_priv->pg = pg = psb_gtt_alloc(dev);
+	if (pg == NULL)
+		return -ENOMEM;
+
+	/* Enable the GTT */
+	pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
+	pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+			      dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+	dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
+	PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+	(void) PSB_RVDC32(PSB_PGETBL_CTL);
+
+	/* The root resource we allocate address space from */
+	dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
+	dev_priv->gtt_initialized = 1;
+
+	pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
+
+	pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+	/*
+	 *	FIXME: video mmu has hw bug to access 0x0D0000000,
+	 *	then make gatt start at 0x0e000,0000
+	 */
+	pg->mmu_gatt_start = 0xE0000000;
+
+	pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
+	gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
+								>> PAGE_SHIFT;
+	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
+								>> PAGE_SHIFT;
+
+	pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
+	vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base
+								- PAGE_SIZE;
+
+	stolen_size = vram_stolen_size;
+
+	printk(KERN_INFO "Stolen memory information\n");
+	printk(KERN_INFO "       base in RAM: 0x%x\n", dev_priv->stolen_base);
+	printk(KERN_INFO "       size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
+		vram_stolen_size/1024);
+	dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7;
+	printk(KERN_INFO "      the correct size should be: %dM(dvmt mode=%d)\n",
+		(dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
+
+	if (resume && (gtt_pages != pg->gtt_pages) &&
+	    (stolen_size != pg->stolen_size)) {
+		dev_err(dev->dev, "GTT resume error.\n");
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	pg->gtt_pages = gtt_pages;
+	pg->stolen_size = stolen_size;
+	dev_priv->vram_stolen_size = vram_stolen_size;
+
+	/*
+	 *	Map the GTT and the stolen memory area
+	 */
+	dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
+						gtt_pages << PAGE_SHIFT);
+	if (!dev_priv->gtt_map) {
+		dev_err(dev->dev, "Failure to map gtt.\n");
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
+	if (!dev_priv->vram_addr) {
+		dev_err(dev->dev, "Failure to map stolen base.\n");
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	/*
+	 * Insert vram stolen pages into the GTT
+	 */
+
+	pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
+	vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
+	printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
+		num_pages, pfn_base, 0);
+	for (i = 0; i < num_pages; ++i) {
+		pte = psb_gtt_mask_pte(pfn_base + i, 0);
+		iowrite32(pte, dev_priv->gtt_map + i);
+	}
+
+	/*
+	 * Init rest of GTT to the scratch page to avoid accidents or scribbles
+	 */
+
+	pfn_base = page_to_pfn(dev_priv->scratch_page);
+	pte = psb_gtt_mask_pte(pfn_base, 0);
+	for (; i < gtt_pages; ++i)
+		iowrite32(pte, dev_priv->gtt_map + i);
+
+	(void) ioread32(dev_priv->gtt_map + i - 1);
+	return 0;
+
+out_err:
+	psb_gtt_takedown(dev);
+	return ret;
+}
diff --git a/drivers/staging/gma500/gtt.h b/drivers/staging/gma500/gtt.h
new file mode 100644
index 0000000..4d6dc5f
--- /dev/null
+++ b/drivers/staging/gma500/gtt.h
@@ -0,0 +1,62 @@
+/**************************************************************************
+ * Copyright (c) 2007-2008, 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_GTT_H_
+#define _PSB_GTT_H_
+
+#include <drm/drmP.h>
+
+/* This wants cleaning up with respect to the psb_dev and un-needed stuff */
+struct psb_gtt {
+	struct drm_device *dev;
+	uint32_t gatt_start;
+	uint32_t mmu_gatt_start;
+	uint32_t gtt_start;
+	uint32_t gtt_phys_start;
+	unsigned gtt_pages;
+	unsigned gatt_pages;
+	unsigned long stolen_size;
+	unsigned long vram_stolen_size;
+	struct rw_semaphore sem;
+};
+
+/*Exported functions*/
+extern int psb_gtt_init(struct drm_device *dev, int resume);
+extern void psb_gtt_takedown(struct drm_device *dev);
+
+/* Each gtt_range describes an allocation in the GTT area */
+struct gtt_range {
+	struct resource resource;	/* Resource for our allocation */
+	u32 offset;			/* GTT offset of our object */
+	struct drm_gem_object gem;	/* GEM high level stuff */
+	int in_gart;			/* Currently in the GART (ref ct) */
+	bool stolen;			/* Backed from stolen RAM */
+	bool mmapping;			/* Is mmappable */
+	struct page **pages;		/* Backing pages if present */
+	int npage;			/* Number of backing pages */
+};
+
+extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
+						const char *name, int backed);
+extern void psb_gtt_kref_put(struct gtt_range *gt);
+extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
+extern int psb_gtt_pin(struct gtt_range *gt);
+extern void psb_gtt_unpin(struct gtt_range *gt);
+
+#endif
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 9c6aba5..307ff9c 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -29,7 +29,7 @@
 #include "psb_drm.h"
 #include "psb_reg.h"
 #include "psb_intel_drv.h"
-#include "psb_gtt.h"
+#include "gtt.h"
 #include "psb_powermgmt.h"
 #include "mrst.h"
 
diff --git a/drivers/staging/gma500/psb_gem.c b/drivers/staging/gma500/psb_gem.c
deleted file mode 100644
index a63ad9e..0000000
--- a/drivers/staging/gma500/psb_gem.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- *  psb GEM interface
- *
- * Copyright (c) 2011, Intel Corporation.
- *
- * 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: Alan Cox
- *
- * TODO:
- *	-	we need to work out if the MMU is relevant (eg for
- *		accelerated operations on a GEM object)
- */
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-
-int psb_gem_init_object(struct drm_gem_object *obj)
-{
-	return -EINVAL;
-}
-
-void psb_gem_free_object(struct drm_gem_object *obj)
-{
-	struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
-	drm_gem_object_release_wrap(obj);
-	/* This must occur last as it frees up the memory of the GEM object */
-	psb_gtt_free_range(obj->dev, gtt);
-}
-
-int psb_gem_get_aperture(struct drm_device *dev, void *data,
-				struct drm_file *file)
-{
-	return -EINVAL;
-}
-
-/**
- *	psb_gem_dumb_map_gtt	-	buffer mapping for dumb interface
- *	@file: our drm client file
- *	@dev: drm device
- *	@handle: GEM handle to the object (from dumb_create)
- *
- *	Do the necessary setup to allow the mapping of the frame buffer
- *	into user memory. We don't have to do much here at the moment.
- */
-int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
-			 uint32_t handle, uint64_t *offset)
-{
-	int ret = 0;
-	struct drm_gem_object *obj;
-
-	if (!(dev->driver->driver_features & DRIVER_GEM))
-		return -ENODEV;
-
-	mutex_lock(&dev->struct_mutex);
-
-	/* GEM does all our handle to object mapping */
-	obj = drm_gem_object_lookup(dev, file, handle);
-	if (obj == NULL) {
-		ret = -ENOENT;
-		goto unlock;
-	}
-	/* What validation is needed here ? */
-
-	/* Make it mmapable */
-	if (!obj->map_list.map) {
-		ret = gem_create_mmap_offset(obj);
-		if (ret)
-			goto out;
-	}
-	/* GEM should really work out the hash offsets for us */
-	*offset = (u64)obj->map_list.hash.key << PAGE_SHIFT;
-out:
-	drm_gem_object_unreference(obj);
-unlock:
-	mutex_unlock(&dev->struct_mutex);
-	return ret;
-}
-
-/**
- *	psb_gem_create		-	create a mappable object
- *	@file: the DRM file of the client
- *	@dev: our device
- *	@size: the size requested
- *	@handlep: returned handle (opaque number)
- *
- *	Create a GEM object, fill in the boilerplate and attach a handle to
- *	it so that userspace can speak about it. This does the core work
- *	for the various methods that do/will create GEM objects for things
- */
-static int psb_gem_create(struct drm_file *file,
-	struct drm_device *dev, uint64_t size, uint32_t *handlep)
-{
-	struct gtt_range *r;
-	int ret;
-	u32 handle;
-
-	size = roundup(size, PAGE_SIZE);
-
-	/* Allocate our object - for now a direct gtt range which is not
-	   stolen memory backed */
-	r = psb_gtt_alloc_range(dev, size, "gem", 0);
-	if (r == NULL) {
-		dev_err(dev->dev, "no memory for %lld byte GEM object\n", size);
-		return -ENOSPC;
-	}
-	/* Initialize the extra goodies GEM needs to do all the hard work */
-	if (drm_gem_object_init(dev, &r->gem, size) != 0) {
-		psb_gtt_free_range(dev, r);
-		/* GEM doesn't give an error code and we don't have an
-		   EGEMSUCKS so make something up for now - FIXME */
-		dev_err(dev->dev, "GEM init failed for %lld\n", size);
-		return -ENOMEM;
-	}
-	/* Give the object a handle so we can carry it more easily */
-	ret = drm_gem_handle_create(file, &r->gem, &handle);
-	if (ret) {
-		dev_err(dev->dev, "GEM handle failed for %p, %lld\n",
-							&r->gem, size);
-		drm_gem_object_release(&r->gem);
-		psb_gtt_free_range(dev, r);
-		return ret;
-	}
-	/* We have the initial and handle reference but need only one now */
-	drm_gem_object_unreference(&r->gem);
-	*handlep = handle;
-	return 0;
-}
-
-/**
- *	psb_gem_dumb_create	-	create a dumb buffer
- *	@drm_file: our client file
- *	@dev: our device
- *	@args: the requested arguments copied from userspace
- *
- *	Allocate a buffer suitable for use for a frame buffer of the
- *	form described by user space. Give userspace a handle by which
- *	to reference it.
- */
-int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
-			struct drm_mode_create_dumb *args)
-{
-	args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
-	args->size = args->pitch * args->height;
-	return psb_gem_create(file, dev, args->size, &args->handle);
-}
-
-/**
- *	psb_gem_dumb_destroy	-	destroy a dumb buffer
- *	@file: client file
- *	@dev: our DRM device
- *	@handle: the object handle
- *
- *	Destroy a handle that was created via psb_gem_dumb_create, at least
- *	we hope it was created that way. i915 seems to assume the caller
- *	does the checking but that might be worth review ! FIXME
- */
-int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
-			uint32_t handle)
-{
-	/* No special work needed, drop the reference and see what falls out */
-	return drm_gem_handle_delete(file, handle);
-}
-
-/**
- *	psb_gem_fault		-	pagefault handler for GEM objects
- *	@vma: the VMA of the GEM object
- *	@vmf: fault detail
- *
- *	Invoked when a fault occurs on an mmap of a GEM managed area. GEM
- *	does most of the work for us including the actual map/unmap calls
- *	but we need to do the actual page work.
- *
- *	This code eventually needs to handle faulting objects in and out
- *	of the GTT and repacking it when we run out of space. We can put
- *	that off for now and for our simple uses
- *
- *	The VMA was set up by GEM. In doing so it also ensured that the
- *	vma->vm_private_data points to the GEM object that is backing this
- *	mapping.
- *
- *	FIXME
- */
-int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-	struct drm_gem_object *obj;
-	struct gtt_range *r;
-	int ret;
-	unsigned long pfn;
-	pgoff_t page_offset;
-	struct drm_device *dev;
-	struct drm_psb_private *dev_priv;
-
-	obj = vma->vm_private_data;	/* GEM object */
-	dev = obj->dev;
-	dev_priv = dev->dev_private;
-
-	r = container_of(obj, struct gtt_range, gem);	/* Get the gtt range */
-
-	/* Make sure we don't parallel update on a fault, nor move or remove
-	   something from beneath our feet */
-	mutex_lock(&dev->struct_mutex);
-
-	/* For now the mmap pins the object and it stays pinned. As things
-	   stand that will do us no harm */
-	if (r->mmapping == 0) {
-		ret = psb_gtt_pin(r);
-		if (ret < 0) {
-			dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
-			goto fail;
-		}
-		r->mmapping = 1;
-	}
-
-	/* Page relative to the VMA start - we must calculate this ourselves
-	   because vmf->pgoff is the fake GEM offset */
-	page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
-				>> PAGE_SHIFT;
-
-	/* CPU view of the page, don't go via the GART for CPU writes */
-	if (r->stolen)
-		pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT;
-	else
-		pfn = page_to_pfn(r->pages[page_offset]);
-	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
-
-fail:
-	mutex_unlock(&dev->struct_mutex);
-	switch (ret) {
-	case 0:
-	case -ERESTARTSYS:
-	case -EINTR:
-		return VM_FAULT_NOPAGE;
-	case -ENOMEM:
-		return VM_FAULT_OOM;
-	default:
-		return VM_FAULT_SIGBUS;
-	}
-}
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
deleted file mode 100644
index 6cfa59b..0000000
--- a/drivers/staging/gma500/psb_gtt.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * 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.
- *
- * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
- *	    Alan Cox <alan@linux.intel.com>
- */
-
-#include <drm/drmP.h>
-#include "psb_drv.h"
-
-
-/*
- *	GTT resource allocator - manage page mappings in GTT space
- */
-
-/**
- *	psb_gtt_mask_pte	-	generate GTT pte entry
- *	@pfn: page number to encode
- *	@type: type of memory in the GTT
- *
- *	Set the GTT entry for the appropriate memory type.
- */
-static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
-{
-	uint32_t mask = PSB_PTE_VALID;
-
-	if (type & PSB_MMU_CACHED_MEMORY)
-		mask |= PSB_PTE_CACHED;
-	if (type & PSB_MMU_RO_MEMORY)
-		mask |= PSB_PTE_RO;
-	if (type & PSB_MMU_WO_MEMORY)
-		mask |= PSB_PTE_WO;
-
-	return (pfn << PAGE_SHIFT) | mask;
-}
-
-/**
- *	psb_gtt_entry		-	find the GTT entries for a gtt_range
- *	@dev: our DRM device
- *	@r: our GTT range
- *
- *	Given a gtt_range object return the GTT offset of the page table
- *	entries for this gtt_range
- */
-u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	unsigned long offset;
-
-	offset = r->resource.start - dev_priv->gtt_mem->start;
-
-	return dev_priv->gtt_map + (offset >> PAGE_SHIFT);
-}
-
-/**
- *	psb_gtt_insert	-	put an object into the GTT
- *	@dev: our DRM device
- *	@r: our GTT range
- *
- *	Take our preallocated GTT range and insert the GEM object into
- *	the GTT.
- *
- *	FIXME: gtt lock ?
- */
-static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
-{
-	u32 *gtt_slot, pte;
-	struct page **pages;
-	int i;
-
-	if (r->pages == NULL) {
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	WARN_ON(r->stolen);	/* refcount these maybe ? */
-
-	gtt_slot = psb_gtt_entry(dev, r);
-	pages = r->pages;
-
-	/* Make sure changes are visible to the GPU */
-	set_pages_array_uc(pages, r->npage);
-
-	/* Write our page entries into the GTT itself */
-	for (i = 0; i < r->npage; i++) {
-		pte = psb_gtt_mask_pte(page_to_pfn(*pages++), 0/*type*/);
-		iowrite32(pte, gtt_slot++);
-	}
-	/* Make sure all the entries are set before we return */
-	ioread32(gtt_slot - 1);
-	return 0;
-}
-
-/**
- *	psb_gtt_remove	-	remove an object from the GTT
- *	@dev: our DRM device
- *	@r: our GTT range
- *
- *	Remove a preallocated GTT range from the GTT. Overwrite all the
- *	page table entries with the dummy page
- */
-
-static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 *gtt_slot, pte;
-	int i;
-
-	WARN_ON(r->stolen);
-
-	gtt_slot = psb_gtt_entry(dev, r);
-	pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
-
-	for (i = 0; i < r->npage; i++)
-		iowrite32(pte, gtt_slot++);
-	ioread32(gtt_slot - 1);
-	set_pages_array_wb(r->pages, r->npage);
-}
-
-/**
- *	psb_gtt_attach_pages	-	attach and pin GEM pages
- *	@gt: the gtt range
- *
- *	Pin and build an in kernel list of the pages that back our GEM object.
- *	While we hold this the pages cannot be swapped out
- */
-static int psb_gtt_attach_pages(struct gtt_range *gt)
-{
-	struct inode *inode;
-	struct address_space *mapping;
-	int i;
-	struct page *p;
-	int pages = gt->gem.size / PAGE_SIZE;
-
-	WARN_ON(gt->pages);
-
-	/* This is the shared memory object that backs the GEM resource */
-	inode = gt->gem.filp->f_path.dentry->d_inode;
-	mapping = inode->i_mapping;
-
-	gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
-	if (gt->pages == NULL)
-		return -ENOMEM;
-	gt->npage = pages;
-
-	for (i = 0; i < pages; i++) {
-		/* FIXME: review flags later */
-		p = read_cache_page_gfp(mapping, i,
-					__GFP_COLD | GFP_KERNEL);
-		if (IS_ERR(p))
-			goto err;
-		gt->pages[i] = p;
-	}
-	return 0;
-
-err:
-	while (i--)
-		page_cache_release(gt->pages[i]);
-	kfree(gt->pages);
-	gt->pages = NULL;
-	return PTR_ERR(p);
-}
-
-/**
- *	psb_gtt_detach_pages	-	attach and pin GEM pages
- *	@gt: the gtt range
- *
- *	Undo the effect of psb_gtt_attach_pages. At this point the pages
- *	must have been removed from the GTT as they could now be paged out
- *	and move bus address.
- */
-static void psb_gtt_detach_pages(struct gtt_range *gt)
-{
-	int i;
-	for (i = 0; i < gt->npage; i++) {
-		/* FIXME: do we need to force dirty */
-		set_page_dirty(gt->pages[i]);
-		page_cache_release(gt->pages[i]);
-	}
-	kfree(gt->pages);
-	gt->pages = NULL;
-}
-
-/**
- *	psb_gtt_pin		-	pin pages into the GTT
- *	@gt: range to pin
- *
- *	Pin a set of pages into the GTT. The pins are refcounted so that
- *	multiple pins need multiple unpins to undo.
- *
- *	Non GEM backed objects treat this as a no-op as they are always GTT
- *	backed objects.
- */
-int psb_gtt_pin(struct gtt_range *gt)
-{
-	int ret = 0;
-	struct drm_device *dev = gt->gem.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	mutex_lock(&dev_priv->gtt_mutex);
-
-	if (gt->in_gart == 0 && gt->stolen == 0) {
-		ret = psb_gtt_attach_pages(gt);
-		if (ret < 0)
-			goto out;
-		ret = psb_gtt_insert(dev, gt);
-		if (ret < 0) {
-			psb_gtt_detach_pages(gt);
-			goto out;
-		}
-	}
-	gt->in_gart++;
-out:
-	mutex_unlock(&dev_priv->gtt_mutex);
-	return ret;
-}
-
-/**
- *	psb_gtt_unpin		-	Drop a GTT pin requirement
- *	@gt: range to pin
- *
- *	Undoes the effect of psb_gtt_pin. On the last drop the GEM object
- *	will be removed from the GTT which will also drop the page references
- *	and allow the VM to clean up or page stuff.
- *
- *	Non GEM backed objects treat this as a no-op as they are always GTT
- *	backed objects.
- */
-void psb_gtt_unpin(struct gtt_range *gt)
-{
-	struct drm_device *dev = gt->gem.dev;
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	mutex_lock(&dev_priv->gtt_mutex);
-
-	WARN_ON(!gt->in_gart);
-
-	gt->in_gart--;
-	if (gt->in_gart == 0 && gt->stolen == 0) {
-		psb_gtt_remove(dev, gt);
-		psb_gtt_detach_pages(gt);
-	}
-	mutex_unlock(&dev_priv->gtt_mutex);
-}
-
-/*
- *	GTT resource allocator - allocate and manage GTT address space
- */
-
-/**
- *	psb_gtt_alloc_range	-	allocate GTT address space
- *	@dev: Our DRM device
- *	@len: length (bytes) of address space required
- *	@name: resource name
- *	@backed: resource should be backed by stolen pages
- *
- *	Ask the kernel core to find us a suitable range of addresses
- *	to use for a GTT mapping.
- *
- *	Returns a gtt_range structure describing the object, or NULL on
- *	error. On successful return the resource is both allocated and marked
- *	as in use.
- */
-struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
-						const char *name, int backed)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct gtt_range *gt;
-	struct resource *r = dev_priv->gtt_mem;
-	int ret;
-	unsigned long start, end;
-
-	if (backed) {
-		/* The start of the GTT is the stolen pages */
-		start = r->start;
-		end = r->start + dev_priv->pg->stolen_size - 1;
-	} else {
-		/* The rest we will use for GEM backed objects */
-		start = r->start + dev_priv->pg->stolen_size;
-		end = r->end;
-	}
-
-	gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
-	if (gt == NULL)
-		return NULL;
-	gt->resource.name = name;
-	gt->stolen = backed;
-	gt->in_gart = backed;
-	/* Ensure this is set for non GEM objects */
-	gt->gem.dev = dev;
-	ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
-				len, start, end, PAGE_SIZE, NULL, NULL);
-	if (ret == 0) {
-		gt->offset = gt->resource.start - r->start;
-		return gt;
-	}
-	kfree(gt);
-	return NULL;
-}
-
-/**
- *	psb_gtt_free_range	-	release GTT address space
- *	@dev: our DRM device
- *	@gt: a mapping created with psb_gtt_alloc_range
- *
- *	Release a resource that was allocated with psb_gtt_alloc_range. If the
- *	object has been pinned by mmap users we clean this up here currently.
- */
-void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
-{
-	/* Undo the mmap pin if we are destroying the object */
-	if (gt->mmapping) {
-		psb_gtt_unpin(gt);
-		gt->mmapping = 0;
-	}
-	WARN_ON(gt->in_gart && !gt->stolen);
-	release_resource(&gt->resource);
-	kfree(gt);
-}
-
-struct psb_gtt *psb_gtt_alloc(struct drm_device *dev)
-{
-	struct psb_gtt *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
-
-	if (!tmp)
-		return NULL;
-
-	init_rwsem(&tmp->sem);
-	tmp->dev = dev;
-
-	return tmp;
-}
-
-void psb_gtt_takedown(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	if (dev_priv->gtt_map) {
-		iounmap(dev_priv->gtt_map);
-		dev_priv->gtt_map = NULL;
-	}
-	if (dev_priv->gtt_initialized) {
-		pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
-				      dev_priv->gmch_ctrl);
-		PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
-		(void) PSB_RVDC32(PSB_PGETBL_CTL);
-	}
-	if (dev_priv->vram_addr)
-		iounmap(dev_priv->gtt_map);
-	kfree(dev_priv->pg);
-	dev_priv->pg = NULL;
-}
-
-int psb_gtt_init(struct drm_device *dev, int resume)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	unsigned gtt_pages;
-	unsigned long stolen_size, vram_stolen_size;
-	unsigned i, num_pages;
-	unsigned pfn_base;
-	uint32_t vram_pages;
-	uint32_t dvmt_mode = 0;
-	struct psb_gtt *pg;
-
-	int ret = 0;
-	uint32_t pte;
-
-	mutex_init(&dev_priv->gtt_mutex);
-
-	dev_priv->pg = pg = psb_gtt_alloc(dev);
-	if (pg == NULL)
-		return -ENOMEM;
-
-	/* Enable the GTT */
-	pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
-	pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
-			      dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
-
-	dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
-	PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
-	(void) PSB_RVDC32(PSB_PGETBL_CTL);
-
-	/* The root resource we allocate address space from */
-	dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
-	dev_priv->gtt_initialized = 1;
-
-	pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
-
-	pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
-	/*
-	 *	FIXME: video mmu has hw bug to access 0x0D0000000,
-	 *	then make gatt start at 0x0e000,0000
-	 */
-	pg->mmu_gatt_start = 0xE0000000;
-
-	pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
-	gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
-								>> PAGE_SHIFT;
-	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
-								>> PAGE_SHIFT;
-
-	pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
-	vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base
-								- PAGE_SIZE;
-
-	stolen_size = vram_stolen_size;
-
-	printk(KERN_INFO "Stolen memory information\n");
-	printk(KERN_INFO "       base in RAM: 0x%x\n", dev_priv->stolen_base);
-	printk(KERN_INFO "       size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
-		vram_stolen_size/1024);
-	dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7;
-	printk(KERN_INFO "      the correct size should be: %dM(dvmt mode=%d)\n",
-		(dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
-
-	if (resume && (gtt_pages != pg->gtt_pages) &&
-	    (stolen_size != pg->stolen_size)) {
-		dev_err(dev->dev, "GTT resume error.\n");
-		ret = -EINVAL;
-		goto out_err;
-	}
-
-	pg->gtt_pages = gtt_pages;
-	pg->stolen_size = stolen_size;
-	dev_priv->vram_stolen_size = vram_stolen_size;
-
-	/*
-	 *	Map the GTT and the stolen memory area
-	 */
-	dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
-						gtt_pages << PAGE_SHIFT);
-	if (!dev_priv->gtt_map) {
-		dev_err(dev->dev, "Failure to map gtt.\n");
-		ret = -ENOMEM;
-		goto out_err;
-	}
-
-	dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
-	if (!dev_priv->vram_addr) {
-		dev_err(dev->dev, "Failure to map stolen base.\n");
-		ret = -ENOMEM;
-		goto out_err;
-	}
-
-	/*
-	 * Insert vram stolen pages into the GTT
-	 */
-
-	pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
-	vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
-	printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
-		num_pages, pfn_base, 0);
-	for (i = 0; i < num_pages; ++i) {
-		pte = psb_gtt_mask_pte(pfn_base + i, 0);
-		iowrite32(pte, dev_priv->gtt_map + i);
-	}
-
-	/*
-	 * Init rest of GTT to the scratch page to avoid accidents or scribbles
-	 */
-
-	pfn_base = page_to_pfn(dev_priv->scratch_page);
-	pte = psb_gtt_mask_pte(pfn_base, 0);
-	for (; i < gtt_pages; ++i)
-		iowrite32(pte, dev_priv->gtt_map + i);
-
-	(void) ioread32(dev_priv->gtt_map + i - 1);
-	return 0;
-
-out_err:
-	psb_gtt_takedown(dev);
-	return ret;
-}
diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h
deleted file mode 100644
index 4d6dc5f..0000000
--- a/drivers/staging/gma500/psb_gtt.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2008, 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_GTT_H_
-#define _PSB_GTT_H_
-
-#include <drm/drmP.h>
-
-/* This wants cleaning up with respect to the psb_dev and un-needed stuff */
-struct psb_gtt {
-	struct drm_device *dev;
-	uint32_t gatt_start;
-	uint32_t mmu_gatt_start;
-	uint32_t gtt_start;
-	uint32_t gtt_phys_start;
-	unsigned gtt_pages;
-	unsigned gatt_pages;
-	unsigned long stolen_size;
-	unsigned long vram_stolen_size;
-	struct rw_semaphore sem;
-};
-
-/*Exported functions*/
-extern int psb_gtt_init(struct drm_device *dev, int resume);
-extern void psb_gtt_takedown(struct drm_device *dev);
-
-/* Each gtt_range describes an allocation in the GTT area */
-struct gtt_range {
-	struct resource resource;	/* Resource for our allocation */
-	u32 offset;			/* GTT offset of our object */
-	struct drm_gem_object gem;	/* GEM high level stuff */
-	int in_gart;			/* Currently in the GART (ref ct) */
-	bool stolen;			/* Backed from stolen RAM */
-	bool mmapping;			/* Is mmappable */
-	struct page **pages;		/* Backing pages if present */
-	int npage;			/* Number of backing pages */
-};
-
-extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
-						const char *name, int backed);
-extern void psb_gtt_kref_put(struct gtt_range *gt);
-extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
-extern int psb_gtt_pin(struct gtt_range *gt);
-extern void psb_gtt_unpin(struct gtt_range *gt);
-
-#endif


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 35/49] gma500: begin the config based split
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (33 preceding siblings ...)
  2011-07-05 14:41 ` [PATCH 34/49] gma500: the GEM and GTT code is device independant Alan Cox
@ 2011-07-05 14:41 ` Alan Cox
  2011-07-05 14:42 ` [PATCH 36/49] gma500: Rename the psb_intel_bios code Alan Cox
                   ` (14 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:41 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We don't want to carry all the extra gunk around on every device so use the
splitting work so far to tidy this up. Poulsbo is still mandatory as it is
used in bits by the other drivers and not neatly modularised.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Kconfig   |   27 ++++++++++++++++++++++++---
 drivers/staging/gma500/Makefile  |   13 ++++++++-----
 drivers/staging/gma500/psb_drv.c |    9 ++++++++-
 drivers/staging/gma500/psb_irq.c |    5 ++++-
 4 files changed, 44 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig
index ce8beda..bfe2166 100644
--- a/drivers/staging/gma500/Kconfig
+++ b/drivers/staging/gma500/Kconfig
@@ -1,5 +1,5 @@
 config DRM_PSB
-	tristate "Intel GMA500 KMS Framebuffer"
+	tristate "Intel GMA5/600 KMS Framebuffer"
 	depends on DRM && PCI && X86
 	select FB_CFB_COPYAREA
         select FB_CFB_FILLRECT
@@ -7,6 +7,27 @@ config DRM_PSB
         select DRM_KMS_HELPER
         select DRM_TTM
 	help
-	  Say yes for an experimental KMS framebuffer driver for the
-	  Intel GMA500 ('Poulsbo') graphics support.
+	  Say yes for an experimental 2D KMS framebuffer driver for the
+	  Intel GMA500 ('Poulsbo') and other Intel IMG based graphics
+	  devices.
 
+config DRM_PSB_MRST
+	bool "Intel GMA600 support (Experimental)"
+	depends on DRM_PSB
+	help
+	  Say yes to include support for GMA600 (Intel Moorestown/Oaktrail)
+	  platforms with LVDS ports. HDMI and MIPI are not currently
+	  supported.
+
+config DRM_PSB_MFLD
+	bool "Intel Medfield support (Experimental)"
+	depends on DRM_PSB
+	help
+	  Say yes to include support for Intel Medfield platforms with MIPI
+	  interfaces.
+	
+config DRM_PSB_CDV
+	bool "Intel Cedarview support (Experimental)"
+	depends on DRM_PSB
+	help
+	  Say yes to include support for Intel Cedarview platforms
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index 0603949..aa60926 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -22,12 +22,15 @@ psb_gfx-y += gem_glue.o \
 	  psb_mmu.o \
 	  psb_irq.o \
 	  psb_device.o \
-	  cdv_device.o \
-	  mid_bios.o \
-	  mrst_device.o \
+	  mid_bios.o
+
+psb_gfx-$(CONFIG_DRM_PSB_CDV) +=  cdv_device.o
+
+psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \
 	  mrst_crtc.o \
-	  mrst_lvds.o \
-	  mdfld_device.o \
+	  mrst_lvds.o
+
+psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \
 	  mdfld_output.o \
 	  mdfld_pyr_cmd.o \
 	  mdfld_tmd_vid.o \
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 4114ffd..69ab61b 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -52,6 +52,7 @@ 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_PSB_MRST)	
 	{ 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
 	{ 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
 	{ 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
@@ -60,6 +61,8 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
 	{ 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
 	{ 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
 	{ 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
+#endif
+#if defined(CONFIG_DRM_PSB_MFLD)
 	{ 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
 	{ 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
 	{ 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
@@ -68,6 +71,8 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
 	{ 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
 	{ 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
 	{ 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
+#endif
+#if defined(CONFIG_DRM_PSB_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},
@@ -76,6 +81,7 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
 	{ 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);
@@ -396,6 +402,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 
 	dev->driver->get_vblank_counter = psb_get_vblank_counter;
 
+#if defined(CONFIG_DRM_PSB_MFLD)
 	/* FIXME: this is not the right place for this stuff ! */
 	if (IS_MFLD(dev)) {
 #ifdef CONFIG_MDFLD_DSI_DPU
@@ -406,7 +413,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 #endif /*CONFIG_MDFLD_DSI_DPU*/
 		/* INIT_WORK(&dev_priv->te_work, mdfld_te_handler_work);*/
 	}
-
+#endif
 	if (drm_psb_no_fb == 0) {
 		psb_modeset_init(dev);
 		psb_fbdev_init(dev);
diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c
index 3768cf1..8fc7070 100644
--- a/drivers/staging/gma500/psb_irq.c
+++ b/drivers/staging/gma500/psb_irq.c
@@ -455,11 +455,12 @@ int psb_enable_vblank(struct drm_device *dev, int pipe)
 	uint32_t reg_val = 0;
 	uint32_t pipeconf_reg = mid_pipeconf(pipe);
 
+#if defined(CONFIG_DRM_PSB_MFLD)
 	/* Medfield is different - we should perhaps extract out vblank
 	   and blacklight etc ops */
 	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
 		return mdfld_enable_te(dev, pipe);
-
+#endif
 	if (gma_power_begin(dev, false)) {
 		reg_val = REG_READ(pipeconf_reg);
 		gma_power_end(dev);
@@ -486,8 +487,10 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	unsigned long irqflags;
 
+#if defined(CONFIG_DRM_PSB_MFLD)
 	if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
 		mdfld_disable_te(dev, pipe);
+#endif
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
 	mid_disable_pipe_event(dev_priv, pipe);


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 36/49] gma500: Rename the psb_intel_bios code
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (34 preceding siblings ...)
  2011-07-05 14:41 ` [PATCH 35/49] gma500: begin the config based split Alan Cox
@ 2011-07-05 14:42 ` Alan Cox
  2011-07-05 14:42 ` [PATCH 37/49] gma500: tidy up the opregion and lid code Alan Cox
                   ` (13 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:42 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

This is generic for the PC class devices and also very similar to the i915
intel_bios.c so rename it. That way the commonality will be obvious and we
can look at merging them one day, or at least synching them up.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile         |    2 
 drivers/staging/gma500/intel_bios.c     |  299 +++++++++++++++++++++++++++++++
 drivers/staging/gma500/psb_intel_bios.c |  299 -------------------------------
 3 files changed, 300 insertions(+), 300 deletions(-)
 create mode 100644 drivers/staging/gma500/intel_bios.c
 delete mode 100644 drivers/staging/gma500/psb_intel_bios.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index aa60926..7f76a19 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -9,9 +9,9 @@ psb_gfx-y += gem_glue.o \
 	  framebuffer.o \
 	  gem.o \
 	  gtt.o \
+	  intel_bios.o \
 	  power.o \
 	  psb_drv.o \
-	  psb_intel_bios.o \
 	  psb_intel_opregion.o \
 	  psb_intel_display.o \
 	  psb_intel_i2c.o \
diff --git a/drivers/staging/gma500/intel_bios.c b/drivers/staging/gma500/intel_bios.c
new file mode 100644
index 0000000..5b3e88c
--- /dev/null
+++ b/drivers/staging/gma500/intel_bios.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2006 Intel Corporation
+ *
+ * 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_bios.h"
+
+
+static void *find_section(struct bdb_header *bdb, int section_id)
+{
+	u8 *base = (u8 *)bdb;
+	int index = 0;
+	u16 total, current_size;
+	u8 current_id;
+
+	/* skip to first section */
+	index += bdb->header_size;
+	total = bdb->bdb_size;
+
+	/* walk the sections looking for section_id */
+	while (index < total) {
+		current_id = *(base + index);
+		index++;
+		current_size = *((u16 *)(base + index));
+		index += 2;
+		if (current_id == section_id)
+			return base + index;
+		index += current_size;
+	}
+
+	return NULL;
+}
+
+static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
+			struct lvds_dvo_timing *dvo_timing)
+{
+	panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
+		dvo_timing->hactive_lo;
+	panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
+		((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
+	panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
+		dvo_timing->hsync_pulse_width;
+	panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
+		((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
+
+	panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
+		dvo_timing->vactive_lo;
+	panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
+		dvo_timing->vsync_off;
+	panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
+		dvo_timing->vsync_pulse_width;
+	panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
+		((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
+	panel_fixed_mode->clock = dvo_timing->clock * 10;
+	panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
+
+	/* Some VBTs have bogus h/vtotal values */
+	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
+		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
+	if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
+		panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
+
+	drm_mode_set_name(panel_fixed_mode);
+}
+
+static void parse_backlight_data(struct drm_psb_private *dev_priv,
+				struct bdb_header *bdb)
+{
+	struct bdb_lvds_backlight *vbt_lvds_bl = NULL;
+	struct bdb_lvds_backlight *lvds_bl;
+	u8 p_type = 0;
+	void *bl_start = NULL;
+	struct bdb_lvds_options *lvds_opts
+				= find_section(bdb, BDB_LVDS_OPTIONS);
+
+	dev_priv->lvds_bl = NULL;
+
+	if (lvds_opts)
+		p_type = lvds_opts->panel_type;
+	else
+		return;
+
+	bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT);
+	vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type;
+
+	lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL);
+	if (!lvds_bl) {
+		dev_err(dev_priv->dev->dev, "out of memory for backlight data\n");
+		return;
+	}
+	memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl));
+	dev_priv->lvds_bl = lvds_bl;
+}
+
+/* Try to find integrated panel data */
+static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
+			    struct bdb_header *bdb)
+{
+	struct bdb_lvds_options *lvds_options;
+	struct bdb_lvds_lfp_data *lvds_lfp_data;
+	struct bdb_lvds_lfp_data_entry *entry;
+	struct lvds_dvo_timing *dvo_timing;
+	struct drm_display_mode *panel_fixed_mode;
+
+	/* Defaults if we can't find VBT info */
+	dev_priv->lvds_dither = 0;
+	dev_priv->lvds_vbt = 0;
+
+	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
+	if (!lvds_options)
+		return;
+
+	dev_priv->lvds_dither = lvds_options->pixel_dither;
+	if (lvds_options->panel_type == 0xff)
+		return;
+
+	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
+	if (!lvds_lfp_data)
+		return;
+
+	dev_priv->lvds_vbt = 1;
+
+	entry = &lvds_lfp_data->data[lvds_options->panel_type];
+	dvo_timing = &entry->dvo_timing;
+
+	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode),
+				      GFP_KERNEL);
+
+	fill_detail_timing_data(panel_fixed_mode, dvo_timing);
+
+	if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) {
+		dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
+		drm_mode_debug_printmodeline(panel_fixed_mode);
+	} else {
+		dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n");
+		dev_priv->lvds_vbt = 0;
+		kfree(panel_fixed_mode);
+	}
+	return;
+}
+
+/* Try to find sdvo panel data */
+static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv,
+		      struct bdb_header *bdb)
+{
+	struct bdb_sdvo_lvds_options *sdvo_lvds_options;
+	struct lvds_dvo_timing *dvo_timing;
+	struct drm_display_mode *panel_fixed_mode;
+
+	dev_priv->sdvo_lvds_vbt_mode = NULL;
+
+	sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
+	if (!sdvo_lvds_options)
+		return;
+
+	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
+	if (!dvo_timing)
+		return;
+
+	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
+
+	if (!panel_fixed_mode)
+		return;
+
+	fill_detail_timing_data(panel_fixed_mode,
+			dvo_timing + sdvo_lvds_options->panel_type);
+
+	dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
+
+	return;
+}
+
+static void parse_general_features(struct drm_psb_private *dev_priv,
+		       struct bdb_header *bdb)
+{
+	struct bdb_general_features *general;
+
+	/* Set sensible defaults in case we can't find the general block */
+	dev_priv->int_tv_support = 1;
+	dev_priv->int_crt_support = 1;
+
+	general = find_section(bdb, BDB_GENERAL_FEATURES);
+	if (general) {
+		dev_priv->int_tv_support = general->int_tv_support;
+		dev_priv->int_crt_support = general->int_crt_support;
+		dev_priv->lvds_use_ssc = general->enable_ssc;
+
+		if (dev_priv->lvds_use_ssc) {
+			dev_priv->lvds_ssc_freq
+				= general->ssc_freq ? 100 : 96;
+		}
+	}
+}
+
+/**
+ * psb_intel_init_bios - initialize VBIOS settings & find VBT
+ * @dev: DRM device
+ *
+ * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
+ * to appropriate values.
+ *
+ * VBT existence is a sanity check that is relied on by other i830_bios.c code.
+ * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
+ * feed an updated VBT back through that, compared to what we'll fetch using
+ * this method of groping around in the BIOS data.
+ *
+ * Returns 0 on success, nonzero on failure.
+ */
+bool psb_intel_init_bios(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct pci_dev *pdev = dev->pdev;
+	struct vbt_header *vbt = NULL;
+	struct bdb_header *bdb;
+	u8 __iomem *bios;
+	size_t size;
+	int i;
+
+	bios = pci_map_rom(pdev, &size);
+	if (!bios)
+		return -1;
+
+	/* Scour memory looking for the VBT signature */
+	for (i = 0; i + 4 < size; i++) {
+		if (!memcmp(bios + i, "$VBT", 4)) {
+			vbt = (struct vbt_header *)(bios + i);
+			break;
+		}
+	}
+
+	if (!vbt) {
+		dev_err(dev->dev, "VBT signature missing\n");
+		pci_unmap_rom(pdev, bios);
+		return -1;
+	}
+
+	bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
+
+	/* Grab useful general definitions */
+	parse_general_features(dev_priv, bdb);
+	parse_lfp_panel_data(dev_priv, bdb);
+	parse_sdvo_panel_data(dev_priv, bdb);
+	parse_backlight_data(dev_priv, bdb);
+
+	pci_unmap_rom(pdev, bios);
+
+	return 0;
+}
+
+/**
+ * Destroy and free VBT data
+ */
+void psb_intel_destroy_bios(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_display_mode *sdvo_lvds_vbt_mode =
+				dev_priv->sdvo_lvds_vbt_mode;
+	struct drm_display_mode *lfp_lvds_vbt_mode =
+				dev_priv->lfp_lvds_vbt_mode;
+	struct bdb_lvds_backlight *lvds_bl =
+				dev_priv->lvds_bl;
+
+	/*free sdvo panel mode*/
+	if (sdvo_lvds_vbt_mode) {
+		dev_priv->sdvo_lvds_vbt_mode = NULL;
+		kfree(sdvo_lvds_vbt_mode);
+	}
+
+	if (lfp_lvds_vbt_mode) {
+		dev_priv->lfp_lvds_vbt_mode = NULL;
+		kfree(lfp_lvds_vbt_mode);
+	}
+
+	if (lvds_bl) {
+		dev_priv->lvds_bl = NULL;
+		kfree(lvds_bl);
+	}
+}
diff --git a/drivers/staging/gma500/psb_intel_bios.c b/drivers/staging/gma500/psb_intel_bios.c
deleted file mode 100644
index 5b3e88c..0000000
--- a/drivers/staging/gma500/psb_intel_bios.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (c) 2006 Intel Corporation
- *
- * 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:
- *    Eric Anholt <eric@anholt.net>
- *
- */
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "psb_drm.h"
-#include "psb_drv.h"
-#include "psb_intel_drv.h"
-#include "psb_intel_reg.h"
-#include "psb_intel_bios.h"
-
-
-static void *find_section(struct bdb_header *bdb, int section_id)
-{
-	u8 *base = (u8 *)bdb;
-	int index = 0;
-	u16 total, current_size;
-	u8 current_id;
-
-	/* skip to first section */
-	index += bdb->header_size;
-	total = bdb->bdb_size;
-
-	/* walk the sections looking for section_id */
-	while (index < total) {
-		current_id = *(base + index);
-		index++;
-		current_size = *((u16 *)(base + index));
-		index += 2;
-		if (current_id == section_id)
-			return base + index;
-		index += current_size;
-	}
-
-	return NULL;
-}
-
-static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
-			struct lvds_dvo_timing *dvo_timing)
-{
-	panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
-		dvo_timing->hactive_lo;
-	panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
-		((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
-	panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
-		dvo_timing->hsync_pulse_width;
-	panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
-		((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
-
-	panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
-		dvo_timing->vactive_lo;
-	panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
-		dvo_timing->vsync_off;
-	panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
-		dvo_timing->vsync_pulse_width;
-	panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
-		((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
-	panel_fixed_mode->clock = dvo_timing->clock * 10;
-	panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
-
-	/* Some VBTs have bogus h/vtotal values */
-	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
-		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
-	if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
-		panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
-
-	drm_mode_set_name(panel_fixed_mode);
-}
-
-static void parse_backlight_data(struct drm_psb_private *dev_priv,
-				struct bdb_header *bdb)
-{
-	struct bdb_lvds_backlight *vbt_lvds_bl = NULL;
-	struct bdb_lvds_backlight *lvds_bl;
-	u8 p_type = 0;
-	void *bl_start = NULL;
-	struct bdb_lvds_options *lvds_opts
-				= find_section(bdb, BDB_LVDS_OPTIONS);
-
-	dev_priv->lvds_bl = NULL;
-
-	if (lvds_opts)
-		p_type = lvds_opts->panel_type;
-	else
-		return;
-
-	bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT);
-	vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type;
-
-	lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL);
-	if (!lvds_bl) {
-		dev_err(dev_priv->dev->dev, "out of memory for backlight data\n");
-		return;
-	}
-	memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl));
-	dev_priv->lvds_bl = lvds_bl;
-}
-
-/* Try to find integrated panel data */
-static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
-			    struct bdb_header *bdb)
-{
-	struct bdb_lvds_options *lvds_options;
-	struct bdb_lvds_lfp_data *lvds_lfp_data;
-	struct bdb_lvds_lfp_data_entry *entry;
-	struct lvds_dvo_timing *dvo_timing;
-	struct drm_display_mode *panel_fixed_mode;
-
-	/* Defaults if we can't find VBT info */
-	dev_priv->lvds_dither = 0;
-	dev_priv->lvds_vbt = 0;
-
-	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
-	if (!lvds_options)
-		return;
-
-	dev_priv->lvds_dither = lvds_options->pixel_dither;
-	if (lvds_options->panel_type == 0xff)
-		return;
-
-	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
-	if (!lvds_lfp_data)
-		return;
-
-	dev_priv->lvds_vbt = 1;
-
-	entry = &lvds_lfp_data->data[lvds_options->panel_type];
-	dvo_timing = &entry->dvo_timing;
-
-	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode),
-				      GFP_KERNEL);
-
-	fill_detail_timing_data(panel_fixed_mode, dvo_timing);
-
-	if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) {
-		dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
-		drm_mode_debug_printmodeline(panel_fixed_mode);
-	} else {
-		dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n");
-		dev_priv->lvds_vbt = 0;
-		kfree(panel_fixed_mode);
-	}
-	return;
-}
-
-/* Try to find sdvo panel data */
-static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv,
-		      struct bdb_header *bdb)
-{
-	struct bdb_sdvo_lvds_options *sdvo_lvds_options;
-	struct lvds_dvo_timing *dvo_timing;
-	struct drm_display_mode *panel_fixed_mode;
-
-	dev_priv->sdvo_lvds_vbt_mode = NULL;
-
-	sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
-	if (!sdvo_lvds_options)
-		return;
-
-	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
-	if (!dvo_timing)
-		return;
-
-	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
-
-	if (!panel_fixed_mode)
-		return;
-
-	fill_detail_timing_data(panel_fixed_mode,
-			dvo_timing + sdvo_lvds_options->panel_type);
-
-	dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
-
-	return;
-}
-
-static void parse_general_features(struct drm_psb_private *dev_priv,
-		       struct bdb_header *bdb)
-{
-	struct bdb_general_features *general;
-
-	/* Set sensible defaults in case we can't find the general block */
-	dev_priv->int_tv_support = 1;
-	dev_priv->int_crt_support = 1;
-
-	general = find_section(bdb, BDB_GENERAL_FEATURES);
-	if (general) {
-		dev_priv->int_tv_support = general->int_tv_support;
-		dev_priv->int_crt_support = general->int_crt_support;
-		dev_priv->lvds_use_ssc = general->enable_ssc;
-
-		if (dev_priv->lvds_use_ssc) {
-			dev_priv->lvds_ssc_freq
-				= general->ssc_freq ? 100 : 96;
-		}
-	}
-}
-
-/**
- * psb_intel_init_bios - initialize VBIOS settings & find VBT
- * @dev: DRM device
- *
- * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
- * to appropriate values.
- *
- * VBT existence is a sanity check that is relied on by other i830_bios.c code.
- * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
- * feed an updated VBT back through that, compared to what we'll fetch using
- * this method of groping around in the BIOS data.
- *
- * Returns 0 on success, nonzero on failure.
- */
-bool psb_intel_init_bios(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct pci_dev *pdev = dev->pdev;
-	struct vbt_header *vbt = NULL;
-	struct bdb_header *bdb;
-	u8 __iomem *bios;
-	size_t size;
-	int i;
-
-	bios = pci_map_rom(pdev, &size);
-	if (!bios)
-		return -1;
-
-	/* Scour memory looking for the VBT signature */
-	for (i = 0; i + 4 < size; i++) {
-		if (!memcmp(bios + i, "$VBT", 4)) {
-			vbt = (struct vbt_header *)(bios + i);
-			break;
-		}
-	}
-
-	if (!vbt) {
-		dev_err(dev->dev, "VBT signature missing\n");
-		pci_unmap_rom(pdev, bios);
-		return -1;
-	}
-
-	bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
-
-	/* Grab useful general definitions */
-	parse_general_features(dev_priv, bdb);
-	parse_lfp_panel_data(dev_priv, bdb);
-	parse_sdvo_panel_data(dev_priv, bdb);
-	parse_backlight_data(dev_priv, bdb);
-
-	pci_unmap_rom(pdev, bios);
-
-	return 0;
-}
-
-/**
- * Destroy and free VBT data
- */
-void psb_intel_destroy_bios(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct drm_display_mode *sdvo_lvds_vbt_mode =
-				dev_priv->sdvo_lvds_vbt_mode;
-	struct drm_display_mode *lfp_lvds_vbt_mode =
-				dev_priv->lfp_lvds_vbt_mode;
-	struct bdb_lvds_backlight *lvds_bl =
-				dev_priv->lvds_bl;
-
-	/*free sdvo panel mode*/
-	if (sdvo_lvds_vbt_mode) {
-		dev_priv->sdvo_lvds_vbt_mode = NULL;
-		kfree(sdvo_lvds_vbt_mode);
-	}
-
-	if (lfp_lvds_vbt_mode) {
-		dev_priv->lfp_lvds_vbt_mode = NULL;
-		kfree(lfp_lvds_vbt_mode);
-	}
-
-	if (lvds_bl) {
-		dev_priv->lvds_bl = NULL;
-		kfree(lvds_bl);
-	}
-}


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 37/49] gma500: tidy up the opregion and lid code
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (35 preceding siblings ...)
  2011-07-05 14:42 ` [PATCH 36/49] gma500: Rename the psb_intel_bios code Alan Cox
@ 2011-07-05 14:42 ` Alan Cox
  2011-07-05 14:42 ` [PATCH 38/49] gma500: move opregion files Alan Cox
                   ` (12 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:42 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

This is leaking an io mapping and also referencing stuff directly that
should not be directly accessed. Sort it out

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/cdv_device.c         |    2 +-
 drivers/staging/gma500/psb_device.c         |    2 +-
 drivers/staging/gma500/psb_drv.c            |    1 +
 drivers/staging/gma500/psb_drv.h            |    5 +++--
 drivers/staging/gma500/psb_intel_opregion.c |   14 +++++++++++---
 drivers/staging/gma500/psb_lid.c            |    6 +++---
 6 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c
index bb0b3f9..5131106 100644
--- a/drivers/staging/gma500/cdv_device.c
+++ b/drivers/staging/gma500/cdv_device.c
@@ -321,7 +321,7 @@ static void cdv_get_core_freq(struct drm_device *dev)
 static int cdv_chip_setup(struct drm_device *dev)
 {
 	cdv_get_core_freq(dev);
-	psb_intel_opregion_init(dev);
+	intel_opregion_init(dev);
 	psb_intel_init_bios(dev);
 	return 0;
 }
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
index 1be6434..8ac9de7 100644
--- a/drivers/staging/gma500/psb_device.c
+++ b/drivers/staging/gma500/psb_device.c
@@ -322,7 +322,7 @@ static void psb_get_core_freq(struct drm_device *dev)
 static int psb_chip_setup(struct drm_device *dev)
 {
 	psb_get_core_freq(dev);
-	psb_intel_opregion_init(dev);
+	intel_opregion_init(dev);
 	psb_intel_init_bios(dev);
 	return 0;
 }
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 69ab61b..e9772ab 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -245,6 +245,7 @@ static int psb_driver_unload(struct drm_device *dev)
 
 	if (dev_priv) {
 		psb_lid_timer_takedown(dev_priv);
+		intel_opregion_exit(dev);
 
 		psb_do_takedown(dev);
 
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 307ff9c..ee782fa 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -727,9 +727,10 @@ extern int mdfld_enable_te(struct drm_device *dev, int pipe);
 extern void mdfld_disable_te(struct drm_device *dev, int pipe);
 
 /*
- * psb_opregion.c
+ * intel_opregion.c
  */
-extern int psb_intel_opregion_init(struct drm_device *dev);
+extern int intel_opregion_init(struct drm_device *dev);
+extern int intel_opregion_exit(struct drm_device *dev);
 
 /*
  * framebuffer.c
diff --git a/drivers/staging/gma500/psb_intel_opregion.c b/drivers/staging/gma500/psb_intel_opregion.c
index 97a8b00..a586f3d 100644
--- a/drivers/staging/gma500/psb_intel_opregion.c
+++ b/drivers/staging/gma500/psb_intel_opregion.c
@@ -47,10 +47,9 @@ struct opregion_acpi {
 	/*FIXME: add it later*/
 } __packed;
 
-int psb_intel_opregion_init(struct drm_device *dev)
+int intel_opregion_init(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	/*struct psb_intel_opregion * opregion = &dev_priv->opregion;*/
 	u32 opregion_phy;
 	void *base;
 	u32 *lid_state;
@@ -68,6 +67,15 @@ int psb_intel_opregion_init(struct drm_device *dev)
 	lid_state = base + 0x01ac;
 
 	dev_priv->lid_state = lid_state;
-	dev_priv->lid_last_state = *lid_state;
+	dev_priv->lid_last_state = readl(lid_state);
 	return 0;
 }
+
+int intel_opregion_exit(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	if (dev_priv->lid_state)
+		iounmap(dev_priv->lid_state);
+	return 0;
+}
+	
\ No newline at end of file
diff --git a/drivers/staging/gma500/psb_lid.c b/drivers/staging/gma500/psb_lid.c
index 21fd202..af32851 100644
--- a/drivers/staging/gma500/psb_lid.c
+++ b/drivers/staging/gma500/psb_lid.c
@@ -32,10 +32,10 @@ static void psb_lid_timer_func(unsigned long data)
 	u32 *lid_state = dev_priv->lid_state;
 	u32 pp_status;
 
-	if (*lid_state == dev_priv->lid_last_state)
+	if (readl(lid_state) == dev_priv->lid_last_state)
 		goto lid_timer_schedule;
 
-	if ((*lid_state) & 0x01) {
+	if ((readl(lid_state)) & 0x01) {
 		/*lid state is open*/
 		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
 		do {
@@ -54,7 +54,7 @@ static void psb_lid_timer_func(unsigned long data)
 	}
 		/* printk(KERN_INFO"%s: lid: closed\n", __FUNCTION__); */
 
-	dev_priv->lid_last_state =  *lid_state;
+	dev_priv->lid_last_state =  readl(lid_state);
 
 lid_timer_schedule:
 	spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 38/49] gma500: move opregion files
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (36 preceding siblings ...)
  2011-07-05 14:42 ` [PATCH 37/49] gma500: tidy up the opregion and lid code Alan Cox
@ 2011-07-05 14:42 ` Alan Cox
  2011-07-05 14:42 ` [PATCH 39/49] gma500: the MMU code is also generic Alan Cox
                   ` (11 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:42 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We've now sorted them out so they can go into the generic code. In actual
fact only the non MID devices use the functions but they are small and
having the name match i915 is going to help any future merging type work.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile             |    2 -
 drivers/staging/gma500/intel_opregion.c     |   80 +++++++++++++++++++++++++++
 drivers/staging/gma500/psb_intel_opregion.c |   81 ---------------------------
 3 files changed, 81 insertions(+), 82 deletions(-)
 create mode 100644 drivers/staging/gma500/intel_opregion.c
 delete mode 100644 drivers/staging/gma500/psb_intel_opregion.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index 7f76a19..c014373 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -10,9 +10,9 @@ psb_gfx-y += gem_glue.o \
 	  gem.o \
 	  gtt.o \
 	  intel_bios.o \
+	  intel_opregion.o \
 	  power.o \
 	  psb_drv.o \
-	  psb_intel_opregion.o \
 	  psb_intel_display.o \
 	  psb_intel_i2c.o \
 	  psb_intel_lvds.o \
diff --git a/drivers/staging/gma500/intel_opregion.c b/drivers/staging/gma500/intel_opregion.c
new file mode 100644
index 0000000..8240965
--- /dev/null
+++ b/drivers/staging/gma500/intel_opregion.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "psb_drv.h"
+
+struct opregion_header {
+	u8 signature[16];
+	u32 size;
+	u32 opregion_ver;
+	u8 bios_ver[32];
+	u8 vbios_ver[16];
+	u8 driver_ver[16];
+	u32 mboxes;
+	u8 reserved[164];
+} __packed;
+
+struct opregion_apci {
+	/*FIXME: add it later*/
+} __packed;
+
+struct opregion_swsci {
+	/*FIXME: add it later*/
+} __packed;
+
+struct opregion_acpi {
+	/*FIXME: add it later*/
+} __packed;
+
+int intel_opregion_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 opregion_phy;
+	void *base;
+	u32 *lid_state;
+
+	dev_priv->lid_state = NULL;
+
+	pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy);
+	if (opregion_phy == 0)
+		return -ENOTSUPP;
+
+	base = ioremap(opregion_phy, 8*1024);
+	if (!base)
+		return -ENOMEM;
+
+	lid_state = base + 0x01ac;
+
+	dev_priv->lid_state = lid_state;
+	dev_priv->lid_last_state = readl(lid_state);
+	return 0;
+}
+
+int intel_opregion_exit(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	if (dev_priv->lid_state)
+		iounmap(dev_priv->lid_state);
+	return 0;
+}
diff --git a/drivers/staging/gma500/psb_intel_opregion.c b/drivers/staging/gma500/psb_intel_opregion.c
deleted file mode 100644
index a586f3d..0000000
--- a/drivers/staging/gma500/psb_intel_opregion.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "psb_drv.h"
-
-struct opregion_header {
-	u8 signature[16];
-	u32 size;
-	u32 opregion_ver;
-	u8 bios_ver[32];
-	u8 vbios_ver[16];
-	u8 driver_ver[16];
-	u32 mboxes;
-	u8 reserved[164];
-} __packed;
-
-struct opregion_apci {
-	/*FIXME: add it later*/
-} __packed;
-
-struct opregion_swsci {
-	/*FIXME: add it later*/
-} __packed;
-
-struct opregion_acpi {
-	/*FIXME: add it later*/
-} __packed;
-
-int intel_opregion_init(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 opregion_phy;
-	void *base;
-	u32 *lid_state;
-
-	dev_priv->lid_state = NULL;
-
-	pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy);
-	if (opregion_phy == 0)
-		return -ENOTSUPP;
-
-	base = ioremap(opregion_phy, 8*1024);
-	if (!base)
-		return -ENOMEM;
-
-	lid_state = base + 0x01ac;
-
-	dev_priv->lid_state = lid_state;
-	dev_priv->lid_last_state = readl(lid_state);
-	return 0;
-}
-
-int intel_opregion_exit(struct drm_device *dev)
-{
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	if (dev_priv->lid_state)
-		iounmap(dev_priv->lid_state);
-	return 0;
-}
-	
\ No newline at end of file


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 39/49] gma500: the MMU code is also generic
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (37 preceding siblings ...)
  2011-07-05 14:42 ` [PATCH 38/49] gma500: move opregion files Alan Cox
@ 2011-07-05 14:42 ` Alan Cox
  2011-07-05 14:43 ` [PATCH 40/49] gma500: move the i2c code Alan Cox
                   ` (10 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:42 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Move this over. In actual fact there are some underlying differences as
some devices have more MMU contexts, but for our 2D purposes we don't
actually care.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile  |    2 
 drivers/staging/gma500/mmu.c     |  858 ++++++++++++++++++++++++++++++++++++++
 drivers/staging/gma500/psb_mmu.c |  858 --------------------------------------
 3 files changed, 859 insertions(+), 859 deletions(-)
 create mode 100644 drivers/staging/gma500/mmu.c
 delete mode 100644 drivers/staging/gma500/psb_mmu.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index c014373..d4a87c0 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -11,6 +11,7 @@ psb_gfx-y += gem_glue.o \
 	  gtt.o \
 	  intel_bios.o \
 	  intel_opregion.o \
+	  mmu.o \
 	  power.o \
 	  psb_drv.o \
 	  psb_intel_display.o \
@@ -19,7 +20,6 @@ psb_gfx-y += gem_glue.o \
 	  psb_intel_modes.o \
 	  psb_intel_sdvo.o \
 	  psb_lid.o \
-	  psb_mmu.o \
 	  psb_irq.o \
 	  psb_device.o \
 	  mid_bios.o
diff --git a/drivers/staging/gma500/mmu.c b/drivers/staging/gma500/mmu.c
new file mode 100644
index 0000000..c904d73
--- /dev/null
+++ b/drivers/staging/gma500/mmu.c
@@ -0,0 +1,858 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * 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 "psb_drv.h"
+#include "psb_reg.h"
+
+/*
+ * Code for the SGX MMU:
+ */
+
+/*
+ * clflush on one processor only:
+ * clflush should apparently flush the cache line on all processors in an
+ * SMP system.
+ */
+
+/*
+ * kmap atomic:
+ * The usage of the slots must be completely encapsulated within a spinlock, and
+ * no other functions that may be using the locks for other purposed may be
+ * called from within the locked region.
+ * Since the slots are per processor, this will guarantee that we are the only
+ * user.
+ */
+
+/*
+ * TODO: Inserting ptes from an interrupt handler:
+ * This may be desirable for some SGX functionality where the GPU can fault in
+ * needed pages. For that, we need to make an atomic insert_pages function, that
+ * may fail.
+ * If it fails, the caller need to insert the page using a workqueue function,
+ * but on average it should be fast.
+ */
+
+struct psb_mmu_driver {
+	/* protects driver- and pd structures. Always take in read mode
+	 * before taking the page table spinlock.
+	 */
+	struct rw_semaphore sem;
+
+	/* protects page tables, directory tables and pt tables.
+	 * and pt structures.
+	 */
+	spinlock_t lock;
+
+	atomic_t needs_tlbflush;
+
+	uint8_t __iomem *register_map;
+	struct psb_mmu_pd *default_pd;
+	/*uint32_t bif_ctrl;*/
+	int has_clflush;
+	int clflush_add;
+	unsigned long clflush_mask;
+
+	struct drm_psb_private *dev_priv;
+};
+
+struct psb_mmu_pd;
+
+struct psb_mmu_pt {
+	struct psb_mmu_pd *pd;
+	uint32_t index;
+	uint32_t count;
+	struct page *p;
+	uint32_t *v;
+};
+
+struct psb_mmu_pd {
+	struct psb_mmu_driver *driver;
+	int hw_context;
+	struct psb_mmu_pt **tables;
+	struct page *p;
+	struct page *dummy_pt;
+	struct page *dummy_page;
+	uint32_t pd_mask;
+	uint32_t invalid_pde;
+	uint32_t invalid_pte;
+};
+
+static inline uint32_t psb_mmu_pt_index(uint32_t offset)
+{
+	return (offset >> PSB_PTE_SHIFT) & 0x3FF;
+}
+
+static inline uint32_t psb_mmu_pd_index(uint32_t offset)
+{
+	return offset >> PSB_PDE_SHIFT;
+}
+
+static inline void psb_clflush(void *addr)
+{
+	__asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
+}
+
+static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
+				   void *addr)
+{
+	if (!driver->has_clflush)
+		return;
+
+	mb();
+	psb_clflush(addr);
+	mb();
+}
+
+static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
+{
+	uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
+	uint32_t clflush_count = PAGE_SIZE / clflush_add;
+	int i;
+	uint8_t *clf;
+
+	clf = kmap_atomic(page, KM_USER0);
+	mb();
+	for (i = 0; i < clflush_count; ++i) {
+		psb_clflush(clf);
+		clf += clflush_add;
+	}
+	mb();
+	kunmap_atomic(clf, KM_USER0);
+}
+
+static void psb_pages_clflush(struct psb_mmu_driver *driver,
+				struct page *page[], unsigned long num_pages)
+{
+	int i;
+
+	if (!driver->has_clflush)
+		return ;
+
+	for (i = 0; i < num_pages; i++)
+		psb_page_clflush(driver, *page++);
+}
+
+static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
+				    int force)
+{
+	atomic_set(&driver->needs_tlbflush, 0);
+}
+
+static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
+{
+	down_write(&driver->sem);
+	psb_mmu_flush_pd_locked(driver, force);
+	up_write(&driver->sem);
+}
+
+void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
+{
+	if (rc_prot)
+		down_write(&driver->sem);
+	if (rc_prot)
+		up_write(&driver->sem);
+}
+
+void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
+{
+	/*ttm_tt_cache_flush(&pd->p, 1);*/
+	psb_pages_clflush(pd->driver, &pd->p, 1);
+	down_write(&pd->driver->sem);
+	wmb();
+	psb_mmu_flush_pd_locked(pd->driver, 1);
+	pd->hw_context = hw_context;
+	up_write(&pd->driver->sem);
+
+}
+
+static inline unsigned long psb_pd_addr_end(unsigned long addr,
+					    unsigned long end)
+{
+
+	addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
+	return (addr < end) ? addr : end;
+}
+
+static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type)
+{
+	uint32_t mask = PSB_PTE_VALID;
+
+	if (type & PSB_MMU_CACHED_MEMORY)
+		mask |= PSB_PTE_CACHED;
+	if (type & PSB_MMU_RO_MEMORY)
+		mask |= PSB_PTE_RO;
+	if (type & PSB_MMU_WO_MEMORY)
+		mask |= PSB_PTE_WO;
+
+	return (pfn << PAGE_SHIFT) | mask;
+}
+
+struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+				    int trap_pagefaults, int invalid_type)
+{
+	struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL);
+	uint32_t *v;
+	int i;
+
+	if (!pd)
+		return NULL;
+
+	pd->p = alloc_page(GFP_DMA32);
+	if (!pd->p)
+		goto out_err1;
+	pd->dummy_pt = alloc_page(GFP_DMA32);
+	if (!pd->dummy_pt)
+		goto out_err2;
+	pd->dummy_page = alloc_page(GFP_DMA32);
+	if (!pd->dummy_page)
+		goto out_err3;
+
+	if (!trap_pagefaults) {
+		pd->invalid_pde =
+		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
+				     invalid_type);
+		pd->invalid_pte =
+		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
+				     invalid_type);
+	} else {
+		pd->invalid_pde = 0;
+		pd->invalid_pte = 0;
+	}
+
+	v = kmap(pd->dummy_pt);
+	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+		v[i] = pd->invalid_pte;
+
+	kunmap(pd->dummy_pt);
+
+	v = kmap(pd->p);
+	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+		v[i] = pd->invalid_pde;
+
+	kunmap(pd->p);
+
+	clear_page(kmap(pd->dummy_page));
+	kunmap(pd->dummy_page);
+
+	pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024);
+	if (!pd->tables)
+		goto out_err4;
+
+	pd->hw_context = -1;
+	pd->pd_mask = PSB_PTE_VALID;
+	pd->driver = driver;
+
+	return pd;
+
+out_err4:
+	__free_page(pd->dummy_page);
+out_err3:
+	__free_page(pd->dummy_pt);
+out_err2:
+	__free_page(pd->p);
+out_err1:
+	kfree(pd);
+	return NULL;
+}
+
+void psb_mmu_free_pt(struct psb_mmu_pt *pt)
+{
+	__free_page(pt->p);
+	kfree(pt);
+}
+
+void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
+{
+	struct psb_mmu_driver *driver = pd->driver;
+	struct psb_mmu_pt *pt;
+	int i;
+
+	down_write(&driver->sem);
+	if (pd->hw_context != -1)
+		psb_mmu_flush_pd_locked(driver, 1);
+
+	/* Should take the spinlock here, but we don't need to do that
+	   since we have the semaphore in write mode. */
+
+	for (i = 0; i < 1024; ++i) {
+		pt = pd->tables[i];
+		if (pt)
+			psb_mmu_free_pt(pt);
+	}
+
+	vfree(pd->tables);
+	__free_page(pd->dummy_page);
+	__free_page(pd->dummy_pt);
+	__free_page(pd->p);
+	kfree(pd);
+	up_write(&driver->sem);
+}
+
+static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
+{
+	struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL);
+	void *v;
+	uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT;
+	uint32_t clflush_count = PAGE_SIZE / clflush_add;
+	spinlock_t *lock = &pd->driver->lock;
+	uint8_t *clf;
+	uint32_t *ptes;
+	int i;
+
+	if (!pt)
+		return NULL;
+
+	pt->p = alloc_page(GFP_DMA32);
+	if (!pt->p) {
+		kfree(pt);
+		return NULL;
+	}
+
+	spin_lock(lock);
+
+	v = kmap_atomic(pt->p, KM_USER0);
+	clf = (uint8_t *) v;
+	ptes = (uint32_t *) v;
+	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+		*ptes++ = pd->invalid_pte;
+
+
+	if (pd->driver->has_clflush && pd->hw_context != -1) {
+		mb();
+		for (i = 0; i < clflush_count; ++i) {
+			psb_clflush(clf);
+			clf += clflush_add;
+		}
+		mb();
+	}
+
+	kunmap_atomic(v, KM_USER0);
+	spin_unlock(lock);
+
+	pt->count = 0;
+	pt->pd = pd;
+	pt->index = 0;
+
+	return pt;
+}
+
+struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
+					     unsigned long addr)
+{
+	uint32_t index = psb_mmu_pd_index(addr);
+	struct psb_mmu_pt *pt;
+	uint32_t *v;
+	spinlock_t *lock = &pd->driver->lock;
+
+	spin_lock(lock);
+	pt = pd->tables[index];
+	while (!pt) {
+		spin_unlock(lock);
+		pt = psb_mmu_alloc_pt(pd);
+		if (!pt)
+			return NULL;
+		spin_lock(lock);
+
+		if (pd->tables[index]) {
+			spin_unlock(lock);
+			psb_mmu_free_pt(pt);
+			spin_lock(lock);
+			pt = pd->tables[index];
+			continue;
+		}
+
+		v = kmap_atomic(pd->p, KM_USER0);
+		pd->tables[index] = pt;
+		v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
+		pt->index = index;
+		kunmap_atomic((void *) v, KM_USER0);
+
+		if (pd->hw_context != -1) {
+			psb_mmu_clflush(pd->driver, (void *) &v[index]);
+			atomic_set(&pd->driver->needs_tlbflush, 1);
+		}
+	}
+	pt->v = kmap_atomic(pt->p, KM_USER0);
+	return pt;
+}
+
+static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd,
+					      unsigned long addr)
+{
+	uint32_t index = psb_mmu_pd_index(addr);
+	struct psb_mmu_pt *pt;
+	spinlock_t *lock = &pd->driver->lock;
+
+	spin_lock(lock);
+	pt = pd->tables[index];
+	if (!pt) {
+		spin_unlock(lock);
+		return NULL;
+	}
+	pt->v = kmap_atomic(pt->p, KM_USER0);
+	return pt;
+}
+
+static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
+{
+	struct psb_mmu_pd *pd = pt->pd;
+	uint32_t *v;
+
+	kunmap_atomic(pt->v, KM_USER0);
+	if (pt->count == 0) {
+		v = kmap_atomic(pd->p, KM_USER0);
+		v[pt->index] = pd->invalid_pde;
+		pd->tables[pt->index] = NULL;
+
+		if (pd->hw_context != -1) {
+			psb_mmu_clflush(pd->driver,
+					(void *) &v[pt->index]);
+			atomic_set(&pd->driver->needs_tlbflush, 1);
+		}
+		kunmap_atomic(pt->v, KM_USER0);
+		spin_unlock(&pd->driver->lock);
+		psb_mmu_free_pt(pt);
+		return;
+	}
+	spin_unlock(&pd->driver->lock);
+}
+
+static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
+				   unsigned long addr, uint32_t pte)
+{
+	pt->v[psb_mmu_pt_index(addr)] = pte;
+}
+
+static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
+					  unsigned long addr)
+{
+	pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
+}
+
+
+void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
+			uint32_t mmu_offset, uint32_t gtt_start,
+			uint32_t gtt_pages)
+{
+	uint32_t *v;
+	uint32_t start = psb_mmu_pd_index(mmu_offset);
+	struct psb_mmu_driver *driver = pd->driver;
+	int num_pages = gtt_pages;
+
+	down_read(&driver->sem);
+	spin_lock(&driver->lock);
+
+	v = kmap_atomic(pd->p, KM_USER0);
+	v += start;
+
+	while (gtt_pages--) {
+		*v++ = gtt_start | pd->pd_mask;
+		gtt_start += PAGE_SIZE;
+	}
+
+	/*ttm_tt_cache_flush(&pd->p, num_pages);*/
+	psb_pages_clflush(pd->driver, &pd->p, num_pages);
+	kunmap_atomic(v, KM_USER0);
+	spin_unlock(&driver->lock);
+
+	if (pd->hw_context != -1)
+		atomic_set(&pd->driver->needs_tlbflush, 1);
+
+	up_read(&pd->driver->sem);
+	psb_mmu_flush_pd(pd->driver, 0);
+}
+
+struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
+{
+	struct psb_mmu_pd *pd;
+
+	/* down_read(&driver->sem); */
+	pd = driver->default_pd;
+	/* up_read(&driver->sem); */
+
+	return pd;
+}
+
+/* Returns the physical address of the PD shared by sgx/msvdx */
+uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
+{
+	struct psb_mmu_pd *pd;
+
+	pd = psb_mmu_get_default_pd(driver);
+	return page_to_pfn(pd->p) << PAGE_SHIFT;
+}
+
+void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
+{
+	psb_mmu_free_pagedir(driver->default_pd);
+	kfree(driver);
+}
+
+struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
+					int trap_pagefaults,
+					int invalid_type,
+					struct drm_psb_private *dev_priv)
+{
+	struct psb_mmu_driver *driver;
+
+	driver = kmalloc(sizeof(*driver), GFP_KERNEL);
+
+	if (!driver)
+		return NULL;
+	driver->dev_priv = dev_priv;
+
+	driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
+					      invalid_type);
+	if (!driver->default_pd)
+		goto out_err1;
+
+	spin_lock_init(&driver->lock);
+	init_rwsem(&driver->sem);
+	down_write(&driver->sem);
+	driver->register_map = registers;
+	atomic_set(&driver->needs_tlbflush, 1);
+
+	driver->has_clflush = 0;
+
+	if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
+		uint32_t tfms, misc, cap0, cap4, clflush_size;
+
+		/*
+		 * clflush size is determined at kernel setup for x86_64
+		 *  but not for i386. We have to do it here.
+		 */
+
+		cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
+		clflush_size = ((misc >> 8) & 0xff) * 8;
+		driver->has_clflush = 1;
+		driver->clflush_add =
+		    PAGE_SIZE * clflush_size / sizeof(uint32_t);
+		driver->clflush_mask = driver->clflush_add - 1;
+		driver->clflush_mask = ~driver->clflush_mask;
+	}
+
+	up_write(&driver->sem);
+	return driver;
+
+out_err1:
+	kfree(driver);
+	return NULL;
+}
+
+static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
+			       unsigned long address, uint32_t num_pages,
+			       uint32_t desired_tile_stride,
+			       uint32_t hw_tile_stride)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t rows = 1;
+	uint32_t i;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long add;
+	unsigned long row_add;
+	unsigned long clflush_add = pd->driver->clflush_add;
+	unsigned long clflush_mask = pd->driver->clflush_mask;
+
+	if (!pd->driver->has_clflush) {
+		/*ttm_tt_cache_flush(&pd->p, num_pages);*/
+		psb_pages_clflush(pd->driver, &pd->p, num_pages);
+		return;
+	}
+
+	if (hw_tile_stride)
+		rows = num_pages / desired_tile_stride;
+	else
+		desired_tile_stride = num_pages;
+
+	add = desired_tile_stride << PAGE_SHIFT;
+	row_add = hw_tile_stride << PAGE_SHIFT;
+	mb();
+	for (i = 0; i < rows; ++i) {
+
+		addr = address;
+		end = addr + add;
+
+		do {
+			next = psb_pd_addr_end(addr, end);
+			pt = psb_mmu_pt_map_lock(pd, addr);
+			if (!pt)
+				continue;
+			do {
+				psb_clflush(&pt->v
+					    [psb_mmu_pt_index(addr)]);
+			} while (addr +=
+				 clflush_add,
+				 (addr & clflush_mask) < next);
+
+			psb_mmu_pt_unmap_unlock(pt);
+		} while (addr = next, next != end);
+		address += row_add;
+	}
+	mb();
+}
+
+void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+				 unsigned long address, uint32_t num_pages)
+{
+	struct psb_mmu_pt *pt;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long f_address = address;
+
+	down_read(&pd->driver->sem);
+
+	addr = address;
+	end = addr + (num_pages << PAGE_SHIFT);
+
+	do {
+		next = psb_pd_addr_end(addr, end);
+		pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+		if (!pt)
+			goto out;
+		do {
+			psb_mmu_invalidate_pte(pt, addr);
+			--pt->count;
+		} while (addr += PAGE_SIZE, addr < next);
+		psb_mmu_pt_unmap_unlock(pt);
+
+	} while (addr = next, next != end);
+
+out:
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
+
+	up_read(&pd->driver->sem);
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 0);
+
+	return;
+}
+
+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)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t rows = 1;
+	uint32_t i;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long add;
+	unsigned long row_add;
+	unsigned long f_address = address;
+
+	if (hw_tile_stride)
+		rows = num_pages / desired_tile_stride;
+	else
+		desired_tile_stride = num_pages;
+
+	add = desired_tile_stride << PAGE_SHIFT;
+	row_add = hw_tile_stride << PAGE_SHIFT;
+
+	/* down_read(&pd->driver->sem); */
+
+	/* Make sure we only need to flush this processor's cache */
+
+	for (i = 0; i < rows; ++i) {
+
+		addr = address;
+		end = addr + add;
+
+		do {
+			next = psb_pd_addr_end(addr, end);
+			pt = psb_mmu_pt_map_lock(pd, addr);
+			if (!pt)
+				continue;
+			do {
+				psb_mmu_invalidate_pte(pt, addr);
+				--pt->count;
+
+			} while (addr += PAGE_SIZE, addr < next);
+			psb_mmu_pt_unmap_unlock(pt);
+
+		} while (addr = next, next != end);
+		address += row_add;
+	}
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages,
+				   desired_tile_stride, hw_tile_stride);
+
+	/* up_read(&pd->driver->sem); */
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 0);
+}
+
+int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
+				unsigned long address, uint32_t num_pages,
+				int type)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t pte;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long f_address = address;
+	int ret = 0;
+
+	down_read(&pd->driver->sem);
+
+	addr = address;
+	end = addr + (num_pages << PAGE_SHIFT);
+
+	do {
+		next = psb_pd_addr_end(addr, end);
+		pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+		if (!pt) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		do {
+			pte = psb_mmu_mask_pte(start_pfn++, type);
+			psb_mmu_set_pte(pt, addr, pte);
+			pt->count++;
+		} while (addr += PAGE_SIZE, addr < next);
+		psb_mmu_pt_unmap_unlock(pt);
+
+	} while (addr = next, next != end);
+
+out:
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
+
+	up_read(&pd->driver->sem);
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 1);
+
+	return ret;
+}
+
+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)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t rows = 1;
+	uint32_t i;
+	uint32_t pte;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long add;
+	unsigned long row_add;
+	unsigned long f_address = address;
+	int ret = 0;
+
+	if (hw_tile_stride) {
+		if (num_pages % desired_tile_stride != 0)
+			return -EINVAL;
+		rows = num_pages / desired_tile_stride;
+	} else {
+		desired_tile_stride = num_pages;
+	}
+
+	add = desired_tile_stride << PAGE_SHIFT;
+	row_add = hw_tile_stride << PAGE_SHIFT;
+
+	down_read(&pd->driver->sem);
+
+	for (i = 0; i < rows; ++i) {
+
+		addr = address;
+		end = addr + add;
+
+		do {
+			next = psb_pd_addr_end(addr, end);
+			pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+			if (!pt) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			do {
+				pte =
+				    psb_mmu_mask_pte(page_to_pfn(*pages++),
+						     type);
+				psb_mmu_set_pte(pt, addr, pte);
+				pt->count++;
+			} while (addr += PAGE_SIZE, addr < next);
+			psb_mmu_pt_unmap_unlock(pt);
+
+		} while (addr = next, next != end);
+
+		address += row_add;
+	}
+out:
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages,
+				   desired_tile_stride, hw_tile_stride);
+
+	up_read(&pd->driver->sem);
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 1);
+
+	return ret;
+}
+
+int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
+			   unsigned long *pfn)
+{
+	int ret;
+	struct psb_mmu_pt *pt;
+	uint32_t tmp;
+	spinlock_t *lock = &pd->driver->lock;
+
+	down_read(&pd->driver->sem);
+	pt = psb_mmu_pt_map_lock(pd, virtual);
+	if (!pt) {
+		uint32_t *v;
+
+		spin_lock(lock);
+		v = kmap_atomic(pd->p, KM_USER0);
+		tmp = v[psb_mmu_pd_index(virtual)];
+		kunmap_atomic(v, KM_USER0);
+		spin_unlock(lock);
+
+		if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
+		    !(pd->invalid_pte & PSB_PTE_VALID)) {
+			ret = -EINVAL;
+			goto out;
+		}
+		ret = 0;
+		*pfn = pd->invalid_pte >> PAGE_SHIFT;
+		goto out;
+	}
+	tmp = pt->v[psb_mmu_pt_index(virtual)];
+	if (!(tmp & PSB_PTE_VALID)) {
+		ret = -EINVAL;
+	} else {
+		ret = 0;
+		*pfn = tmp >> PAGE_SHIFT;
+	}
+	psb_mmu_pt_unmap_unlock(pt);
+out:
+	up_read(&pd->driver->sem);
+	return ret;
+}
diff --git a/drivers/staging/gma500/psb_mmu.c b/drivers/staging/gma500/psb_mmu.c
deleted file mode 100644
index c904d73..0000000
--- a/drivers/staging/gma500/psb_mmu.c
+++ /dev/null
@@ -1,858 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007, Intel Corporation.
- *
- * 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 "psb_drv.h"
-#include "psb_reg.h"
-
-/*
- * Code for the SGX MMU:
- */
-
-/*
- * clflush on one processor only:
- * clflush should apparently flush the cache line on all processors in an
- * SMP system.
- */
-
-/*
- * kmap atomic:
- * The usage of the slots must be completely encapsulated within a spinlock, and
- * no other functions that may be using the locks for other purposed may be
- * called from within the locked region.
- * Since the slots are per processor, this will guarantee that we are the only
- * user.
- */
-
-/*
- * TODO: Inserting ptes from an interrupt handler:
- * This may be desirable for some SGX functionality where the GPU can fault in
- * needed pages. For that, we need to make an atomic insert_pages function, that
- * may fail.
- * If it fails, the caller need to insert the page using a workqueue function,
- * but on average it should be fast.
- */
-
-struct psb_mmu_driver {
-	/* protects driver- and pd structures. Always take in read mode
-	 * before taking the page table spinlock.
-	 */
-	struct rw_semaphore sem;
-
-	/* protects page tables, directory tables and pt tables.
-	 * and pt structures.
-	 */
-	spinlock_t lock;
-
-	atomic_t needs_tlbflush;
-
-	uint8_t __iomem *register_map;
-	struct psb_mmu_pd *default_pd;
-	/*uint32_t bif_ctrl;*/
-	int has_clflush;
-	int clflush_add;
-	unsigned long clflush_mask;
-
-	struct drm_psb_private *dev_priv;
-};
-
-struct psb_mmu_pd;
-
-struct psb_mmu_pt {
-	struct psb_mmu_pd *pd;
-	uint32_t index;
-	uint32_t count;
-	struct page *p;
-	uint32_t *v;
-};
-
-struct psb_mmu_pd {
-	struct psb_mmu_driver *driver;
-	int hw_context;
-	struct psb_mmu_pt **tables;
-	struct page *p;
-	struct page *dummy_pt;
-	struct page *dummy_page;
-	uint32_t pd_mask;
-	uint32_t invalid_pde;
-	uint32_t invalid_pte;
-};
-
-static inline uint32_t psb_mmu_pt_index(uint32_t offset)
-{
-	return (offset >> PSB_PTE_SHIFT) & 0x3FF;
-}
-
-static inline uint32_t psb_mmu_pd_index(uint32_t offset)
-{
-	return offset >> PSB_PDE_SHIFT;
-}
-
-static inline void psb_clflush(void *addr)
-{
-	__asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
-}
-
-static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
-				   void *addr)
-{
-	if (!driver->has_clflush)
-		return;
-
-	mb();
-	psb_clflush(addr);
-	mb();
-}
-
-static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
-{
-	uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
-	uint32_t clflush_count = PAGE_SIZE / clflush_add;
-	int i;
-	uint8_t *clf;
-
-	clf = kmap_atomic(page, KM_USER0);
-	mb();
-	for (i = 0; i < clflush_count; ++i) {
-		psb_clflush(clf);
-		clf += clflush_add;
-	}
-	mb();
-	kunmap_atomic(clf, KM_USER0);
-}
-
-static void psb_pages_clflush(struct psb_mmu_driver *driver,
-				struct page *page[], unsigned long num_pages)
-{
-	int i;
-
-	if (!driver->has_clflush)
-		return ;
-
-	for (i = 0; i < num_pages; i++)
-		psb_page_clflush(driver, *page++);
-}
-
-static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
-				    int force)
-{
-	atomic_set(&driver->needs_tlbflush, 0);
-}
-
-static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
-{
-	down_write(&driver->sem);
-	psb_mmu_flush_pd_locked(driver, force);
-	up_write(&driver->sem);
-}
-
-void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
-{
-	if (rc_prot)
-		down_write(&driver->sem);
-	if (rc_prot)
-		up_write(&driver->sem);
-}
-
-void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
-{
-	/*ttm_tt_cache_flush(&pd->p, 1);*/
-	psb_pages_clflush(pd->driver, &pd->p, 1);
-	down_write(&pd->driver->sem);
-	wmb();
-	psb_mmu_flush_pd_locked(pd->driver, 1);
-	pd->hw_context = hw_context;
-	up_write(&pd->driver->sem);
-
-}
-
-static inline unsigned long psb_pd_addr_end(unsigned long addr,
-					    unsigned long end)
-{
-
-	addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
-	return (addr < end) ? addr : end;
-}
-
-static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type)
-{
-	uint32_t mask = PSB_PTE_VALID;
-
-	if (type & PSB_MMU_CACHED_MEMORY)
-		mask |= PSB_PTE_CACHED;
-	if (type & PSB_MMU_RO_MEMORY)
-		mask |= PSB_PTE_RO;
-	if (type & PSB_MMU_WO_MEMORY)
-		mask |= PSB_PTE_WO;
-
-	return (pfn << PAGE_SHIFT) | mask;
-}
-
-struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
-				    int trap_pagefaults, int invalid_type)
-{
-	struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL);
-	uint32_t *v;
-	int i;
-
-	if (!pd)
-		return NULL;
-
-	pd->p = alloc_page(GFP_DMA32);
-	if (!pd->p)
-		goto out_err1;
-	pd->dummy_pt = alloc_page(GFP_DMA32);
-	if (!pd->dummy_pt)
-		goto out_err2;
-	pd->dummy_page = alloc_page(GFP_DMA32);
-	if (!pd->dummy_page)
-		goto out_err3;
-
-	if (!trap_pagefaults) {
-		pd->invalid_pde =
-		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
-				     invalid_type);
-		pd->invalid_pte =
-		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
-				     invalid_type);
-	} else {
-		pd->invalid_pde = 0;
-		pd->invalid_pte = 0;
-	}
-
-	v = kmap(pd->dummy_pt);
-	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
-		v[i] = pd->invalid_pte;
-
-	kunmap(pd->dummy_pt);
-
-	v = kmap(pd->p);
-	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
-		v[i] = pd->invalid_pde;
-
-	kunmap(pd->p);
-
-	clear_page(kmap(pd->dummy_page));
-	kunmap(pd->dummy_page);
-
-	pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024);
-	if (!pd->tables)
-		goto out_err4;
-
-	pd->hw_context = -1;
-	pd->pd_mask = PSB_PTE_VALID;
-	pd->driver = driver;
-
-	return pd;
-
-out_err4:
-	__free_page(pd->dummy_page);
-out_err3:
-	__free_page(pd->dummy_pt);
-out_err2:
-	__free_page(pd->p);
-out_err1:
-	kfree(pd);
-	return NULL;
-}
-
-void psb_mmu_free_pt(struct psb_mmu_pt *pt)
-{
-	__free_page(pt->p);
-	kfree(pt);
-}
-
-void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
-{
-	struct psb_mmu_driver *driver = pd->driver;
-	struct psb_mmu_pt *pt;
-	int i;
-
-	down_write(&driver->sem);
-	if (pd->hw_context != -1)
-		psb_mmu_flush_pd_locked(driver, 1);
-
-	/* Should take the spinlock here, but we don't need to do that
-	   since we have the semaphore in write mode. */
-
-	for (i = 0; i < 1024; ++i) {
-		pt = pd->tables[i];
-		if (pt)
-			psb_mmu_free_pt(pt);
-	}
-
-	vfree(pd->tables);
-	__free_page(pd->dummy_page);
-	__free_page(pd->dummy_pt);
-	__free_page(pd->p);
-	kfree(pd);
-	up_write(&driver->sem);
-}
-
-static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
-{
-	struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL);
-	void *v;
-	uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT;
-	uint32_t clflush_count = PAGE_SIZE / clflush_add;
-	spinlock_t *lock = &pd->driver->lock;
-	uint8_t *clf;
-	uint32_t *ptes;
-	int i;
-
-	if (!pt)
-		return NULL;
-
-	pt->p = alloc_page(GFP_DMA32);
-	if (!pt->p) {
-		kfree(pt);
-		return NULL;
-	}
-
-	spin_lock(lock);
-
-	v = kmap_atomic(pt->p, KM_USER0);
-	clf = (uint8_t *) v;
-	ptes = (uint32_t *) v;
-	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
-		*ptes++ = pd->invalid_pte;
-
-
-	if (pd->driver->has_clflush && pd->hw_context != -1) {
-		mb();
-		for (i = 0; i < clflush_count; ++i) {
-			psb_clflush(clf);
-			clf += clflush_add;
-		}
-		mb();
-	}
-
-	kunmap_atomic(v, KM_USER0);
-	spin_unlock(lock);
-
-	pt->count = 0;
-	pt->pd = pd;
-	pt->index = 0;
-
-	return pt;
-}
-
-struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
-					     unsigned long addr)
-{
-	uint32_t index = psb_mmu_pd_index(addr);
-	struct psb_mmu_pt *pt;
-	uint32_t *v;
-	spinlock_t *lock = &pd->driver->lock;
-
-	spin_lock(lock);
-	pt = pd->tables[index];
-	while (!pt) {
-		spin_unlock(lock);
-		pt = psb_mmu_alloc_pt(pd);
-		if (!pt)
-			return NULL;
-		spin_lock(lock);
-
-		if (pd->tables[index]) {
-			spin_unlock(lock);
-			psb_mmu_free_pt(pt);
-			spin_lock(lock);
-			pt = pd->tables[index];
-			continue;
-		}
-
-		v = kmap_atomic(pd->p, KM_USER0);
-		pd->tables[index] = pt;
-		v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
-		pt->index = index;
-		kunmap_atomic((void *) v, KM_USER0);
-
-		if (pd->hw_context != -1) {
-			psb_mmu_clflush(pd->driver, (void *) &v[index]);
-			atomic_set(&pd->driver->needs_tlbflush, 1);
-		}
-	}
-	pt->v = kmap_atomic(pt->p, KM_USER0);
-	return pt;
-}
-
-static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd,
-					      unsigned long addr)
-{
-	uint32_t index = psb_mmu_pd_index(addr);
-	struct psb_mmu_pt *pt;
-	spinlock_t *lock = &pd->driver->lock;
-
-	spin_lock(lock);
-	pt = pd->tables[index];
-	if (!pt) {
-		spin_unlock(lock);
-		return NULL;
-	}
-	pt->v = kmap_atomic(pt->p, KM_USER0);
-	return pt;
-}
-
-static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
-{
-	struct psb_mmu_pd *pd = pt->pd;
-	uint32_t *v;
-
-	kunmap_atomic(pt->v, KM_USER0);
-	if (pt->count == 0) {
-		v = kmap_atomic(pd->p, KM_USER0);
-		v[pt->index] = pd->invalid_pde;
-		pd->tables[pt->index] = NULL;
-
-		if (pd->hw_context != -1) {
-			psb_mmu_clflush(pd->driver,
-					(void *) &v[pt->index]);
-			atomic_set(&pd->driver->needs_tlbflush, 1);
-		}
-		kunmap_atomic(pt->v, KM_USER0);
-		spin_unlock(&pd->driver->lock);
-		psb_mmu_free_pt(pt);
-		return;
-	}
-	spin_unlock(&pd->driver->lock);
-}
-
-static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
-				   unsigned long addr, uint32_t pte)
-{
-	pt->v[psb_mmu_pt_index(addr)] = pte;
-}
-
-static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
-					  unsigned long addr)
-{
-	pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
-}
-
-
-void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
-			uint32_t mmu_offset, uint32_t gtt_start,
-			uint32_t gtt_pages)
-{
-	uint32_t *v;
-	uint32_t start = psb_mmu_pd_index(mmu_offset);
-	struct psb_mmu_driver *driver = pd->driver;
-	int num_pages = gtt_pages;
-
-	down_read(&driver->sem);
-	spin_lock(&driver->lock);
-
-	v = kmap_atomic(pd->p, KM_USER0);
-	v += start;
-
-	while (gtt_pages--) {
-		*v++ = gtt_start | pd->pd_mask;
-		gtt_start += PAGE_SIZE;
-	}
-
-	/*ttm_tt_cache_flush(&pd->p, num_pages);*/
-	psb_pages_clflush(pd->driver, &pd->p, num_pages);
-	kunmap_atomic(v, KM_USER0);
-	spin_unlock(&driver->lock);
-
-	if (pd->hw_context != -1)
-		atomic_set(&pd->driver->needs_tlbflush, 1);
-
-	up_read(&pd->driver->sem);
-	psb_mmu_flush_pd(pd->driver, 0);
-}
-
-struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
-{
-	struct psb_mmu_pd *pd;
-
-	/* down_read(&driver->sem); */
-	pd = driver->default_pd;
-	/* up_read(&driver->sem); */
-
-	return pd;
-}
-
-/* Returns the physical address of the PD shared by sgx/msvdx */
-uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
-{
-	struct psb_mmu_pd *pd;
-
-	pd = psb_mmu_get_default_pd(driver);
-	return page_to_pfn(pd->p) << PAGE_SHIFT;
-}
-
-void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
-{
-	psb_mmu_free_pagedir(driver->default_pd);
-	kfree(driver);
-}
-
-struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
-					int trap_pagefaults,
-					int invalid_type,
-					struct drm_psb_private *dev_priv)
-{
-	struct psb_mmu_driver *driver;
-
-	driver = kmalloc(sizeof(*driver), GFP_KERNEL);
-
-	if (!driver)
-		return NULL;
-	driver->dev_priv = dev_priv;
-
-	driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
-					      invalid_type);
-	if (!driver->default_pd)
-		goto out_err1;
-
-	spin_lock_init(&driver->lock);
-	init_rwsem(&driver->sem);
-	down_write(&driver->sem);
-	driver->register_map = registers;
-	atomic_set(&driver->needs_tlbflush, 1);
-
-	driver->has_clflush = 0;
-
-	if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
-		uint32_t tfms, misc, cap0, cap4, clflush_size;
-
-		/*
-		 * clflush size is determined at kernel setup for x86_64
-		 *  but not for i386. We have to do it here.
-		 */
-
-		cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
-		clflush_size = ((misc >> 8) & 0xff) * 8;
-		driver->has_clflush = 1;
-		driver->clflush_add =
-		    PAGE_SIZE * clflush_size / sizeof(uint32_t);
-		driver->clflush_mask = driver->clflush_add - 1;
-		driver->clflush_mask = ~driver->clflush_mask;
-	}
-
-	up_write(&driver->sem);
-	return driver;
-
-out_err1:
-	kfree(driver);
-	return NULL;
-}
-
-static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
-			       unsigned long address, uint32_t num_pages,
-			       uint32_t desired_tile_stride,
-			       uint32_t hw_tile_stride)
-{
-	struct psb_mmu_pt *pt;
-	uint32_t rows = 1;
-	uint32_t i;
-	unsigned long addr;
-	unsigned long end;
-	unsigned long next;
-	unsigned long add;
-	unsigned long row_add;
-	unsigned long clflush_add = pd->driver->clflush_add;
-	unsigned long clflush_mask = pd->driver->clflush_mask;
-
-	if (!pd->driver->has_clflush) {
-		/*ttm_tt_cache_flush(&pd->p, num_pages);*/
-		psb_pages_clflush(pd->driver, &pd->p, num_pages);
-		return;
-	}
-
-	if (hw_tile_stride)
-		rows = num_pages / desired_tile_stride;
-	else
-		desired_tile_stride = num_pages;
-
-	add = desired_tile_stride << PAGE_SHIFT;
-	row_add = hw_tile_stride << PAGE_SHIFT;
-	mb();
-	for (i = 0; i < rows; ++i) {
-
-		addr = address;
-		end = addr + add;
-
-		do {
-			next = psb_pd_addr_end(addr, end);
-			pt = psb_mmu_pt_map_lock(pd, addr);
-			if (!pt)
-				continue;
-			do {
-				psb_clflush(&pt->v
-					    [psb_mmu_pt_index(addr)]);
-			} while (addr +=
-				 clflush_add,
-				 (addr & clflush_mask) < next);
-
-			psb_mmu_pt_unmap_unlock(pt);
-		} while (addr = next, next != end);
-		address += row_add;
-	}
-	mb();
-}
-
-void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
-				 unsigned long address, uint32_t num_pages)
-{
-	struct psb_mmu_pt *pt;
-	unsigned long addr;
-	unsigned long end;
-	unsigned long next;
-	unsigned long f_address = address;
-
-	down_read(&pd->driver->sem);
-
-	addr = address;
-	end = addr + (num_pages << PAGE_SHIFT);
-
-	do {
-		next = psb_pd_addr_end(addr, end);
-		pt = psb_mmu_pt_alloc_map_lock(pd, addr);
-		if (!pt)
-			goto out;
-		do {
-			psb_mmu_invalidate_pte(pt, addr);
-			--pt->count;
-		} while (addr += PAGE_SIZE, addr < next);
-		psb_mmu_pt_unmap_unlock(pt);
-
-	} while (addr = next, next != end);
-
-out:
-	if (pd->hw_context != -1)
-		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
-
-	up_read(&pd->driver->sem);
-
-	if (pd->hw_context != -1)
-		psb_mmu_flush(pd->driver, 0);
-
-	return;
-}
-
-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)
-{
-	struct psb_mmu_pt *pt;
-	uint32_t rows = 1;
-	uint32_t i;
-	unsigned long addr;
-	unsigned long end;
-	unsigned long next;
-	unsigned long add;
-	unsigned long row_add;
-	unsigned long f_address = address;
-
-	if (hw_tile_stride)
-		rows = num_pages / desired_tile_stride;
-	else
-		desired_tile_stride = num_pages;
-
-	add = desired_tile_stride << PAGE_SHIFT;
-	row_add = hw_tile_stride << PAGE_SHIFT;
-
-	/* down_read(&pd->driver->sem); */
-
-	/* Make sure we only need to flush this processor's cache */
-
-	for (i = 0; i < rows; ++i) {
-
-		addr = address;
-		end = addr + add;
-
-		do {
-			next = psb_pd_addr_end(addr, end);
-			pt = psb_mmu_pt_map_lock(pd, addr);
-			if (!pt)
-				continue;
-			do {
-				psb_mmu_invalidate_pte(pt, addr);
-				--pt->count;
-
-			} while (addr += PAGE_SIZE, addr < next);
-			psb_mmu_pt_unmap_unlock(pt);
-
-		} while (addr = next, next != end);
-		address += row_add;
-	}
-	if (pd->hw_context != -1)
-		psb_mmu_flush_ptes(pd, f_address, num_pages,
-				   desired_tile_stride, hw_tile_stride);
-
-	/* up_read(&pd->driver->sem); */
-
-	if (pd->hw_context != -1)
-		psb_mmu_flush(pd->driver, 0);
-}
-
-int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
-				unsigned long address, uint32_t num_pages,
-				int type)
-{
-	struct psb_mmu_pt *pt;
-	uint32_t pte;
-	unsigned long addr;
-	unsigned long end;
-	unsigned long next;
-	unsigned long f_address = address;
-	int ret = 0;
-
-	down_read(&pd->driver->sem);
-
-	addr = address;
-	end = addr + (num_pages << PAGE_SHIFT);
-
-	do {
-		next = psb_pd_addr_end(addr, end);
-		pt = psb_mmu_pt_alloc_map_lock(pd, addr);
-		if (!pt) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		do {
-			pte = psb_mmu_mask_pte(start_pfn++, type);
-			psb_mmu_set_pte(pt, addr, pte);
-			pt->count++;
-		} while (addr += PAGE_SIZE, addr < next);
-		psb_mmu_pt_unmap_unlock(pt);
-
-	} while (addr = next, next != end);
-
-out:
-	if (pd->hw_context != -1)
-		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
-
-	up_read(&pd->driver->sem);
-
-	if (pd->hw_context != -1)
-		psb_mmu_flush(pd->driver, 1);
-
-	return ret;
-}
-
-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)
-{
-	struct psb_mmu_pt *pt;
-	uint32_t rows = 1;
-	uint32_t i;
-	uint32_t pte;
-	unsigned long addr;
-	unsigned long end;
-	unsigned long next;
-	unsigned long add;
-	unsigned long row_add;
-	unsigned long f_address = address;
-	int ret = 0;
-
-	if (hw_tile_stride) {
-		if (num_pages % desired_tile_stride != 0)
-			return -EINVAL;
-		rows = num_pages / desired_tile_stride;
-	} else {
-		desired_tile_stride = num_pages;
-	}
-
-	add = desired_tile_stride << PAGE_SHIFT;
-	row_add = hw_tile_stride << PAGE_SHIFT;
-
-	down_read(&pd->driver->sem);
-
-	for (i = 0; i < rows; ++i) {
-
-		addr = address;
-		end = addr + add;
-
-		do {
-			next = psb_pd_addr_end(addr, end);
-			pt = psb_mmu_pt_alloc_map_lock(pd, addr);
-			if (!pt) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			do {
-				pte =
-				    psb_mmu_mask_pte(page_to_pfn(*pages++),
-						     type);
-				psb_mmu_set_pte(pt, addr, pte);
-				pt->count++;
-			} while (addr += PAGE_SIZE, addr < next);
-			psb_mmu_pt_unmap_unlock(pt);
-
-		} while (addr = next, next != end);
-
-		address += row_add;
-	}
-out:
-	if (pd->hw_context != -1)
-		psb_mmu_flush_ptes(pd, f_address, num_pages,
-				   desired_tile_stride, hw_tile_stride);
-
-	up_read(&pd->driver->sem);
-
-	if (pd->hw_context != -1)
-		psb_mmu_flush(pd->driver, 1);
-
-	return ret;
-}
-
-int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
-			   unsigned long *pfn)
-{
-	int ret;
-	struct psb_mmu_pt *pt;
-	uint32_t tmp;
-	spinlock_t *lock = &pd->driver->lock;
-
-	down_read(&pd->driver->sem);
-	pt = psb_mmu_pt_map_lock(pd, virtual);
-	if (!pt) {
-		uint32_t *v;
-
-		spin_lock(lock);
-		v = kmap_atomic(pd->p, KM_USER0);
-		tmp = v[psb_mmu_pd_index(virtual)];
-		kunmap_atomic(v, KM_USER0);
-		spin_unlock(lock);
-
-		if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
-		    !(pd->invalid_pte & PSB_PTE_VALID)) {
-			ret = -EINVAL;
-			goto out;
-		}
-		ret = 0;
-		*pfn = pd->invalid_pte >> PAGE_SHIFT;
-		goto out;
-	}
-	tmp = pt->v[psb_mmu_pt_index(virtual)];
-	if (!(tmp & PSB_PTE_VALID)) {
-		ret = -EINVAL;
-	} else {
-		ret = 0;
-		*pfn = tmp >> PAGE_SHIFT;
-	}
-	psb_mmu_pt_unmap_unlock(pt);
-out:
-	up_read(&pd->driver->sem);
-	return ret;
-}


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 40/49] gma500: move the i2c code
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (38 preceding siblings ...)
  2011-07-05 14:42 ` [PATCH 39/49] gma500: the MMU code is also generic Alan Cox
@ 2011-07-05 14:43 ` Alan Cox
  2011-07-05 14:43 ` [PATCH 41/49] gma500: tidying up the power stuff a spot Alan Cox
                   ` (9 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:43 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

This again is similar to upstream so give it a sensible name ready to look
at any merging or synchronization

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile        |    2 
 drivers/staging/gma500/intel_i2c.c     |  169 ++++++++++++++++++++++++++++++++
 drivers/staging/gma500/psb_intel_i2c.c |  169 --------------------------------
 3 files changed, 170 insertions(+), 170 deletions(-)
 create mode 100644 drivers/staging/gma500/intel_i2c.c
 delete mode 100644 drivers/staging/gma500/psb_intel_i2c.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index d4a87c0..961a60c 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -10,12 +10,12 @@ psb_gfx-y += gem_glue.o \
 	  gem.o \
 	  gtt.o \
 	  intel_bios.o \
+	  intel_i2c.o \
 	  intel_opregion.o \
 	  mmu.o \
 	  power.o \
 	  psb_drv.o \
 	  psb_intel_display.o \
-	  psb_intel_i2c.o \
 	  psb_intel_lvds.o \
 	  psb_intel_modes.o \
 	  psb_intel_sdvo.o \
diff --git a/drivers/staging/gma500/intel_i2c.c b/drivers/staging/gma500/intel_i2c.c
new file mode 100644
index 0000000..e33432d
--- /dev/null
+++ b/drivers/staging/gma500/intel_i2c.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright © 2006-2007 Intel Corporation
+ *
+ * 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:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+
+/*
+ * Intel GPIO access functions
+ */
+
+#define I2C_RISEFALL_TIME 20
+
+static int get_clock(void *data)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 val;
+
+	val = REG_READ(chan->reg);
+	return (val & GPIO_CLOCK_VAL_IN) != 0;
+}
+
+static int get_data(void *data)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 val;
+
+	val = REG_READ(chan->reg);
+	return (val & GPIO_DATA_VAL_IN) != 0;
+}
+
+static void set_clock(void *data, int state_high)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 reserved = 0, clock_bits;
+
+	/* On most chips, these bits must be preserved in software. */
+	reserved =
+		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
+					   GPIO_CLOCK_PULLUP_DISABLE);
+
+	if (state_high)
+		clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
+	else
+		clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
+		    GPIO_CLOCK_VAL_MASK;
+	REG_WRITE(chan->reg, reserved | clock_bits);
+	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */
+}
+
+static void set_data(void *data, int state_high)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 reserved = 0, data_bits;
+
+	/* On most chips, these bits must be preserved in software. */
+	reserved =
+		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
+					   GPIO_CLOCK_PULLUP_DISABLE);
+
+	if (state_high)
+		data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
+	else
+		data_bits =
+		    GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
+		    GPIO_DATA_VAL_MASK;
+
+	REG_WRITE(chan->reg, reserved | data_bits);
+	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */
+}
+
+/**
+ * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
+ * @dev: DRM device
+ * @output: driver specific output device
+ * @reg: GPIO reg to use
+ * @name: name for this bus
+ *
+ * Creates and registers a new i2c bus with the Linux i2c layer, for use
+ * in output probing and control (e.g. DDC or SDVO control functions).
+ *
+ * Possible values for @reg include:
+ *   %GPIOA
+ *   %GPIOB
+ *   %GPIOC
+ *   %GPIOD
+ *   %GPIOE
+ *   %GPIOF
+ *   %GPIOG
+ *   %GPIOH
+ * see PRM for details on how these different busses are used.
+ */
+struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
+					const u32 reg, const char *name)
+{
+	struct psb_intel_i2c_chan *chan;
+
+	chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL);
+	if (!chan)
+		goto out_free;
+
+	chan->drm_dev = dev;
+	chan->reg = reg;
+	snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
+	chan->adapter.owner = THIS_MODULE;
+	chan->adapter.algo_data = &chan->algo;
+	chan->adapter.dev.parent = &dev->pdev->dev;
+	chan->algo.setsda = set_data;
+	chan->algo.setscl = set_clock;
+	chan->algo.getsda = get_data;
+	chan->algo.getscl = get_clock;
+	chan->algo.udelay = 20;
+	chan->algo.timeout = usecs_to_jiffies(2200);
+	chan->algo.data = chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	if (i2c_bit_add_bus(&chan->adapter))
+		goto out_free;
+
+	/* JJJ:  raise SCL and SDA? */
+	set_data(chan, 1);
+	set_clock(chan, 1);
+	udelay(20);
+
+	return chan;
+
+out_free:
+	kfree(chan);
+	return NULL;
+}
+
+/**
+ * psb_intel_i2c_destroy - unregister and free i2c bus resources
+ * @output: channel to free
+ *
+ * Unregister the adapter from the i2c layer, then free the structure.
+ */
+void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan)
+{
+	if (!chan)
+		return;
+
+	i2c_del_adapter(&chan->adapter);
+	kfree(chan);
+}
diff --git a/drivers/staging/gma500/psb_intel_i2c.c b/drivers/staging/gma500/psb_intel_i2c.c
deleted file mode 100644
index e33432d..0000000
--- a/drivers/staging/gma500/psb_intel_i2c.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright © 2006-2007 Intel Corporation
- *
- * 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:
- *	Eric Anholt <eric@anholt.net>
- */
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-#include "psb_drv.h"
-#include "psb_intel_reg.h"
-
-/*
- * Intel GPIO access functions
- */
-
-#define I2C_RISEFALL_TIME 20
-
-static int get_clock(void *data)
-{
-	struct psb_intel_i2c_chan *chan = data;
-	struct drm_device *dev = chan->drm_dev;
-	u32 val;
-
-	val = REG_READ(chan->reg);
-	return (val & GPIO_CLOCK_VAL_IN) != 0;
-}
-
-static int get_data(void *data)
-{
-	struct psb_intel_i2c_chan *chan = data;
-	struct drm_device *dev = chan->drm_dev;
-	u32 val;
-
-	val = REG_READ(chan->reg);
-	return (val & GPIO_DATA_VAL_IN) != 0;
-}
-
-static void set_clock(void *data, int state_high)
-{
-	struct psb_intel_i2c_chan *chan = data;
-	struct drm_device *dev = chan->drm_dev;
-	u32 reserved = 0, clock_bits;
-
-	/* On most chips, these bits must be preserved in software. */
-	reserved =
-		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
-					   GPIO_CLOCK_PULLUP_DISABLE);
-
-	if (state_high)
-		clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
-	else
-		clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
-		    GPIO_CLOCK_VAL_MASK;
-	REG_WRITE(chan->reg, reserved | clock_bits);
-	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */
-}
-
-static void set_data(void *data, int state_high)
-{
-	struct psb_intel_i2c_chan *chan = data;
-	struct drm_device *dev = chan->drm_dev;
-	u32 reserved = 0, data_bits;
-
-	/* On most chips, these bits must be preserved in software. */
-	reserved =
-		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
-					   GPIO_CLOCK_PULLUP_DISABLE);
-
-	if (state_high)
-		data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
-	else
-		data_bits =
-		    GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
-		    GPIO_DATA_VAL_MASK;
-
-	REG_WRITE(chan->reg, reserved | data_bits);
-	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */
-}
-
-/**
- * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
- * @dev: DRM device
- * @output: driver specific output device
- * @reg: GPIO reg to use
- * @name: name for this bus
- *
- * Creates and registers a new i2c bus with the Linux i2c layer, for use
- * in output probing and control (e.g. DDC or SDVO control functions).
- *
- * Possible values for @reg include:
- *   %GPIOA
- *   %GPIOB
- *   %GPIOC
- *   %GPIOD
- *   %GPIOE
- *   %GPIOF
- *   %GPIOG
- *   %GPIOH
- * see PRM for details on how these different busses are used.
- */
-struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
-					const u32 reg, const char *name)
-{
-	struct psb_intel_i2c_chan *chan;
-
-	chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL);
-	if (!chan)
-		goto out_free;
-
-	chan->drm_dev = dev;
-	chan->reg = reg;
-	snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
-	chan->adapter.owner = THIS_MODULE;
-	chan->adapter.algo_data = &chan->algo;
-	chan->adapter.dev.parent = &dev->pdev->dev;
-	chan->algo.setsda = set_data;
-	chan->algo.setscl = set_clock;
-	chan->algo.getsda = get_data;
-	chan->algo.getscl = get_clock;
-	chan->algo.udelay = 20;
-	chan->algo.timeout = usecs_to_jiffies(2200);
-	chan->algo.data = chan;
-
-	i2c_set_adapdata(&chan->adapter, chan);
-
-	if (i2c_bit_add_bus(&chan->adapter))
-		goto out_free;
-
-	/* JJJ:  raise SCL and SDA? */
-	set_data(chan, 1);
-	set_clock(chan, 1);
-	udelay(20);
-
-	return chan;
-
-out_free:
-	kfree(chan);
-	return NULL;
-}
-
-/**
- * psb_intel_i2c_destroy - unregister and free i2c bus resources
- * @output: channel to free
- *
- * Unregister the adapter from the i2c layer, then free the structure.
- */
-void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan)
-{
-	if (!chan)
-		return;
-
-	i2c_del_adapter(&chan->adapter);
-	kfree(chan);
-}


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 41/49] gma500: tidying up the power stuff a spot
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (39 preceding siblings ...)
  2011-07-05 14:43 ` [PATCH 40/49] gma500: move the i2c code Alan Cox
@ 2011-07-05 14:43 ` Alan Cox
  2011-07-05 14:43 ` [PATCH 42/49] gma500: move the BIOS header Alan Cox
                   ` (8 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:43 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

In particular don't destroy static mutexes, it upsets things

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/power.c |   33 +++++++++++++--------------------
 1 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
index fc2324e..0eee7fb 100644
--- a/drivers/staging/gma500/power.c
+++ b/drivers/staging/gma500/power.c
@@ -27,6 +27,7 @@
  * Massively reworked
  *    Alan Cox <alan@linux.intel.com>
  */
+
 #include "psb_powermgmt.h"
 #include "psb_drv.h"
 #include "psb_reg.h"
@@ -34,7 +35,8 @@
 #include <linux/mutex.h>
 #include <linux/pm_runtime.h>
 
-static struct mutex power_mutex;
+static struct mutex power_mutex;	/* Serialize power ops */
+static struct mutex power_ctrl_mutex;	/* Serialize power claim */
 
 /**
  *	gma_power_init		-	initialise power manager
@@ -46,8 +48,7 @@ void gma_power_init(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
 
-	/* FIXME: need to sort out fetching apm_reg for both platforms ?? */
-
+	/* FIXME: Move APM/OSPM base into relevant device code */
 	dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
 	dev_priv->ospm_base &= 0xffff;
 
@@ -55,6 +56,7 @@ void gma_power_init(struct drm_device *dev)
 	dev_priv->display_count = 0;	/* Currently no users */
 	dev_priv->suspended = false;	/* And not suspended */
 	mutex_init(&power_mutex);
+	mutex_init(&power_ctrl_mutex);
 
 	dev_priv->ops->init_pm(dev);
 }
@@ -67,23 +69,15 @@ void gma_power_init(struct drm_device *dev)
  */
 void gma_power_uninit(struct drm_device *dev)
 {
-	mutex_destroy(&power_mutex);
 	pm_runtime_disable(&dev->pdev->dev);
 	pm_runtime_set_suspended(&dev->pdev->dev);
 }
 
-
-
-
 /**
  *	gma_suspend_display	-	suspend the display logic
  *	@dev: our DRM device
  *
  *	Suspend the display logic of the graphics interface
- *
- *	FIXME: This ought to be replaced by a dev_priv-> ops interface
- *	where the various platforms register their save/restore methods
- *	and keep them in their own support files.
  */
 static void gma_suspend_display(struct drm_device *dev)
 {
@@ -210,7 +204,6 @@ int gma_power_suspend(struct pci_dev *pdev, pm_message_t state)
 	return 0;
 }
 
-
 /**
  *	gma_power_resume		-	resume power
  *	@pdev: PCI device
@@ -230,8 +223,6 @@ int gma_power_resume(struct pci_dev *pdev)
 	return 0;
 }
 
-
-
 /**
  *	gma_power_is_on		-	returne true if power is on
  *	@dev: our DRM device
@@ -244,7 +235,6 @@ bool gma_power_is_on(struct drm_device *dev)
 	return dev_priv->display_power;
 }
 
-
 /**
  *	gma_power_begin		-	begin requiring power
  *	@dev: our DRM device
@@ -252,22 +242,22 @@ bool gma_power_is_on(struct drm_device *dev)
  *
  *	Begin an action that requires the display power island is enabled.
  *	We refcount the islands.
- *
- *	FIXME: locking
  */
 bool gma_power_begin(struct drm_device *dev, bool force_on)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	int ret;
 
+	mutex_lock(&power_ctrl_mutex);
 	/* Power already on ? */
 	if (dev_priv->display_power) {
 		dev_priv->display_count++;
 		pm_runtime_get(&dev->pdev->dev);
+		mutex_unlock(&power_ctrl_mutex);
 		return true;
 	}
 	if (force_on == false)
-		return false;
+		goto out_false;
 
 	/* Ok power up needed */
 	ret = gma_resume_pci(dev->pdev);
@@ -276,12 +266,14 @@ bool gma_power_begin(struct drm_device *dev, bool force_on)
 		psb_irq_postinstall(dev);
 		pm_runtime_get(&dev->pdev->dev);
 		dev_priv->display_count++;
+		mutex_unlock(&power_ctrl_mutex);
 		return true;
 	}
+out_false:
+	mutex_unlock(&power_ctrl_mutex);
 	return false;
 }
 
-
 /**
  *	gma_power_end		-	end use of power
  *	@dev: Our DRM device
@@ -292,8 +284,10 @@ bool gma_power_begin(struct drm_device *dev, bool force_on)
 void gma_power_end(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
+	mutex_lock(&power_ctrl_mutex);
 	dev_priv->display_count--;
 	WARN_ON(dev_priv->display_count < 0);
+	mutex_unlock(&power_ctrl_mutex);
 	pm_runtime_put(&dev->pdev->dev);
 }
 
@@ -317,4 +311,3 @@ int psb_runtime_idle(struct device *dev)
 	else
 		return 1;
 }
-


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 42/49] gma500: move the BIOS header
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (40 preceding siblings ...)
  2011-07-05 14:43 ` [PATCH 41/49] gma500: tidying up the power stuff a spot Alan Cox
@ 2011-07-05 14:43 ` Alan Cox
  2011-07-05 14:43 ` [PATCH 43/49] gma500: move the power header Alan Cox
                   ` (7 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:43 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We can move this to patch up as well. Shuffle the relevant includes as we
go

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/backlight.c      |    2 
 drivers/staging/gma500/cdv_device.c     |    2 
 drivers/staging/gma500/intel_bios.c     |    2 
 drivers/staging/gma500/intel_bios.h     |  430 +++++++++++++++++++++++++++++++
 drivers/staging/gma500/mrst_lvds.c      |    2 
 drivers/staging/gma500/psb_device.c     |    2 
 drivers/staging/gma500/psb_drv.c        |    2 
 drivers/staging/gma500/psb_intel_bios.h |  430 -------------------------------
 drivers/staging/gma500/psb_intel_lvds.c |    4 
 9 files changed, 437 insertions(+), 439 deletions(-)
 create mode 100644 drivers/staging/gma500/intel_bios.h
 delete mode 100644 drivers/staging/gma500/psb_intel_bios.h

diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c
index 47681c9..117649b 100644
--- a/drivers/staging/gma500/backlight.c
+++ b/drivers/staging/gma500/backlight.c
@@ -23,7 +23,7 @@
 #include "psb_drv.h"
 #include "psb_intel_reg.h"
 #include "psb_intel_drv.h"
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
 #include "psb_powermgmt.h"
 
 int gma_backlight_init(struct drm_device *dev)
diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c
index 5131106..530e8a2 100644
--- a/drivers/staging/gma500/cdv_device.c
+++ b/drivers/staging/gma500/cdv_device.c
@@ -24,7 +24,7 @@
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
 
 
 static int cdv_output_init(struct drm_device *dev)
diff --git a/drivers/staging/gma500/intel_bios.c b/drivers/staging/gma500/intel_bios.c
index 5b3e88c..1c4714d 100644
--- a/drivers/staging/gma500/intel_bios.c
+++ b/drivers/staging/gma500/intel_bios.c
@@ -24,7 +24,7 @@
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
 
 
 static void *find_section(struct bdb_header *bdb, int section_id)
diff --git a/drivers/staging/gma500/intel_bios.h b/drivers/staging/gma500/intel_bios.h
new file mode 100644
index 0000000..70f1bf0
--- /dev/null
+++ b/drivers/staging/gma500/intel_bios.h
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 2006 Intel Corporation
+ *
+ * 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:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _I830_BIOS_H_
+#define _I830_BIOS_H_
+
+#include <drm/drmP.h>
+
+struct vbt_header {
+	u8 signature[20];		/**< Always starts with 'VBT$' */
+	u16 version;			/**< decimal */
+	u16 header_size;		/**< in bytes */
+	u16 vbt_size;			/**< in bytes */
+	u8 vbt_checksum;
+	u8 reserved0;
+	u32 bdb_offset;			/**< from beginning of VBT */
+	u32 aim_offset[4];		/**< from beginning of VBT */
+} __attribute__((packed));
+
+
+struct bdb_header {
+	u8 signature[16];		/**< Always 'BIOS_DATA_BLOCK' */
+	u16 version;			/**< decimal */
+	u16 header_size;		/**< in bytes */
+	u16 bdb_size;			/**< in bytes */
+};
+
+/* strictly speaking, this is a "skip" block, but it has interesting info */
+struct vbios_data {
+	u8 type; /* 0 == desktop, 1 == mobile */
+	u8 relstage;
+	u8 chipset;
+	u8 lvds_present:1;
+	u8 tv_present:1;
+	u8 rsvd2:6; /* finish byte */
+	u8 rsvd3[4];
+	u8 signon[155];
+	u8 copyright[61];
+	u16 code_segment;
+	u8 dos_boot_mode;
+	u8 bandwidth_percent;
+	u8 rsvd4; /* popup memory size */
+	u8 resize_pci_bios;
+	u8 rsvd5; /* is crt already on ddc2 */
+} __attribute__((packed));
+
+/*
+ * There are several types of BIOS data blocks (BDBs), each block has
+ * an ID and size in the first 3 bytes (ID in first, size in next 2).
+ * Known types are listed below.
+ */
+#define BDB_GENERAL_FEATURES	  1
+#define BDB_GENERAL_DEFINITIONS	  2
+#define BDB_OLD_TOGGLE_LIST	  3
+#define BDB_MODE_SUPPORT_LIST	  4
+#define BDB_GENERIC_MODE_TABLE	  5
+#define BDB_EXT_MMIO_REGS	  6
+#define BDB_SWF_IO		  7
+#define BDB_SWF_MMIO		  8
+#define BDB_DOT_CLOCK_TABLE	  9
+#define BDB_MODE_REMOVAL_TABLE	 10
+#define BDB_CHILD_DEVICE_TABLE	 11
+#define BDB_DRIVER_FEATURES	 12
+#define BDB_DRIVER_PERSISTENCE	 13
+#define BDB_EXT_TABLE_PTRS	 14
+#define BDB_DOT_CLOCK_OVERRIDE	 15
+#define BDB_DISPLAY_SELECT	 16
+/* 17 rsvd */
+#define BDB_DRIVER_ROTATION	 18
+#define BDB_DISPLAY_REMOVE	 19
+#define BDB_OEM_CUSTOM		 20
+#define BDB_EFP_LIST		 21 /* workarounds for VGA hsync/vsync */
+#define BDB_SDVO_LVDS_OPTIONS	 22
+#define BDB_SDVO_PANEL_DTDS	 23
+#define BDB_SDVO_LVDS_PNP_IDS	 24
+#define BDB_SDVO_LVDS_POWER_SEQ	 25
+#define BDB_TV_OPTIONS		 26
+#define BDB_LVDS_OPTIONS	 40
+#define BDB_LVDS_LFP_DATA_PTRS	 41
+#define BDB_LVDS_LFP_DATA	 42
+#define BDB_LVDS_BACKLIGHT	 43
+#define BDB_LVDS_POWER		 44
+#define BDB_SKIP		254 /* VBIOS private block, ignore */
+
+struct bdb_general_features {
+	/* bits 1 */
+	u8 panel_fitting:2;
+	u8 flexaim:1;
+	u8 msg_enable:1;
+	u8 clear_screen:3;
+	u8 color_flip:1;
+
+	/* bits 2 */
+	u8 download_ext_vbt:1;
+	u8 enable_ssc:1;
+	u8 ssc_freq:1;
+	u8 enable_lfp_on_override:1;
+	u8 disable_ssc_ddt:1;
+	u8 rsvd8:3; /* finish byte */
+
+	/* bits 3 */
+	u8 disable_smooth_vision:1;
+	u8 single_dvi:1;
+	u8 rsvd9:6; /* finish byte */
+
+	/* bits 4 */
+	u8 legacy_monitor_detect;
+
+	/* bits 5 */
+	u8 int_crt_support:1;
+	u8 int_tv_support:1;
+	u8 rsvd11:6; /* finish byte */
+} __attribute__((packed));
+
+struct bdb_general_definitions {
+	/* DDC GPIO */
+	u8 crt_ddc_gmbus_pin;
+
+	/* DPMS bits */
+	u8 dpms_acpi:1;
+	u8 skip_boot_crt_detect:1;
+	u8 dpms_aim:1;
+	u8 rsvd1:5; /* finish byte */
+
+	/* boot device bits */
+	u8 boot_display[2];
+	u8 child_dev_size;
+
+	/* device info */
+	u8 tv_or_lvds_info[33];
+	u8 dev1[33];
+	u8 dev2[33];
+	u8 dev3[33];
+	u8 dev4[33];
+	/* may be another device block here on some platforms */
+};
+
+struct bdb_lvds_options {
+	u8 panel_type;
+	u8 rsvd1;
+	/* LVDS capabilities, stored in a dword */
+	u8 pfit_mode:2;
+	u8 pfit_text_mode_enhanced:1;
+	u8 pfit_gfx_mode_enhanced:1;
+	u8 pfit_ratio_auto:1;
+	u8 pixel_dither:1;
+	u8 lvds_edid:1;
+	u8 rsvd2:1;
+	u8 rsvd4;
+} __attribute__((packed));
+
+struct bdb_lvds_backlight {
+	u8 type:2;
+	u8 pol:1;
+	u8 gpio:3;
+	u8 gmbus:2;
+	u16 freq;
+	u8 minbrightness;
+	u8 i2caddr;
+	u8 brightnesscmd;
+	/*FIXME: more...*/
+} __attribute__((packed));
+
+/* LFP pointer table contains entries to the struct below */
+struct bdb_lvds_lfp_data_ptr {
+	u16 fp_timing_offset; /* offsets are from start of bdb */
+	u8 fp_table_size;
+	u16 dvo_timing_offset;
+	u8 dvo_table_size;
+	u16 panel_pnp_id_offset;
+	u8 pnp_table_size;
+} __attribute__((packed));
+
+struct bdb_lvds_lfp_data_ptrs {
+	u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
+	struct bdb_lvds_lfp_data_ptr ptr[16];
+} __attribute__((packed));
+
+/* LFP data has 3 blocks per entry */
+struct lvds_fp_timing {
+	u16 x_res;
+	u16 y_res;
+	u32 lvds_reg;
+	u32 lvds_reg_val;
+	u32 pp_on_reg;
+	u32 pp_on_reg_val;
+	u32 pp_off_reg;
+	u32 pp_off_reg_val;
+	u32 pp_cycle_reg;
+	u32 pp_cycle_reg_val;
+	u32 pfit_reg;
+	u32 pfit_reg_val;
+	u16 terminator;
+} __attribute__((packed));
+
+struct lvds_dvo_timing {
+	u16 clock;		/**< In 10khz */
+	u8 hactive_lo;
+	u8 hblank_lo;
+	u8 hblank_hi:4;
+	u8 hactive_hi:4;
+	u8 vactive_lo;
+	u8 vblank_lo;
+	u8 vblank_hi:4;
+	u8 vactive_hi:4;
+	u8 hsync_off_lo;
+	u8 hsync_pulse_width;
+	u8 vsync_pulse_width:4;
+	u8 vsync_off:4;
+	u8 rsvd0:6;
+	u8 hsync_off_hi:2;
+	u8 h_image;
+	u8 v_image;
+	u8 max_hv;
+	u8 h_border;
+	u8 v_border;
+	u8 rsvd1:3;
+	u8 digital:2;
+	u8 vsync_positive:1;
+	u8 hsync_positive:1;
+	u8 rsvd2:1;
+} __attribute__((packed));
+
+struct lvds_pnp_id {
+	u16 mfg_name;
+	u16 product_code;
+	u32 serial;
+	u8 mfg_week;
+	u8 mfg_year;
+} __attribute__((packed));
+
+struct bdb_lvds_lfp_data_entry {
+	struct lvds_fp_timing fp_timing;
+	struct lvds_dvo_timing dvo_timing;
+	struct lvds_pnp_id pnp_id;
+} __attribute__((packed));
+
+struct bdb_lvds_lfp_data {
+	struct bdb_lvds_lfp_data_entry data[16];
+} __attribute__((packed));
+
+struct aimdb_header {
+	char signature[16];
+	char oem_device[20];
+	u16 aimdb_version;
+	u16 aimdb_header_size;
+	u16 aimdb_size;
+} __attribute__((packed));
+
+struct aimdb_block {
+	u8 aimdb_id;
+	u16 aimdb_size;
+} __attribute__((packed));
+
+struct vch_panel_data {
+	u16 fp_timing_offset;
+	u8 fp_timing_size;
+	u16 dvo_timing_offset;
+	u8 dvo_timing_size;
+	u16 text_fitting_offset;
+	u8 text_fitting_size;
+	u16 graphics_fitting_offset;
+	u8 graphics_fitting_size;
+} __attribute__((packed));
+
+struct vch_bdb_22 {
+	struct aimdb_block aimdb_block;
+	struct vch_panel_data panels[16];
+} __attribute__((packed));
+
+struct bdb_sdvo_lvds_options {
+	u8 panel_backlight;
+	u8 h40_set_panel_type;
+	u8 panel_type;
+	u8 ssc_clk_freq;
+	u16 als_low_trip;
+	u16 als_high_trip;
+	u8 sclalarcoeff_tab_row_num;
+	u8 sclalarcoeff_tab_row_size;
+	u8 coefficient[8];
+	u8 panel_misc_bits_1;
+	u8 panel_misc_bits_2;
+	u8 panel_misc_bits_3;
+	u8 panel_misc_bits_4;
+} __attribute__((packed));
+
+
+extern bool psb_intel_init_bios(struct drm_device *dev);
+extern void psb_intel_destroy_bios(struct drm_device *dev);
+
+/*
+ * Driver<->VBIOS interaction occurs through scratch bits in
+ * GR18 & SWF*.
+ */
+
+/* GR18 bits are set on display switch and hotkey events */
+#define GR18_DRIVER_SWITCH_EN	(1<<7) /* 0: VBIOS control, 1: driver control */
+#define GR18_HOTKEY_MASK	0x78 /* See also SWF4 15:0 */
+#define   GR18_HK_NONE		(0x0<<3)
+#define   GR18_HK_LFP_STRETCH	(0x1<<3)
+#define   GR18_HK_TOGGLE_DISP	(0x2<<3)
+#define   GR18_HK_DISP_SWITCH	(0x4<<3) /* see SWF14 15:0 for what to enable */
+#define   GR18_HK_POPUP_DISABLED (0x6<<3)
+#define   GR18_HK_POPUP_ENABLED	(0x7<<3)
+#define   GR18_HK_PFIT		(0x8<<3)
+#define   GR18_HK_APM_CHANGE	(0xa<<3)
+#define   GR18_HK_MULTIPLE	(0xc<<3)
+#define GR18_USER_INT_EN	(1<<2)
+#define GR18_A0000_FLUSH_EN	(1<<1)
+#define GR18_SMM_EN		(1<<0)
+
+/* Set by driver, cleared by VBIOS */
+#define SWF00_YRES_SHIFT	16
+#define SWF00_XRES_SHIFT	0
+#define SWF00_RES_MASK		0xffff
+
+/* Set by VBIOS at boot time and driver at runtime */
+#define SWF01_TV2_FORMAT_SHIFT	8
+#define SWF01_TV1_FORMAT_SHIFT	0
+#define SWF01_TV_FORMAT_MASK	0xffff
+
+#define SWF10_VBIOS_BLC_I2C_EN	(1<<29)
+#define SWF10_GTT_OVERRIDE_EN	(1<<28)
+#define SWF10_LFP_DPMS_OVR	(1<<27) /* override DPMS on display switch */
+#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
+#define   SWF10_OLD_TOGGLE	0x0
+#define   SWF10_TOGGLE_LIST_1	0x1
+#define   SWF10_TOGGLE_LIST_2	0x2
+#define   SWF10_TOGGLE_LIST_3	0x3
+#define   SWF10_TOGGLE_LIST_4	0x4
+#define SWF10_PANNING_EN	(1<<23)
+#define SWF10_DRIVER_LOADED	(1<<22)
+#define SWF10_EXTENDED_DESKTOP	(1<<21)
+#define SWF10_EXCLUSIVE_MODE	(1<<20)
+#define SWF10_OVERLAY_EN	(1<<19)
+#define SWF10_PLANEB_HOLDOFF	(1<<18)
+#define SWF10_PLANEA_HOLDOFF	(1<<17)
+#define SWF10_VGA_HOLDOFF	(1<<16)
+#define SWF10_ACTIVE_DISP_MASK	0xffff
+#define   SWF10_PIPEB_LFP2	(1<<15)
+#define   SWF10_PIPEB_EFP2	(1<<14)
+#define   SWF10_PIPEB_TV2	(1<<13)
+#define   SWF10_PIPEB_CRT2	(1<<12)
+#define   SWF10_PIPEB_LFP	(1<<11)
+#define   SWF10_PIPEB_EFP	(1<<10)
+#define   SWF10_PIPEB_TV	(1<<9)
+#define   SWF10_PIPEB_CRT	(1<<8)
+#define   SWF10_PIPEA_LFP2	(1<<7)
+#define   SWF10_PIPEA_EFP2	(1<<6)
+#define   SWF10_PIPEA_TV2	(1<<5)
+#define   SWF10_PIPEA_CRT2	(1<<4)
+#define   SWF10_PIPEA_LFP	(1<<3)
+#define   SWF10_PIPEA_EFP	(1<<2)
+#define   SWF10_PIPEA_TV	(1<<1)
+#define   SWF10_PIPEA_CRT	(1<<0)
+
+#define SWF11_MEMORY_SIZE_SHIFT	16
+#define SWF11_SV_TEST_EN	(1<<15)
+#define SWF11_IS_AGP		(1<<14)
+#define SWF11_DISPLAY_HOLDOFF	(1<<13)
+#define SWF11_DPMS_REDUCED	(1<<12)
+#define SWF11_IS_VBE_MODE	(1<<11)
+#define SWF11_PIPEB_ACCESS	(1<<10) /* 0 here means pipe a */
+#define SWF11_DPMS_MASK		0x07
+#define   SWF11_DPMS_OFF	(1<<2)
+#define   SWF11_DPMS_SUSPEND	(1<<1)
+#define   SWF11_DPMS_STANDBY	(1<<0)
+#define   SWF11_DPMS_ON		0
+
+#define SWF14_GFX_PFIT_EN	(1<<31)
+#define SWF14_TEXT_PFIT_EN	(1<<30)
+#define SWF14_LID_STATUS_CLOSED	(1<<29) /* 0 here means open */
+#define SWF14_POPUP_EN		(1<<28)
+#define SWF14_DISPLAY_HOLDOFF	(1<<27)
+#define SWF14_DISP_DETECT_EN	(1<<26)
+#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
+#define SWF14_DRIVER_STATUS	(1<<24)
+#define SWF14_OS_TYPE_WIN9X	(1<<23)
+#define SWF14_OS_TYPE_WINNT	(1<<22)
+/* 21:19 rsvd */
+#define SWF14_PM_TYPE_MASK	0x00070000
+#define   SWF14_PM_ACPI_VIDEO	(0x4 << 16)
+#define   SWF14_PM_ACPI		(0x3 << 16)
+#define   SWF14_PM_APM_12	(0x2 << 16)
+#define   SWF14_PM_APM_11	(0x1 << 16)
+#define SWF14_HK_REQUEST_MASK	0x0000ffff /* see GR18 6:3 for event type */
+	  /* if GR18 indicates a display switch */
+#define   SWF14_DS_PIPEB_LFP2_EN (1<<15)
+#define   SWF14_DS_PIPEB_EFP2_EN (1<<14)
+#define   SWF14_DS_PIPEB_TV2_EN  (1<<13)
+#define   SWF14_DS_PIPEB_CRT2_EN (1<<12)
+#define   SWF14_DS_PIPEB_LFP_EN  (1<<11)
+#define   SWF14_DS_PIPEB_EFP_EN  (1<<10)
+#define   SWF14_DS_PIPEB_TV_EN	 (1<<9)
+#define   SWF14_DS_PIPEB_CRT_EN  (1<<8)
+#define   SWF14_DS_PIPEA_LFP2_EN (1<<7)
+#define   SWF14_DS_PIPEA_EFP2_EN (1<<6)
+#define   SWF14_DS_PIPEA_TV2_EN  (1<<5)
+#define   SWF14_DS_PIPEA_CRT2_EN (1<<4)
+#define   SWF14_DS_PIPEA_LFP_EN  (1<<3)
+#define   SWF14_DS_PIPEA_EFP_EN  (1<<2)
+#define   SWF14_DS_PIPEA_TV_EN	 (1<<1)
+#define   SWF14_DS_PIPEA_CRT_EN  (1<<0)
+	  /* if GR18 indicates a panel fitting request */
+#define   SWF14_PFIT_EN		(1<<0) /* 0 means disable */
+	  /* if GR18 indicates an APM change request */
+#define   SWF14_APM_HIBERNATE	0x4
+#define   SWF14_APM_SUSPEND	0x3
+#define   SWF14_APM_STANDBY	0x1
+#define   SWF14_APM_RESTORE	0x0
+
+#endif /* _I830_BIOS_H_ */
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
index a746571..9ecb99b 100644
--- a/drivers/staging/gma500/mrst_lvds.c
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -24,7 +24,7 @@
 #include <drm/drmP.h>
 #include <asm/mrst.h>
 
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c
index 8ac9de7..0774c06 100644
--- a/drivers/staging/gma500/psb_device.c
+++ b/drivers/staging/gma500/psb_device.c
@@ -24,7 +24,7 @@
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
 
 
 static int psb_output_init(struct drm_device *dev)
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index e9772ab..a7f3c08 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -26,7 +26,7 @@
 #include "framebuffer.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
 #include "mid_bios.h"
 #include "mdfld_dsi_dbi.h"
 #include <drm/drm_pciids.h>
diff --git a/drivers/staging/gma500/psb_intel_bios.h b/drivers/staging/gma500/psb_intel_bios.h
deleted file mode 100644
index 70f1bf0..0000000
--- a/drivers/staging/gma500/psb_intel_bios.h
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright (c) 2006 Intel Corporation
- *
- * 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:
- *    Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifndef _I830_BIOS_H_
-#define _I830_BIOS_H_
-
-#include <drm/drmP.h>
-
-struct vbt_header {
-	u8 signature[20];		/**< Always starts with 'VBT$' */
-	u16 version;			/**< decimal */
-	u16 header_size;		/**< in bytes */
-	u16 vbt_size;			/**< in bytes */
-	u8 vbt_checksum;
-	u8 reserved0;
-	u32 bdb_offset;			/**< from beginning of VBT */
-	u32 aim_offset[4];		/**< from beginning of VBT */
-} __attribute__((packed));
-
-
-struct bdb_header {
-	u8 signature[16];		/**< Always 'BIOS_DATA_BLOCK' */
-	u16 version;			/**< decimal */
-	u16 header_size;		/**< in bytes */
-	u16 bdb_size;			/**< in bytes */
-};
-
-/* strictly speaking, this is a "skip" block, but it has interesting info */
-struct vbios_data {
-	u8 type; /* 0 == desktop, 1 == mobile */
-	u8 relstage;
-	u8 chipset;
-	u8 lvds_present:1;
-	u8 tv_present:1;
-	u8 rsvd2:6; /* finish byte */
-	u8 rsvd3[4];
-	u8 signon[155];
-	u8 copyright[61];
-	u16 code_segment;
-	u8 dos_boot_mode;
-	u8 bandwidth_percent;
-	u8 rsvd4; /* popup memory size */
-	u8 resize_pci_bios;
-	u8 rsvd5; /* is crt already on ddc2 */
-} __attribute__((packed));
-
-/*
- * There are several types of BIOS data blocks (BDBs), each block has
- * an ID and size in the first 3 bytes (ID in first, size in next 2).
- * Known types are listed below.
- */
-#define BDB_GENERAL_FEATURES	  1
-#define BDB_GENERAL_DEFINITIONS	  2
-#define BDB_OLD_TOGGLE_LIST	  3
-#define BDB_MODE_SUPPORT_LIST	  4
-#define BDB_GENERIC_MODE_TABLE	  5
-#define BDB_EXT_MMIO_REGS	  6
-#define BDB_SWF_IO		  7
-#define BDB_SWF_MMIO		  8
-#define BDB_DOT_CLOCK_TABLE	  9
-#define BDB_MODE_REMOVAL_TABLE	 10
-#define BDB_CHILD_DEVICE_TABLE	 11
-#define BDB_DRIVER_FEATURES	 12
-#define BDB_DRIVER_PERSISTENCE	 13
-#define BDB_EXT_TABLE_PTRS	 14
-#define BDB_DOT_CLOCK_OVERRIDE	 15
-#define BDB_DISPLAY_SELECT	 16
-/* 17 rsvd */
-#define BDB_DRIVER_ROTATION	 18
-#define BDB_DISPLAY_REMOVE	 19
-#define BDB_OEM_CUSTOM		 20
-#define BDB_EFP_LIST		 21 /* workarounds for VGA hsync/vsync */
-#define BDB_SDVO_LVDS_OPTIONS	 22
-#define BDB_SDVO_PANEL_DTDS	 23
-#define BDB_SDVO_LVDS_PNP_IDS	 24
-#define BDB_SDVO_LVDS_POWER_SEQ	 25
-#define BDB_TV_OPTIONS		 26
-#define BDB_LVDS_OPTIONS	 40
-#define BDB_LVDS_LFP_DATA_PTRS	 41
-#define BDB_LVDS_LFP_DATA	 42
-#define BDB_LVDS_BACKLIGHT	 43
-#define BDB_LVDS_POWER		 44
-#define BDB_SKIP		254 /* VBIOS private block, ignore */
-
-struct bdb_general_features {
-	/* bits 1 */
-	u8 panel_fitting:2;
-	u8 flexaim:1;
-	u8 msg_enable:1;
-	u8 clear_screen:3;
-	u8 color_flip:1;
-
-	/* bits 2 */
-	u8 download_ext_vbt:1;
-	u8 enable_ssc:1;
-	u8 ssc_freq:1;
-	u8 enable_lfp_on_override:1;
-	u8 disable_ssc_ddt:1;
-	u8 rsvd8:3; /* finish byte */
-
-	/* bits 3 */
-	u8 disable_smooth_vision:1;
-	u8 single_dvi:1;
-	u8 rsvd9:6; /* finish byte */
-
-	/* bits 4 */
-	u8 legacy_monitor_detect;
-
-	/* bits 5 */
-	u8 int_crt_support:1;
-	u8 int_tv_support:1;
-	u8 rsvd11:6; /* finish byte */
-} __attribute__((packed));
-
-struct bdb_general_definitions {
-	/* DDC GPIO */
-	u8 crt_ddc_gmbus_pin;
-
-	/* DPMS bits */
-	u8 dpms_acpi:1;
-	u8 skip_boot_crt_detect:1;
-	u8 dpms_aim:1;
-	u8 rsvd1:5; /* finish byte */
-
-	/* boot device bits */
-	u8 boot_display[2];
-	u8 child_dev_size;
-
-	/* device info */
-	u8 tv_or_lvds_info[33];
-	u8 dev1[33];
-	u8 dev2[33];
-	u8 dev3[33];
-	u8 dev4[33];
-	/* may be another device block here on some platforms */
-};
-
-struct bdb_lvds_options {
-	u8 panel_type;
-	u8 rsvd1;
-	/* LVDS capabilities, stored in a dword */
-	u8 pfit_mode:2;
-	u8 pfit_text_mode_enhanced:1;
-	u8 pfit_gfx_mode_enhanced:1;
-	u8 pfit_ratio_auto:1;
-	u8 pixel_dither:1;
-	u8 lvds_edid:1;
-	u8 rsvd2:1;
-	u8 rsvd4;
-} __attribute__((packed));
-
-struct bdb_lvds_backlight {
-	u8 type:2;
-	u8 pol:1;
-	u8 gpio:3;
-	u8 gmbus:2;
-	u16 freq;
-	u8 minbrightness;
-	u8 i2caddr;
-	u8 brightnesscmd;
-	/*FIXME: more...*/
-} __attribute__((packed));
-
-/* LFP pointer table contains entries to the struct below */
-struct bdb_lvds_lfp_data_ptr {
-	u16 fp_timing_offset; /* offsets are from start of bdb */
-	u8 fp_table_size;
-	u16 dvo_timing_offset;
-	u8 dvo_table_size;
-	u16 panel_pnp_id_offset;
-	u8 pnp_table_size;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data_ptrs {
-	u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
-	struct bdb_lvds_lfp_data_ptr ptr[16];
-} __attribute__((packed));
-
-/* LFP data has 3 blocks per entry */
-struct lvds_fp_timing {
-	u16 x_res;
-	u16 y_res;
-	u32 lvds_reg;
-	u32 lvds_reg_val;
-	u32 pp_on_reg;
-	u32 pp_on_reg_val;
-	u32 pp_off_reg;
-	u32 pp_off_reg_val;
-	u32 pp_cycle_reg;
-	u32 pp_cycle_reg_val;
-	u32 pfit_reg;
-	u32 pfit_reg_val;
-	u16 terminator;
-} __attribute__((packed));
-
-struct lvds_dvo_timing {
-	u16 clock;		/**< In 10khz */
-	u8 hactive_lo;
-	u8 hblank_lo;
-	u8 hblank_hi:4;
-	u8 hactive_hi:4;
-	u8 vactive_lo;
-	u8 vblank_lo;
-	u8 vblank_hi:4;
-	u8 vactive_hi:4;
-	u8 hsync_off_lo;
-	u8 hsync_pulse_width;
-	u8 vsync_pulse_width:4;
-	u8 vsync_off:4;
-	u8 rsvd0:6;
-	u8 hsync_off_hi:2;
-	u8 h_image;
-	u8 v_image;
-	u8 max_hv;
-	u8 h_border;
-	u8 v_border;
-	u8 rsvd1:3;
-	u8 digital:2;
-	u8 vsync_positive:1;
-	u8 hsync_positive:1;
-	u8 rsvd2:1;
-} __attribute__((packed));
-
-struct lvds_pnp_id {
-	u16 mfg_name;
-	u16 product_code;
-	u32 serial;
-	u8 mfg_week;
-	u8 mfg_year;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data_entry {
-	struct lvds_fp_timing fp_timing;
-	struct lvds_dvo_timing dvo_timing;
-	struct lvds_pnp_id pnp_id;
-} __attribute__((packed));
-
-struct bdb_lvds_lfp_data {
-	struct bdb_lvds_lfp_data_entry data[16];
-} __attribute__((packed));
-
-struct aimdb_header {
-	char signature[16];
-	char oem_device[20];
-	u16 aimdb_version;
-	u16 aimdb_header_size;
-	u16 aimdb_size;
-} __attribute__((packed));
-
-struct aimdb_block {
-	u8 aimdb_id;
-	u16 aimdb_size;
-} __attribute__((packed));
-
-struct vch_panel_data {
-	u16 fp_timing_offset;
-	u8 fp_timing_size;
-	u16 dvo_timing_offset;
-	u8 dvo_timing_size;
-	u16 text_fitting_offset;
-	u8 text_fitting_size;
-	u16 graphics_fitting_offset;
-	u8 graphics_fitting_size;
-} __attribute__((packed));
-
-struct vch_bdb_22 {
-	struct aimdb_block aimdb_block;
-	struct vch_panel_data panels[16];
-} __attribute__((packed));
-
-struct bdb_sdvo_lvds_options {
-	u8 panel_backlight;
-	u8 h40_set_panel_type;
-	u8 panel_type;
-	u8 ssc_clk_freq;
-	u16 als_low_trip;
-	u16 als_high_trip;
-	u8 sclalarcoeff_tab_row_num;
-	u8 sclalarcoeff_tab_row_size;
-	u8 coefficient[8];
-	u8 panel_misc_bits_1;
-	u8 panel_misc_bits_2;
-	u8 panel_misc_bits_3;
-	u8 panel_misc_bits_4;
-} __attribute__((packed));
-
-
-extern bool psb_intel_init_bios(struct drm_device *dev);
-extern void psb_intel_destroy_bios(struct drm_device *dev);
-
-/*
- * Driver<->VBIOS interaction occurs through scratch bits in
- * GR18 & SWF*.
- */
-
-/* GR18 bits are set on display switch and hotkey events */
-#define GR18_DRIVER_SWITCH_EN	(1<<7) /* 0: VBIOS control, 1: driver control */
-#define GR18_HOTKEY_MASK	0x78 /* See also SWF4 15:0 */
-#define   GR18_HK_NONE		(0x0<<3)
-#define   GR18_HK_LFP_STRETCH	(0x1<<3)
-#define   GR18_HK_TOGGLE_DISP	(0x2<<3)
-#define   GR18_HK_DISP_SWITCH	(0x4<<3) /* see SWF14 15:0 for what to enable */
-#define   GR18_HK_POPUP_DISABLED (0x6<<3)
-#define   GR18_HK_POPUP_ENABLED	(0x7<<3)
-#define   GR18_HK_PFIT		(0x8<<3)
-#define   GR18_HK_APM_CHANGE	(0xa<<3)
-#define   GR18_HK_MULTIPLE	(0xc<<3)
-#define GR18_USER_INT_EN	(1<<2)
-#define GR18_A0000_FLUSH_EN	(1<<1)
-#define GR18_SMM_EN		(1<<0)
-
-/* Set by driver, cleared by VBIOS */
-#define SWF00_YRES_SHIFT	16
-#define SWF00_XRES_SHIFT	0
-#define SWF00_RES_MASK		0xffff
-
-/* Set by VBIOS at boot time and driver at runtime */
-#define SWF01_TV2_FORMAT_SHIFT	8
-#define SWF01_TV1_FORMAT_SHIFT	0
-#define SWF01_TV_FORMAT_MASK	0xffff
-
-#define SWF10_VBIOS_BLC_I2C_EN	(1<<29)
-#define SWF10_GTT_OVERRIDE_EN	(1<<28)
-#define SWF10_LFP_DPMS_OVR	(1<<27) /* override DPMS on display switch */
-#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
-#define   SWF10_OLD_TOGGLE	0x0
-#define   SWF10_TOGGLE_LIST_1	0x1
-#define   SWF10_TOGGLE_LIST_2	0x2
-#define   SWF10_TOGGLE_LIST_3	0x3
-#define   SWF10_TOGGLE_LIST_4	0x4
-#define SWF10_PANNING_EN	(1<<23)
-#define SWF10_DRIVER_LOADED	(1<<22)
-#define SWF10_EXTENDED_DESKTOP	(1<<21)
-#define SWF10_EXCLUSIVE_MODE	(1<<20)
-#define SWF10_OVERLAY_EN	(1<<19)
-#define SWF10_PLANEB_HOLDOFF	(1<<18)
-#define SWF10_PLANEA_HOLDOFF	(1<<17)
-#define SWF10_VGA_HOLDOFF	(1<<16)
-#define SWF10_ACTIVE_DISP_MASK	0xffff
-#define   SWF10_PIPEB_LFP2	(1<<15)
-#define   SWF10_PIPEB_EFP2	(1<<14)
-#define   SWF10_PIPEB_TV2	(1<<13)
-#define   SWF10_PIPEB_CRT2	(1<<12)
-#define   SWF10_PIPEB_LFP	(1<<11)
-#define   SWF10_PIPEB_EFP	(1<<10)
-#define   SWF10_PIPEB_TV	(1<<9)
-#define   SWF10_PIPEB_CRT	(1<<8)
-#define   SWF10_PIPEA_LFP2	(1<<7)
-#define   SWF10_PIPEA_EFP2	(1<<6)
-#define   SWF10_PIPEA_TV2	(1<<5)
-#define   SWF10_PIPEA_CRT2	(1<<4)
-#define   SWF10_PIPEA_LFP	(1<<3)
-#define   SWF10_PIPEA_EFP	(1<<2)
-#define   SWF10_PIPEA_TV	(1<<1)
-#define   SWF10_PIPEA_CRT	(1<<0)
-
-#define SWF11_MEMORY_SIZE_SHIFT	16
-#define SWF11_SV_TEST_EN	(1<<15)
-#define SWF11_IS_AGP		(1<<14)
-#define SWF11_DISPLAY_HOLDOFF	(1<<13)
-#define SWF11_DPMS_REDUCED	(1<<12)
-#define SWF11_IS_VBE_MODE	(1<<11)
-#define SWF11_PIPEB_ACCESS	(1<<10) /* 0 here means pipe a */
-#define SWF11_DPMS_MASK		0x07
-#define   SWF11_DPMS_OFF	(1<<2)
-#define   SWF11_DPMS_SUSPEND	(1<<1)
-#define   SWF11_DPMS_STANDBY	(1<<0)
-#define   SWF11_DPMS_ON		0
-
-#define SWF14_GFX_PFIT_EN	(1<<31)
-#define SWF14_TEXT_PFIT_EN	(1<<30)
-#define SWF14_LID_STATUS_CLOSED	(1<<29) /* 0 here means open */
-#define SWF14_POPUP_EN		(1<<28)
-#define SWF14_DISPLAY_HOLDOFF	(1<<27)
-#define SWF14_DISP_DETECT_EN	(1<<26)
-#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
-#define SWF14_DRIVER_STATUS	(1<<24)
-#define SWF14_OS_TYPE_WIN9X	(1<<23)
-#define SWF14_OS_TYPE_WINNT	(1<<22)
-/* 21:19 rsvd */
-#define SWF14_PM_TYPE_MASK	0x00070000
-#define   SWF14_PM_ACPI_VIDEO	(0x4 << 16)
-#define   SWF14_PM_ACPI		(0x3 << 16)
-#define   SWF14_PM_APM_12	(0x2 << 16)
-#define   SWF14_PM_APM_11	(0x1 << 16)
-#define SWF14_HK_REQUEST_MASK	0x0000ffff /* see GR18 6:3 for event type */
-	  /* if GR18 indicates a display switch */
-#define   SWF14_DS_PIPEB_LFP2_EN (1<<15)
-#define   SWF14_DS_PIPEB_EFP2_EN (1<<14)
-#define   SWF14_DS_PIPEB_TV2_EN  (1<<13)
-#define   SWF14_DS_PIPEB_CRT2_EN (1<<12)
-#define   SWF14_DS_PIPEB_LFP_EN  (1<<11)
-#define   SWF14_DS_PIPEB_EFP_EN  (1<<10)
-#define   SWF14_DS_PIPEB_TV_EN	 (1<<9)
-#define   SWF14_DS_PIPEB_CRT_EN  (1<<8)
-#define   SWF14_DS_PIPEA_LFP2_EN (1<<7)
-#define   SWF14_DS_PIPEA_EFP2_EN (1<<6)
-#define   SWF14_DS_PIPEA_TV2_EN  (1<<5)
-#define   SWF14_DS_PIPEA_CRT2_EN (1<<4)
-#define   SWF14_DS_PIPEA_LFP_EN  (1<<3)
-#define   SWF14_DS_PIPEA_EFP_EN  (1<<2)
-#define   SWF14_DS_PIPEA_TV_EN	 (1<<1)
-#define   SWF14_DS_PIPEA_CRT_EN  (1<<0)
-	  /* if GR18 indicates a panel fitting request */
-#define   SWF14_PFIT_EN		(1<<0) /* 0 means disable */
-	  /* if GR18 indicates an APM change request */
-#define   SWF14_APM_HIBERNATE	0x4
-#define   SWF14_APM_SUSPEND	0x3
-#define   SWF14_APM_STANDBY	0x1
-#define   SWF14_APM_RESTORE	0x0
-
-#endif /* _I830_BIOS_H_ */
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index 41b96d2..c9a13a4 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -21,11 +21,9 @@
  */
 
 #include <linux/i2c.h>
-/* #include <drm/drm_crtc.h> */
-/* #include <drm/drm_edid.h> */
 #include <drm/drmP.h>
 
-#include "psb_intel_bios.h"
+#include "intel_bios.h"
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 43/49] gma500: move the power header
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (41 preceding siblings ...)
  2011-07-05 14:43 ` [PATCH 42/49] gma500: move the BIOS header Alan Cox
@ 2011-07-05 14:43 ` Alan Cox
  2011-07-05 14:44 ` [PATCH 44/49] gma500: begin adding CDV specific code Alan Cox
                   ` (6 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:43 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

At this point we now have the file naming making somewhat more sense
although the dependancies are not as clean as would be ideal

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/backlight.c         |    2 -
 drivers/staging/gma500/mdfld_dsi_dbi.c     |    2 -
 drivers/staging/gma500/mdfld_dsi_dbi.h     |    2 -
 drivers/staging/gma500/mdfld_dsi_output.h  |    2 -
 drivers/staging/gma500/mrst_crtc.c         |    2 -
 drivers/staging/gma500/mrst_lvds.c         |    2 -
 drivers/staging/gma500/power.c             |    2 -
 drivers/staging/gma500/power.h             |   67 ++++++++++++++++++++++++++++
 drivers/staging/gma500/psb_drv.c           |    2 -
 drivers/staging/gma500/psb_drv.h           |    2 -
 drivers/staging/gma500/psb_intel_display.c |    2 -
 drivers/staging/gma500/psb_intel_lvds.c    |    2 -
 drivers/staging/gma500/psb_irq.c           |    2 -
 drivers/staging/gma500/psb_powermgmt.h     |   67 ----------------------------
 14 files changed, 79 insertions(+), 79 deletions(-)
 create mode 100644 drivers/staging/gma500/power.h
 delete mode 100644 drivers/staging/gma500/psb_powermgmt.h

diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c
index 117649b..4027e70 100644
--- a/drivers/staging/gma500/backlight.c
+++ b/drivers/staging/gma500/backlight.c
@@ -24,7 +24,7 @@
 #include "psb_intel_reg.h"
 #include "psb_intel_drv.h"
 #include "intel_bios.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 
 int gma_backlight_init(struct drm_device *dev)
 {
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c
index 15055c8..9d2d97d 100644
--- a/drivers/staging/gma500/mdfld_dsi_dbi.c
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.c
@@ -29,7 +29,7 @@
 #include "mdfld_dsi_dbi_dpu.h"
 #include "mdfld_dsi_pkg_sender.h"
 
-#include "psb_powermgmt.h"
+#include "power.h"
 #include <linux/pm_runtime.h>
 
 int enable_gfx_rtpm;
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.h b/drivers/staging/gma500/mdfld_dsi_dbi.h
index 5b04951..a76813e 100644
--- a/drivers/staging/gma500/mdfld_dsi_dbi.h
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.h
@@ -38,7 +38,7 @@
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 
 #include "mdfld_dsi_output.h"
 #include "mdfld_output.h"
diff --git a/drivers/staging/gma500/mdfld_dsi_output.h b/drivers/staging/gma500/mdfld_dsi_output.h
index ac25e55..0bf00ea 100644
--- a/drivers/staging/gma500/mdfld_dsi_output.h
+++ b/drivers/staging/gma500/mdfld_dsi_output.h
@@ -38,7 +38,7 @@
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 #include "mdfld_output.h"
 
 #include <asm/mrst.h>
diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c
index d12d1a6..72464dd 100644
--- a/drivers/staging/gma500/mrst_crtc.c
+++ b/drivers/staging/gma500/mrst_crtc.c
@@ -24,7 +24,7 @@
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
 #include "psb_intel_display.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 
 struct psb_intel_range_t {
 	int min, max;
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
index 9ecb99b..127b200 100644
--- a/drivers/staging/gma500/mrst_lvds.c
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -28,7 +28,7 @@
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 #include <linux/pm_runtime.h>
 
 /* The max/min PWM frequency in BPCR[31:17] - */
diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
index 0eee7fb..79eb670 100644
--- a/drivers/staging/gma500/power.c
+++ b/drivers/staging/gma500/power.c
@@ -28,7 +28,7 @@
  *    Alan Cox <alan@linux.intel.com>
  */
 
-#include "psb_powermgmt.h"
+#include "power.h"
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
diff --git a/drivers/staging/gma500/power.h b/drivers/staging/gma500/power.h
new file mode 100644
index 0000000..333b28d
--- /dev/null
+++ b/drivers/staging/gma500/power.h
@@ -0,0 +1,67 @@
+/**************************************************************************
+ * Copyright (c) 2009-2011, Intel Corporation.
+ * All Rights Reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ * Massively reworked
+ *    Alan Cox <alan@linux.intel.com>
+ */
+#ifndef _PSB_POWERMGMT_H_
+#define _PSB_POWERMGMT_H_
+
+#include <linux/pci.h>
+#include <drm/drmP.h>
+
+void gma_power_init(struct drm_device *dev);
+void gma_power_uninit(struct drm_device *dev);
+
+/*
+ * The kernel bus power management  will call these functions
+ */
+int gma_power_suspend(struct pci_dev *pdev, pm_message_t state);
+int gma_power_resume(struct pci_dev *pdev);
+
+/*
+ * These are the functions the driver should use to wrap all hw access
+ * (i.e. register reads and writes)
+ */
+bool gma_power_begin(struct drm_device *dev, bool force);
+void gma_power_end(struct drm_device *dev);
+
+/*
+ * Use this function to do an instantaneous check for if the hw is on.
+ * Only use this in cases where you know the mutex is already held such
+ * as in irq install/uninstall and you need to
+ * prevent a deadlock situation.  Otherwise use gma_power_begin().
+ */
+bool gma_power_is_on(struct drm_device *dev);
+
+/*
+ * GFX-Runtime PM callbacks
+ */
+int psb_runtime_suspend(struct device *dev);
+int psb_runtime_resume(struct device *dev);
+int psb_runtime_idle(struct device *dev);
+
+#endif /*_PSB_POWERMGMT_H_*/
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index a7f3c08..264fdf4 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -30,7 +30,7 @@
 #include "mid_bios.h"
 #include "mdfld_dsi_dbi.h"
 #include <drm/drm_pciids.h>
-#include "psb_powermgmt.h"
+#include "power.h"
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/spinlock.h>
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index ee782fa..9e4f361 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -30,7 +30,7 @@
 #include "psb_reg.h"
 #include "psb_intel_drv.h"
 #include "gtt.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 #include "mrst.h"
 
 /* Append new drm mode definition here, align with libdrm definition */
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 0b650a0..8f503d9 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -27,7 +27,7 @@
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
 #include "psb_intel_display.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 
 #include "mdfld_output.h"
 
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
index c9a13a4..4a0d234 100644
--- a/drivers/staging/gma500/psb_intel_lvds.c
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -27,7 +27,7 @@
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 #include <linux/pm_runtime.h>
 
 u32 CoreClock;
diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c
index 8fc7070..4a0fa42 100644
--- a/drivers/staging/gma500/psb_irq.c
+++ b/drivers/staging/gma500/psb_irq.c
@@ -26,7 +26,7 @@
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
-#include "psb_powermgmt.h"
+#include "power.h"
 #include "mdfld_output.h"
 
 /*
diff --git a/drivers/staging/gma500/psb_powermgmt.h b/drivers/staging/gma500/psb_powermgmt.h
deleted file mode 100644
index 333b28d..0000000
--- a/drivers/staging/gma500/psb_powermgmt.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2009-2011, Intel Corporation.
- * All Rights Reserved.
-
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors:
- *    Benjamin Defnet <benjamin.r.defnet@intel.com>
- *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
- * Massively reworked
- *    Alan Cox <alan@linux.intel.com>
- */
-#ifndef _PSB_POWERMGMT_H_
-#define _PSB_POWERMGMT_H_
-
-#include <linux/pci.h>
-#include <drm/drmP.h>
-
-void gma_power_init(struct drm_device *dev);
-void gma_power_uninit(struct drm_device *dev);
-
-/*
- * The kernel bus power management  will call these functions
- */
-int gma_power_suspend(struct pci_dev *pdev, pm_message_t state);
-int gma_power_resume(struct pci_dev *pdev);
-
-/*
- * These are the functions the driver should use to wrap all hw access
- * (i.e. register reads and writes)
- */
-bool gma_power_begin(struct drm_device *dev, bool force);
-void gma_power_end(struct drm_device *dev);
-
-/*
- * Use this function to do an instantaneous check for if the hw is on.
- * Only use this in cases where you know the mutex is already held such
- * as in irq install/uninstall and you need to
- * prevent a deadlock situation.  Otherwise use gma_power_begin().
- */
-bool gma_power_is_on(struct drm_device *dev);
-
-/*
- * GFX-Runtime PM callbacks
- */
-int psb_runtime_suspend(struct device *dev);
-int psb_runtime_resume(struct device *dev);
-int psb_runtime_idle(struct device *dev);
-
-#endif /*_PSB_POWERMGMT_H_*/


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 44/49] gma500: begin adding CDV specific code
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (42 preceding siblings ...)
  2011-07-05 14:43 ` [PATCH 43/49] gma500: move the power header Alan Cox
@ 2011-07-05 14:44 ` Alan Cox
  2011-07-05 14:44 ` [PATCH 45/49] gma500: Add the HDMI bits Alan Cox
                   ` (5 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:44 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

A lot of the intel_display stuff is duplicated, but we will add it first,
clean it up and then investigate the best way to merge stuff.

This first block integrates the various basic chunks of the CDV display setup.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile            |    5 
 drivers/staging/gma500/cdv_device.c        |  195 ++--
 drivers/staging/gma500/cdv_intel_display.c | 1513 ++++++++++++++++++++++++++++
 drivers/staging/gma500/cdv_intel_lvds.c    |  718 +++++++++++++
 drivers/staging/gma500/framebuffer.c       |    9 
 drivers/staging/gma500/gtt.c               |   33 +
 drivers/staging/gma500/psb_intel_display.c |    3 
 drivers/staging/gma500/psb_intel_reg.h     |   91 ++
 8 files changed, 2459 insertions(+), 108 deletions(-)
 create mode 100644 drivers/staging/gma500/cdv_intel_display.c
 create mode 100644 drivers/staging/gma500/cdv_intel_lvds.c

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index 961a60c..507aaaf 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -24,7 +24,10 @@ psb_gfx-y += gem_glue.o \
 	  psb_device.o \
 	  mid_bios.o
 
-psb_gfx-$(CONFIG_DRM_PSB_CDV) +=  cdv_device.o
+psb_gfx-$(CONFIG_DRM_PSB_CDV) +=  cdv_device.o \
+	  cdv_intel_display.o \
+	  cdv_intel_crt.o \
+	  cdv_intel_lvds.o
 
 psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \
 	  mrst_crtc.o \
diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c
index 530e8a2..622c955 100644
--- a/drivers/staging/gma500/cdv_device.c
+++ b/drivers/staging/gma500/cdv_device.c
@@ -25,13 +25,42 @@
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
 #include "intel_bios.h"
+#include "cdv_device.h"
 
+#define VGA_SR_INDEX		0x3c4
+#define VGA_SR_DATA		0x3c5
+
+/* FIXME: should check if we are the active VGA device ?? */
+static void cdv_disable_vga(struct drm_device *dev)
+{
+	u8 sr1;
+	u32 vga_reg;
+
+	vga_reg = VGACNTRL;
+
+	outb(1, VGA_SR_INDEX);
+	sr1 = inb(VGA_SR_DATA);
+	outb(sr1 | 1<<5, VGA_SR_DATA);
+	udelay(300);
+
+	REG_WRITE(vga_reg, VGA_DISP_DISABLE);
+	REG_READ(vga_reg);
+}
 
 static int cdv_output_init(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	psb_intel_lvds_init(dev, &dev_priv->mode_dev);
-	psb_intel_sdvo_init(dev, SDVOB);
+	cdv_disable_vga(dev);
+
+	cdv_intel_crt_init(dev, &dev_priv->mode_dev);
+	cdv_intel_lvds_init(dev, &dev_priv->mode_dev);
+
+	/* These bits indicate HDMI not SDVO on CDV, but we don't yet support
+	   the HDMI interface */
+	if (REG_READ(SDVOB) & SDVO_DETECTED)
+		DRM_ERROR("HDMI not supported yet\n");
+	if (REG_READ(SDVOC) & SDVO_DETECTED)
+		DRM_ERROR("HDMI not supported yet\n");
 	return 0;
 }
 
@@ -148,19 +177,70 @@ static int cdv_backlight_init(struct drm_device *dev)
 #endif
 
 /*
- *	Provide the Poulsbo specific chip logic and low level methods
+ *	Provide the Cedarview specific chip logic and low level methods
  *	for power management
+ *
+ *	FIXME: we need to implement the apm/ospm base management bits
+ *	for this and the MID devices.
  */
 
+static inline u32 CDV_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 CDV_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);
+}
+
+#define PSB_APM_CMD			0x0
+#define PSB_APM_STS			0x04
+#define PSB_PM_SSC			0x20
+#define PSB_PM_SSS			0x30
+#define PSB_PWRGT_GFX_MASK		0x3
+#define CDV_PWRGT_DISPLAY_CNTR		0x000fc00c
+#define CDV_PWRGT_DISPLAY_STS		0x000fc00c
+
 static void cdv_init_pm(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-
-	u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
-	gating &= ~3;	/* Disable 2D clock gating */
-	gating |= 1;
-	PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
-	PSB_RSGX32(PSB_CR_CLKGATECTL);
+	u32 pwr_cnt;
+	int i;
+
+	dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, PSB_APMBA) & 0xFFFF;
+	dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, PSB_OSPMBA) & 0xFFFF;
+
+	/* Force power on for now */
+	pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
+	pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
+
+	outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
+	for (i = 0; i < 5; i++) {
+		u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
+		if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0)
+			break;
+		udelay(10);
+	}
+	pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
+	pwr_cnt &= ~CDV_PWRGT_DISPLAY_CNTR;
+	outl(pwr_cnt, dev_priv->ospm_base + PSB_PM_SSC);
+	for (i = 0; i < 5; i++) {
+		u32 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+		if ((pwr_sts & CDV_PWRGT_DISPLAY_STS) == 0)
+			break;
+		udelay(10);
+	}
 }
 
 /**
@@ -169,34 +249,11 @@ static void cdv_init_pm(struct drm_device *dev)
  *
  *	Save the state we need in order to be able to restore the interface
  *	upon resume from suspend
+ *
+ *	FIXME: review
  */
 static int cdv_save_display_registers(struct drm_device *dev)
 {
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	struct drm_connector *connector;
-
-	/* Display arbitration control + watermarks */
-	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
-	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
-	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
-	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
-	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
-	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
-	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
-	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
-
-	/* Save crtc and output state */
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		if (drm_helper_crtc_in_use(crtc))
-			crtc->funcs->save(crtc);
-	}
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-		connector->funcs->save(connector);
-
-	mutex_unlock(&dev->mode_config.mutex);
 	return 0;
 }
 
@@ -205,67 +262,11 @@ static int cdv_save_display_registers(struct drm_device *dev)
  *	@dev: our DRM device
  *
  *	Restore register state that was lost during suspend and resume.
+ *
+ *	FIXME: review
  */
 static int cdv_restore_display_registers(struct drm_device *dev)
 {
-	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	struct drm_connector *connector;
-	int pp_stat;
-
-	/* Display arbitration + watermarks */
-	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
-	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
-	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
-	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
-	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
-	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
-	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
-	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
-
-	/*make sure VGA plane is off. it initializes to on after reset!*/
-	PSB_WVDC32(0x80000000, VGACNTRL);
-
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-		if (drm_helper_crtc_in_use(crtc))
-			crtc->funcs->restore(crtc);
-
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
-		connector->funcs->restore(connector);
-
-	mutex_unlock(&dev->mode_config.mutex);
-
-	if (dev_priv->iLVDS_enable) {
-		/*shutdown the panel*/
-		PSB_WVDC32(0, PP_CONTROL);
-		do {
-			pp_stat = PSB_RVDC32(PP_STATUS);
-		} while (pp_stat & 0x80000000);
-
-		/* Turn off the plane */
-		PSB_WVDC32(0x58000000, DSPACNTR);
-		PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
-		/* Wait ~4 ticks */
-		msleep(4);
-		/* Turn off pipe */
-		PSB_WVDC32(0x0, PIPEACONF);
-		/* Wait ~8 ticks */
-		msleep(8);
-
-		/* Turn off PLLs */
-		PSB_WVDC32(0, MRST_DPLL_A);
-	} else {
-		PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
-		PSB_WVDC32(0x0, PIPEACONF);
-		PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
-		while (REG_READ(0x70008) & 0x40000000)
-			cpu_relax();
-		while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
-			!= DPI_FIFO_EMPTY)
-			cpu_relax();
-		PSB_WVDC32(0, DEVICE_READY_REG);
-	}
 	return 0;
 }
 
@@ -286,9 +287,6 @@ static void cdv_get_core_freq(struct drm_device *dev)
 	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
 	struct drm_psb_private *dev_priv = dev->dev_private;
 
-	/*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
-	/*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
-
 	pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
 	pci_read_config_dword(pci_root, 0xD4, &clock);
 	pci_dev_put(pci_root);
@@ -326,7 +324,7 @@ static int cdv_chip_setup(struct drm_device *dev)
 	return 0;
 }
 
-/* CDV is much like Poulsbo but has MID like SGX offsets */
+/* CDV is much like Poulsbo but has MID like SGX offsets and PM */
 
 const struct psb_ops cdv_chip_ops = {
 	.name = "Cedartrail",
@@ -335,8 +333,8 @@ const struct psb_ops cdv_chip_ops = {
 	.sgx_offset = MRST_SGX_OFFSET,
 	.chip_setup = cdv_chip_setup,
 
-	.crtc_helper = &psb_intel_helper_funcs,
-	.crtc_funcs = &psb_intel_crtc_funcs,
+	.crtc_helper = &cdv_intel_helper_funcs,
+	.crtc_funcs = &cdv_intel_crtc_funcs,
 
 	.output_init = cdv_output_init,
 
@@ -350,4 +348,3 @@ const struct psb_ops cdv_chip_ops = {
 	.power_down = cdv_power_down,
 	.power_up = cdv_power_up,	
 };
-
diff --git a/drivers/staging/gma500/cdv_intel_display.c b/drivers/staging/gma500/cdv_intel_display.c
new file mode 100644
index 0000000..2042e98
--- /dev/null
+++ b/drivers/staging/gma500/cdv_intel_display.c
@@ -0,0 +1,1513 @@
+/*
+ * Copyright © 2006-2011 Intel Corporation
+ *
+ * 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:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drmP.h>
+#include "framebuffer.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_display.h"
+#include "power.h"
+#include "cdv_device.h"
+
+
+struct cdv_intel_range_t {
+	int min, max;
+};
+
+struct cdv_intel_p2_t {
+	int dot_limit;
+	int p2_slow, p2_fast;
+};
+
+struct cdv_intel_clock_t
+{
+	/* given values */
+	int n;
+	int m1, m2;
+	int p1, p2;
+	/* derived values */
+	int dot;
+	int vco;
+	int m;
+	int p;
+};
+
+#define INTEL_P2_NUM		      2
+
+struct cdv_intel_limit_t {
+	struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1;
+	struct cdv_intel_p2_t p2;
+};
+
+#define CDV_LIMIT_SINGLE_LVDS_96	0
+#define CDV_LIMIT_SINGLE_LVDS_100	1
+#define CDV_LIMIT_DAC_HDMI_27		2
+#define CDV_LIMIT_DAC_HDMI_96		3
+
+static const struct cdv_intel_limit_t cdv_intel_limits[] = {
+	{			/* CDV_SIGNLE_LVDS_96MHz */
+	 .dot = {.min = 20000, .max = 115500},
+	 .vco = {.min = 1800000, .max = 3600000},
+	 .n = {.min = 2, .max = 6},
+	 .m = {.min = 60, .max = 160},
+	 .m1 = {.min = 0, .max = 0},
+	 .m2 = {.min = 58, .max = 158},
+	 .p = {.min = 28, .max = 140},
+	 .p1 = {.min = 2, .max = 10},
+	 .p2 = {.dot_limit = 200000,
+		.p2_slow = 14, .p2_fast = 14},
+	 },
+	{			/* CDV_SINGLE_LVDS_100MHz */
+	 .dot = {.min = 20000, .max = 115500},
+	 .vco = {.min = 1800000, .max = 3600000},
+	 .n = {.min = 2, .max = 6},
+	 .m = {.min = 60, .max = 160},
+	 .m1 = {.min = 0, .max = 0},
+	 .m2 = {.min = 58, .max = 158},
+	 .p = {.min = 28, .max = 140},
+	 .p1 = {.min = 2, .max = 10},
+	 /* The single-channel range is 25-112Mhz, and dual-channel
+	  * is 80-224Mhz.  Prefer single channel as much as possible.
+	  */
+	 .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
+	 },
+	{			/* CDV_DAC_HDMI_27MHz */
+	 .dot = {.min = 20000, .max = 400000},
+	 .vco = {.min = 1809000, .max = 3564000},
+	 .n = {.min = 1, .max = 1},
+	 .m = {.min = 67, .max = 132},
+	 .m1 = {.min = 0, .max = 0},
+	 .m2 = {.min = 65, .max = 130},
+	 .p = {.min = 5, .max = 90},
+	 .p1 = {.min = 1, .max = 9},
+	 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
+	 },
+	{			/* CDV_DAC_HDMI_96MHz */
+	 .dot = {.min = 20000, .max = 400000},
+	 .vco = {.min = 1800000, .max = 3600000},
+	 .n = {.min = 2, .max = 6},
+	 .m = {.min = 60, .max = 160},
+	 .m1 = {.min = 0, .max = 0},
+	 .m2 = {.min = 58, .max = 158},
+	 .p = {.min = 5, .max = 100},
+	 .p1 = {.min = 1, .max = 10},
+	 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
+	 },
+};
+
+#define _wait_for(COND, MS, W) ({ \
+        unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);       \
+        int ret__ = 0;                                                  \
+        while (! (COND)) {                                              \
+                if (time_after(jiffies, timeout__)) {                   \
+                        ret__ = -ETIMEDOUT;                             \
+                        break;                                          \
+                }                                                       \
+                if (W && !in_dbg_master()) msleep(W);                   \
+        }                                                               \
+        ret__;                                                          \
+})      
+
+#define wait_for(COND, MS) _wait_for(COND, MS, 1)
+
+
+static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val)
+{
+	int ret;
+
+	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
+	if (ret) {
+		DRM_ERROR("timeout waiting for SB to idle before read\n");
+		return ret;
+	}
+
+	REG_WRITE(SB_ADDR, reg);
+	REG_WRITE(SB_PCKT,
+		   SET_FIELD(SB_OPCODE_READ, SB_OPCODE) |
+		   SET_FIELD(SB_DEST_DPLL, SB_DEST) |
+		   SET_FIELD(0xf, SB_BYTE_ENABLE));
+
+	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
+	if (ret) {
+		DRM_ERROR("timeout waiting for SB to idle after read\n");
+		return ret;
+	}
+
+	*val = REG_READ(SB_DATA);
+
+	return 0;
+}
+
+static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val)
+{
+	int ret;
+	static bool dpio_debug = true;
+	u32 temp;
+
+	if (dpio_debug) {
+		if (cdv_sb_read(dev, reg, &temp) == 0)
+			DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp);
+		DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val);
+	}
+
+	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
+	if (ret) {
+		DRM_ERROR("timeout waiting for SB to idle before write\n");
+		return ret;
+	}
+
+	REG_WRITE(SB_ADDR, reg);
+	REG_WRITE(SB_DATA, val);
+	REG_WRITE(SB_PCKT,
+		   SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) |
+		   SET_FIELD(SB_DEST_DPLL, SB_DEST) |
+		   SET_FIELD(0xf, SB_BYTE_ENABLE));
+
+	ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
+	if (ret) {
+		DRM_ERROR("timeout waiting for SB to idle after write\n");
+		return ret;
+	}
+
+	if (dpio_debug) {
+		if (cdv_sb_read(dev, reg, &temp) == 0)
+			DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp);
+	}
+
+	return 0;
+}
+
+/* Reset the DPIO configuration register.  The BIOS does this at every
+ * mode set.
+ */
+static void cdv_sb_reset(struct drm_device *dev)
+{
+
+	REG_WRITE(DPIO_CFG, 0);
+	REG_READ(DPIO_CFG);
+	REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N);
+}
+
+/* Unlike most Intel display engines, on Cedarview the DPLL registers
+ * are behind this sideband bus.  They must be programmed while the
+ * DPLL reference clock is on in the DPLL control register, but before
+ * the DPLL is enabled in the DPLL control register.
+ */
+static int
+cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
+			       struct cdv_intel_clock_t *clock)
+{
+	struct psb_intel_crtc *psb_crtc =
+				to_psb_intel_crtc(crtc);
+	int pipe = psb_crtc->pipe;
+	u32 m, n_vco, p;
+	int ret = 0;
+	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	u32 ref_value;
+
+	cdv_sb_reset(dev);
+
+	if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) {
+		DRM_ERROR("Attempting to set DPLL with refclk disabled\n");
+		return -EBUSY;
+	}
+
+	/* Follow the BIOS and write the REF/SFR Register. Hardcoded value */
+	ref_value = 0x68A701;
+
+	cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value);
+	
+	/* We don't know what the other fields of these regs are, so
+	 * leave them in place.
+	 */
+	ret = cdv_sb_read(dev, SB_M(pipe), &m);
+	if (ret)
+		return ret;
+	m &= ~SB_M_DIVIDER_MASK;
+	m |= ((clock->m2) << SB_M_DIVIDER_SHIFT);
+	ret = cdv_sb_write(dev, SB_M(pipe), m);
+	if (ret)
+		return ret;
+
+	ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco);
+	if (ret)
+		return ret;
+
+	/* Follow the BIOS to program the N_DIVIDER REG */
+	n_vco &= 0xFFFF;
+	n_vco |= 0x107;
+	n_vco &= ~(SB_N_VCO_SEL_MASK |
+		   SB_N_DIVIDER_MASK |
+		   SB_N_CB_TUNE_MASK);
+
+	n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT);
+
+	if (clock->vco < 2250000) {
+		n_vco |= (2 << SB_N_CB_TUNE_SHIFT);
+		n_vco |= (0 << SB_N_VCO_SEL_SHIFT);
+	} else if (clock->vco < 2750000) {
+		n_vco |= (1 << SB_N_CB_TUNE_SHIFT);
+		n_vco |= (1 << SB_N_VCO_SEL_SHIFT);
+	} else if (clock->vco < 3300000) {
+		n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
+		n_vco |= (2 << SB_N_VCO_SEL_SHIFT);
+	} else {
+		n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
+		n_vco |= (3 << SB_N_VCO_SEL_SHIFT);
+	}
+
+	ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco);
+	if (ret)
+		return ret;
+
+	ret = cdv_sb_read(dev, SB_P(pipe), &p);
+	if (ret)
+		return ret;
+	p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK);
+	p |= SET_FIELD(clock->p1, SB_P1_DIVIDER);
+	switch (clock->p2) {
+	case 5:
+		p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER);
+		break;
+	case 10:
+		p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER);
+		break;
+	case 14:
+		p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER);
+		break;
+	case 7:
+		p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER);
+		break;
+	default:
+		DRM_ERROR("Bad P2 clock: %d\n", clock->p2);
+		return -EINVAL;
+	}
+	ret = cdv_sb_write(dev, SB_P(pipe), p);
+	if (ret)
+		return ret;
+
+	/* always Program the Lane Register for the Pipe A*/
+	if (pipe == 0) {
+		/* Program the Lane0/1 for HDMI B */
+		u32 lane_reg, lane_value;
+
+		lane_reg = PSB_LANE0;
+		cdv_sb_read(dev, lane_reg, &lane_value);
+		lane_value &= ~(LANE_PLL_MASK);
+		lane_value |= LANE_PLL_ENABLE;
+		cdv_sb_write(dev, lane_reg, lane_value);
+
+		lane_reg = PSB_LANE1;
+		cdv_sb_read(dev, lane_reg, &lane_value);
+		lane_value &= ~(LANE_PLL_MASK);
+		lane_value |= LANE_PLL_ENABLE;
+		cdv_sb_write(dev, lane_reg, lane_value);
+
+		/* Program the Lane2/3 for HDMI C */	
+		lane_reg = PSB_LANE2;
+		cdv_sb_read(dev, lane_reg, &lane_value);
+		lane_value &= ~(LANE_PLL_MASK);
+		lane_value |= LANE_PLL_ENABLE;
+		cdv_sb_write(dev, lane_reg, lane_value);
+
+	
+		lane_reg = PSB_LANE3;
+		cdv_sb_read(dev, lane_reg, &lane_value);
+		lane_value &= ~(LANE_PLL_MASK);
+		lane_value |= LANE_PLL_ENABLE;
+		cdv_sb_write(dev, lane_reg, lane_value);
+	}
+
+	return 0;
+}
+
+/*
+ * Returns whether any output on the specified pipe is of the specified type
+ */
+bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_connector *l_entry;
+
+	list_for_each_entry(l_entry, &mode_config->connector_list, head) {
+		if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
+			struct psb_intel_output *psb_intel_output =
+			    to_psb_intel_output(l_entry);
+			if (psb_intel_output->type == type)
+				return true;
+		}
+	}
+	return false;
+}
+
+static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc, int refclk)
+{
+	const struct cdv_intel_limit_t *limit;
+	if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+		/*
+ 		 * Now only single-channel LVDS is supported on CDV. If it is
+ 		 * incorrect, please add the dual-channel LVDS.
+ 		 */
+		if (refclk == 96000)
+			limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
+		else 
+			limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
+	} else {
+		if (refclk == 27000)
+			limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27];
+		else
+			limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96];
+	}
+	return limit;
+}
+
+/* m1 is reserved as 0 in CDV, n is a ring counter */
+static void cdv_intel_clock(struct drm_device *dev, 
+			int refclk, struct cdv_intel_clock_t *clock)
+{
+	clock->m = clock->m2 + 2;
+	clock->p = clock->p1 * clock->p2;
+	clock->vco = (refclk * clock->m) / clock->n;
+	clock->dot = clock->vco / clock->p;
+}
+
+
+#define INTELPllInvalid(s)   { /* ErrorF (s) */; return false; }
+static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc,
+				const struct cdv_intel_limit_t *limit,
+			       struct cdv_intel_clock_t *clock)
+{
+	if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
+		INTELPllInvalid("p1 out of range\n");
+	if (clock->p < limit->p.min || limit->p.max < clock->p)
+		INTELPllInvalid("p out of range\n");
+	/* unnecessary to check the range of m(m1/M2)/n again */
+	if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
+		INTELPllInvalid("vco out of range\n");
+	/* XXX: We may need to be checking "Dot clock"
+	 * depending on the multiplier, connector, etc.,
+	 * rather than just a single range.
+	 */
+	if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
+		INTELPllInvalid("dot out of range\n");
+
+	return true;
+}
+
+static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target,
+				int refclk,
+				struct cdv_intel_clock_t *best_clock)
+{
+	struct drm_device *dev = crtc->dev;
+	struct cdv_intel_clock_t clock;
+	const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk);
+	int err = target;
+
+
+	if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+	    (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
+		/*
+		 * For LVDS, if the panel is on, just rely on its current
+		 * settings for dual-channel.  We haven't figured out how to
+		 * reliably set up different single/dual channel state, if we
+		 * even can.
+		 */
+		if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+		    LVDS_CLKB_POWER_UP)
+			clock.p2 = limit->p2.p2_fast;
+		else
+			clock.p2 = limit->p2.p2_slow;
+	} else {
+		if (target < limit->p2.dot_limit)
+			clock.p2 = limit->p2.p2_slow;
+		else
+			clock.p2 = limit->p2.p2_fast;
+	}
+
+	memset(best_clock, 0, sizeof(*best_clock));
+	clock.m1 = 0;
+	/* m1 is reserved as 0 in CDV, n is a ring counter. So skip the m1 loop */
+	for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
+		for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max;
+					     clock.m2++) {
+			for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
+				     clock.p1++) {
+				int this_err;
+
+				cdv_intel_clock(dev, refclk, &clock);
+
+				if (!cdv_intel_PLL_is_valid(crtc, limit, &clock))
+						continue;
+				
+				this_err = abs(clock.dot - target);
+				if (this_err < err) {
+					*best_clock = clock;
+					err = this_err;
+				}
+			}
+		}
+	}
+
+	return err != target;
+}
+
+int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
+			    int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+	int pipe = psb_intel_crtc->pipe;
+	unsigned long start, offset;
+	int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
+	int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
+	int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
+	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+	u32 dspcntr;
+	int ret = 0;
+
+	if (!gma_power_begin(dev, true))
+		return 0;
+
+	/* no fb bound */
+	if (!crtc->fb) {
+		dev_err(dev->dev, "No FB bound\n");
+		goto psb_intel_pipe_cleaner;
+	}
+
+
+	/* We are displaying this buffer, make sure it is actually loaded
+	   into the GTT */
+	ret = psb_gtt_pin(psbfb->gtt);
+	if (ret < 0)
+		goto psb_intel_pipe_set_base_exit;
+	start = psbfb->gtt->offset;
+	offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+
+	REG_WRITE(dspstride, crtc->fb->pitch);
+
+	dspcntr = REG_READ(dspcntr_reg);
+	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+
+	switch (crtc->fb->bits_per_pixel) {
+	case 8:
+		dspcntr |= DISPPLANE_8BPP;
+		break;
+	case 16:
+		if (crtc->fb->depth == 15)
+			dspcntr |= DISPPLANE_15_16BPP;
+		else
+			dspcntr |= DISPPLANE_16BPP;
+		break;
+	case 24:
+	case 32:
+		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+		break;
+	default:
+		dev_err(dev->dev, "Unknown color depth\n");
+		ret = -EINVAL;
+		goto psb_intel_pipe_set_base_exit;
+	}
+	REG_WRITE(dspcntr_reg, dspcntr);
+
+	dev_dbg(dev->dev,
+	        "Writing base %08lX %08lX %d %d\n", start, offset, x, y);
+
+	REG_WRITE(dspbase, offset);
+	REG_READ(dspbase);
+	REG_WRITE(dspsurf, start);
+	REG_READ(dspsurf);
+
+psb_intel_pipe_cleaner:
+	/* If there was a previous display we can now unpin it */
+	if (old_fb)
+		psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
+
+psb_intel_pipe_set_base_exit:
+	gma_power_end(dev);
+	return ret;
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+	int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
+	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+	u32 temp;
+	bool enabled;
+
+	/* XXX: When our outputs are all unaware of DPMS modes other than off
+	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+	 */
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+		/* Enable the DPLL */
+		temp = REG_READ(dpll_reg);
+		if ((temp & DPLL_VCO_ENABLE) == 0) {
+			REG_WRITE(dpll_reg, temp);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to stabilize. */
+			udelay(150);
+			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to stabilize. */
+			udelay(150);
+			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to stabilize. */
+			udelay(150);
+		}
+
+		/* Jim Bish - switch plan and pipe per scott */
+		/* Enable the plane */
+		temp = REG_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+			REG_WRITE(dspcntr_reg,
+				  temp | DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+		}
+
+		udelay(150);
+
+		/* Enable the pipe */
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) == 0)
+			REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
+
+		psb_intel_crtc_load_lut(crtc);
+
+		/* Give the overlay scaler a chance to enable
+		 * if it's on this pipe */
+		/* psb_intel_crtc_dpms_video(crtc, true); TODO */
+		break;
+	case DRM_MODE_DPMS_OFF:
+		/* Give the overlay scaler a chance to disable
+		 * if it's on this pipe */
+		/* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
+
+		/* Disable the VGA plane that we never use */
+		REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+		/* Jim Bish - changed pipe/plane here as well. */
+
+		/* Wait for vblank for the disable to take effect */
+		cdv_intel_wait_for_vblank(dev);
+
+		/* Next, disable display pipes */
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+			REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+			REG_READ(pipeconf_reg);
+		}
+
+		/* Wait for vblank for the disable to take effect. */
+		cdv_intel_wait_for_vblank(dev);
+
+		udelay(150);
+
+		/* Disable display plane */
+		temp = REG_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+			REG_WRITE(dspcntr_reg,
+				  temp & ~DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+			REG_READ(dspbase_reg);
+		}
+
+		temp = REG_READ(dpll_reg);
+		if ((temp & DPLL_VCO_ENABLE) != 0) {
+			REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+		}
+
+		/* Wait for the clocks to turn off. */
+		udelay(150);
+		break;
+	}
+	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
+	/*Set FIFO Watermarks*/
+	REG_WRITE(DSPARB, 0x3F3E);
+}
+
+static void cdv_intel_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void cdv_intel_crtc_commit(struct drm_crtc *crtc)
+{
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+void cdv_intel_encoder_prepare(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs =
+	    encoder->helper_private;
+	/* lvds has its own version of prepare see cdv_intel_lvds_prepare */
+	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+void cdv_intel_encoder_commit(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs =
+	    encoder->helper_private;
+	/* lvds has its own version of commit see cdv_intel_lvds_commit */
+	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+
+/**
+ * Return the pipe currently connected to the panel fitter,
+ * or -1 if the panel fitter is not present or not in use
+ */
+static int cdv_intel_panel_fitter_pipe(struct drm_device *dev)
+{
+	u32 pfit_control;
+
+	pfit_control = REG_READ(PFIT_CONTROL);
+
+	/* See if the panel fitter is in use */
+	if ((pfit_control & PFIT_ENABLE) == 0)
+		return -1;
+	return (pfit_control >> 29) & 0x3;
+}
+
+static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode,
+			       int x, int y,
+			       struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
+	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+	int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+	int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+	int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+	int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+	int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+	int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+	int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
+	int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
+	int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+	int refclk;
+	struct cdv_intel_clock_t clock;
+	u32 dpll = 0, dspcntr, pipeconf;
+	bool ok, is_sdvo = false, is_dvo = false;
+	bool is_crt = false, is_lvds = false, is_tv = false;
+	bool is_hdmi = false;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &mode_config->connector_list, head) {
+		struct psb_intel_output *psb_intel_output =
+		    to_psb_intel_output(connector);
+
+		if (!connector->encoder
+		    || connector->encoder->crtc != crtc)
+			continue;
+
+		switch (psb_intel_output->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_SDVO:
+			is_sdvo = true;
+			break;
+		case INTEL_OUTPUT_DVO:
+			is_dvo = true;
+			break;
+		case INTEL_OUTPUT_TVOUT:
+			is_tv = true;
+			break;
+		case INTEL_OUTPUT_ANALOG:
+			is_crt = true;
+			break;
+		case INTEL_OUTPUT_HDMI:
+			is_hdmi = true;
+			break;
+		}
+	}
+
+	refclk = 96000;
+
+	/* Hack selection about ref clk for CRT */
+	/* Select 27MHz as the reference clk for HDMI */
+	if (is_crt || is_hdmi)
+		refclk = 27000;
+
+	drm_mode_debug_printmodeline(adjusted_mode);
+
+	ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
+				 &clock);
+	if (!ok) {
+		dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
+		return 0;
+	}
+
+	dpll = DPLL_VGA_MODE_DIS;
+	if (is_tv) {
+		/* XXX: just matching BIOS for now */
+/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
+		dpll |= 3;
+	}
+		dpll |= PLL_REF_INPUT_DREFCLK;
+
+	dpll |= DPLL_SYNCLOCK_ENABLE;
+	dpll |= DPLL_VGA_MODE_DIS;
+	if (is_lvds)
+		dpll |= DPLLB_MODE_LVDS;
+	else
+		dpll |= DPLLB_MODE_DAC_SERIAL;
+	//dpll |= (2 << 11);
+
+	/* setup pipeconf */
+	pipeconf = REG_READ(pipeconf_reg);
+
+	/* Set up the display plane register */
+	dspcntr = DISPPLANE_GAMMA_ENABLE;
+
+	if (pipe == 0)
+		dspcntr |= DISPPLANE_SEL_PIPE_A;
+	else
+		dspcntr |= DISPPLANE_SEL_PIPE_B;
+
+	dspcntr |= DISPLAY_PLANE_ENABLE;
+	pipeconf |= PIPEACONF_ENABLE;
+
+	REG_WRITE(dpll_reg,
+                   dpll | DPLL_VGA_MODE_DIS |
+                   DPLL_SYNCLOCK_ENABLE);
+        REG_READ(dpll_reg);
+
+	cdv_dpll_set_clock_cdv(dev, crtc, &clock);
+
+        udelay(150);
+
+
+	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
+	 * This is an exception to the general rule that mode_set doesn't turn
+	 * things on.
+	 */
+	if (is_lvds) {
+		u32 lvds = REG_READ(LVDS);
+
+		lvds |=
+		    LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP |
+		    LVDS_PIPEB_SELECT;
+		/* Set the B0-B3 data pairs corresponding to
+		 * whether we're going to
+		 * set the DPLLs for dual-channel mode or not.
+		 */
+		if (clock.p2 == 7)
+			lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+		else
+			lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
+
+		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+		 * appropriately here, but we need to look more
+		 * thoroughly into how panels behave in the two modes.
+		 */
+
+		REG_WRITE(LVDS, lvds);
+		REG_READ(LVDS);
+	}
+
+	dpll |= DPLL_VCO_ENABLE;
+
+		
+	/* Disable the panel fitter if it was on our pipe */
+	if (cdv_intel_panel_fitter_pipe(dev) == pipe)
+		REG_WRITE(PFIT_CONTROL, 0);
+
+	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+	drm_mode_debug_printmodeline(mode);
+
+	REG_WRITE(dpll_reg,
+                   (REG_READ(dpll_reg) & ~DPLL_LOCK) |
+                   DPLL_VCO_ENABLE);
+        REG_READ(dpll_reg);
+	/* Wait for the clocks to stabilize. */
+        udelay(150); /* 42 usec w/o calibration, 110 with.  rounded up. */
+
+        if (!(REG_READ(dpll_reg) & DPLL_LOCK)) {
+                dev_err(dev->dev, "Failed to get DPLL lock\n");
+                return -EBUSY;
+        }
+
+        {
+        	int sdvo_pixel_multiply =
+		    adjusted_mode->clock / mode->clock;
+		REG_WRITE(dpll_md_reg,
+			  (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+			  ((sdvo_pixel_multiply -
+			    1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+	}
+
+	REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+		  ((adjusted_mode->crtc_htotal - 1) << 16));
+	REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+		  ((adjusted_mode->crtc_hblank_end - 1) << 16));
+	REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+		  ((adjusted_mode->crtc_hsync_end - 1) << 16));
+	REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+		  ((adjusted_mode->crtc_vtotal - 1) << 16));
+	REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+		  ((adjusted_mode->crtc_vblank_end - 1) << 16));
+	REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+		  ((adjusted_mode->crtc_vsync_end - 1) << 16));
+	/* pipesrc and dspsize control the size that is scaled from,
+	 * which should always be the user's requested size.
+	 */
+	REG_WRITE(dspsize_reg,
+		  ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
+	REG_WRITE(dsppos_reg, 0);
+	REG_WRITE(pipesrc_reg,
+		  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+	REG_WRITE(pipeconf_reg, pipeconf);
+	REG_READ(pipeconf_reg);
+
+	cdv_intel_wait_for_vblank(dev);
+
+	REG_WRITE(dspcntr_reg, dspcntr);
+
+	/* Flush the plane changes */
+	{
+		struct drm_crtc_helper_funcs *crtc_funcs =
+		    crtc->helper_private;
+		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+	}
+
+	cdv_intel_wait_for_vblank(dev);
+
+	return 0;
+}
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv =
+				(struct drm_psb_private *)dev->dev_private;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int palreg = PALETTE_A;
+	int i;
+
+	/* The clocks have to be on to load the palette. */
+	if (!crtc->enabled)
+		return;
+
+	switch (psb_intel_crtc->pipe) {
+	case 0:
+		break;
+	case 1:
+		palreg = PALETTE_B;
+		break;
+	case 2:
+		palreg = PALETTE_C;
+		break;
+	default:
+		dev_err(dev->dev, "Illegal Pipe Number. \n");
+		return;
+	}
+	
+	if (gma_power_begin(dev, false)) {
+		for (i = 0; i < 256; i++) {
+			REG_WRITE(palreg + 4 * i,
+				  ((psb_intel_crtc->lut_r[i] +
+				  psb_intel_crtc->lut_adj[i]) << 16) |
+				  ((psb_intel_crtc->lut_g[i] +
+				  psb_intel_crtc->lut_adj[i]) << 8) |
+				  (psb_intel_crtc->lut_b[i] +
+				  psb_intel_crtc->lut_adj[i]));
+		}
+		gma_power_end(dev);
+	} else {
+		for (i = 0; i < 256; i++) {
+			dev_priv->save_palette_a[i] =
+				  ((psb_intel_crtc->lut_r[i] +
+				  psb_intel_crtc->lut_adj[i]) << 16) |
+				  ((psb_intel_crtc->lut_g[i] +
+				  psb_intel_crtc->lut_adj[i]) << 8) |
+				  (psb_intel_crtc->lut_b[i] +
+				  psb_intel_crtc->lut_adj[i]);
+		}
+
+	}
+}
+
+/**
+ * Save HW states of giving crtc
+ */
+static void cdv_intel_crtc_save(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	/* struct drm_psb_private *dev_priv =
+			(struct drm_psb_private *)dev->dev_private; */
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+	int pipeA = (psb_intel_crtc->pipe == 0);
+	uint32_t paletteReg;
+	int i;
+
+	if (!crtc_state) {
+		dev_dbg(dev->dev, "No CRTC state found\n");
+		return;
+	}
+
+	crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
+	crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
+	crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
+	crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
+	crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
+	crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
+	crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
+	crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
+	crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
+	crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
+	crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
+	crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
+	crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
+
+	/*NOTE: DSPSIZE DSPPOS only for psb*/
+	crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
+	crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
+
+	crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
+
+	DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+			crtc_state->saveDSPCNTR,
+			crtc_state->savePIPECONF,
+			crtc_state->savePIPESRC,
+			crtc_state->saveFP0,
+			crtc_state->saveFP1,
+			crtc_state->saveDPLL,
+			crtc_state->saveHTOTAL,
+			crtc_state->saveHBLANK,
+			crtc_state->saveHSYNC,
+			crtc_state->saveVTOTAL,
+			crtc_state->saveVBLANK,
+			crtc_state->saveVSYNC,
+			crtc_state->saveDSPSTRIDE,
+			crtc_state->saveDSPSIZE,
+			crtc_state->saveDSPPOS,
+			crtc_state->saveDSPBASE
+		);
+
+	paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+	for (i = 0; i < 256; ++i)
+		crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
+}
+
+/**
+ * Restore HW states of giving crtc
+ */
+static void cdv_intel_crtc_restore(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	/* struct drm_psb_private * dev_priv =
+				(struct drm_psb_private *)dev->dev_private; */
+	struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc);
+	struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+	/* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
+	int pipeA = (psb_intel_crtc->pipe == 0);
+	uint32_t paletteReg;
+	int i;
+
+	if (!crtc_state) {
+		dev_dbg(dev->dev, "No crtc state\n");
+		return;
+	}
+
+	DRM_DEBUG(
+		"current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+		REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
+		REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
+		REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
+		REG_READ(pipeA ? FPA0 : FPB0),
+		REG_READ(pipeA ? FPA1 : FPB1),
+		REG_READ(pipeA ? DPLL_A : DPLL_B),
+		REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
+		REG_READ(pipeA ? HBLANK_A : HBLANK_B),
+		REG_READ(pipeA ? HSYNC_A : HSYNC_B),
+		REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
+		REG_READ(pipeA ? VBLANK_A : VBLANK_B),
+		REG_READ(pipeA ? VSYNC_A : VSYNC_B),
+		REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
+		REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
+		REG_READ(pipeA ? DSPAPOS : DSPBPOS),
+		REG_READ(pipeA ? DSPABASE : DSPBBASE)
+		);
+
+	DRM_DEBUG(
+		"saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+		crtc_state->saveDSPCNTR,
+		crtc_state->savePIPECONF,
+		crtc_state->savePIPESRC,
+		crtc_state->saveFP0,
+		crtc_state->saveFP1,
+		crtc_state->saveDPLL,
+		crtc_state->saveHTOTAL,
+		crtc_state->saveHBLANK,
+		crtc_state->saveHSYNC,
+		crtc_state->saveVTOTAL,
+		crtc_state->saveVBLANK,
+		crtc_state->saveVSYNC,
+		crtc_state->saveDSPSTRIDE,
+		crtc_state->saveDSPSIZE,
+		crtc_state->saveDSPPOS,
+		crtc_state->saveDSPBASE
+		);
+
+
+	if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
+		REG_WRITE(pipeA ? DPLL_A : DPLL_B,
+			crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
+		REG_READ(pipeA ? DPLL_A : DPLL_B);
+		DRM_DEBUG("write dpll: %x\n",
+				REG_READ(pipeA ? DPLL_A : DPLL_B));
+		udelay(150);
+	}
+
+	REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
+	REG_READ(pipeA ? FPA0 : FPB0);
+
+	REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
+	REG_READ(pipeA ? FPA1 : FPB1);
+
+	REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
+	REG_READ(pipeA ? DPLL_A : DPLL_B);
+	udelay(150);
+
+	REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
+	REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
+	REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
+	REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
+	REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
+	REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
+	REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
+
+	REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
+	REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
+
+	REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
+	REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+	REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
+
+	cdv_intel_wait_for_vblank(dev);
+
+	REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
+	REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+
+	cdv_intel_wait_for_vblank(dev);
+
+	paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+	for (i = 0; i < 256; ++i)
+		REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
+}
+
+static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
+				 struct drm_file *file_priv,
+				 uint32_t handle,
+				 uint32_t width, uint32_t height)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
+	uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
+	uint32_t temp;
+	size_t addr = 0;
+	struct gtt_range *gt;
+	struct drm_gem_object *obj;
+	int ret;
+
+	/* if we want to turn of the cursor ignore width and height */
+	if (!handle) {
+		/* turn off the cursor */
+		temp = CURSOR_MODE_DISABLE;
+
+		if (gma_power_begin(dev, false)) {
+			REG_WRITE(control, temp);
+			REG_WRITE(base, 0);
+			gma_power_end(dev);
+		}
+
+		/* unpin the old GEM object */
+		if (psb_intel_crtc->cursor_obj) {
+			gt = container_of(psb_intel_crtc->cursor_obj,
+							struct gtt_range, gem);
+			psb_gtt_unpin(gt);
+			drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+			psb_intel_crtc->cursor_obj = NULL;
+		}
+
+		return 0;
+	}
+
+	/* Currently we only support 64x64 cursors */
+	if (width != 64 || height != 64) {
+		dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
+		return -EINVAL;
+	}
+
+	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	if (!obj)
+		return -ENOENT;
+
+	if (obj->size < width * height * 4) {
+		dev_dbg(dev->dev, "buffer is to small\n");
+		return -ENOMEM;
+	}
+
+	gt = container_of(obj, struct gtt_range, gem);
+
+	/* Pin the memory into the GTT */
+	ret = psb_gtt_pin(gt);
+	if (ret) {
+		dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
+		return ret;
+	}
+
+	addr = gt->offset;	/* Or resource.start ??? */
+
+	psb_intel_crtc->cursor_addr = addr;
+
+	temp = 0;
+	/* set the pipe for the cursor */
+	temp |= (pipe << 28);
+	temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+
+	if (gma_power_begin(dev, false)) {
+		REG_WRITE(control, temp);
+		REG_WRITE(base, addr);
+		gma_power_end(dev);
+	}
+
+	/* unpin the old GEM object */
+	if (psb_intel_crtc->cursor_obj) {
+		gt = container_of(psb_intel_crtc->cursor_obj,
+							struct gtt_range, gem);
+		psb_gtt_unpin(gt);
+		drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
+		psb_intel_crtc->cursor_obj = obj;
+	}
+	return 0;
+}
+
+static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	uint32_t temp = 0;
+	uint32_t adder;
+
+
+	if (x < 0) {
+		temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+		x = -x;
+	}
+	if (y < 0) {
+		temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+		y = -y;
+	}
+
+	temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
+	temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+
+	adder = psb_intel_crtc->cursor_addr;
+
+	if (gma_power_begin(dev, false)) {
+		REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
+		REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
+		gma_power_end(dev);
+	}
+	return 0;
+}
+
+static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
+				 u16 *green, u16 *blue, uint32_t start, uint32_t size)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int i;
+	int end = (start + size > 256) ? 256 : start + size;
+
+	for (i = start; i < end; i++) {
+		psb_intel_crtc->lut_r[i] = red[i] >> 8;
+		psb_intel_crtc->lut_g[i] = green[i] >> 8;
+		psb_intel_crtc->lut_b[i] = blue[i] >> 8;
+	}
+
+	cdv_intel_crtc_load_lut(crtc);
+}
+
+static int cdv_crtc_set_config(struct drm_mode_set *set)
+{
+	int ret = 0;
+	struct drm_device * dev = set->crtc->dev;
+	struct drm_psb_private * dev_priv = dev->dev_private;
+
+	if(!dev_priv->rpm_enabled)
+		return drm_crtc_helper_set_config(set);
+
+	pm_runtime_forbid(&dev->pdev->dev);
+
+	ret = drm_crtc_helper_set_config(set);
+
+	pm_runtime_allow(&dev->pdev->dev);
+
+	return ret;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
+
+/* FIXME: why are we using this, should it be cdv_ in this tree ? */
+
+static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock)
+{
+	clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
+	clock->p = clock->p1 * clock->p2;
+	clock->vco = refclk * clock->m / (clock->n + 2);
+	clock->dot = clock->vco / clock->p;
+}
+
+/* Returns the clock of the currently programmed mode of the given pipe. */
+static int cdv_intel_crtc_clock_get(struct drm_device *dev,
+				struct drm_crtc *crtc)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	u32 dpll;
+	u32 fp;
+	struct cdv_intel_clock_t clock;
+	bool is_lvds;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (gma_power_begin(dev, false)) {
+		dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
+		if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
+			fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
+		else
+			fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
+		is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
+		gma_power_end(dev);
+	} else {
+		dpll = (pipe == 0) ?
+			dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
+
+		if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
+			fp = (pipe == 0) ?
+				dev_priv->saveFPA0 :
+				dev_priv->saveFPB0;
+		else
+			fp = (pipe == 0) ?
+				dev_priv->saveFPA1 :
+				dev_priv->saveFPB1;
+
+		is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
+	}
+
+	clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
+	clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
+	clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
+
+	if (is_lvds) {
+		clock.p1 =
+		    ffs((dpll &
+			 DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
+			DPLL_FPA01_P1_POST_DIV_SHIFT);
+		if (clock.p1 == 0) {
+			clock.p1 = 4;
+			dev_err(dev->dev, "PLL %d\n", dpll);
+		}
+		clock.p2 = 14;
+
+		if ((dpll & PLL_REF_INPUT_MASK) ==
+		    PLLB_REF_INPUT_SPREADSPECTRUMIN) {
+			/* XXX: might not be 66MHz */
+			i8xx_clock(66000, &clock);
+		} else
+			i8xx_clock(48000, &clock);
+	} else {
+		if (dpll & PLL_P1_DIVIDE_BY_TWO)
+			clock.p1 = 2;
+		else {
+			clock.p1 =
+			    ((dpll &
+			      DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
+			     DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
+		}
+		if (dpll & PLL_P2_DIVIDE_BY_4)
+			clock.p2 = 4;
+		else
+			clock.p2 = 2;
+
+		i8xx_clock(48000, &clock);
+	}
+
+	/* XXX: It would be nice to validate the clocks, but we can't reuse
+	 * i830PllIsValid() because it relies on the xf86_config connector
+	 * configuration being accurate, which it isn't necessarily.
+	 */
+
+	return clock.dot;
+}
+
+/** Returns the currently programmed mode of the given pipe. */
+struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
+					     struct drm_crtc *crtc)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	struct drm_display_mode *mode;
+	int htot;
+	int hsync;
+	int vtot;
+	int vsync;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (gma_power_begin(dev, false)) {
+		htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
+		hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
+		vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
+		vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
+		gma_power_end(dev);
+	} else {
+		htot = (pipe == 0) ?
+			dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
+		hsync = (pipe == 0) ?
+			dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
+		vtot = (pipe == 0) ?
+			dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
+		vsync = (pipe == 0) ?
+			dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
+	}
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode)
+		return NULL;
+
+	mode->clock = cdv_intel_crtc_clock_get(dev, crtc);
+	mode->hdisplay = (htot & 0xffff) + 1;
+	mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
+	mode->hsync_start = (hsync & 0xffff) + 1;
+	mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
+	mode->vdisplay = (vtot & 0xffff) + 1;
+	mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
+	mode->vsync_start = (vsync & 0xffff) + 1;
+	mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	return mode;
+}
+
+static void cdv_intel_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+	kfree(psb_intel_crtc->crtc_state);
+	drm_crtc_cleanup(crtc);
+	kfree(psb_intel_crtc);
+}
+
+const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
+	.dpms = cdv_intel_crtc_dpms,
+	.mode_fixup = cdv_intel_crtc_mode_fixup,
+	.mode_set = cdv_intel_crtc_mode_set,
+	.mode_set_base = cdv_intel_pipe_set_base,
+	.prepare = cdv_intel_crtc_prepare,
+	.commit = cdv_intel_crtc_commit,
+};
+
+const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
+	.save = cdv_intel_crtc_save,
+	.restore = cdv_intel_crtc_restore,
+	.cursor_set = cdv_intel_crtc_cursor_set,
+	.cursor_move = cdv_intel_crtc_cursor_move,
+	.gamma_set = cdv_intel_crtc_gamma_set,
+	.set_config = cdv_crtc_set_config,
+	.destroy = cdv_intel_crtc_destroy,
+};
+
+/*
+ * Set the default value of cursor control and base register
+ * to zero. This is a workaround for h/w defect on oaktrail
+ */
+void cdv_intel_cursor_init(struct drm_device *dev, int pipe)
+{
+	uint32_t control;
+	uint32_t base;
+      
+	switch (pipe) {
+	case 0:
+		control = CURACNTR;
+		base = CURABASE;
+		break;
+	case 1:
+		control = CURBCNTR;
+		base = CURBBASE;
+		break;
+	case 2:
+		control = CURCCNTR;
+		base = CURCBASE;
+		break;
+	default:
+		return;
+	}
+
+	REG_WRITE(control, 0);
+	REG_WRITE(base, 0);
+}
+
diff --git a/drivers/staging/gma500/cdv_intel_lvds.c b/drivers/staging/gma500/cdv_intel_lvds.c
new file mode 100644
index 0000000..d9b2290
--- /dev/null
+++ b/drivers/staging/gma500/cdv_intel_lvds.c
@@ -0,0 +1,718 @@
+/*
+ * Copyright © 2006-2011 Intel Corporation
+ *
+ * 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:
+ *	Eric Anholt <eric@anholt.net>
+ *	Dave Airlie <airlied@linux.ie>
+ *	Jesse Barnes <jesse.barnes@intel.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/dmi.h>
+#include <drm/drmP.h>
+
+#include "intel_bios.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "power.h"
+#include <linux/pm_runtime.h>
+#include "cdv_device.h"
+
+/**
+ * LVDS I2C backlight control macros
+ */
+#define BRIGHTNESS_MAX_LEVEL 100
+#define BRIGHTNESS_MASK 0xFF
+#define BLC_I2C_TYPE	0x01
+#define BLC_PWM_TYPT	0x02
+
+#define BLC_POLARITY_NORMAL 0
+#define BLC_POLARITY_INVERSE 1
+
+#define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE)
+#define PSB_BLC_MIN_PWM_REG_FREQ	(0x2)
+#define PSB_BLC_PWM_PRECISION_FACTOR	(10)
+#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
+#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
+
+struct cdv_intel_lvds_priv {
+	/**
+	 * Saved LVDO output states
+	 */
+	uint32_t savePP_ON;
+	uint32_t savePP_OFF;
+	uint32_t saveLVDS;
+	uint32_t savePP_CONTROL;
+	uint32_t savePP_CYCLE;
+	uint32_t savePFIT_CONTROL;
+	uint32_t savePFIT_PGM_RATIOS;
+	uint32_t saveBLC_PWM_CTL;
+};
+
+/*
+ * Returns the maximum level of the backlight duty cycle field.
+ */
+static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 retval;
+
+	if (gma_power_begin(dev, false)) {
+		retval = ((REG_READ(BLC_PWM_CTL) &
+			  BACKLIGHT_MODULATION_FREQ_MASK) >>
+			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+		gma_power_end(dev);
+	} else
+		retval = ((dev_priv->saveBLC_PWM_CTL &
+			  BACKLIGHT_MODULATION_FREQ_MASK) >>
+			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+	return retval;
+}
+
+/*
+ * Set LVDS backlight level by I2C command
+ */
+static int cdv_lvds_i2c_set_brightness(struct drm_device *dev,
+					unsigned int level)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
+	u8 out_buf[2];
+	unsigned int blc_i2c_brightness;
+
+	struct i2c_msg msgs[] = {
+		{
+			.addr = lvds_i2c_bus->slave_addr,
+			.flags = 0,
+			.len = 2,
+			.buf = out_buf,
+		}
+	};
+
+	blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
+			     BRIGHTNESS_MASK /
+			     BRIGHTNESS_MAX_LEVEL);
+
+	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
+		blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
+
+	out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
+	out_buf[1] = (u8)blc_i2c_brightness;
+
+	if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1)
+		return 0;
+
+	DRM_ERROR("I2C transfer error\n");
+	return -1;
+}
+
+
+static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	u32 max_pwm_blc;
+	u32 blc_pwm_duty_cycle;
+
+	max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev);
+
+	/*BLC_PWM_CTL Should be initiated while backlight device init*/
+	BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
+
+	blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
+
+	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
+		blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
+
+	blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
+	REG_WRITE(BLC_PWM_CTL,
+		  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
+		  (blc_pwm_duty_cycle));
+
+	return 0;
+}
+
+/*
+ * Set LVDS backlight level either by I2C or PWM
+ */
+void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (!dev_priv->lvds_bl) {
+		DRM_ERROR("NO LVDS Backlight Info\n");
+		return;
+	}
+
+	if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
+		cdv_lvds_i2c_set_brightness(dev, level);
+	else
+		cdv_lvds_pwm_set_brightness(dev, level);
+}
+
+/**
+ * Sets the backlight level.
+ *
+ * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight().
+ */
+static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 blc_pwm_ctl;
+
+	if (gma_power_begin(dev, false)) {
+		blc_pwm_ctl =
+			REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+		REG_WRITE(BLC_PWM_CTL,
+				(blc_pwm_ctl |
+				(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
+		gma_power_end(dev);
+	} else {
+		blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
+				~BACKLIGHT_DUTY_CYCLE_MASK;
+		dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
+					(level << BACKLIGHT_DUTY_CYCLE_SHIFT));
+	}
+}
+
+/**
+ * Sets the power state for the panel.
+ */
+static void cdv_intel_lvds_set_power(struct drm_device *dev,
+				 struct psb_intel_output *output, bool on)
+{
+	u32 pp_status;
+
+	if (!gma_power_begin(dev, true))
+	        return;
+
+	if (on) {
+		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
+			  POWER_TARGET_ON);
+		do {
+			pp_status = REG_READ(PP_STATUS);
+		} while ((pp_status & PP_ON) == 0);
+
+		cdv_intel_lvds_set_backlight(dev,
+					 output->
+					 mode_dev->backlight_duty_cycle);
+	} else {
+		cdv_intel_lvds_set_backlight(dev, 0);
+
+		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
+			  ~POWER_TARGET_ON);
+		do {
+			pp_status = REG_READ(PP_STATUS);
+		} while (pp_status & PP_ON);
+	}
+	gma_power_end(dev);
+}
+
+static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	if (mode == DRM_MODE_DPMS_ON)
+		cdv_intel_lvds_set_power(dev, output, true);
+	else
+		cdv_intel_lvds_set_power(dev, output, false);
+	/* XXX: We never power down the LVDS pairs. */
+}
+
+static void cdv_intel_lvds_save(struct drm_connector *connector)
+{
+}
+
+static void cdv_intel_lvds_restore(struct drm_connector *connector)
+{
+}
+
+int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
+				 struct drm_display_mode *mode)
+{
+	struct psb_intel_output *psb_intel_output =
+				to_psb_intel_output(connector);
+	struct drm_display_mode *fixed_mode =
+	    psb_intel_output->mode_dev->panel_fixed_mode;
+
+	/* just in case */
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		return MODE_NO_DBLESCAN;
+
+	/* just in case */
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		return MODE_NO_INTERLACE;
+
+	if (fixed_mode) {
+		if (mode->hdisplay > fixed_mode->hdisplay)
+			return MODE_PANEL;
+		if (mode->vdisplay > fixed_mode->vdisplay)
+			return MODE_PANEL;
+	}
+	return MODE_OK;
+}
+
+bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	struct psb_intel_mode_device *mode_dev =
+	    enc_to_psb_intel_output(encoder)->mode_dev;
+	struct drm_device *dev = encoder->dev;
+	struct drm_encoder *tmp_encoder;
+	struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
+
+	/* Should never happen!! */
+	list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
+			    head) {
+		if (tmp_encoder != encoder
+		    && tmp_encoder->crtc == encoder->crtc) {
+			printk(KERN_ERR "Can't enable LVDS and another "
+			       "encoder on the same pipe\n");
+			return false;
+		}
+	}
+
+	/*
+	 * If we have timings from the BIOS for the panel, put them in
+	 * to the adjusted mode.  The CRTC will be set up for this mode,
+	 * with the panel scaling set up to source from the H/VDisplay
+	 * of the original mode.
+	 */
+	if (panel_fixed_mode != NULL) {
+		adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
+		adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
+		adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
+		adjusted_mode->htotal = panel_fixed_mode->htotal;
+		adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
+		adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
+		adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
+		adjusted_mode->vtotal = panel_fixed_mode->vtotal;
+		adjusted_mode->clock = panel_fixed_mode->clock;
+		drm_mode_set_crtcinfo(adjusted_mode,
+				      CRTC_INTERLACE_HALVE_V);
+	}
+
+	/*
+	 * XXX: It would be nice to support lower refresh rates on the
+	 * panels to reduce power consumption, and perhaps match the
+	 * user's requested refresh rate.
+	 */
+
+	return true;
+}
+
+static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	struct psb_intel_mode_device *mode_dev = output->mode_dev;
+
+	if (!gma_power_begin(dev, true))
+		return;
+
+	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
+	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
+					  BACKLIGHT_DUTY_CYCLE_MASK);
+
+	cdv_intel_lvds_set_power(dev, output, false);
+
+	gma_power_end(dev);
+}
+
+static void cdv_intel_lvds_commit(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	struct psb_intel_mode_device *mode_dev = output->mode_dev;
+
+	if (mode_dev->backlight_duty_cycle == 0)
+		mode_dev->backlight_duty_cycle =
+		    cdv_intel_lvds_get_max_backlight(dev);
+
+	cdv_intel_lvds_set_power(dev, output, true);
+}
+
+static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct psb_intel_mode_device *mode_dev =
+	    enc_to_psb_intel_output(encoder)->mode_dev;
+	struct drm_device *dev = encoder->dev;
+	u32 pfit_control;
+
+	/*
+	 * The LVDS pin pair will already have been turned on in the
+	 * cdv_intel_crtc_mode_set since it has a large impact on the DPLL
+	 * settings.
+	 */
+
+	/*
+	 * Enable automatic panel scaling so that non-native modes fill the
+	 * screen.  Should be enabled before the pipe is enabled, according to
+	 * register description and PRM.
+	 */
+	if (mode->hdisplay != adjusted_mode->hdisplay ||
+	    mode->vdisplay != adjusted_mode->vdisplay)
+		pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
+				HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
+				HORIZ_INTERP_BILINEAR);
+	else
+		pfit_control = 0;
+
+	if (mode_dev->panel_wants_dither)
+		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+
+	REG_WRITE(PFIT_CONTROL, pfit_control);
+}
+
+/**
+ * Detect the LVDS connection.
+ *
+ * This always returns CONNECTOR_STATUS_CONNECTED.
+ * This connector should only have
+ * been set up if the LVDS was actually connected anyway.
+ */
+static enum drm_connector_status cdv_intel_lvds_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+/**
+ * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
+ */
+static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+	struct psb_intel_mode_device *mode_dev =
+					psb_intel_output->mode_dev;
+	int ret;
+
+	ret = psb_intel_ddc_get_modes(psb_intel_output);
+
+	if (ret)
+		return ret;
+
+	/* Didn't get an EDID, so
+	 * Set wide sync ranges so we get all modes
+	 * handed to valid_mode for checking
+	 */
+	connector->display_info.min_vfreq = 0;
+	connector->display_info.max_vfreq = 200;
+	connector->display_info.min_hfreq = 0;
+	connector->display_info.max_hfreq = 200;
+	if (mode_dev->panel_fixed_mode != NULL) {
+		struct drm_display_mode *mode =
+		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+		drm_mode_probed_add(connector, mode);
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * cdv_intel_lvds_destroy - unregister and free LVDS structures
+ * @connector: connector to free
+ *
+ * Unregister the DDC bus for this connector then free the driver private
+ * structure.
+ */
+void cdv_intel_lvds_destroy(struct drm_connector *connector)
+{
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+
+	if (psb_intel_output->ddc_bus)
+		psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+int cdv_intel_lvds_set_property(struct drm_connector *connector,
+				       struct drm_property *property,
+				       uint64_t value)
+{
+	struct drm_encoder *encoder = connector->encoder;
+
+	if (!strcmp(property->name, "scaling mode") && encoder) {
+		struct psb_intel_crtc *crtc =
+					to_psb_intel_crtc(encoder->crtc);
+		uint64_t curValue;
+
+		if (!crtc)
+			return -1;
+
+		switch (value) {
+		case DRM_MODE_SCALE_FULLSCREEN:
+			break;
+		case DRM_MODE_SCALE_NO_SCALE:
+			break;
+		case DRM_MODE_SCALE_ASPECT:
+			break;
+		default:
+			return -1;
+		}
+
+		if (drm_connector_property_get_value(connector,
+						     property,
+						     &curValue))
+			return -1;
+
+		if (curValue == value)
+			return 0;
+
+		if (drm_connector_property_set_value(connector,
+							property,
+							value))
+			return -1;
+
+		if (crtc->saved_mode.hdisplay != 0 &&
+		    crtc->saved_mode.vdisplay != 0) {
+			if (!drm_crtc_helper_set_mode(encoder->crtc,
+						      &crtc->saved_mode,
+						      encoder->crtc->x,
+						      encoder->crtc->y,
+						      encoder->crtc->fb))
+				return -1;
+		}
+	} else if (!strcmp(property->name, "backlight") && encoder) {
+		if (drm_connector_property_set_value(connector,
+							property,
+							value))
+			return -1;
+		else {
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+                	struct drm_psb_private *dev_priv =
+						encoder->dev->dev_private;
+			struct backlight_device *bd = dev_priv->backlight_device;
+			bd->props.brightness = value;
+			backlight_update_status(bd);
+#endif
+		}
+	} else if (!strcmp(property->name, "DPMS") && encoder) {
+		struct drm_encoder_helper_funcs *helpers = encoder->helper_private;
+		helpers->dpms(encoder, value);
+	}
+	return 0;
+}
+
+static const struct drm_encoder_helper_funcs cdv_intel_lvds_helper_funcs = {
+	.dpms = cdv_intel_lvds_encoder_dpms,
+	.mode_fixup = cdv_intel_lvds_mode_fixup,
+	.prepare = cdv_intel_lvds_prepare,
+	.mode_set = cdv_intel_lvds_mode_set,
+	.commit = cdv_intel_lvds_commit,
+};
+
+static const struct drm_connector_helper_funcs
+    cdv_intel_lvds_connector_helper_funcs = {
+	.get_modes = cdv_intel_lvds_get_modes,
+	.mode_valid = cdv_intel_lvds_mode_valid,
+	.best_encoder = psb_intel_best_encoder,
+};
+
+static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.save = cdv_intel_lvds_save,
+	.restore = cdv_intel_lvds_restore,
+	.detect = cdv_intel_lvds_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = cdv_intel_lvds_set_property,
+	.destroy = cdv_intel_lvds_destroy,
+};
+
+
+static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
+	.destroy = cdv_intel_lvds_enc_destroy,
+};
+
+/**
+ * cdv_intel_lvds_init - setup LVDS connectors on this device
+ * @dev: drm device
+ *
+ * Create the connector, register the LVDS DDC bus, and try to figure out what
+ * modes we can display on the LVDS panel (if present).
+ */
+void cdv_intel_lvds_init(struct drm_device *dev,
+		     struct psb_intel_mode_device *mode_dev)
+{
+	struct psb_intel_output *psb_intel_output;
+	struct cdv_intel_lvds_priv *lvds_priv;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct drm_display_mode *scan;
+	struct drm_crtc *crtc;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 lvds;
+	int pipe;
+
+	psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
+			sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL);
+	if (!psb_intel_output)
+		return;
+
+	lvds_priv = (struct cdv_intel_lvds_priv *)(psb_intel_output + 1);
+
+	psb_intel_output->dev_priv = lvds_priv;
+
+	psb_intel_output->mode_dev = mode_dev;
+	connector = &psb_intel_output->base;
+	encoder = &psb_intel_output->enc;
+
+
+	drm_connector_init(dev, &psb_intel_output->base,
+			   &cdv_intel_lvds_connector_funcs,
+			   DRM_MODE_CONNECTOR_LVDS);
+
+	drm_encoder_init(dev, &psb_intel_output->enc,
+			 &cdv_intel_lvds_enc_funcs,
+			 DRM_MODE_ENCODER_LVDS);
+
+
+	drm_mode_connector_attach_encoder(&psb_intel_output->base,
+					  &psb_intel_output->enc);
+	psb_intel_output->type = INTEL_OUTPUT_LVDS;
+
+	drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs);
+	drm_connector_helper_add(connector,
+				 &cdv_intel_lvds_connector_helper_funcs);
+	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+	connector->interlace_allowed = false;
+	connector->doublescan_allowed = false;
+
+	/*Attach connector properties*/
+	drm_connector_attach_property(connector,
+				      dev->mode_config.scaling_mode_property,
+				      DRM_MODE_SCALE_FULLSCREEN);
+	drm_connector_attach_property(connector,
+				      dev_priv->backlight_property,
+				      BRIGHTNESS_MAX_LEVEL);
+
+	/**
+	 * Set up I2C bus
+	 * FIXME: distroy i2c_bus when exit
+	 */
+	psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
+							 GPIOB,
+							 "LVDSBLC_B");
+	if (!psb_intel_output->i2c_bus) {
+		dev_printk(KERN_ERR,
+			&dev->pdev->dev, "I2C bus registration failed.\n");
+		goto failed_blc_i2c;
+	}
+	psb_intel_output->i2c_bus->slave_addr = 0x2C;
+	dev_priv->lvds_i2c_bus =  psb_intel_output->i2c_bus;
+
+	/*
+	 * LVDS discovery:
+	 * 1) check for EDID on DDC
+	 * 2) check for VBT data
+	 * 3) check to see if LVDS is already on
+	 *    if none of the above, no panel
+	 * 4) make sure lid is open
+	 *    if closed, act like it's not there for now
+	 */
+
+	/* Set up the DDC bus. */
+	psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
+							 GPIOC,
+							 "LVDSDDC_C");
+	if (!psb_intel_output->ddc_bus) {
+		dev_printk(KERN_ERR, &dev->pdev->dev,
+			   "DDC bus registration " "failed.\n");
+		goto failed_ddc;
+	}
+
+	/*
+	 * Attempt to get the fixed panel mode from DDC.  Assume that the
+	 * preferred mode is the right one.
+	 */
+	psb_intel_ddc_get_modes(psb_intel_output);
+	list_for_each_entry(scan, &connector->probed_modes, head) {
+		if (scan->type & DRM_MODE_TYPE_PREFERRED) {
+			mode_dev->panel_fixed_mode =
+			    drm_mode_duplicate(dev, scan);
+			goto out;	/* FIXME: check for quirks */
+		}
+	}
+
+	/* Failed to get EDID, what about VBT? do we need this?*/
+	if (dev_priv->lfp_lvds_vbt_mode) {
+		mode_dev->panel_fixed_mode =
+			drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
+		if (mode_dev->panel_fixed_mode) {
+			mode_dev->panel_fixed_mode->type |=
+				DRM_MODE_TYPE_PREFERRED;
+			goto out;	/* FIXME: check for quirks */
+		}
+	}
+	/*
+	 * If we didn't get EDID, try checking if the panel is already turned
+	 * on.	If so, assume that whatever is currently programmed is the
+	 * correct mode.
+	 */
+	lvds = REG_READ(LVDS);
+	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
+	crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
+
+	if (crtc && (lvds & LVDS_PORT_EN)) {
+		mode_dev->panel_fixed_mode =
+		    cdv_intel_crtc_mode_get(dev, crtc);
+		if (mode_dev->panel_fixed_mode) {
+			mode_dev->panel_fixed_mode->type |=
+			    DRM_MODE_TYPE_PREFERRED;
+			goto out;	/* FIXME: check for quirks */
+		}
+	}
+
+	/* If we still don't have a mode after all that, give up. */
+	if (!mode_dev->panel_fixed_mode) {
+		DRM_DEBUG
+			("Found no modes on the lvds, ignoring the LVDS\n");
+		goto failed_find;
+	}
+
+out:
+	drm_sysfs_connector_add(connector);
+	return;
+
+failed_find:
+	printk(KERN_ERR "Failed find\n");
+	if (psb_intel_output->ddc_bus)
+		psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
+failed_ddc:
+	printk(KERN_ERR "Failed DDC\n");
+	if (psb_intel_output->i2c_bus)
+		psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
+failed_blc_i2c:
+	printk(KERN_ERR "Failed BLC\n");
+	drm_encoder_cleanup(encoder);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c
index 716a7b9..c6dd4d8 100644
--- a/drivers/staging/gma500/framebuffer.c
+++ b/drivers/staging/gma500/framebuffer.c
@@ -732,6 +732,10 @@ static void psb_setup_outputs(struct drm_device *dev)
 
 		/* valid crtcs */
 		switch (psb_intel_output->type) {
+		case INTEL_OUTPUT_ANALOG:
+			crtc_mask = (1 << 0);
+			clone_mask = (1 << INTEL_OUTPUT_ANALOG);
+			break;
 		case INTEL_OUTPUT_SDVO:
 			crtc_mask = ((1 << 0) | (1 << 1));
 			clone_mask = (1 << INTEL_OUTPUT_SDVO);
@@ -752,7 +756,10 @@ static void psb_setup_outputs(struct drm_device *dev)
 			clone_mask = (1 << INTEL_OUTPUT_MIPI2);
 			break;
 		case INTEL_OUTPUT_HDMI:
-			crtc_mask = (1 << 1);
+		        if (IS_MFLD(dev))
+        			crtc_mask = (1 << 1);
+                        else	/* FIXME: review Oaktrail */
+                                crtc_mask = (1 << 0);	/* Cedarview */
 			clone_mask = (1 << INTEL_OUTPUT_HDMI);
 			break;
 		}
diff --git a/drivers/staging/gma500/gtt.c b/drivers/staging/gma500/gtt.c
index 6cfa59b..28f2261 100644
--- a/drivers/staging/gma500/gtt.c
+++ b/drivers/staging/gma500/gtt.c
@@ -395,12 +395,10 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	(void) PSB_RVDC32(PSB_PGETBL_CTL);
 
 	/* The root resource we allocate address space from */
-	dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
 	dev_priv->gtt_initialized = 1;
 
-	pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
-
-	pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+	pg->gtt_phys_start = dev_priv->pge_ctl;
+	
 	/*
 	 *	FIXME: video mmu has hw bug to access 0x0D0000000,
 	 *	then make gatt start at 0x0e000,0000
@@ -410,8 +408,33 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
 	gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
 								>> PAGE_SHIFT;
+	/* CDV workaround */
+	if (pg->gtt_start == 0 || gtt_pages == 0) {
+		dev_err(dev->dev, "GTT PCI BAR not initialized.\n");
+		gtt_pages = 64;
+		pg->gtt_start = dev_priv->pge_ctl;
+	}
+
+	pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
 	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
 								>> PAGE_SHIFT;
+	dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
+
+	if (pg->gatt_pages == 0 || pg->gatt_start == 0) {
+		static struct resource fudge;	/* Preferably peppermint */
+
+		/* This can occur on CDV SDV systems. Fudge it in this case.
+		   We really don't care what imaginary space is being allocated
+		   at this point */
+		dev_err(dev->dev, "GATT PCI BAR not initialized.\n");
+		pg->gatt_start = 0x40000000;
+		pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT;
+		fudge.start = 0x40000000;
+		fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1;
+		fudge.name = "fudge";
+		fudge.flags = IORESOURCE_MEM;
+		dev_priv->gtt_mem = &fudge;
+	}
 
 	pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
 	vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base
@@ -463,7 +486,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
 	vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
 	printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
-		num_pages, pfn_base, 0);
+		num_pages, pfn_base << PAGE_SHIFT, 0);
 	for (i = 0; i < num_pages; ++i) {
 		pte = psb_gtt_mask_pte(pfn_base + i, 0);
 		iowrite32(pte, dev_priv->gtt_map + i);
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index 8f503d9..bd0a4bc 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -1039,14 +1039,13 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
 	}
 
 	/* unpin the old bo */
-	if (psb_intel_crtc->cursor_obj && psb_intel_crtc->cursor_obj != obj) {
+	if (psb_intel_crtc->cursor_obj) {
 		gt = container_of(psb_intel_crtc->cursor_obj,
 							struct gtt_range, gem);
 		psb_gtt_unpin(gt);
 		drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
 		psb_intel_crtc->cursor_obj = obj;
 	}
-
 	return 0;
 }
 
diff --git a/drivers/staging/gma500/psb_intel_reg.h b/drivers/staging/gma500/psb_intel_reg.h
index c9630a2..1ac16aa 100644
--- a/drivers/staging/gma500/psb_intel_reg.h
+++ b/drivers/staging/gma500/psb_intel_reg.h
@@ -142,6 +142,8 @@
 #define DPLLB_LVDS_P2_CLOCK_DIV_7	(1 << 24)	/* i915 */
 #define DPLL_P2_CLOCK_DIV_MASK		0x03000000	/* i915 */
 #define DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000	/* i915 */
+#define DPLL_LOCK			(1 << 15)	/* CDV */
+
 /*
  *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
  * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
@@ -271,6 +273,20 @@
 #define TV_HOTPLUG_INT_EN		(1 << 18)
 #define CRT_HOTPLUG_INT_EN		(1 << 9)
 #define CRT_HOTPLUG_FORCE_DETECT	(1 << 3)
+/* CDV.. */
+#define CRT_HOTPLUG_ACTIVATION_PERIOD_64	(1 << 8)
+#define CRT_HOTPLUG_DAC_ON_TIME_2M		(0 << 7)
+#define CRT_HOTPLUG_DAC_ON_TIME_4M		(1 << 7)
+#define CRT_HOTPLUG_VOLTAGE_COMPARE_40		(0 << 5)
+#define CRT_HOTPLUG_VOLTAGE_COMPARE_50		(1 << 5)
+#define CRT_HOTPLUG_VOLTAGE_COMPARE_60		(2 << 5)
+#define CRT_HOTPLUG_VOLTAGE_COMPARE_70		(3 << 5)
+#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK	(3 << 5)
+#define CRT_HOTPLUG_DETECT_DELAY_1G		(0 << 4)
+#define CRT_HOTPLUG_DETECT_DELAY_2G		(1 << 4)
+#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV	(0 << 2)
+#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV	(1 << 2)
+#define CRT_HOTPLUG_DETECT_MASK			0x000000F8
 
 #define PORT_HOTPLUG_STAT	0x61114
 #define CRT_HOTPLUG_INT_STATUS		(1 << 11)
@@ -1141,4 +1157,79 @@ No status bits are changed.
 #define SKU_100L			0x04
 #define SKU_BYPASS			0x08
 
+/* Some handy macros for playing with bitfields. */
+#define PSB_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low))
+#define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK)
+#define GET_FIELD(word, field) (((word)  & field ## _MASK) >> field ## _SHIFT)
+
+#define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a)))
+
+/* PCI config space */
+
+#define SB_PCKT         0x02100 /* cedarview */
+# define SB_OPCODE_MASK                         PSB_MASK(31, 16)
+# define SB_OPCODE_SHIFT                        16
+# define SB_OPCODE_READ                         0
+# define SB_OPCODE_WRITE                        1
+# define SB_DEST_MASK                           PSB_MASK(15, 8)
+# define SB_DEST_SHIFT                          8
+# define SB_DEST_DPLL                           0x88
+# define SB_BYTE_ENABLE_MASK                    PSB_MASK(7, 4)
+# define SB_BYTE_ENABLE_SHIFT                   4
+# define SB_BUSY                                (1 << 0)
+
+
+/* 32-bit value read/written from the DPIO reg. */
+#define SB_DATA		0x02104 /* cedarview */
+/* 32-bit address of the DPIO reg to be read/written. */
+#define SB_ADDR		0x02108 /* cedarview */
+#define DPIO_CFG	0x02110 /* cedarview */
+# define DPIO_MODE_SELECT_1			(1 << 3)
+# define DPIO_MODE_SELECT_0			(1 << 2)
+# define DPIO_SFR_BYPASS			(1 << 1)
+/* reset is active low */
+# define DPIO_CMN_RESET_N			(1 << 0)
+
+/* Cedarview sideband registers */
+#define _SB_M_A			0x8008
+#define _SB_M_B			0x8028
+#define SB_M(pipe) _PIPE(pipe, _SB_M_A, _SB_M_B)
+# define SB_M_DIVIDER_MASK			(0xFF << 24)
+# define SB_M_DIVIDER_SHIFT			24
+
+#define _SB_N_VCO_A		0x8014
+#define _SB_N_VCO_B		0x8034
+#define SB_N_VCO(pipe) _PIPE(pipe, _SB_N_VCO_A, _SB_N_VCO_B)
+#define SB_N_VCO_SEL_MASK			PSB_MASK(31, 30)
+#define SB_N_VCO_SEL_SHIFT			30
+#define SB_N_DIVIDER_MASK			PSB_MASK(29, 26)
+#define SB_N_DIVIDER_SHIFT			26
+#define SB_N_CB_TUNE_MASK			PSB_MASK(25, 24)
+#define SB_N_CB_TUNE_SHIFT			24
+
+#define _SB_REF_A		0x8018
+#define _SB_REF_B		0x8038
+#define SB_REF_SFR(pipe)	_PIPE(pipe, _SB_REF_A, _SB_REF_B)
+
+#define _SB_P_A			0x801c
+#define _SB_P_B			0x803c
+#define SB_P(pipe) _PIPE(pipe, _SB_P_A, _SB_P_B)
+#define SB_P2_DIVIDER_MASK			PSB_MASK(31, 30)
+#define SB_P2_DIVIDER_SHIFT			30
+#define SB_P2_10				0 /* HDMI, DP, DAC */
+#define SB_P2_5				1 /* DAC */
+#define SB_P2_14				2 /* LVDS single */
+#define SB_P2_7				3 /* LVDS double */
+#define SB_P1_DIVIDER_MASK			PSB_MASK(15, 12)
+#define SB_P1_DIVIDER_SHIFT			12
+
+#define PSB_LANE0		0x120
+#define PSB_LANE1		0x220
+#define PSB_LANE2		0x2320
+#define PSB_LANE3		0x2420
+
+#define LANE_PLL_MASK		(0x7 << 20)
+#define LANE_PLL_ENABLE		(0x3 << 20)
+
+
 #endif


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 45/49] gma500: Add the HDMI bits
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (43 preceding siblings ...)
  2011-07-05 14:44 ` [PATCH 44/49] gma500: begin adding CDV specific code Alan Cox
@ 2011-07-05 14:44 ` Alan Cox
  2011-07-05 14:44 ` [PATCH 46/49] gma500: Fix backlight crash Alan Cox
                   ` (4 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:44 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

This adds the basic HDMI support for Cedarview.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/Makefile        |    3 ++-
 drivers/staging/gma500/cdv_device.c    |    4 ++--
 drivers/staging/gma500/psb_intel_drv.h |    2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index 507aaaf..e515edf 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -25,8 +25,9 @@ psb_gfx-y += gem_glue.o \
 	  mid_bios.o
 
 psb_gfx-$(CONFIG_DRM_PSB_CDV) +=  cdv_device.o \
-	  cdv_intel_display.o \
 	  cdv_intel_crt.o \
+	  cdv_intel_display.o \
+	  cdv_intel_hdmi.o \
 	  cdv_intel_lvds.o
 
 psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \
diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c
index 622c955..680f1bb 100644
--- a/drivers/staging/gma500/cdv_device.c
+++ b/drivers/staging/gma500/cdv_device.c
@@ -58,9 +58,9 @@ static int cdv_output_init(struct drm_device *dev)
 	/* These bits indicate HDMI not SDVO on CDV, but we don't yet support
 	   the HDMI interface */
 	if (REG_READ(SDVOB) & SDVO_DETECTED)
-		DRM_ERROR("HDMI not supported yet\n");
+		cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB);
 	if (REG_READ(SDVOC) & SDVO_DETECTED)
-		DRM_ERROR("HDMI not supported yet\n");
+		cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC);
 	return 0;
 }
 
diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h
index 9d7151a..36b554b 100644
--- a/drivers/staging/gma500/psb_intel_drv.h
+++ b/drivers/staging/gma500/psb_intel_drv.h
@@ -105,7 +105,7 @@ struct psb_intel_output {
 	void *dev_priv;
 
 	struct psb_intel_mode_device *mode_dev;
-
+	struct i2c_adapter *hdmi_i2c_adapter;	/* for control functions */
 };
 
 struct psb_intel_crtc_state {


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 46/49] gma500: Fix backlight crash
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (44 preceding siblings ...)
  2011-07-05 14:44 ` [PATCH 45/49] gma500: Add the HDMI bits Alan Cox
@ 2011-07-05 14:44 ` Alan Cox
  2011-07-05 14:44 ` [PATCH 47/49] gma500: Workaround for Medfield/Cedarview cursor bug Alan Cox
                   ` (3 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:44 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

We need to check the NULL case earlier.

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/backlight.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c
index 4027e70..d3e698b 100644
--- a/drivers/staging/gma500/backlight.c
+++ b/drivers/staging/gma500/backlight.c
@@ -38,9 +38,10 @@ void gma_backlight_exit(struct drm_device *dev)
 {
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	dev_priv->backlight_device->props.brightness = 0;
-	backlight_update_status(dev_priv->backlight_device);
-	if (dev_priv->backlight_device)
+	if (dev_priv->backlight_device) {
+		dev_priv->backlight_device->props.brightness = 0;
+		backlight_update_status(dev_priv->backlight_device);
 		backlight_device_unregister(dev_priv->backlight_device);
+	}
 #endif
 }


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 47/49] gma500: Workaround for Medfield/Cedarview cursor bug
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (45 preceding siblings ...)
  2011-07-05 14:44 ` [PATCH 46/49] gma500: Fix backlight crash Alan Cox
@ 2011-07-05 14:44 ` Alan Cox
  2011-07-05 14:45 ` [PATCH 48/49] gma500: Fix missing memory check Alan Cox
                   ` (2 subsequent siblings)
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:44 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/psb_intel_display.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
index bd0a4bc..8b84462 100644
--- a/drivers/staging/gma500/psb_intel_display.c
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -1278,6 +1278,19 @@ const struct drm_crtc_funcs psb_intel_crtc_funcs = {
 	.destroy = psb_intel_crtc_destroy,
 };
 
+/*
+ * Set the default value of cursor control and base register
+ * to zero. This is a workaround for h/w defect on Oaktrail
+ */
+static void psb_intel_cursor_init(struct drm_device *dev, int pipe)
+{
+        u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR };
+        u32 base[3] = { CURABASE, CURBBASE, CURCBASE };
+        
+	REG_WRITE(control[pipe], 0);
+	REG_WRITE(base[pipe], 0);
+}
+
 void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 		     struct psb_intel_mode_device *mode_dev)
 {
@@ -1341,6 +1354,7 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
 	psb_intel_crtc->mode_set.connectors =
 	    (struct drm_connector **) (psb_intel_crtc + 1);
 	psb_intel_crtc->mode_set.num_connectors = 0;
+	psb_intel_cursor_init(dev, pipe);
 }
 
 int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 48/49] gma500: Fix missing memory check
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (46 preceding siblings ...)
  2011-07-05 14:44 ` [PATCH 47/49] gma500: Workaround for Medfield/Cedarview cursor bug Alan Cox
@ 2011-07-05 14:45 ` Alan Cox
  2011-07-05 14:45 ` [PATCH 49/49] gma500: power can be touched in IRQ state Alan Cox
  2011-07-05 15:23 ` [PATCH 00/49] GMA50 series update Greg KH
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:45 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/intel_bios.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/gma500/intel_bios.c b/drivers/staging/gma500/intel_bios.c
index 1c4714d..096757f 100644
--- a/drivers/staging/gma500/intel_bios.c
+++ b/drivers/staging/gma500/intel_bios.c
@@ -139,14 +139,18 @@ static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
 	if (!lvds_lfp_data)
 		return;
 
-	dev_priv->lvds_vbt = 1;
 
 	entry = &lvds_lfp_data->data[lvds_options->panel_type];
 	dvo_timing = &entry->dvo_timing;
 
 	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode),
 				      GFP_KERNEL);
+	if (panel_fixed_mode == NULL) {
+		dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n");
+		return;
+	}
 
+	dev_priv->lvds_vbt = 1;
 	fill_detail_timing_data(panel_fixed_mode, dvo_timing);
 
 	if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) {


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* [PATCH 49/49] gma500: power can be touched in IRQ state
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (47 preceding siblings ...)
  2011-07-05 14:45 ` [PATCH 48/49] gma500: Fix missing memory check Alan Cox
@ 2011-07-05 14:45 ` Alan Cox
  2011-07-05 15:23 ` [PATCH 00/49] GMA50 series update Greg KH
  49 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-07-05 14:45 UTC (permalink / raw)
  To: greg, linux-kernel

From: Alan Cox <alan@linux.intel.com>

So we need to use a spinlock here

Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/staging/gma500/power.c |   18 ++++++++++--------
 1 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
index 79eb670..5cd5023 100644
--- a/drivers/staging/gma500/power.c
+++ b/drivers/staging/gma500/power.c
@@ -36,7 +36,7 @@
 #include <linux/pm_runtime.h>
 
 static struct mutex power_mutex;	/* Serialize power ops */
-static struct mutex power_ctrl_mutex;	/* Serialize power claim */
+static spinlock_t power_ctrl_lock;	/* Serialize power claim */
 
 /**
  *	gma_power_init		-	initialise power manager
@@ -55,8 +55,8 @@ void gma_power_init(struct drm_device *dev)
 	dev_priv->display_power = true;	/* We start active */
 	dev_priv->display_count = 0;	/* Currently no users */
 	dev_priv->suspended = false;	/* And not suspended */
+	spin_lock_init(&power_ctrl_lock);
 	mutex_init(&power_mutex);
-	mutex_init(&power_ctrl_mutex);
 
 	dev_priv->ops->init_pm(dev);
 }
@@ -247,13 +247,14 @@ bool gma_power_begin(struct drm_device *dev, bool force_on)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	int ret;
+	unsigned long flags;
 
-	mutex_lock(&power_ctrl_mutex);
+	spin_lock_irqsave(&power_ctrl_lock, flags);
 	/* Power already on ? */
 	if (dev_priv->display_power) {
 		dev_priv->display_count++;
 		pm_runtime_get(&dev->pdev->dev);
-		mutex_unlock(&power_ctrl_mutex);
+		spin_unlock_irqrestore(&power_ctrl_lock, flags);
 		return true;
 	}
 	if (force_on == false)
@@ -266,11 +267,11 @@ bool gma_power_begin(struct drm_device *dev, bool force_on)
 		psb_irq_postinstall(dev);
 		pm_runtime_get(&dev->pdev->dev);
 		dev_priv->display_count++;
-		mutex_unlock(&power_ctrl_mutex);
+		spin_unlock_irqrestore(&power_ctrl_lock, flags);
 		return true;
 	}
 out_false:
-	mutex_unlock(&power_ctrl_mutex);
+	spin_unlock_irqrestore(&power_ctrl_lock, flags);
 	return false;
 }
 
@@ -284,10 +285,11 @@ out_false:
 void gma_power_end(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	mutex_lock(&power_ctrl_mutex);
+	unsigned long flags;
+	spin_lock_irqsave(&power_ctrl_lock, flags);
 	dev_priv->display_count--;
 	WARN_ON(dev_priv->display_count < 0);
-	mutex_unlock(&power_ctrl_mutex);
+	spin_unlock_irqrestore(&power_ctrl_lock, flags);
 	pm_runtime_put(&dev->pdev->dev);
 }
 


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* Re: [PATCH 00/49] GMA50 series update
  2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
                   ` (48 preceding siblings ...)
  2011-07-05 14:45 ` [PATCH 49/49] gma500: power can be touched in IRQ state Alan Cox
@ 2011-07-05 15:23 ` Greg KH
  2011-07-05 15:36   ` Greg KH
  2011-07-05 18:03   ` Alan Cox
  49 siblings, 2 replies; 75+ messages in thread
From: Greg KH @ 2011-07-05 15:23 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel

On Tue, Jul 05, 2011 at 03:33:48PM +0100, Alan Cox wrote:
> (Rebased versus the patches Greg took earlier)
> 
> The main things here are modularisation and support for Cedarview (this is
> unaccelerated as it has no 2D acceleration). I have some crazy ideas about using
> the GTT to do 2D console acceleration however but not much can be done for X.
> 
> At this point I think the Poulsbo (GMA500) and Cedarview code are probably ready
> to move out of staging - hence the modularisation work. The MID platforms need
> more cleaning up.
> 
> HDMI support at this point is pretty basic with no HDMI audio support. I'm hoping
> that will be something that can be addressed in future and now the basic bits
> are there I need to take a look at Oaktrail (Atom Z760/GMA600) and see if the
> same code can be used to bring up HDMI on that device too.

I've applied this series, but I get the following error when building:

make[2]: *** No rule to make target `drivers/staging/gma500/cdv_intel_crt.o', needed by `drivers/staging/gma500/psb_gfx.o'.  Stop.

Care to send a follow-on patch fixing this?

Also, should I be able to select all of the different platforms even
though I'm only building for a x86-64 platform?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 00/49] GMA50 series update
  2011-07-05 15:23 ` [PATCH 00/49] GMA50 series update Greg KH
@ 2011-07-05 15:36   ` Greg KH
  2011-07-05 18:03   ` Alan Cox
  1 sibling, 0 replies; 75+ messages in thread
From: Greg KH @ 2011-07-05 15:36 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel

On Tue, Jul 05, 2011 at 08:23:02AM -0700, Greg KH wrote:
> On Tue, Jul 05, 2011 at 03:33:48PM +0100, Alan Cox wrote:
> > (Rebased versus the patches Greg took earlier)
> > 
> > The main things here are modularisation and support for Cedarview (this is
> > unaccelerated as it has no 2D acceleration). I have some crazy ideas about using
> > the GTT to do 2D console acceleration however but not much can be done for X.
> > 
> > At this point I think the Poulsbo (GMA500) and Cedarview code are probably ready
> > to move out of staging - hence the modularisation work. The MID platforms need
> > more cleaning up.
> > 
> > HDMI support at this point is pretty basic with no HDMI audio support. I'm hoping
> > that will be something that can be addressed in future and now the basic bits
> > are there I need to take a look at Oaktrail (Atom Z760/GMA600) and see if the
> > same code can be used to bring up HDMI on that device too.
> 
> I've applied this series, but I get the following error when building:
> 
> make[2]: *** No rule to make target `drivers/staging/gma500/cdv_intel_crt.o', needed by `drivers/staging/gma500/psb_gfx.o'.  Stop.
> 
> Care to send a follow-on patch fixing this?
> 
> Also, should I be able to select all of the different platforms even
> though I'm only building for a x86-64 platform?

And I get the following error as well:
drivers/staging/gma500/cdv_device.c:28:24: fatal error: cdv_device.h: No such file or directory


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 25/49] commit ee12661199b82934552c7636b10217a9aa42958a
  2011-07-05 14:39 ` [PATCH 25/49] commit ee12661199b82934552c7636b10217a9aa42958a Alan Cox
@ 2011-07-05 15:55   ` Greg KH
  0 siblings, 0 replies; 75+ messages in thread
From: Greg KH @ 2011-07-05 15:55 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel

What kind of a Subject is that?

On Tue, Jul 05, 2011 at 03:39:31PM +0100, Alan Cox wrote:
> From: Jani Nikula <jani.nikula@intel.com>
> 
> gma500: fix build without backlight device support
> 
>     Fix unmatched curly brackets when CONFIG_BACKLIGHT_CLASS_DEVICE is not
>     defined.
> 
>     Signed-off-by: Jani Nikula <jani.nikula@intel.com>
>     Signed-off-by: Alan Cox <alan@linux.intel.com>
> ---

Ah, ok, I'll edit it by hand :(

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 00/49] GMA50 series update
  2011-07-05 15:23 ` [PATCH 00/49] GMA50 series update Greg KH
  2011-07-05 15:36   ` Greg KH
@ 2011-07-05 18:03   ` Alan Cox
  2011-07-06  2:44     ` Greg KH
  1 sibling, 1 reply; 75+ messages in thread
From: Alan Cox @ 2011-07-05 18:03 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel


> I've applied this series, but I get the following error when building:
> 
> make[2]: *** No rule to make target `drivers/staging/gma500/cdv_intel_crt.o', needed by `drivers/staging/gma500/psb_gfx.o'.  Stop.
> 
> Care to send a follow-on patch fixing this?

Done

> 
> Also, should I be able to select all of the different platforms even
> though I'm only building for a x86-64 platform?

They should all build. I thought Linus wanted stuff that would build to
be buildable where it could so that it got build testing done.


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 00/49] GMA50 series update
  2011-07-05 18:03   ` Alan Cox
@ 2011-07-06  2:44     ` Greg KH
  0 siblings, 0 replies; 75+ messages in thread
From: Greg KH @ 2011-07-06  2:44 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-kernel

On Tue, Jul 05, 2011 at 07:03:54PM +0100, Alan Cox wrote:
> 
> > I've applied this series, but I get the following error when building:
> > 
> > make[2]: *** No rule to make target `drivers/staging/gma500/cdv_intel_crt.o', needed by `drivers/staging/gma500/psb_gfx.o'.  Stop.
> > 
> > Care to send a follow-on patch fixing this?
> 
> Done
> 
> > 
> > Also, should I be able to select all of the different platforms even
> > though I'm only building for a x86-64 platform?
> 
> They should all build. I thought Linus wanted stuff that would build to
> be buildable where it could so that it got build testing done.

Ok, that's great, hopefully after your next patches, it will build :)

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-07-05 14:41 ` [PATCH 34/49] gma500: the GEM and GTT code is device independant Alan Cox
@ 2011-07-08  1:14   ` Hugh Dickins
  2011-07-08  8:38     ` Alan Cox
  0 siblings, 1 reply; 75+ messages in thread
From: Hugh Dickins @ 2011-07-08  1:14 UTC (permalink / raw)
  To: Alan Cox; +Cc: Andrew Morton, greg, linux-kernel

Hi Alan,

On Tue, 5 Jul 2011, Alan Cox wrote:
> From: Alan Cox <alan@linux.intel.com>
> 
> Rename the gem and gtt files accordingly.
> 
> Signed-off-by: Alan Cox <alan@linux.intel.com>

This caught my eye, and I realize that I'm in the process of
sabotaging your work, or vice versa: sorry!

> +
> +	for (i = 0; i < pages; i++) {
> +		/* FIXME: review flags later */
> +		p = read_cache_page_gfp(mapping, i,
> +					__GFP_COLD | GFP_KERNEL);
...
> -
> -	for (i = 0; i < pages; i++) {
> -		/* FIXME: review flags later */
> -		p = read_cache_page_gfp(mapping, i,
> -					__GFP_COLD | GFP_KERNEL);

I've been eliminating drm/i915's calls to read_cache_page_gfp(),
while you've been adding them to staging/gma500.  It still works in
3.0-rc, but if my further changes go through from mmotm to 3.1-rc,
then read_cache_page_gfp() on a shmem/tmpfs file will crash on the
lack of a readpage method (we could easily make it error instead
of crash, but you'd probably prefer something that actually works).

As example, below is the patch where I updated drm/i915 to be ready
for the changeover.  They set __GFP_RECLAIMABLE on the mapping because
they've got a way to discard unpinned object pages when memory is tight;
and sometimes add in __GFP_NORETRY|__GFP_NOWARN when allocating.

I'm guessing you'd just want to use shmem_read_mapping_page() throughout,
after initializing mapping with the appropriate flags (GFP_HIGHUSER_MOVABLE
is fs/inode.c's default: maybe your pages aren't easily movable and you'd
better say GFP_HIGHUSER, or maybe you have reason to need GFP_KERNEL).

Hugh

commit 5949eac4d9b5bf936c12cb7ec3a09084c1326834
Author: Hugh Dickins <hughd@google.com>
Date:   Mon Jun 27 16:18:18 2011 -0700

    drm/i915: use shmem_read_mapping_page
    
    Soon tmpfs will stop supporting ->readpage and read_cache_page_gfp(): once
    "tmpfs: add shmem_read_mapping_page_gfp" has been applied, this patch can
    be applied to ease the transition.
    
    Make i915_gem_object_get_pages_gtt() use shmem_read_mapping_page_gfp() in
    the one place it's needed; elsewhere use shmem_read_mapping_page(), with
    the mapping's gfp_mask properly initialized.
    
    Forget about __GFP_COLD: since tmpfs initializes its pages with memset,
    asking for a cold page is counter-productive.
    
    Include linux/shmem_fs.h also in drm_gem.c: with shmem_file_setup() now
    declared there too, we shall remove the prototype from linux/mm.h later.
    
    Signed-off-by: Hugh Dickins <hughd@google.com>
    Cc: Christoph Hellwig <hch@infradead.org>
    Cc: Chris Wilson <chris@chris-wilson.co.uk>
    Cc: Keith Packard <keithp@keithp.com>
    Cc: Dave Airlie <airlied@redhat.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 74e4ff5..4012fe4 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
+#include <linux/shmem_fs.h>
 #include "drmP.h"
 
 /** @file drm_gem.c
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index c6389de..fa560ce 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -31,6 +31,7 @@
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
+#include <linux/shmem_fs.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/pci.h>
@@ -359,8 +360,7 @@ i915_gem_shmem_pread_fast(struct drm_device *dev,
 		if ((page_offset + remain) > PAGE_SIZE)
 			page_length = PAGE_SIZE - page_offset;
 
-		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
-					   GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
 		if (IS_ERR(page))
 			return PTR_ERR(page);
 
@@ -463,8 +463,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev,
 		if ((data_page_offset + page_length) > PAGE_SIZE)
 			page_length = PAGE_SIZE - data_page_offset;
 
-		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
-					   GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
 		if (IS_ERR(page)) {
 			ret = PTR_ERR(page);
 			goto out;
@@ -797,8 +796,7 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev,
 		if ((page_offset + remain) > PAGE_SIZE)
 			page_length = PAGE_SIZE - page_offset;
 
-		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
-					   GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
 		if (IS_ERR(page))
 			return PTR_ERR(page);
 
@@ -907,8 +905,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev,
 		if ((data_page_offset + page_length) > PAGE_SIZE)
 			page_length = PAGE_SIZE - data_page_offset;
 
-		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
-					   GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
 		if (IS_ERR(page)) {
 			ret = PTR_ERR(page);
 			goto out;
@@ -1558,12 +1555,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
 
 	inode = obj->base.filp->f_path.dentry->d_inode;
 	mapping = inode->i_mapping;
+	gfpmask |= mapping_gfp_mask(mapping);
+
 	for (i = 0; i < page_count; i++) {
-		page = read_cache_page_gfp(mapping, i,
-					   GFP_HIGHUSER |
-					   __GFP_COLD |
-					   __GFP_RECLAIMABLE |
-					   gfpmask);
+		page = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
 		if (IS_ERR(page))
 			goto err_pages;
 
@@ -3565,6 +3560,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
+	struct address_space *mapping;
 
 	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
 	if (obj == NULL)
@@ -3575,6 +3571,9 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 		return NULL;
 	}
 
+	mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
+	mapping_set_gfp_mask(mapping, GFP_HIGHUSER | __GFP_RECLAIMABLE);
+
 	i915_gem_info_add_obj(dev_priv, size);
 
 	obj->base.write_domain = I915_GEM_DOMAIN_CPU;
@@ -3950,8 +3949,7 @@ void i915_gem_detach_phys_object(struct drm_device *dev,
 
 	page_count = obj->base.size / PAGE_SIZE;
 	for (i = 0; i < page_count; i++) {
-		struct page *page = read_cache_page_gfp(mapping, i,
-							GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		struct page *page = shmem_read_mapping_page(mapping, i);
 		if (!IS_ERR(page)) {
 			char *dst = kmap_atomic(page);
 			memcpy(dst, vaddr + i*PAGE_SIZE, PAGE_SIZE);
@@ -4012,8 +4010,7 @@ i915_gem_attach_phys_object(struct drm_device *dev,
 		struct page *page;
 		char *dst, *src;
 
-		page = read_cache_page_gfp(mapping, i,
-					   GFP_HIGHUSER | __GFP_RECLAIMABLE);
+		page = shmem_read_mapping_page(mapping, i);
 		if (IS_ERR(page))
 			return PTR_ERR(page);
 


^ permalink raw reply related	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-07-08  1:14   ` Hugh Dickins
@ 2011-07-08  8:38     ` Alan Cox
  2011-07-08 17:06       ` Hugh Dickins
  0 siblings, 1 reply; 75+ messages in thread
From: Alan Cox @ 2011-07-08  8:38 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: Andrew Morton, greg, linux-kernel

> As example, below is the patch where I updated drm/i915 to be ready
> for the changeover.  They set __GFP_RECLAIMABLE on the mapping because
> they've got a way to discard unpinned object pages when memory is tight;
> and sometimes add in __GFP_NORETRY|__GFP_NOWARN when allocating.
> 
> I'm guessing you'd just want to use shmem_read_mapping_page() throughout,
> after initializing mapping with the appropriate flags (GFP_HIGHUSER_MOVABLE
> is fs/inode.c's default: maybe your pages aren't easily movable and you'd
> better say GFP_HIGHUSER, or maybe you have reason to need GFP_KERNEL).

I need the pages in the low 4GB ideally and have no way to release them
if they are pinned. For the usage pattern I have that's not a problem.

At the moment the 4G isn't a problem either as you can't attach enough
memory to cause problems to any of these devices.


What I don't entirely understand from your change is what stops another
user task with the shmemfs file handle open from doing something else
which changes the mapping flags, or is it guaranteed that only the
mapping owner gets to play ?

Alan

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-07-08  8:38     ` Alan Cox
@ 2011-07-08 17:06       ` Hugh Dickins
  2011-07-11 16:25         ` Alan Cox
  0 siblings, 1 reply; 75+ messages in thread
From: Hugh Dickins @ 2011-07-08 17:06 UTC (permalink / raw)
  To: Alan Cox; +Cc: Andrew Morton, greg, linux-kernel

On Fri, 8 Jul 2011, Alan Cox wrote:
> > As example, below is the patch where I updated drm/i915 to be ready
> > for the changeover.  They set __GFP_RECLAIMABLE on the mapping because
> > they've got a way to discard unpinned object pages when memory is tight;
> > and sometimes add in __GFP_NORETRY|__GFP_NOWARN when allocating.
> > 
> > I'm guessing you'd just want to use shmem_read_mapping_page() throughout,
> > after initializing mapping with the appropriate flags (GFP_HIGHUSER_MOVABLE
> > is fs/inode.c's default: maybe your pages aren't easily movable and you'd
> > better say GFP_HIGHUSER, or maybe you have reason to need GFP_KERNEL).
> 
> I need the pages in the low 4GB ideally and have no way to release them
> if they are pinned. For the usage pattern I have that's not a problem.

Maybe you'll want to use GFP_KERNEL | GFP_DMA32.

> 
> At the moment the 4G isn't a problem either as you can't attach enough
> memory to cause problems to any of these devices.
> 
> 
> What I don't entirely understand from your change is what stops another
> user task with the shmemfs file handle open from doing something else
> which changes the mapping flags, or is it guaranteed that only the
> mapping owner gets to play ?

My changes (which were directed to eliminating shmem_readpage, which
complicates shmem.c somewhat) haven't made any difference there: except
that, like you, I'm wary of letting people mess with gfp flags all over,
so preferred drm/i915 to set the right flags on the mapping initially,
then add in the __GFP_NORETRY | __GFP_NOWARN in the one place needed,
instead of using the _gfp()-modifying variant everywhere.

I don't think a user task has any interface to change the mapping flags,
does it?  But Linus freaked out a little 18 months ago when he noticed
drm/i915 fiddling with mapping flags via mapping_set_gfp_mask() (whose
declaration comments "This is non-atomic.  Only to be used before the
mapping is activated."), so gave them read_cache_page_gfp() instead.

I'd prefer we didn't have to support it, but i915 does have good use
for it: so long as they only play with transient flags such as NORETRY
(which will affect the allocation being made by the caller, but not
affect mapping itself or concurrent allocations to it from elsewhere).

But your question does make me worry about when a page is brought back
from swap.  The swapin readahead code is liable to read in several pages
with the same gfp mask as the page it's actually needing; but if adjacent
swap locations have been used for pages of objects with different gfp
needs, that could cause a problem.  (NUMA mempolicy gets ignored by
swapin in the same way.)

Your <4GB pages won't get swapped out while they're pinned.  But can
it happen that they'd be unpinned, swapped out, swapped back in >4GB
pages, then cause trouble for you when needed again?

I didn't care very deeply about the difference between __GFP_MOVABLE
and __GFP_RECLAIMABLE in the i915 case, but your 4GB requirement sounds
more important to get right (though you do say "ideally" above: if it's
just a matter of slowdown, maybe we can ignore it for now).

Hugh

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-07-08 17:06       ` Hugh Dickins
@ 2011-07-11 16:25         ` Alan Cox
  2011-07-11 17:49           ` Hugh Dickins
  0 siblings, 1 reply; 75+ messages in thread
From: Alan Cox @ 2011-07-11 16:25 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: Andrew Morton, greg, linux-kernel

> Your <4GB pages won't get swapped out while they're pinned.  But can
> it happen that they'd be unpinned, swapped out, swapped back in >4GB
> pages, then cause trouble for you when needed again?

It does look that way, in which case that will eventually need fixing. At
the moment you can't put enough memory into a device using these chips
but that won't always be true I imagine.

Alan

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-07-11 16:25         ` Alan Cox
@ 2011-07-11 17:49           ` Hugh Dickins
  2011-09-12 23:19             ` Konrad Rzeszutek Wilk
  2011-10-09 20:15             ` Patrik Jakobsson
  0 siblings, 2 replies; 75+ messages in thread
From: Hugh Dickins @ 2011-07-11 17:49 UTC (permalink / raw)
  To: Alan Cox; +Cc: Andrew Morton, greg, linux-kernel

On Mon, 11 Jul 2011, Alan Cox wrote:
> > Your <4GB pages won't get swapped out while they're pinned.  But can
> > it happen that they'd be unpinned, swapped out, swapped back in >4GB
> > pages, then cause trouble for you when needed again?
> 
> It does look that way, in which case that will eventually need fixing. At
> the moment you can't put enough memory into a device using these chips
> but that won't always be true I imagine.

Thanks, I won't worry about it at this moment, but we'd better not forget.

If it's easy for you to include a WARN_ON_ONCE check (perhaps
on page_to_pfn(page)), that may be worth doing to remind us.

It's a bit sad to learn this requirement just after I'd completed
removing the readpage copying code, and a bit strange to have shmem
confined by hardware constraints; but I guess that's what we took on
when we opened it up to GEM.

It will probably make sense for me to add synchronous migration when
a shmem swap page is found not to match the contraints wanted by the
mapping it goes into: mainly for NUMA, but covering your case too.

Hugh

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-07-11 17:49           ` Hugh Dickins
@ 2011-09-12 23:19             ` Konrad Rzeszutek Wilk
  2011-09-13  8:15               ` Alan Cox
  2011-10-09 20:15             ` Patrik Jakobsson
  1 sibling, 1 reply; 75+ messages in thread
From: Konrad Rzeszutek Wilk @ 2011-09-12 23:19 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: Alan Cox, Andrew Morton, greg, linux-kernel

On Mon, Jul 11, 2011 at 10:49:31AM -0700, Hugh Dickins wrote:
> On Mon, 11 Jul 2011, Alan Cox wrote:
> > > Your <4GB pages won't get swapped out while they're pinned.  But can
> > > it happen that they'd be unpinned, swapped out, swapped back in >4GB
> > > pages, then cause trouble for you when needed again?
> > 
> > It does look that way, in which case that will eventually need fixing. At
> > the moment you can't put enough memory into a device using these chips
> > but that won't always be true I imagine.
> 
> Thanks, I won't worry about it at this moment, but we'd better not forget.

I recall seeing the GMA driver using the TTM at some point
(but then those calls disappared), and I've written a patch to deal with
a similar issue (where the DMA and the virtual address needed to
be passed along to the code that programs the cards MMU).

It also survives suspend/resume, swap, etc.

https://lkml.org/lkml/2011/8/30/460

Don't know if it would be too complicated to make the GMA500 code
use TTM, and the URL I posted still needs a review, but perhaps
that could solve this problem in the future for you guys?

> 
> If it's easy for you to include a WARN_ON_ONCE check (perhaps
> on page_to_pfn(page)), that may be worth doing to remind us.
> 
> It's a bit sad to learn this requirement just after I'd completed
> removing the readpage copying code, and a bit strange to have shmem
> confined by hardware constraints; but I guess that's what we took on
> when we opened it up to GEM.
> 
> It will probably make sense for me to add synchronous migration when
> a shmem swap page is found not to match the contraints wanted by the
> mapping it goes into: mainly for NUMA, but covering your case too.
> 
> Hugh
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-09-12 23:19             ` Konrad Rzeszutek Wilk
@ 2011-09-13  8:15               ` Alan Cox
  0 siblings, 0 replies; 75+ messages in thread
From: Alan Cox @ 2011-09-13  8:15 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk; +Cc: Hugh Dickins, Andrew Morton, greg, linux-kernel

> I recall seeing the GMA driver using the TTM at some point
> (but then those calls disappared),

The base code it came from still had bits of TTM stuff in that I was
eliminating. The driver itself doesn't use TTM. It's GEM based and uses
GEM extensively.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-07-11 17:49           ` Hugh Dickins
  2011-09-12 23:19             ` Konrad Rzeszutek Wilk
@ 2011-10-09 20:15             ` Patrik Jakobsson
  2011-10-10 18:37               ` Hugh Dickins
  1 sibling, 1 reply; 75+ messages in thread
From: Patrik Jakobsson @ 2011-10-09 20:15 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: Alan Cox, Andrew Morton, greg, linux-kernel

On Mon, Jul 11, 2011 at 7:49 PM, Hugh Dickins wrote:
> On Mon, 11 Jul 2011, Alan Cox wrote:
>> > Your <4GB pages won't get swapped out while they're pinned.  But can
>> > it happen that they'd be unpinned, swapped out, swapped back in >4GB
>> > pages, then cause trouble for you when needed again?
>>
>> It does look that way, in which case that will eventually need fixing. At
>> the moment you can't put enough memory into a device using these chips
>> but that won't always be true I imagine.
>
> Thanks, I won't worry about it at this moment, but we'd better not forget.
>
> If it's easy for you to include a WARN_ON_ONCE check (perhaps
> on page_to_pfn(page)), that may be worth doing to remind us.
>
> It's a bit sad to learn this requirement just after I'd completed
> removing the readpage copying code, and a bit strange to have shmem
> confined by hardware constraints; but I guess that's what we took on
> when we opened it up to GEM.
>
> It will probably make sense for me to add synchronous migration when
> a shmem swap page is found not to match the contraints wanted by the
> mapping it goes into: mainly for NUMA, but covering your case too.
>
> Hugh

I think we need to revisit this problem. On 3.1-rc4 with some of my own changes
I've just triggered read_cache_page_gfp in psb_gtt_attach_pages when trying to
set a resolution that doesn't fit in stolen memory. Replacing it with
shmem_read_mapping_page seems to work but how do we go about solving the >4GB
issue? Is it ok for now to just use shmem_read_mapping_page or did any of you
have a better solution?

Thanks
Patrik

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-09 20:15             ` Patrik Jakobsson
@ 2011-10-10 18:37               ` Hugh Dickins
  2011-10-12 12:03                 ` Patrik Jakobsson
  2011-10-15 14:30                 ` Rob Clark
  0 siblings, 2 replies; 75+ messages in thread
From: Hugh Dickins @ 2011-10-10 18:37 UTC (permalink / raw)
  To: Patrik Jakobsson; +Cc: Alan Cox, Andrew Morton, Rob Clark, greg, linux-kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 5798 bytes --]

On Sun, 9 Oct 2011, Patrik Jakobsson wrote:
> On Mon, Jul 11, 2011 at 7:49 PM, Hugh Dickins wrote:
> > On Mon, 11 Jul 2011, Alan Cox wrote:
> >> > Your <4GB pages won't get swapped out while they're pinned.  But can
> >> > it happen that they'd be unpinned, swapped out, swapped back in >4GB
> >> > pages, then cause trouble for you when needed again?
> >>
> >> It does look that way, in which case that will eventually need fixing. At
> >> the moment you can't put enough memory into a device using these chips
> >> but that won't always be true I imagine.
> >
> > Thanks, I won't worry about it at this moment, but we'd better not forget.
> >
> > If it's easy for you to include a WARN_ON_ONCE check (perhaps
> > on page_to_pfn(page)), that may be worth doing to remind us.
> >
> > It's a bit sad to learn this requirement just after I'd completed
> > removing the readpage copying code, and a bit strange to have shmem
> > confined by hardware constraints; but I guess that's what we took on
> > when we opened it up to GEM.
> >
> > It will probably make sense for me to add synchronous migration when
> > a shmem swap page is found not to match the contraints wanted by the
> > mapping it goes into: mainly for NUMA, but covering your case too.
> 
> I think we need to revisit this problem. On 3.1-rc4 with some of my own changes
> I've just triggered read_cache_page_gfp in psb_gtt_attach_pages when trying to
> set a resolution that doesn't fit in stolen memory. Replacing it with
> shmem_read_mapping_page seems to work but how do we go about solving the >4GB
> issue? Is it ok for now to just use shmem_read_mapping_page or did any of you
> have a better solution?

I was surprised to see drivers/staging/gma500 appearing still to use
read_cache_page_gfp().  I assumed that since nobody was complaining,
it must be on a currently unusable path.  But you have code coming up,
that now enables that path?

Am I right to think that your immediate problem is just the oops in
__read_cache_page(), that you're not yet about to hit the 4GB issue?

I haven't rushed to address the 4GB issue, but what I have in mind is
killing two-and-a-half birds with one stone, by putting a little cookie
into the swapper_space radix_tree when we free a swapcache page, that
specifies node/zone and hashes object/offset.

NUMA mempolicies are too complex to be encapsulated in a sizeof(long)
cookie, but it should improve the common case after swapin; while
solving your 4GB GEM case, and vastly speeding up swapoff.

Here's the kind of patch I imagined would be going in for gma500, that
specifies __GFP_DMA32 on the mapping, so even swapoff can know that
this object needs its pages below 4GB (even before my recent changes,
swapoff would have broken you by inserting higher pages in the cache)
- once I implement that.  But I've not tested this patch at all...


[PATCH] gma500: use shmem_read_mapping_page

In 3.1 onwards, read_cache_page_gfp() just oopses on GEM objects:
switch gma500 over to shmem_read_mapping_page() like i915.  But when
larger devices arrive, gma500 will need to keep its pages below 4GB, so
specify __GFP_DMA32 (though that limit is not yet enforced in shmem.c).

Signed-off-by: Hugh Dicking <hughd@google.com>
---

 drivers/staging/gma500/framebuffer.c |    7 +++++++
 drivers/staging/gma500/gem.c         |    4 ++++
 drivers/staging/gma500/gtt.c         |    5 ++---
 3 files changed, 13 insertions(+), 3 deletions(-)

--- 3.1-rc9/drivers/staging/gma500/framebuffer.c	2011-08-07 23:44:38.587914954 -0700
+++ linux/drivers/staging/gma500/framebuffer.c	2011-10-10 10:40:06.422389114 -0700
@@ -317,7 +317,9 @@ static struct drm_framebuffer *psb_frame
  */
 static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
 {
+	struct address_space *mapping;
 	struct gtt_range *backing;
+
 	/* Begin by trying to use stolen memory backing */
 	backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
 	if (backing) {
@@ -336,6 +338,11 @@ static struct gtt_range *psbfb_alloc(str
 		psb_gtt_free_range(dev, backing);
 		return NULL;
 	}
+
+	/* Specify that its pages be allocated below 4GB */
+	mapping = backing->gem.filp->f_path.dentry->d_inode->i_mapping;
+	mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32);
+
 	return backing;
 }
 
--- 3.1-rc9/drivers/staging/gma500/gem.c	2011-08-07 23:44:38.587914954 -0700
+++ linux/drivers/staging/gma500/gem.c	2011-10-10 10:39:31.974219007 -0700
@@ -104,6 +104,7 @@ unlock:
 static int psb_gem_create(struct drm_file *file,
 	struct drm_device *dev, uint64_t size, uint32_t *handlep)
 {
+	struct address_space *mapping;
 	struct gtt_range *r;
 	int ret;
 	u32 handle;
@@ -125,6 +126,9 @@ static int psb_gem_create(struct drm_fil
 		dev_err(dev->dev, "GEM init failed for %lld\n", size);
 		return -ENOMEM;
 	}
+	/* Specify that its pages be allocated below 4GB */
+	mapping = r->gem.filp->f_path.dentry->d_inode->i_mapping;
+	mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32);
 	/* Give the object a handle so we can carry it more easily */
 	ret = drm_gem_handle_create(file, &r->gem, &handle);
 	if (ret) {
--- 3.1-rc9/drivers/staging/gma500/gtt.c	2011-08-07 23:44:38.591914970 -0700
+++ linux/drivers/staging/gma500/gtt.c	2011-10-10 10:19:31.424265313 -0700
@@ -20,6 +20,7 @@
  */
 
 #include <drm/drmP.h>
+#include <linux/shmem_fs.h>
 #include "psb_drv.h"
 
 
@@ -158,9 +159,7 @@ static int psb_gtt_attach_pages(struct g
 	gt->npage = pages;
 
 	for (i = 0; i < pages; i++) {
-		/* FIXME: review flags later */
-		p = read_cache_page_gfp(mapping, i,
-					__GFP_COLD | GFP_KERNEL);
+		p = shmem_read_mapping_page(mapping, i);
 		if (IS_ERR(p))
 			goto err;
 		gt->pages[i] = p;

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-10 18:37               ` Hugh Dickins
@ 2011-10-12 12:03                 ` Patrik Jakobsson
  2011-10-15 14:30                 ` Rob Clark
  1 sibling, 0 replies; 75+ messages in thread
From: Patrik Jakobsson @ 2011-10-12 12:03 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: Alan Cox, Andrew Morton, Rob Clark, greg, linux-kernel

On Mon, Oct 10, 2011 at 8:37 PM, Hugh Dickins wrote:
> I was surprised to see drivers/staging/gma500 appearing still to use
> read_cache_page_gfp().  I assumed that since nobody was complaining,
> it must be on a currently unusable path.  But you have code coming up,
> that now enables that path?

Yes, I have a couple of patches for getting SDVO to properly set up DDC.
It seems we hit that path when framebuffer size exceeds a certain limit.

> Am I right to think that your immediate problem is just the oops in
> __read_cache_page(), that you're not yet about to hit the 4GB issue?

Correct, I have only seen 1GB and 2GB platforms so far. But the driver
does support platforms that I haven't got my hands on yet.

> I haven't rushed to address the 4GB issue, but what I have in mind is
> killing two-and-a-half birds with one stone, by putting a little cookie
> into the swapper_space radix_tree when we free a swapcache page, that
> specifies node/zone and hashes object/offset.
>
> NUMA mempolicies are too complex to be encapsulated in a sizeof(long)
> cookie, but it should improve the common case after swapin; while
> solving your 4GB GEM case, and vastly speeding up swapoff.
>
> Here's the kind of patch I imagined would be going in for gma500, that
> specifies __GFP_DMA32 on the mapping, so even swapoff can know that
> this object needs its pages below 4GB (even before my recent changes,
> swapoff would have broken you by inserting higher pages in the cache)
> - once I implement that.  But I've not tested this patch at all...

There are some other issues with SDVO when running at higher resolutions
that triggers the path. Will test your patch as soon as I get those things
sorted out, though it looks ok to me.

Thanks
Patrik

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-10 18:37               ` Hugh Dickins
  2011-10-12 12:03                 ` Patrik Jakobsson
@ 2011-10-15 14:30                 ` Rob Clark
  2011-10-17 17:48                   ` Hugh Dickins
  1 sibling, 1 reply; 75+ messages in thread
From: Rob Clark @ 2011-10-15 14:30 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Patrik Jakobsson, Alan Cox, Andrew Morton, greg, linux-kernel

On Mon, Oct 10, 2011 at 1:37 PM, Hugh Dickins <hughd@google.com> wrote:
> On Sun, 9 Oct 2011, Patrik Jakobsson wrote:
>> On Mon, Jul 11, 2011 at 7:49 PM, Hugh Dickins wrote:
>> > On Mon, 11 Jul 2011, Alan Cox wrote:
>> >> > Your <4GB pages won't get swapped out while they're pinned.  But can
>> >> > it happen that they'd be unpinned, swapped out, swapped back in >4GB
>> >> > pages, then cause trouble for you when needed again?
>> >>
>> >> It does look that way, in which case that will eventually need fixing. At
>> >> the moment you can't put enough memory into a device using these chips
>> >> but that won't always be true I imagine.
>> >
>> > Thanks, I won't worry about it at this moment, but we'd better not forget.
>> >
>> > If it's easy for you to include a WARN_ON_ONCE check (perhaps
>> > on page_to_pfn(page)), that may be worth doing to remind us.
>> >
>> > It's a bit sad to learn this requirement just after I'd completed
>> > removing the readpage copying code, and a bit strange to have shmem
>> > confined by hardware constraints; but I guess that's what we took on
>> > when we opened it up to GEM.
>> >
>> > It will probably make sense for me to add synchronous migration when
>> > a shmem swap page is found not to match the contraints wanted by the
>> > mapping it goes into: mainly for NUMA, but covering your case too.
>>
>> I think we need to revisit this problem. On 3.1-rc4 with some of my own changes
>> I've just triggered read_cache_page_gfp in psb_gtt_attach_pages when trying to
>> set a resolution that doesn't fit in stolen memory. Replacing it with
>> shmem_read_mapping_page seems to work but how do we go about solving the >4GB
>> issue? Is it ok for now to just use shmem_read_mapping_page or did any of you
>> have a better solution?
>
> I was surprised to see drivers/staging/gma500 appearing still to use
> read_cache_page_gfp().  I assumed that since nobody was complaining,
> it must be on a currently unusable path.  But you have code coming up,
> that now enables that path?
>
> Am I right to think that your immediate problem is just the oops in
> __read_cache_page(), that you're not yet about to hit the 4GB issue?
>
> I haven't rushed to address the 4GB issue, but what I have in mind is
> killing two-and-a-half birds with one stone, by putting a little cookie
> into the swapper_space radix_tree when we free a swapcache page, that
> specifies node/zone and hashes object/offset.

Without really knowing the details about how hard it would be to
implement, it would solve one additional problem if we could have a
per-mapping callback fxn for allocating pages.

At least on ARM (but I guess probably some other architectures too),
we really want to avoid having a page mapped cachable in the kernel,
and uncached/writecombine in userspace.  With a per-mapping page
allocation fxn, we could do something like
dma_alloc_coherant/writecombine (for example) to allocate backing
pages for GEM buffers which are mmap'd to userspace as something other
than cachable.

BR,
-R

> NUMA mempolicies are too complex to be encapsulated in a sizeof(long)
> cookie, but it should improve the common case after swapin; while
> solving your 4GB GEM case, and vastly speeding up swapoff.
>
> Here's the kind of patch I imagined would be going in for gma500, that
> specifies __GFP_DMA32 on the mapping, so even swapoff can know that
> this object needs its pages below 4GB (even before my recent changes,
> swapoff would have broken you by inserting higher pages in the cache)
> - once I implement that.  But I've not tested this patch at all...
>
>
> [PATCH] gma500: use shmem_read_mapping_page
>
> In 3.1 onwards, read_cache_page_gfp() just oopses on GEM objects:
> switch gma500 over to shmem_read_mapping_page() like i915.  But when
> larger devices arrive, gma500 will need to keep its pages below 4GB, so
> specify __GFP_DMA32 (though that limit is not yet enforced in shmem.c).
>
> Signed-off-by: Hugh Dicking <hughd@google.com>
> ---
>
>  drivers/staging/gma500/framebuffer.c |    7 +++++++
>  drivers/staging/gma500/gem.c         |    4 ++++
>  drivers/staging/gma500/gtt.c         |    5 ++---
>  3 files changed, 13 insertions(+), 3 deletions(-)
>
> --- 3.1-rc9/drivers/staging/gma500/framebuffer.c        2011-08-07 23:44:38.587914954 -0700
> +++ linux/drivers/staging/gma500/framebuffer.c  2011-10-10 10:40:06.422389114 -0700
> @@ -317,7 +317,9 @@ static struct drm_framebuffer *psb_frame
>  */
>  static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
>  {
> +       struct address_space *mapping;
>        struct gtt_range *backing;
> +
>        /* Begin by trying to use stolen memory backing */
>        backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
>        if (backing) {
> @@ -336,6 +338,11 @@ static struct gtt_range *psbfb_alloc(str
>                psb_gtt_free_range(dev, backing);
>                return NULL;
>        }
> +
> +       /* Specify that its pages be allocated below 4GB */
> +       mapping = backing->gem.filp->f_path.dentry->d_inode->i_mapping;
> +       mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32);
> +
>        return backing;
>  }
>
> --- 3.1-rc9/drivers/staging/gma500/gem.c        2011-08-07 23:44:38.587914954 -0700
> +++ linux/drivers/staging/gma500/gem.c  2011-10-10 10:39:31.974219007 -0700
> @@ -104,6 +104,7 @@ unlock:
>  static int psb_gem_create(struct drm_file *file,
>        struct drm_device *dev, uint64_t size, uint32_t *handlep)
>  {
> +       struct address_space *mapping;
>        struct gtt_range *r;
>        int ret;
>        u32 handle;
> @@ -125,6 +126,9 @@ static int psb_gem_create(struct drm_fil
>                dev_err(dev->dev, "GEM init failed for %lld\n", size);
>                return -ENOMEM;
>        }
> +       /* Specify that its pages be allocated below 4GB */
> +       mapping = r->gem.filp->f_path.dentry->d_inode->i_mapping;
> +       mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32);
>        /* Give the object a handle so we can carry it more easily */
>        ret = drm_gem_handle_create(file, &r->gem, &handle);
>        if (ret) {
> --- 3.1-rc9/drivers/staging/gma500/gtt.c        2011-08-07 23:44:38.591914970 -0700
> +++ linux/drivers/staging/gma500/gtt.c  2011-10-10 10:19:31.424265313 -0700
> @@ -20,6 +20,7 @@
>  */
>
>  #include <drm/drmP.h>
> +#include <linux/shmem_fs.h>
>  #include "psb_drv.h"
>
>
> @@ -158,9 +159,7 @@ static int psb_gtt_attach_pages(struct g
>        gt->npage = pages;
>
>        for (i = 0; i < pages; i++) {
> -               /* FIXME: review flags later */
> -               p = read_cache_page_gfp(mapping, i,
> -                                       __GFP_COLD | GFP_KERNEL);
> +               p = shmem_read_mapping_page(mapping, i);
>                if (IS_ERR(p))
>                        goto err;
>                gt->pages[i] = p;

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-15 14:30                 ` Rob Clark
@ 2011-10-17 17:48                   ` Hugh Dickins
  2011-10-17 21:39                     ` Alan Cox
  0 siblings, 1 reply; 75+ messages in thread
From: Hugh Dickins @ 2011-10-17 17:48 UTC (permalink / raw)
  To: Rob Clark
  Cc: Patrik Jakobsson, Alan Cox, Andrew Morton, Christoph Hellwig,
	greg, linux-kernel

On Sat, 15 Oct 2011, Rob Clark wrote:
> On Mon, Oct 10, 2011 at 1:37 PM, Hugh Dickins <hughd@google.com> wrote:
> >
> > I haven't rushed to address the 4GB issue, but what I have in mind is
> > killing two-and-a-half birds with one stone, by putting a little cookie
> > into the swapper_space radix_tree when we free a swapcache page, that
> > specifies node/zone and hashes object/offset.
> 
> Without really knowing the details about how hard it would be to
> implement, it would solve one additional problem if we could have a
> per-mapping callback fxn for allocating pages.
> 
> At least on ARM (but I guess probably some other architectures too),
> we really want to avoid having a page mapped cachable in the kernel,
> and uncached/writecombine in userspace.  With a per-mapping page
> allocation fxn, we could do something like
> dma_alloc_coherant/writecombine (for example) to allocate backing
> pages for GEM buffers which are mmap'd to userspace as something other
> than cachable.

It feels to me like GEM is pulling shmem in an ever more alien direction:
these device constraints are so foreign to the nature of tmpfs; and
beyond my expertise, so that I'd be ever more likely to make the wrong
decisions (mixing swap and uncached pages? hmmm).

We ought to re-examine whether GEM should be using tmpfs at all, whether
it would be better served by its own filesystem or other infrastructure.

Really, the one reason for wanting tmpfs is to have the benefit of offload
to swap (and that is indeed a feature I wouldn't care to distribute around
to drivers).

Hugh

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-17 17:48                   ` Hugh Dickins
@ 2011-10-17 21:39                     ` Alan Cox
  2011-10-17 22:34                       ` Hugh Dickins
  2011-10-18 11:16                       ` Patrik Jakobsson
  0 siblings, 2 replies; 75+ messages in thread
From: Alan Cox @ 2011-10-17 21:39 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Rob Clark, Patrik Jakobsson, Andrew Morton, Christoph Hellwig,
	greg, linux-kernel

> It feels to me like GEM is pulling shmem in an ever more alien direction:
> these device constraints are so foreign to the nature of tmpfs; and
> beyond my expertise, so that I'd be ever more likely to make the wrong
> decisions (mixing swap and uncached pages? hmmm).

For the most part we fixed that. You can now have a GEM object that is
backed by a private memory object rather than having to be tmpfs.
GMA500 uses it to attach 'stolen' memory to GEM handles, and at least
one other pending submission uses it with a private CMA style allocator.

The gma500 report seems an odd one - no GMA500 box has >4GB memory so how
did the test code get a page that was unsuitable - is the test buggy ?

Alan

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-17 21:39                     ` Alan Cox
@ 2011-10-17 22:34                       ` Hugh Dickins
  2011-10-17 23:32                         ` Rob Clark
  2011-10-18 11:16                       ` Patrik Jakobsson
  1 sibling, 1 reply; 75+ messages in thread
From: Hugh Dickins @ 2011-10-17 22:34 UTC (permalink / raw)
  To: Alan Cox
  Cc: Rob Clark, Patrik Jakobsson, Andrew Morton, Christoph Hellwig,
	greg, linux-kernel

On Mon, 17 Oct 2011, Alan Cox wrote:
> > It feels to me like GEM is pulling shmem in an ever more alien direction:
> > these device constraints are so foreign to the nature of tmpfs; and
> > beyond my expertise, so that I'd be ever more likely to make the wrong
> > decisions (mixing swap and uncached pages? hmmm).
> 
> For the most part we fixed that. You can now have a GEM object that is
> backed by a private memory object rather than having to be tmpfs.
> GMA500 uses it to attach 'stolen' memory to GEM handles, and at least
> one other pending submission uses it with a private CMA style allocator.

Sounds good.
> 
> The gma500 report seems an odd one - no GMA500 box has >4GB memory so how
> did the test code get a page that was unsuitable - is the test buggy ?

This is the first I heard of some gma500 test seeing a problem with >4GB.

In this thread we have Patrik hitting the oops in read_cache_page_gfp()
because of some changes he is preparing, but I thought he and Rob were
just thinking ahead when they raise the 4GB issue.

Can you point us to another thread on a another list?

Hugh

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-17 22:34                       ` Hugh Dickins
@ 2011-10-17 23:32                         ` Rob Clark
  2011-10-18 10:45                           ` Alan Cox
  0 siblings, 1 reply; 75+ messages in thread
From: Rob Clark @ 2011-10-17 23:32 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Alan Cox, Patrik Jakobsson, Andrew Morton, Christoph Hellwig,
	greg, linux-kernel

On Mon, Oct 17, 2011 at 5:34 PM, Hugh Dickins <hughd@google.com> wrote:
> On Mon, 17 Oct 2011, Alan Cox wrote:
>> > It feels to me like GEM is pulling shmem in an ever more alien direction:
>> > these device constraints are so foreign to the nature of tmpfs; and
>> > beyond my expertise, so that I'd be ever more likely to make the wrong
>> > decisions (mixing swap and uncached pages? hmmm).
>>
>> For the most part we fixed that. You can now have a GEM object that is
>> backed by a private memory object rather than having to be tmpfs.
>> GMA500 uses it to attach 'stolen' memory to GEM handles, and at least
>> one other pending submission uses it with a private CMA style allocator.
>
> Sounds good.

Well, that means we could implement our own shmem/tmpfs.. although I'm
not entirely sure that I would want to..  a couple drm drivers are
using private memory objects, but I think primarily for scanout
buffers (which can't really be swapped out anyways).  I don't think
we'd want to use this for everything.

What troubles could you see for swap+uncached (or more likely,
writecombine) pages?

BR,
-R

>>
>> The gma500 report seems an odd one - no GMA500 box has >4GB memory so how
>> did the test code get a page that was unsuitable - is the test buggy ?
>
> This is the first I heard of some gma500 test seeing a problem with >4GB.
>
> In this thread we have Patrik hitting the oops in read_cache_page_gfp()
> because of some changes he is preparing, but I thought he and Rob were
> just thinking ahead when they raise the 4GB issue.
>
> Can you point us to another thread on a another list?
>
> Hugh
>

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-17 23:32                         ` Rob Clark
@ 2011-10-18 10:45                           ` Alan Cox
  2011-10-18 11:59                             ` Rob Clark
  0 siblings, 1 reply; 75+ messages in thread
From: Alan Cox @ 2011-10-18 10:45 UTC (permalink / raw)
  To: Rob Clark
  Cc: Hugh Dickins, Patrik Jakobsson, Andrew Morton, Christoph Hellwig,
	greg, linux-kernel

> What troubles could you see for swap+uncached (or more likely,
> writecombine) pages?

That should never occur. I would argue the driver is responsible for
putting the cache state of the page back sensibly before it unpins it.
That's a simple enough rule and one I think all the drivers follow at
this point.

Alan

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-17 21:39                     ` Alan Cox
  2011-10-17 22:34                       ` Hugh Dickins
@ 2011-10-18 11:16                       ` Patrik Jakobsson
  1 sibling, 0 replies; 75+ messages in thread
From: Patrik Jakobsson @ 2011-10-18 11:16 UTC (permalink / raw)
  To: Alan Cox
  Cc: Hugh Dickins, Rob Clark, Andrew Morton, Christoph Hellwig, greg,
	linux-kernel

On Mon, Oct 17, 2011 at 11:39 PM, Alan Cox wrote:
>> It feels to me like GEM is pulling shmem in an ever more alien direction:
>> these device constraints are so foreign to the nature of tmpfs; and
>> beyond my expertise, so that I'd be ever more likely to make the wrong
>> decisions (mixing swap and uncached pages? hmmm).
>
> For the most part we fixed that. You can now have a GEM object that is
> backed by a private memory object rather than having to be tmpfs.
> GMA500 uses it to attach 'stolen' memory to GEM handles, and at least
> one other pending submission uses it with a private CMA style allocator.
>
> The gma500 report seems an odd one - no GMA500 box has >4GB memory so how
> did the test code get a page that was unsuitable - is the test buggy ?

Hi Alan

I didn't hit any >4GB issues but when I got SDVO working I tried setting
1920x1080 which needs more then the ~8MB that BIOS sets aside
as stolen memory.

What happens is that a gem object outside stolen mem is created and
when we try to pin it we go down the path:

psb_gtt_pin -> psb_gtt_attach_pages -> read_cache_page_gfp

This triggers the following oops:

-----

[   43.604167] BUG: unable to handle kernel NULL pointer dereference at   (null)
[   43.604349] IP: [<  (null)>]   (null)
[   43.604477] *pde = 00000000
[   43.604603] Oops: 0000 [#1] SMP
[   43.604778] Modules linked in: psb_gfx(C+) drm_kms_helper drm
agpgart i2c_algo_bit psmouse i2c_isch gpio_sch video coretemp lpc_sch
serio_raw usbhid hid r8169 mii
[   43.605746]
[   43.605825] Pid: 1255, comm: modprobe Tainted: G         C
3.1.0-rc4+ #13 CompuLab SBC-FITPC2/SBC-FITPC2
[   43.606089] EIP: 0060:[<00000000>] EFLAGS: 00010246 CPU: 1
[   43.606180] EIP is at 0x0
[   43.606261] EAX: 00000000 EBX: f62ea340 ECX: f5e04020 EDX: f62ea340
[   43.606351] ESI: f683f288 EDI: 00000000 EBP: f698bbb8 ESP: f698bb9c
[   43.606441]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[   43.606531] Process modprobe (pid: 1255, ti=f698a000 task=f4bb6500
task.ti=f698a000)
[   43.606641] Stack:
[   43.606718]  c10dbe31 000000d0 00000014 00000000 000001d0 00000000
f683f288 f698bbcc
[   43.607153]  c10dbf34 00000000 000001d0 f686f9c0 f698bbf4 f85afcee
f85aeb7a f6caf400
[   43.607582]  f683f288 f6f5205c 000007e9 fffffff4 f53cc600 f698bc7c
f698bc54 f85af0b2
[   43.608017] Call Trace:
[   43.608032]  [<c10dbe31>] ? do_read_cache_page+0x71/0x150
[   43.608032]  [<c10dbf34>] read_cache_page_gfp+0x24/0x30
[   43.608032]  [<f85afcee>] psb_gtt_pin+0xbe/0x220 [psb_gfx]
[   43.608032]  [<f85aeb7a>] ? psb_framebuffer_init+0x6a/0xa0 [psb_gfx]
[   43.608032]  [<f85af0b2>] psbfb_probe+0x3f2/0x460 [psb_gfx]
[   43.608032]  [<f80ccae7>] drm_fb_helper_single_fb_probe+0x127/0x2c0
[drm_kms_helper]
[   43.608032]  [<f80cce32>] drm_fb_helper_initial_config+0x1b2/0x210
[drm_kms_helper]
[   43.608032]  [<c1113ebe>] ? __kmalloc+0x13e/0x1d0
[   43.608032]  [<c1113c8d>] ? kmem_cache_alloc_trace+0xbd/0x120
[   43.608032]  [<f85af3e0>] psb_fbdev_init+0x70/0xb0 [psb_gfx]
[   43.608032]  [<f85b4c8e>] psb_driver_load+0x4ae/0x4c0 [psb_gfx]
[   43.608032]  [<f80a65a4>] drm_get_pci_dev+0x144/0x270 [drm]
[   43.608032]  [<c14a47cf>] ? _raw_spin_lock_irqsave+0x2f/0x50
[   43.608032]  [<f85b4642>] psb_probe+0x12/0x20 [psb_gfx]
[   43.608032]  [<c12609c7>] local_pci_probe+0x47/0xb0
[   43.608032]  [<c1261f08>] pci_device_probe+0x68/0x90
[   43.608032]  [<c12f0def>] driver_probe_device+0x7f/0x190
[   43.608032]  [<c1261e73>] ? pci_match_device+0xb3/0xc0
[   43.608032]  [<c12f0f81>] __driver_attach+0x81/0x90
[   43.608032]  [<c12f0f00>] ? driver_probe_device+0x190/0x190
[   43.608032]  [<c12f0048>] bus_for_each_dev+0x48/0x70
[   43.608032]  [<c1261920>] ? pci_pm_suspend+0x100/0x100
[   43.608032]  [<c12f0afe>] driver_attach+0x1e/0x20
[   43.608032]  [<c12f0f00>] ? driver_probe_device+0x190/0x190
[   43.608032]  [<c12f0718>] bus_add_driver+0xb8/0x250
[   43.608032]  [<c1261920>] ? pci_pm_suspend+0x100/0x100
[   43.608032]  [<c12f14d6>] driver_register+0x66/0x110
[   43.608032]  [<c1261035>] __pci_register_driver+0x45/0xb0
[   43.608032]  [<f80a67b1>] drm_pci_init+0xe1/0x110 [drm]
[   43.608032]  [<f8078012>] psb_init+0x12/0x1000 [psb_gfx]
[   43.608032]  [<c1001245>] do_one_initcall+0x35/0x170
[   43.608032]  [<f8078000>] ? 0xf8077fff
[   43.608032]  [<c107fcbb>] sys_init_module+0x13b/0x1aa0
[   43.608032]  [<c14ab21f>] sysenter_do_call+0x12/0x28
[   43.608032] Code:  Bad EIP value.
[   43.608032] EIP: [<00000000>] 0x0 SS:ESP 0068:f698bb9c
[   43.608032] CR2: 0000000000000000
[   43.612492] ---[ end trace 7c48b83f43438436 ]---

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-18 10:45                           ` Alan Cox
@ 2011-10-18 11:59                             ` Rob Clark
  2011-10-18 12:08                               ` Alan Cox
  0 siblings, 1 reply; 75+ messages in thread
From: Rob Clark @ 2011-10-18 11:59 UTC (permalink / raw)
  To: Alan Cox
  Cc: Hugh Dickins, Patrik Jakobsson, Andrew Morton, Christoph Hellwig,
	greg, linux-kernel

On Tue, Oct 18, 2011 at 5:45 AM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
>> What troubles could you see for swap+uncached (or more likely,
>> writecombine) pages?
>
> That should never occur. I would argue the driver is responsible for
> putting the cache state of the page back sensibly before it unpins it.
> That's a simple enough rule and one I think all the drivers follow at
> this point.

no, what I'm trying to avoid is having two virtual mappings to the
same physical page with different cache attributes.  This is not
allowed on some architectures (like ARM)

BR,
-R

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-18 11:59                             ` Rob Clark
@ 2011-10-18 12:08                               ` Alan Cox
  2011-10-18 13:36                                 ` Rob Clark
  0 siblings, 1 reply; 75+ messages in thread
From: Alan Cox @ 2011-10-18 12:08 UTC (permalink / raw)
  To: Rob Clark
  Cc: Hugh Dickins, Patrik Jakobsson, Andrew Morton, Christoph Hellwig,
	greg, linux-kernel

On Tue, 18 Oct 2011 06:59:28 -0500
Rob Clark <rob.clark@linaro.org> wrote:

> On Tue, Oct 18, 2011 at 5:45 AM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> >> What troubles could you see for swap+uncached (or more likely,
> >> writecombine) pages?
> >
> > That should never occur. I would argue the driver is responsible for
> > putting the cache state of the page back sensibly before it unpins it.
> > That's a simple enough rule and one I think all the drivers follow at
> > this point.
> 
> no, what I'm trying to avoid is having two virtual mappings to the
> same physical page with different cache attributes.  This is not
> allowed on some architectures (like ARM)

Nor x86... that's a matter for the core architecture code to deal with
not the drivers.

Alan

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [PATCH 34/49] gma500: the GEM and GTT code is device independant
  2011-10-18 12:08                               ` Alan Cox
@ 2011-10-18 13:36                                 ` Rob Clark
  0 siblings, 0 replies; 75+ messages in thread
From: Rob Clark @ 2011-10-18 13:36 UTC (permalink / raw)
  To: Alan Cox
  Cc: Hugh Dickins, Patrik Jakobsson, Andrew Morton, Christoph Hellwig,
	greg, linux-kernel

On Tue, Oct 18, 2011 at 7:08 AM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> On Tue, 18 Oct 2011 06:59:28 -0500
> Rob Clark <rob.clark@linaro.org> wrote:
>
>> On Tue, Oct 18, 2011 at 5:45 AM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
>> >> What troubles could you see for swap+uncached (or more likely,
>> >> writecombine) pages?
>> >
>> > That should never occur. I would argue the driver is responsible for
>> > putting the cache state of the page back sensibly before it unpins it.
>> > That's a simple enough rule and one I think all the drivers follow at
>> > this point.
>>
>> no, what I'm trying to avoid is having two virtual mappings to the
>> same physical page with different cache attributes.  This is not
>> allowed on some architectures (like ARM)
>
> Nor x86... that's a matter for the core architecture code to deal with
> not the drivers.
>

hmm, maybe I'm missing something, but how is this ensured on x86?
Default drm_gem_mmap() maps pages to userspace as writecombine..  but
if page comes from kernel linear map (not highmem), that will be a
cached kernel virtual mapping in addition to the wc userspace mapping.

BR,
-R

> Alan
>

^ permalink raw reply	[flat|nested] 75+ messages in thread

end of thread, other threads:[~2011-10-18 13:36 UTC | newest]

Thread overview: 75+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-05 14:33 [PATCH 00/49] GMA50 series update Alan Cox
2011-07-05 14:34 ` [PATCH 01/49] gma500: Ensure the frame buffer has a linear virtual mapping Alan Cox
2011-07-05 14:34 ` [PATCH 02/49] gma500: revamp frame buffer creation and handling Alan Cox
2011-07-05 14:34 ` [PATCH 03/49] gma500: Do sane FB cleanup Alan Cox
2011-07-05 14:34 ` [PATCH 04/49] gma500: trim some of the debug Alan Cox
2011-07-05 14:34 ` [PATCH 05/49] gma500: polish for completion of this phase Alan Cox
2011-07-05 14:35 ` [PATCH 06/49] gma500: 2D acceleration tidying Alan Cox
2011-07-05 14:35 ` [PATCH 07/49] gma500: nuke the last bits of TTM code Alan Cox
2011-07-05 14:35 ` [PATCH 08/49] gma500: nuke the PSB debug stuff Alan Cox
2011-07-05 14:35 ` [PATCH 09/49] gma500: Kill spare kref Alan Cox
2011-07-05 14:35 ` [PATCH 10/49] gma500: GEM glue Alan Cox
2011-07-05 14:36 ` [PATCH 11/49] gma500: Use the GEM tweaks to provide a GEM frame buffer Alan Cox
2011-07-05 14:36 ` [PATCH 12/49] gma500: CodingStyle pass Alan Cox
2011-07-05 14:36 ` [PATCH 13/49] gma500: 2D polish Alan Cox
2011-07-05 14:36 ` [PATCH 14/49] gma500: Medfield support Alan Cox
2011-07-05 14:37 ` [PATCH 15/49] gma500: Move our other GEM helper into the bits want to push into GEM Alan Cox
2011-07-05 14:37 ` [PATCH 16/49] gma500: Extract BIOSisy stuff from psb_drv Alan Cox
2011-07-05 14:37 ` [PATCH 17/49] gma500: psb_fb tidy/cleanup pass Alan Cox
2011-07-05 14:37 ` [PATCH 18/49] gma500: Update the GEM todo Alan Cox
2011-07-05 14:38 ` [PATCH 19/49] gma500: Only fiddle with clock gating on PSB Alan Cox
2011-07-05 14:38 ` [PATCH 20/49] gma500: being abstracting out devices a bit more Alan Cox
2011-07-05 14:38 ` [PATCH 21/49] gma500: continue abstracting platform specific code Alan Cox
2011-07-05 14:38 ` [PATCH 22/49] gma500: Fix early Medfield crash Alan Cox
2011-07-05 14:39 ` [PATCH 23/49] gma500: Read the GCT panel type information for Medfield Alan Cox
2011-07-05 14:39 ` [PATCH 24/49] gma500: enable Medfield CRTC support Alan Cox
2011-07-05 14:39 ` [PATCH 25/49] commit ee12661199b82934552c7636b10217a9aa42958a Alan Cox
2011-07-05 15:55   ` Greg KH
2011-07-05 14:39 ` [PATCH 26/49] gma500: add more ops Alan Cox
2011-07-05 14:40 ` [PATCH 27/49] gma500: remove an un-needed check Alan Cox
2011-07-05 14:40 ` [PATCH 28/49] gma500: move configuration bits into the psb_ops structure Alan Cox
2011-07-05 14:40 ` [PATCH 29/49] gma500: Add the beginnings of Cedarview support Alan Cox
2011-07-05 14:40 ` [PATCH 30/49] gma500: the 'mrst' BIOS is actually MID generic Alan Cox
2011-07-05 14:40 ` [PATCH 31/49] gma500: tidy the framebuffer fixme and oddments Alan Cox
2011-07-05 14:41 ` [PATCH 32/49] gma500: move framebuffer file Alan Cox
2011-07-05 14:41 ` [PATCH 33/49] gma500: The 2D code is now also device independent Alan Cox
2011-07-05 14:41 ` [PATCH 34/49] gma500: the GEM and GTT code is device independant Alan Cox
2011-07-08  1:14   ` Hugh Dickins
2011-07-08  8:38     ` Alan Cox
2011-07-08 17:06       ` Hugh Dickins
2011-07-11 16:25         ` Alan Cox
2011-07-11 17:49           ` Hugh Dickins
2011-09-12 23:19             ` Konrad Rzeszutek Wilk
2011-09-13  8:15               ` Alan Cox
2011-10-09 20:15             ` Patrik Jakobsson
2011-10-10 18:37               ` Hugh Dickins
2011-10-12 12:03                 ` Patrik Jakobsson
2011-10-15 14:30                 ` Rob Clark
2011-10-17 17:48                   ` Hugh Dickins
2011-10-17 21:39                     ` Alan Cox
2011-10-17 22:34                       ` Hugh Dickins
2011-10-17 23:32                         ` Rob Clark
2011-10-18 10:45                           ` Alan Cox
2011-10-18 11:59                             ` Rob Clark
2011-10-18 12:08                               ` Alan Cox
2011-10-18 13:36                                 ` Rob Clark
2011-10-18 11:16                       ` Patrik Jakobsson
2011-07-05 14:41 ` [PATCH 35/49] gma500: begin the config based split Alan Cox
2011-07-05 14:42 ` [PATCH 36/49] gma500: Rename the psb_intel_bios code Alan Cox
2011-07-05 14:42 ` [PATCH 37/49] gma500: tidy up the opregion and lid code Alan Cox
2011-07-05 14:42 ` [PATCH 38/49] gma500: move opregion files Alan Cox
2011-07-05 14:42 ` [PATCH 39/49] gma500: the MMU code is also generic Alan Cox
2011-07-05 14:43 ` [PATCH 40/49] gma500: move the i2c code Alan Cox
2011-07-05 14:43 ` [PATCH 41/49] gma500: tidying up the power stuff a spot Alan Cox
2011-07-05 14:43 ` [PATCH 42/49] gma500: move the BIOS header Alan Cox
2011-07-05 14:43 ` [PATCH 43/49] gma500: move the power header Alan Cox
2011-07-05 14:44 ` [PATCH 44/49] gma500: begin adding CDV specific code Alan Cox
2011-07-05 14:44 ` [PATCH 45/49] gma500: Add the HDMI bits Alan Cox
2011-07-05 14:44 ` [PATCH 46/49] gma500: Fix backlight crash Alan Cox
2011-07-05 14:44 ` [PATCH 47/49] gma500: Workaround for Medfield/Cedarview cursor bug Alan Cox
2011-07-05 14:45 ` [PATCH 48/49] gma500: Fix missing memory check Alan Cox
2011-07-05 14:45 ` [PATCH 49/49] gma500: power can be touched in IRQ state Alan Cox
2011-07-05 15:23 ` [PATCH 00/49] GMA50 series update Greg KH
2011-07-05 15:36   ` Greg KH
2011-07-05 18:03   ` Alan Cox
2011-07-06  2:44     ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.