浏览代码

drm: Merge branch 'drm-gma500-alancox' into drm-core-next

This merges a topic branch containing patches from Alan for the GMA500 driver.

* drm-gma500-alancox:
  gma500: Oaktrail BIOS handling
  gma500: Fix oaktrail probing part 1
  gma500: Be smarter about layout
  gma500: gtt based hardware scrolling console
  gma500: frame buffer locking
  gma500: Fix backlight crash
  gma500: kill bogus code
  gma500: Convert spaces to tabs in accel_2d.c.
  gma500: do a pass over the FIXME tags
  gma500: Add VBLANK support for Poulsbo hardware
  gma500: Don't enable MSI on Poulsbo
  gma500: Only register interrupt handler for poulsbo hardware
  gma500: kill virtual mapping support
  gma500: Move the API
  gma500: kill off NUM_PIPE define
  gma500: Rename the ioctls to avoid clashing with the legacy drivers
  drm/gma500: begin pruning dead bits of API
Dave Airlie 13 年之前
父节点
当前提交
cee5ec4346

+ 7 - 5
drivers/gpu/drm/gma500/accel_2d.c

@@ -111,14 +111,15 @@ static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
 	int ret = 0;
 	int i;
 	unsigned submit_size;
+	unsigned long flags;
 
-	mutex_lock(&dev_priv->mutex_2d);
+	spin_lock_irqsave(&dev_priv->lock_2d, flags);
 	while (size > 0) {
 		submit_size = (size < 0x60) ? size : 0x60;
 		size -= submit_size;
 		ret = psb_2d_wait_available(dev_priv, submit_size);
 		if (ret)
-		        break;
+			break;
 
 		submit_size <<= 2;
 
@@ -127,7 +128,7 @@ static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
 
 		(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
 	}
-	mutex_unlock(&dev_priv->mutex_2d);
+	spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
 	return ret;
 }
 
@@ -327,8 +328,9 @@ int psbfb_sync(struct fb_info *info)
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	unsigned long _end = jiffies + DRM_HZ;
 	int busy = 0;
+	unsigned long flags;
 
-	mutex_lock(&dev_priv->mutex_2d);
+	spin_lock_irqsave(&dev_priv->lock_2d, flags);
 	/*
 	 * First idle the 2D engine.
 	 */
@@ -357,6 +359,6 @@ int psbfb_sync(struct fb_info *info)
 					_PSB_C2B_STATUS_BUSY) != 0);
 
 out:
-	mutex_unlock(&dev_priv->mutex_2d);
+	spin_unlock_irqrestore(&dev_priv->lock_2d, flags);
 	return (busy) ? -EBUSY : 0;
 }

+ 1 - 2
drivers/gpu/drm/gma500/cdv_device.c

@@ -20,7 +20,7 @@
 #include <linux/backlight.h>
 #include <drm/drmP.h>
 #include <drm/drm.h>
-#include "psb_drm.h"
+#include "gma_drm.h"
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
@@ -30,7 +30,6 @@
 #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;

+ 97 - 57
drivers/gpu/drm/gma500/framebuffer.c

@@ -38,6 +38,7 @@
 #include "psb_intel_reg.h"
 #include "psb_intel_drv.h"
 #include "framebuffer.h"
+#include "gtt.h"
 
 static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
 static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
@@ -90,6 +91,25 @@ static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 	return 0;
 }
 
+static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = &fbdev->pfb;
+	struct drm_device *dev = psbfb->base.dev;
+
+	/*
+	 *	We have to poke our nose in here. The core fb code assumes
+	 *	panning is part of the hardware that can be invoked before
+	 *	the actual fb is mapped. In our case that isn't quite true.
+	 */
+	if (psbfb->gtt->npage) {
+		/* GTT roll shifts in 4K pages, we need to shift the right
+		   number of pages */
+		int pages = info->fix.line_length >> 12;
+		psb_gtt_roll(dev, psbfb->gtt, var->yoffset * pages);
+	}
+        return 0;
+}
 
 void psbfb_suspend(struct drm_device *dev)
 {
@@ -216,6 +236,21 @@ static struct fb_ops psbfb_ops = {
 	.fb_ioctl = psbfb_ioctl,
 };
 
+static struct fb_ops psbfb_roll_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_pan_display = psbfb_pan,
+	.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,
@@ -306,16 +341,14 @@ static struct drm_framebuffer *psb_framebuffer_create
  *	psbfb_alloc		-	allocate frame buffer memory
  *	@dev: the DRM device
  *	@aligned_size: space needed
+ *	@force: fall back to GEM buffers if need be
  *
  *	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.
+ *	we fail as we don't have the virtual mapping space to really vmap it
+ *	and the kernel console code can't handle non linear framebuffers.
  *
- *	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.
+ *	Re-address this as and if the framebuffer layer grows this ability.
  */
 static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
 {
@@ -328,17 +361,7 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
 			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;
+	return NULL;
 }
 
 /**
@@ -362,6 +385,8 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	int ret;
 	struct gtt_range *backing;
 	u32 bpp, depth;
+	int gtt_roll = 0;
+	int pitch_lines = 0;
 
 	mode_cmd.width = sizes->surface_width;
 	mode_cmd.height = sizes->surface_height;
@@ -371,17 +396,51 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	if (bpp == 24)
 		bpp = 32;
 
-	/* HW requires pitch to be 64 byte aligned */
-	mode_cmd.pitches[0] =  ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64);
-	depth = sizes->surface_depth;
+	do {
+		/*
+		 * Acceleration via the GTT requires pitch to be
+		 * power of two aligned. Preferably page but less
+		 * is ok with some fonts
+		 */
+        	mode_cmd.pitches[0] =  ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096 >> pitch_lines);
+        	depth = sizes->surface_depth;
 
-	size = mode_cmd.pitches[0] * mode_cmd.height;
-	size = ALIGN(size, PAGE_SIZE);
+        	size = mode_cmd.pitches[0] * 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;
+		/* Allocate the fb in the GTT with stolen page backing */
+		backing = psbfb_alloc(dev, size);
+
+		if (pitch_lines)
+			pitch_lines *= 2;
+		else
+			pitch_lines = 1;
+		gtt_roll++;
+	} while (backing == NULL && pitch_lines <= 16);
+
+	/* The final pitch we accepted if we succeeded */
+	pitch_lines /= 2;
+
+	if (backing == NULL) {
+		/*
+		 *	We couldn't get the space we wanted, fall back to the
+		 *	display engine requirement instead.  The HW requires
+		 *	the pitch to be 64 byte aligned
+		 */
+
+		gtt_roll = 0;	/* Don't use GTT accelerated scrolling */
+		pitch_lines = 64;
+
+		mode_cmd.pitches[0] =  ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64);
+
+		size = mode_cmd.pitches[0] * 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);
 
@@ -407,11 +466,13 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 	strcpy(info->fix.id, "psbfb");
 
 	info->flags = FBINFO_DEFAULT;
-	/* No 2D engine */
-	if (!dev_priv->ops->accel_2d)
-		info->fbops = &psbfb_unaccel_ops;
-	else
+	if (dev_priv->ops->accel_2d && pitch_lines > 8)	/* 2D engine */
 		info->fbops = &psbfb_ops;
+	else if (gtt_roll) {	/* GTT rolling seems best */
+		info->fbops = &psbfb_roll_ops;
+		info->flags |= FBINFO_HWACCEL_YPAN;
+	} else	/* Software */
+		info->fbops = &psbfb_unaccel_ops;
 
 	ret = fb_alloc_cmap(&info->cmap, 256, 0);
 	if (ret) {
@@ -421,23 +482,12 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 
 	info->fix.smem_start = dev->mode_config.fb_base;
 	info->fix.smem_len = size;
+	info->fix.ywrapstep = gtt_roll;
+	info->fix.ypanstep = 0;
 
-	if (backing->stolen) {
-		/* Accessed stolen memory directly */
-		info->screen_base = (char *)dev_priv->vram_addr +
+	/* 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->gtt.stolen_size) {
@@ -471,11 +521,8 @@ static int psbfb_create(struct psb_fbdev *fbdev,
 out_unref:
 	if (backing->stolen)
 		psb_gtt_free_range(dev, backing);
-	else {
-		if (psbfb->vm_map)
-			vm_unmap_ram(info->screen_base, backing->npage);
+	else
 		drm_gem_object_unreference(&backing->gem);
-	}
 out_err1:
 	mutex_unlock(&dev->struct_mutex);
 	psb_gtt_free_range(dev, backing);
@@ -549,13 +596,6 @@ 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);
-		}
 		unregister_framebuffer(info);
 		if (info->cmap.len)
 			fb_dealloc_cmap(&info->cmap);
@@ -765,7 +805,7 @@ void psb_modeset_init(struct drm_device *dev)
 	dev->mode_config.funcs = (void *) &psb_mode_funcs;
 
 	/* set memory base */
-	/* MRST and PSB should use BAR 2*/
+	/* Oaktrail and Poulsbo should use BAR 2*/
 	pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
 					&(dev->mode_config.fb_base));
 

+ 0 - 1
drivers/gpu/drm/gma500/framebuffer.h

@@ -32,7 +32,6 @@ 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 {

+ 4 - 7
drivers/gpu/drm/gma500/gem.c

@@ -25,7 +25,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm.h>
-#include "psb_drm.h"
+#include "gma_drm.h"
 #include "psb_drv.h"
 
 int psb_gem_init_object(struct drm_gem_object *obj)
@@ -120,8 +120,7 @@ static int psb_gem_create(struct drm_file *file,
 	/* 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 */
+		/* GEM doesn't give an error code so use -ENOMEM */
 		dev_err(dev->dev, "GEM init failed for %lld\n", size);
 		return -ENOMEM;
 	}
@@ -191,8 +190,6 @@ int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
  *	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)
 {
@@ -274,13 +271,13 @@ int psb_gem_create_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_psb_gem_create *args = data;
 	int ret;
-	if (args->flags & PSB_GEM_CREATE_STOLEN) {
+	if (args->flags & GMA_GEM_CREATE_STOLEN) {
 		ret = psb_gem_create_stolen(file, dev, args->size,
 							&args->handle);
 		if (ret == 0)
 			return 0;
 		/* Fall throguh */
-		args->flags &= ~PSB_GEM_CREATE_STOLEN;
+		args->flags &= ~GMA_GEM_CREATE_STOLEN;
 	}
 	return psb_gem_create(file, dev, args->size, &args->handle);
 }

+ 67 - 14
drivers/gpu/drm/gma500/gtt.c

@@ -72,9 +72,8 @@ u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
  *	@r: our GTT range
  *
  *	Take our preallocated GTT range and insert the GEM object into
- *	the GTT.
- *
- *	FIXME: gtt lock ?
+ *	the GTT. This is protected via the gtt mutex which the caller
+ *	must hold.
  */
 static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
 {
@@ -96,12 +95,17 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
 	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*/);
+	for (i = r->roll; i < r->npage; i++) {
+		pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+		iowrite32(pte, gtt_slot++);
+	}
+	for (i = 0; i < r->roll; i++) {
+		pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
 		iowrite32(pte, gtt_slot++);
 	}
 	/* Make sure all the entries are set before we return */
 	ioread32(gtt_slot - 1);
+
 	return 0;
 }
 
@@ -111,9 +115,9 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
  *	@r: our GTT range
  *
  *	Remove a preallocated GTT range from the GTT. Overwrite all the
- *	page table entries with the dummy page
+ *	page table entries with the dummy page. This is protected via the gtt
+ *	mutex which the caller must hold.
  */
-
 static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
@@ -131,12 +135,53 @@ static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
 	set_pages_array_wb(r->pages, r->npage);
 }
 
+/**
+ *	psb_gtt_roll	-	set scrolling position
+ *	@dev: our DRM device
+ *	@r: the gtt mapping we are using
+ *	@roll: roll offset
+ *
+ *	Roll an existing pinned mapping by moving the pages through the GTT.
+ *	This allows us to implement hardware scrolling on the consoles without
+ *	a 2D engine
+ */
+void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll)
+{
+	u32 *gtt_slot, pte;
+	int i;
+
+	if (roll >= r->npage) {
+		WARN_ON(1);
+		return;
+	}
+
+	r->roll = roll;
+
+	/* Not currently in the GTT - no worry we will write the mapping at
+	   the right position when it gets pinned */
+	if (!r->stolen && !r->in_gart)
+		return;
+
+	gtt_slot = psb_gtt_entry(dev, r);
+
+	for (i = r->roll; i < r->npage; i++) {
+		pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+		iowrite32(pte, gtt_slot++);
+	}
+	for (i = 0; i < r->roll; i++) {
+		pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0);
+		iowrite32(pte, gtt_slot++);
+	}
+	ioread32(gtt_slot - 1);
+}
+
 /**
  *	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
+ *	While we hold this the pages cannot be swapped out. This is protected
+ *	via the gtt mutex which the caller must hold.
  */
 static int psb_gtt_attach_pages(struct gtt_range *gt)
 {
@@ -158,7 +203,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt)
 	gt->npage = pages;
 
 	for (i = 0; i < pages; i++) {
-		/* FIXME: review flags later */
+		/* FIXME: needs updating as per mail from Hugh Dickins */
 		p = read_cache_page_gfp(mapping, i,
 					__GFP_COLD | GFP_KERNEL);
 		if (IS_ERR(p))
@@ -181,7 +226,8 @@ 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.
+ *	and move bus address. This is protected via the gtt mutex which the
+ *	caller must hold.
  */
 static void psb_gtt_detach_pages(struct gtt_range *gt)
 {
@@ -300,6 +346,7 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
 	gt->resource.name = name;
 	gt->stolen = backed;
 	gt->in_gart = backed;
+	gt->roll = 0;
 	/* Ensure this is set for non GEM objects */
 	gt->gem.dev = dev;
 	ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
@@ -390,15 +437,18 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 	pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
 
 	/*
-	 *	FIXME: video mmu has hw bug to access 0x0D0000000,
-	 *	then make gatt start at 0x0e000,0000
+	 *	The video mmu has a hw bug when accessing 0x0D0000000.
+	 *	Make gatt start at 0x0e000,0000. This doesn't actually
+	 *	matter for us but may do if the video acceleration ever
+	 *	gets opened up.
 	 */
 	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;
-	/* CDV workaround */
+	/* Some CDV firmware doesn't report this currently. In which case the
+	   system has 64 gtt pages */
 	if (pg->gtt_start == 0 || gtt_pages == 0) {
 		dev_err(dev->dev, "GTT PCI BAR not initialized.\n");
 		gtt_pages = 64;
@@ -412,13 +462,16 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 
 	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;
+		/* This is a little confusing but in fact the GTT is providing
+		   a view from the GPU into memory and not vice versa. As such
+		   this is really allocating space that is not the same as the
+		   CPU address space on CDV */
 		fudge.start = 0x40000000;
 		fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1;
 		fudge.name = "fudge";

+ 3 - 0
drivers/gpu/drm/gma500/gtt.h

@@ -49,6 +49,7 @@ struct gtt_range {
 	bool mmapping;			/* Is mmappable */
 	struct page **pages;		/* Backing pages if present */
 	int npage;			/* Number of backing pages */
+	int roll;			/* Roll applied to the GTT entries */
 };
 
 extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
@@ -57,5 +58,7 @@ 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);
+extern void psb_gtt_roll(struct drm_device *dev,
+					struct gtt_range *gt, int roll);
 
 #endif

+ 1 - 1
drivers/gpu/drm/gma500/intel_bios.c

@@ -20,7 +20,7 @@
  */
 #include <drm/drmP.h>
 #include <drm/drm.h>
-#include "psb_drm.h"
+#include "gma_drm.h"
 #include "psb_drv.h"
 #include "psb_intel_drv.h"
 #include "psb_intel_reg.h"

+ 1 - 0
drivers/gpu/drm/gma500/intel_opregion.c

@@ -20,6 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
+ * FIXME: resolve with the i915 version
  */
 
 #include "psb_drv.h"

+ 7 - 1
drivers/gpu/drm/gma500/mid_bios.c

@@ -25,7 +25,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm.h>
-#include "psb_drm.h"
+#include "gma_drm.h"
 #include "psb_drv.h"
 #include "mid_bios.h"
 
@@ -142,6 +142,12 @@ static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
 	memcpy(vbt, vbt_virtual, sizeof(*vbt));
 	iounmap(vbt_virtual); /* Free virtual address space */
 
+	/* No matching signature don't process the data */
+	if (memcmp(vbt->signature, "$GCT", 4)) {
+		vbt->size = 0;
+		return;
+	}
+
 	dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision);
 
 	switch (vbt->revision) {

+ 5 - 11
drivers/gpu/drm/gma500/oaktrail_crtc.c

@@ -521,12 +521,11 @@ int oaktrail_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);
 	int pipe = psb_intel_crtc->pipe;
 	unsigned long start, offset;
-	/* FIXME: check if we need this surely MRST is pipe 0 only */
+
 	int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE);
 	int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 	int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
@@ -572,15 +571,10 @@ int oaktrail_pipe_set_base(struct drm_crtc *crtc,
 	}
 	REG_WRITE(dspcntr_reg, dspcntr);
 
-	if (0 /* FIXMEAC - check what PSB needs */) {
-		REG_WRITE(dspbase, offset);
-		REG_READ(dspbase);
-		REG_WRITE(dspsurf, start);
-		REG_READ(dspsurf);
-	} else {
-		REG_WRITE(dspbase, start + offset);
-		REG_READ(dspbase);
-	}
+	REG_WRITE(dspbase, offset);
+	REG_READ(dspbase);
+	REG_WRITE(dspsurf, start);
+	REG_READ(dspsurf);
 
 pipe_set_base_exit:
 	gma_power_end(dev);

+ 25 - 2
drivers/gpu/drm/gma500/oaktrail_device.c

@@ -22,13 +22,14 @@
 #include <linux/dmi.h>
 #include <drm/drmP.h>
 #include <drm/drm.h>
-#include "psb_drm.h"
+#include "gma_drm.h"
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
 #include <asm/mrst.h>
 #include <asm/intel_scu_ipc.h>
 #include "mid_bios.h"
+#include "intel_bios.h"
 
 static int oaktrail_output_init(struct drm_device *dev)
 {
@@ -456,9 +457,31 @@ static int oaktrail_power_up(struct drm_device *dev)
 }
 
 
+static int oaktrail_chip_setup(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct oaktrail_vbt *vbt = &dev_priv->vbt_data;
+	int ret;
+	
+	ret = mid_chip_setup(dev);
+	if (ret < 0)
+		return ret;
+	if (vbt->size == 0) {
+		/* Now pull the BIOS data */
+		gma_intel_opregion_init(dev);
+		psb_intel_init_bios(dev);
+	}
+	return 0;
+}
+
 static void oaktrail_teardown(struct drm_device *dev)
 {
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct oaktrail_vbt *vbt = &dev_priv->vbt_data;
+
 	oaktrail_hdmi_teardown(dev);
+	if (vbt->size == 0)
+		psb_intel_destroy_bios(dev);
 }
 
 const struct psb_ops oaktrail_chip_ops = {
@@ -468,7 +491,7 @@ const struct psb_ops oaktrail_chip_ops = {
 	.crtcs = 2,
 	.sgx_offset = MRST_SGX_OFFSET,
 
-	.chip_setup = mid_chip_setup,
+	.chip_setup = oaktrail_chip_setup,
 	.chip_teardown = oaktrail_teardown,
 	.crtc_helper = &oaktrail_helper_funcs,
 	.crtc_funcs = &psb_intel_crtc_funcs,

+ 27 - 10
drivers/gpu/drm/gma500/oaktrail_lvds.c

@@ -228,17 +228,20 @@ static struct drm_display_mode lvds_configuration_modes[] = {
 
 /* Returns the panel fixed mode from configuration. */
 
-static struct drm_display_mode *
-oaktrail_lvds_get_configuration_mode(struct drm_device *dev)
+static void oaktrail_lvds_get_configuration_mode(struct drm_device *dev,
+					struct psb_intel_mode_device *mode_dev)
 {
 	struct drm_display_mode *mode = NULL;
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD;
 
+	mode_dev->panel_fixed_mode = NULL;
+
+	/* Use the firmware provided data on Moorestown */
 	if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/
 		mode = kzalloc(sizeof(*mode), GFP_KERNEL);
 		if (!mode)
-			return NULL;
+			return;
 
 		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
 		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
@@ -270,13 +273,27 @@ oaktrail_lvds_get_configuration_mode(struct drm_device *dev)
 		printk(KERN_INFO "vtotal is %d\n", mode->vtotal);
 		printk(KERN_INFO "clock is %d\n", mode->clock);
 #endif
-	} else
-		mode = drm_mode_duplicate(dev, &lvds_configuration_modes[2]);
-
-	drm_mode_set_name(mode);
-	drm_mode_set_crtcinfo(mode, 0);
+		mode_dev->panel_fixed_mode = mode;
+	}
 
-	return mode;
+	/* Use the BIOS VBT mode if available */
+	if (mode_dev->panel_fixed_mode == NULL && mode_dev->vbt_mode)
+		mode_dev->panel_fixed_mode = drm_mode_duplicate(dev,
+						mode_dev->vbt_mode);
+
+	/* Then try the LVDS VBT mode */
+	if (mode_dev->panel_fixed_mode == NULL)
+		if (dev_priv->lfp_lvds_vbt_mode)
+			mode_dev->panel_fixed_mode =
+				drm_mode_duplicate(dev,
+					dev_priv->lfp_lvds_vbt_mode);
+	/* Then guess */
+	if (mode_dev->panel_fixed_mode == NULL)
+		mode_dev->panel_fixed_mode
+			= drm_mode_duplicate(dev, &lvds_configuration_modes[2]);
+
+	drm_mode_set_name(mode_dev->panel_fixed_mode);
+	drm_mode_set_crtcinfo(mode_dev->panel_fixed_mode, 0);
 }
 
 /**
@@ -375,7 +392,7 @@ void oaktrail_lvds_init(struct drm_device *dev,
 	 * If we didn't get EDID, try geting panel timing
 	 * from configuration data
 	 */
-	mode_dev->panel_fixed_mode = oaktrail_lvds_get_configuration_mode(dev);
+	oaktrail_lvds_get_configuration_mode(dev, mode_dev);
 
 	if (mode_dev->panel_fixed_mode) {
 		mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;

+ 1 - 1
drivers/gpu/drm/gma500/power.c

@@ -302,7 +302,7 @@ int psb_runtime_suspend(struct device *dev)
 
 int psb_runtime_resume(struct device *dev)
 {
-	return 0;
+	return gma_power_resume(dev);;
 }
 
 int psb_runtime_idle(struct device *dev)

+ 1 - 33
drivers/gpu/drm/gma500/psb_device.c

@@ -20,7 +20,7 @@
 #include <linux/backlight.h>
 #include <drm/drmP.h>
 #include <drm/drm.h>
-#include "psb_drm.h"
+#include "gma_drm.h"
 #include "psb_drv.h"
 #include "psb_reg.h"
 #include "psb_intel_reg.h"
@@ -213,7 +213,6 @@ 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);
@@ -237,37 +236,6 @@ static int psb_restore_display_registers(struct drm_device *dev)
 		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;
 }
 

+ 0 - 207
drivers/gpu/drm/gma500/psb_drm.h

@@ -1,207 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2007-2011, Intel Corporation.
- * All Rights Reserved.
- * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#ifndef _PSB_DRM_H_
-#define _PSB_DRM_H_
-
-#define PSB_NUM_PIPE 3
-
-#define PSB_GPU_ACCESS_READ         (1ULL << 32)
-#define PSB_GPU_ACCESS_WRITE        (1ULL << 33)
-#define PSB_GPU_ACCESS_MASK         (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)
-
-#define PSB_BO_FLAG_COMMAND         (1ULL << 52)
-
-/*
- * Feedback components:
- */
-
-struct drm_psb_sizes_arg {
-	u32 ta_mem_size;
-	u32 mmu_size;
-	u32 pds_size;
-	u32 rastgeom_size;
-	u32 tt_size;
-	u32 vram_size;
-};
-
-struct drm_psb_dpst_lut_arg {
-	uint8_t lut[256];
-	int output_id;
-};
-
-#define PSB_DC_CRTC_SAVE 0x01
-#define PSB_DC_CRTC_RESTORE 0x02
-#define PSB_DC_OUTPUT_SAVE 0x04
-#define PSB_DC_OUTPUT_RESTORE 0x08
-#define PSB_DC_CRTC_MASK 0x03
-#define PSB_DC_OUTPUT_MASK 0x0C
-
-struct drm_psb_dc_state_arg {
-	u32 flags;
-	u32 obj_id;
-};
-
-struct drm_psb_mode_operation_arg {
-	u32 obj_id;
-	u16 operation;
-	struct drm_mode_modeinfo mode;
-	void *data;
-};
-
-struct drm_psb_stolen_memory_arg {
-	u32 base;
-	u32 size;
-};
-
-/*Display Register Bits*/
-#define REGRWBITS_PFIT_CONTROLS			(1 << 0)
-#define REGRWBITS_PFIT_AUTOSCALE_RATIOS		(1 << 1)
-#define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS	(1 << 2)
-#define REGRWBITS_PIPEASRC			(1 << 3)
-#define REGRWBITS_PIPEBSRC			(1 << 4)
-#define REGRWBITS_VTOTAL_A			(1 << 5)
-#define REGRWBITS_VTOTAL_B			(1 << 6)
-#define REGRWBITS_DSPACNTR	(1 << 8)
-#define REGRWBITS_DSPBCNTR	(1 << 9)
-#define REGRWBITS_DSPCCNTR	(1 << 10)
-
-/*Overlay Register Bits*/
-#define OV_REGRWBITS_OVADD			(1 << 0)
-#define OV_REGRWBITS_OGAM_ALL			(1 << 1)
-
-#define OVC_REGRWBITS_OVADD                  (1 << 2)
-#define OVC_REGRWBITS_OGAM_ALL			(1 << 3)
-
-struct drm_psb_register_rw_arg {
-	u32 b_force_hw_on;
-
-	u32 display_read_mask;
-	u32 display_write_mask;
-
-	struct {
-		u32 pfit_controls;
-		u32 pfit_autoscale_ratios;
-		u32 pfit_programmed_scale_ratios;
-		u32 pipeasrc;
-		u32 pipebsrc;
-		u32 vtotal_a;
-		u32 vtotal_b;
-	} display;
-
-	u32 overlay_read_mask;
-	u32 overlay_write_mask;
-
-	struct {
-		u32 OVADD;
-		u32 OGAMC0;
-		u32 OGAMC1;
-		u32 OGAMC2;
-		u32 OGAMC3;
-		u32 OGAMC4;
-		u32 OGAMC5;
-		u32 IEP_ENABLED;
-		u32 IEP_BLE_MINMAX;
-		u32 IEP_BSSCC_CONTROL;
-		u32 b_wait_vblank;
-	} overlay;
-
-	u32 sprite_enable_mask;
-	u32 sprite_disable_mask;
-
-	struct {
-		u32 dspa_control;
-		u32 dspa_key_value;
-		u32 dspa_key_mask;
-		u32 dspc_control;
-		u32 dspc_stride;
-		u32 dspc_position;
-		u32 dspc_linear_offset;
-		u32 dspc_size;
-		u32 dspc_surface;
-	} sprite;
-
-	u32 subpicture_enable_mask;
-	u32 subpicture_disable_mask;
-};
-
-/* Controlling the kernel modesetting buffers */
-
-#define DRM_PSB_SIZES           0x07
-#define DRM_PSB_FUSE_REG	0x08
-#define DRM_PSB_DC_STATE	0x0A
-#define DRM_PSB_ADB		0x0B
-#define DRM_PSB_MODE_OPERATION	0x0C
-#define DRM_PSB_STOLEN_MEMORY	0x0D
-#define DRM_PSB_REGISTER_RW	0x0E
-
-/*
- * NOTE: Add new commands here, but increment
- * the values below and increment their
- * corresponding defines where they're
- * defined elsewhere.
- */
-
-#define DRM_PSB_GEM_CREATE	0x10
-#define DRM_PSB_2D_OP		0x11		/* Will be merged later */
-#define DRM_PSB_GEM_MMAP	0x12
-#define DRM_PSB_DPST		0x1B
-#define DRM_PSB_GAMMA		0x1C
-#define DRM_PSB_DPST_BL		0x1D
-#define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F
-
-#define PSB_MODE_OPERATION_MODE_VALID	0x01
-#define PSB_MODE_OPERATION_SET_DC_BASE  0x02
-
-struct drm_psb_get_pipe_from_crtc_id_arg {
-	/** ID of CRTC being requested **/
-	u32 crtc_id;
-
-	/** pipe of requested CRTC **/
-	u32 pipe;
-};
-
-/* FIXME: move this into a medfield header once we are sure it isn't needed for an
-   ioctl  */
-struct psb_drm_dpu_rect {  
-	int x, y;             
-	int width, height;    
-};  
-
-struct drm_psb_gem_create {
-	__u64 size;
-	__u32 handle;
-	__u32 flags;
-#define PSB_GEM_CREATE_STOLEN		1	/* Stolen memory can be used */
-};
-
-struct drm_psb_gem_mmap {
-	__u32 handle;
-	__u32 pad;
-	/**
-	 * Fake offset to use for subsequent mmap call
-	 *
-	 * This is a fixed-size type for 32/64 compatibility.
-	 */
-	__u64 offset;
-};
-
-#endif

+ 17 - 521
drivers/gpu/drm/gma500/psb_drv.c

@@ -21,7 +21,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm.h>
-#include "psb_drm.h"
+#include "gma_drm.h"
 #include "psb_drv.h"
 #include "framebuffer.h"
 #include "psb_reg.h"
@@ -80,58 +80,36 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
  * Standard IOCTLs.
  */
 
-#define DRM_IOCTL_PSB_SIZES	\
-		DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
-			struct drm_psb_sizes_arg)
-#define DRM_IOCTL_PSB_FUSE_REG	\
-		DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t)
-#define DRM_IOCTL_PSB_DC_STATE	\
-		DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \
-			struct drm_psb_dc_state_arg)
 #define DRM_IOCTL_PSB_ADB	\
-		DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t)
+		DRM_IOWR(DRM_GMA_ADB + DRM_COMMAND_BASE, uint32_t)
 #define DRM_IOCTL_PSB_MODE_OPERATION	\
-		DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \
+		DRM_IOWR(DRM_GMA_MODE_OPERATION + DRM_COMMAND_BASE, \
 			 struct drm_psb_mode_operation_arg)
 #define DRM_IOCTL_PSB_STOLEN_MEMORY	\
-		DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \
+		DRM_IOWR(DRM_GMA_STOLEN_MEMORY + DRM_COMMAND_BASE, \
 			 struct drm_psb_stolen_memory_arg)
-#define DRM_IOCTL_PSB_REGISTER_RW	\
-		DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \
-			 struct drm_psb_register_rw_arg)
-#define DRM_IOCTL_PSB_DPST	\
-		DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \
-			 uint32_t)
 #define DRM_IOCTL_PSB_GAMMA	\
-		DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \
+		DRM_IOWR(DRM_GMA_GAMMA + DRM_COMMAND_BASE, \
 			 struct drm_psb_dpst_lut_arg)
 #define DRM_IOCTL_PSB_DPST_BL	\
-		DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \
+		DRM_IOWR(DRM_GMA_DPST_BL + DRM_COMMAND_BASE, \
 			 uint32_t)
 #define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID	\
-		DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
+		DRM_IOWR(DRM_GMA_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
 			 struct drm_psb_get_pipe_from_crtc_id_arg)
 #define DRM_IOCTL_PSB_GEM_CREATE	\
-		DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \
+		DRM_IOWR(DRM_GMA_GEM_CREATE + DRM_COMMAND_BASE, \
 			 struct drm_psb_gem_create)
 #define DRM_IOCTL_PSB_GEM_MMAP	\
-		DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \
+		DRM_IOWR(DRM_GMA_GEM_MMAP + DRM_COMMAND_BASE, \
 			 struct drm_psb_gem_mmap)
 
-static int psb_sizes_ioctl(struct drm_device *dev, void *data,
-			   struct drm_file *file_priv);
-static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
-			      struct drm_file *file_priv);
 static int psb_adb_ioctl(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
 				    struct drm_file *file_priv);
 static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
 				   struct drm_file *file_priv);
-static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
-				 struct drm_file *file_priv);
-static int psb_dpst_ioctl(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv);
 static int psb_gamma_ioctl(struct drm_device *dev, void *data,
 			   struct drm_file *file_priv);
 static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
@@ -141,16 +119,11 @@ 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_SIZES, psb_sizes_ioctl, DRM_AUTH),
-	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH),
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH),
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl,
 		      DRM_AUTH),
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl,
 		      DRM_AUTH),
-	PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl,
-		      DRM_AUTH),
-	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH),
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH),
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
 	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID,
@@ -168,7 +141,6 @@ static void psb_lastclose(struct drm_device *dev)
 
 static void psb_do_takedown(struct drm_device *dev)
 {
-	/* FIXME: do we need to clean up the gtt here ? */
 }
 
 static int psb_do_init(struct drm_device *dev)
@@ -214,7 +186,7 @@ static int psb_do_init(struct drm_device *dev)
 
 
 	spin_lock_init(&dev_priv->irqmask_lock);
-	mutex_init(&dev_priv->mutex_2d);
+	spin_lock_init(&dev_priv->lock_2d);
 
 	PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
 	PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
@@ -314,6 +286,11 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	dev_priv->dev = dev;
 	dev->dev_private = (void *) dev_priv;
 
+	if (!IS_PSB(dev)) {
+		if (pci_enable_msi(dev->pdev))
+			dev_warn(dev->dev, "Enabling MSI failed!\n");
+	}
+
 	dev_priv->num_pipe = dev_priv->ops->pipes;
 
 	resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
@@ -395,7 +372,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
 	PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
 	PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
 	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
-	if (drm_core_check_feature(dev, DRIVER_MODESET))
+	if (IS_PSB(dev) && drm_core_check_feature(dev, DRIVER_MODESET))
 		drm_irq_install(dev);
 
 	dev->vblank_disable_allowed = 1;
@@ -442,75 +419,6 @@ int psb_driver_device_is_agp(struct drm_device *dev)
 	return 0;
 }
 
-
-static int psb_sizes_ioctl(struct drm_device *dev, void *data,
-			   struct drm_file *file_priv)
-{
-	struct drm_psb_private *dev_priv = psb_priv(dev);
-	struct drm_psb_sizes_arg *arg =
-		(struct drm_psb_sizes_arg *) data;
-
-	*arg = dev_priv->sizes;
-	return 0;
-}
-
-static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
-				struct drm_file *file_priv)
-{
-	uint32_t flags;
-	uint32_t obj_id;
-	struct drm_mode_object *obj;
-	struct drm_connector *connector;
-	struct drm_crtc *crtc;
-	struct drm_psb_dc_state_arg *arg = data;
-
-
-	/* Double check MRST case */
-	if (IS_MRST(dev) || IS_MFLD(dev))
-		return -EOPNOTSUPP;
-
-	flags = arg->flags;
-	obj_id = arg->obj_id;
-
-	if (flags & PSB_DC_CRTC_MASK) {
-		obj = drm_mode_object_find(dev, obj_id,
-				DRM_MODE_OBJECT_CRTC);
-		if (!obj) {
-			dev_dbg(dev->dev, "Invalid CRTC object.\n");
-			return -EINVAL;
-		}
-
-		crtc = obj_to_crtc(obj);
-
-		mutex_lock(&dev->mode_config.mutex);
-		if (drm_helper_crtc_in_use(crtc)) {
-			if (flags & PSB_DC_CRTC_SAVE)
-				crtc->funcs->save(crtc);
-			else
-				crtc->funcs->restore(crtc);
-		}
-		mutex_unlock(&dev->mode_config.mutex);
-
-		return 0;
-	} else if (flags & PSB_DC_OUTPUT_MASK) {
-		obj = drm_mode_object_find(dev, obj_id,
-				DRM_MODE_OBJECT_CONNECTOR);
-		if (!obj) {
-			dev_dbg(dev->dev, "Invalid connector id.\n");
-			return -EINVAL;
-		}
-
-		connector = obj_to_connector(obj);
-		if (flags & PSB_DC_OUTPUT_SAVE)
-			connector->funcs->save(connector);
-		else
-			connector->funcs->restore(connector);
-
-		return 0;
-	}
-	return -EINVAL;
-}
-
 static inline void get_brightness(struct backlight_device *bd)
 {
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
@@ -543,36 +451,6 @@ static int psb_adb_ioctl(struct drm_device *dev, void *data,
 	return 0;
 }
 
-/* return the current mode to the dpst module */
-static int psb_dpst_ioctl(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv)
-{
-	struct drm_psb_private *dev_priv = psb_priv(dev);
-	uint32_t *arg = data;
-	uint32_t x;
-	uint32_t y;
-	uint32_t reg;
-
-	if (!gma_power_begin(dev, 0))
-		return -EIO;
-
-	reg = PSB_RVDC32(PIPEASRC);
-
-	gma_power_end(dev);
-
-	/* horizontal is the left 16 bits */
-	x = reg >> 16;
-	/* vertical is the right 16 bits */
-	y = reg & 0x0000ffff;
-
-	/* the values are the image size minus one */
-	x++;
-	y++;
-
-	*arg = (x << 16) | y;
-
-	return 0;
-}
 static int psb_gamma_ioctl(struct drm_device *dev, void *data,
 			   struct drm_file *file_priv)
 {
@@ -613,37 +491,15 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
 	struct drm_psb_mode_operation_arg *arg;
 	struct drm_mode_object *obj;
 	struct drm_connector *connector;
-	struct drm_framebuffer *drm_fb;
-	struct psb_framebuffer *psb_fb;
 	struct drm_connector_helper_funcs *connector_funcs;
 	int ret = 0;
 	int resp = MODE_OK;
-	struct drm_psb_private *dev_priv = psb_priv(dev);
 
 	arg = (struct drm_psb_mode_operation_arg *)data;
 	obj_id = arg->obj_id;
 	op = arg->operation;
 
 	switch (op) {
-	case PSB_MODE_OPERATION_SET_DC_BASE:
-		obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB);
-		if (!obj) {
-			dev_dbg(dev->dev, "Invalid FB id %d\n", obj_id);
-			return -EINVAL;
-		}
-
-		drm_fb = obj_to_fb(obj);
-		psb_fb = to_psb_fb(drm_fb);
-
-		if (gma_power_begin(dev, 0)) {
-			REG_WRITE(DSPASURF, psb_fb->gtt->offset);
-			REG_READ(DSPASURF);
-			gma_power_end(dev);
-		} else {
-			dev_priv->saveDSPASURF = psb_fb->gtt->offset;
-		}
-
-		return 0;
 	case PSB_MODE_OPERATION_MODE_VALID:
 		umode = &arg->mode;
 
@@ -689,7 +545,7 @@ static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
 
 		if (connector_funcs->mode_valid) {
 			resp = connector_funcs->mode_valid(connector, mode);
-			arg->data = (void *)resp;
+			arg->data = resp;
 		}
 
 		/*do some clean up work*/
@@ -719,363 +575,6 @@ 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)
-{
-	struct drm_psb_private *dev_priv = psb_priv(dev);
-	struct drm_psb_register_rw_arg *arg = data;
-	bool usage = arg->b_force_hw_on ? true : false;
-
-	if (arg->display_write_mask != 0) {
-		if (gma_power_begin(dev, usage)) {
-			if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
-				PSB_WVDC32(arg->display.pfit_controls,
-					   PFIT_CONTROL);
-			if (arg->display_write_mask &
-			    REGRWBITS_PFIT_AUTOSCALE_RATIOS)
-				PSB_WVDC32(arg->display.pfit_autoscale_ratios,
-					   PFIT_AUTO_RATIOS);
-			if (arg->display_write_mask &
-			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
-				PSB_WVDC32(
-				   arg->display.pfit_programmed_scale_ratios,
-				   PFIT_PGM_RATIOS);
-			if (arg->display_write_mask & REGRWBITS_PIPEASRC)
-				PSB_WVDC32(arg->display.pipeasrc,
-					   PIPEASRC);
-			if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
-				PSB_WVDC32(arg->display.pipebsrc,
-					   PIPEBSRC);
-			if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
-				PSB_WVDC32(arg->display.vtotal_a,
-					   VTOTAL_A);
-			if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
-				PSB_WVDC32(arg->display.vtotal_b,
-					   VTOTAL_B);
-			gma_power_end(dev);
-		} else {
-			if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
-				dev_priv->savePFIT_CONTROL =
-						arg->display.pfit_controls;
-			if (arg->display_write_mask &
-			    REGRWBITS_PFIT_AUTOSCALE_RATIOS)
-				dev_priv->savePFIT_AUTO_RATIOS =
-					arg->display.pfit_autoscale_ratios;
-			if (arg->display_write_mask &
-			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
-				dev_priv->savePFIT_PGM_RATIOS =
-				   arg->display.pfit_programmed_scale_ratios;
-			if (arg->display_write_mask & REGRWBITS_PIPEASRC)
-				dev_priv->savePIPEASRC = arg->display.pipeasrc;
-			if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
-				dev_priv->savePIPEBSRC = arg->display.pipebsrc;
-			if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
-				dev_priv->saveVTOTAL_A = arg->display.vtotal_a;
-			if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
-				dev_priv->saveVTOTAL_B = arg->display.vtotal_b;
-		}
-	}
-
-	if (arg->display_read_mask != 0) {
-		if (gma_power_begin(dev, usage)) {
-			if (arg->display_read_mask &
-			    REGRWBITS_PFIT_CONTROLS)
-				arg->display.pfit_controls =
-						PSB_RVDC32(PFIT_CONTROL);
-			if (arg->display_read_mask &
-			    REGRWBITS_PFIT_AUTOSCALE_RATIOS)
-				arg->display.pfit_autoscale_ratios =
-						PSB_RVDC32(PFIT_AUTO_RATIOS);
-			if (arg->display_read_mask &
-			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
-				arg->display.pfit_programmed_scale_ratios =
-						PSB_RVDC32(PFIT_PGM_RATIOS);
-			if (arg->display_read_mask & REGRWBITS_PIPEASRC)
-				arg->display.pipeasrc = PSB_RVDC32(PIPEASRC);
-			if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
-				arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC);
-			if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
-				arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A);
-			if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
-				arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B);
-			gma_power_end(dev);
-		} else {
-			if (arg->display_read_mask &
-			    REGRWBITS_PFIT_CONTROLS)
-				arg->display.pfit_controls =
-						dev_priv->savePFIT_CONTROL;
-			if (arg->display_read_mask &
-			    REGRWBITS_PFIT_AUTOSCALE_RATIOS)
-				arg->display.pfit_autoscale_ratios =
-						dev_priv->savePFIT_AUTO_RATIOS;
-			if (arg->display_read_mask &
-			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
-				arg->display.pfit_programmed_scale_ratios =
-						dev_priv->savePFIT_PGM_RATIOS;
-			if (arg->display_read_mask & REGRWBITS_PIPEASRC)
-				arg->display.pipeasrc = dev_priv->savePIPEASRC;
-			if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
-				arg->display.pipebsrc = dev_priv->savePIPEBSRC;
-			if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
-				arg->display.vtotal_a = dev_priv->saveVTOTAL_A;
-			if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
-				arg->display.vtotal_b = dev_priv->saveVTOTAL_B;
-		}
-	}
-
-	if (arg->overlay_write_mask != 0) {
-		if (gma_power_begin(dev, usage)) {
-			if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
-				PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5);
-				PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4);
-				PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3);
-				PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2);
-				PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1);
-				PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0);
-			}
-			if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
-				PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5);
-				PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4);
-				PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3);
-				PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2);
-				PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1);
-				PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0);
-			}
-
-			if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) {
-				PSB_WVDC32(arg->overlay.OVADD, OV_OVADD);
-
-				if (arg->overlay.b_wait_vblank) {
-					/* Wait for 20ms.*/
-					unsigned long vblank_timeout = jiffies
-								+ HZ/50;
-					uint32_t temp;
-					while (time_before_eq(jiffies,
-							vblank_timeout)) {
-						temp = PSB_RVDC32(OV_DOVASTA);
-						if ((temp & (0x1 << 31)) != 0)
-							break;
-						cpu_relax();
-					}
-				}
-			}
-			if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) {
-				PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD);
-				if (arg->overlay.b_wait_vblank) {
-					/* Wait for 20ms.*/
-					unsigned long vblank_timeout =
-							jiffies + HZ/50;
-					uint32_t temp;
-					while (time_before_eq(jiffies,
-							vblank_timeout)) {
-						temp = PSB_RVDC32(OVC_DOVCSTA);
-						if ((temp & (0x1 << 31)) != 0)
-							break;
-						cpu_relax();
-					}
-				}
-			}
-			gma_power_end(dev);
-		} else {
-			if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
-				dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5;
-				dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4;
-				dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3;
-				dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2;
-				dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1;
-				dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0;
-			}
-			if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
-				dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5;
-				dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4;
-				dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3;
-				dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2;
-				dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1;
-				dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0;
-			}
-			if (arg->overlay_write_mask & OV_REGRWBITS_OVADD)
-				dev_priv->saveOV_OVADD = arg->overlay.OVADD;
-			if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD)
-				dev_priv->saveOVC_OVADD = arg->overlay.OVADD;
-		}
-	}
-
-	if (arg->overlay_read_mask != 0) {
-		if (gma_power_begin(dev, usage)) {
-			if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
-				arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5);
-				arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4);
-				arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3);
-				arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2);
-				arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1);
-				arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0);
-			}
-			if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
-				arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5);
-				arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4);
-				arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3);
-				arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2);
-				arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1);
-				arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0);
-			}
-			if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
-				arg->overlay.OVADD = PSB_RVDC32(OV_OVADD);
-			if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
-				arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD);
-			gma_power_end(dev);
-		} else {
-			if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
-				arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5;
-				arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4;
-				arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3;
-				arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2;
-				arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1;
-				arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0;
-			}
-			if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
-				arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5;
-				arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4;
-				arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3;
-				arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2;
-				arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1;
-				arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0;
-			}
-			if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
-				arg->overlay.OVADD = dev_priv->saveOV_OVADD;
-			if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
-				arg->overlay.OVADD = dev_priv->saveOVC_OVADD;
-		}
-	}
-
-	if (arg->sprite_enable_mask != 0) {
-		if (gma_power_begin(dev, usage)) {
-			PSB_WVDC32(0x1F3E, DSPARB);
-			PSB_WVDC32(arg->sprite.dspa_control
-					| PSB_RVDC32(DSPACNTR), DSPACNTR);
-			PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL);
-			PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK);
-			PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF);
-			PSB_RVDC32(DSPASURF);
-			PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR);
-			PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE);
-			PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS);
-			PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF);
-			PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE);
-			PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
-			PSB_RVDC32(DSPCSURF);
-			gma_power_end(dev);
-		}
-	}
-
-	if (arg->sprite_disable_mask != 0) {
-		if (gma_power_begin(dev, usage)) {
-			PSB_WVDC32(0x3F3E, DSPARB);
-			PSB_WVDC32(0x0, DSPCCNTR);
-			PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
-			PSB_RVDC32(DSPCSURF);
-			gma_power_end(dev);
-		}
-	}
-
-	if (arg->subpicture_enable_mask != 0) {
-		if (gma_power_begin(dev, usage)) {
-			uint32_t temp;
-			if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) {
-				temp =  PSB_RVDC32(DSPACNTR);
-				temp &= ~DISPPLANE_PIXFORMAT_MASK;
-				temp &= ~DISPPLANE_BOTTOM;
-				temp |= DISPPLANE_32BPP;
-				PSB_WVDC32(temp, DSPACNTR);
-
-				temp =  PSB_RVDC32(DSPABASE);
-				PSB_WVDC32(temp, DSPABASE);
-				PSB_RVDC32(DSPABASE);
-				temp =  PSB_RVDC32(DSPASURF);
-				PSB_WVDC32(temp, DSPASURF);
-				PSB_RVDC32(DSPASURF);
-			}
-			if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) {
-				temp =  PSB_RVDC32(DSPBCNTR);
-				temp &= ~DISPPLANE_PIXFORMAT_MASK;
-				temp &= ~DISPPLANE_BOTTOM;
-				temp |= DISPPLANE_32BPP;
-				PSB_WVDC32(temp, DSPBCNTR);
-
-				temp =  PSB_RVDC32(DSPBBASE);
-				PSB_WVDC32(temp, DSPBBASE);
-				PSB_RVDC32(DSPBBASE);
-				temp =  PSB_RVDC32(DSPBSURF);
-				PSB_WVDC32(temp, DSPBSURF);
-				PSB_RVDC32(DSPBSURF);
-			}
-			if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) {
-				temp =  PSB_RVDC32(DSPCCNTR);
-				temp &= ~DISPPLANE_PIXFORMAT_MASK;
-				temp &= ~DISPPLANE_BOTTOM;
-				temp |= DISPPLANE_32BPP;
-				PSB_WVDC32(temp, DSPCCNTR);
-
-				temp =  PSB_RVDC32(DSPCBASE);
-				PSB_WVDC32(temp, DSPCBASE);
-				PSB_RVDC32(DSPCBASE);
-				temp =  PSB_RVDC32(DSPCSURF);
-				PSB_WVDC32(temp, DSPCSURF);
-				PSB_RVDC32(DSPCSURF);
-			}
-			gma_power_end(dev);
-		}
-	}
-
-	if (arg->subpicture_disable_mask != 0) {
-		if (gma_power_begin(dev, usage)) {
-			uint32_t temp;
-			if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) {
-				temp =  PSB_RVDC32(DSPACNTR);
-				temp &= ~DISPPLANE_PIXFORMAT_MASK;
-				temp |= DISPPLANE_32BPP_NO_ALPHA;
-				PSB_WVDC32(temp, DSPACNTR);
-
-				temp =  PSB_RVDC32(DSPABASE);
-				PSB_WVDC32(temp, DSPABASE);
-				PSB_RVDC32(DSPABASE);
-				temp =  PSB_RVDC32(DSPASURF);
-				PSB_WVDC32(temp, DSPASURF);
-				PSB_RVDC32(DSPASURF);
-			}
-			if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) {
-				temp =  PSB_RVDC32(DSPBCNTR);
-				temp &= ~DISPPLANE_PIXFORMAT_MASK;
-				temp |= DISPPLANE_32BPP_NO_ALPHA;
-				PSB_WVDC32(temp, DSPBCNTR);
-
-				temp =  PSB_RVDC32(DSPBBASE);
-				PSB_WVDC32(temp, DSPBBASE);
-				PSB_RVDC32(DSPBBASE);
-				temp =  PSB_RVDC32(DSPBSURF);
-				PSB_WVDC32(temp, DSPBSURF);
-				PSB_RVDC32(DSPBSURF);
-			}
-			if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) {
-				temp =  PSB_RVDC32(DSPCCNTR);
-				temp &= ~DISPPLANE_PIXFORMAT_MASK;
-				temp |= DISPPLANE_32BPP_NO_ALPHA;
-				PSB_WVDC32(temp, DSPCCNTR);
-
-				temp =  PSB_RVDC32(DSPCBASE);
-				PSB_WVDC32(temp, DSPCBASE);
-				PSB_RVDC32(DSPCBASE);
-				temp =  PSB_RVDC32(DSPCSURF);
-				PSB_WVDC32(temp, DSPCSURF);
-				PSB_RVDC32(DSPCSURF);
-			}
-			gma_power_end(dev);
-		}
-	}
-
-	return 0;
-}
-
 static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
 {
 	return 0;
@@ -1188,9 +687,6 @@ static struct pci_driver psb_pci_driver = {
 
 static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	/* MLD Added this from Inaky's patch */
-	if (pci_enable_msi(pdev))
-		dev_warn(&pdev->dev, "Enable MSI failed!\n");
 	return drm_get_pci_dev(pdev, ent, &driver);
 }
 

+ 8 - 4
drivers/gpu/drm/gma500/psb_drv.h

@@ -25,7 +25,7 @@
 #include <drm/drmP.h>
 #include "drm_global.h"
 #include "gem_glue.h"
-#include "psb_drm.h"
+#include "gma_drm.h"
 #include "psb_reg.h"
 #include "psb_intel_drv.h"
 #include "gtt.h"
@@ -42,6 +42,7 @@ enum {
 	CHIP_MFLD_0130 = 3,		/* Medfield */
 };
 
+#define IS_PSB(dev) (((dev)->pci_device & 0xfffe) == 0x8108)
 #define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100)
 #define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130)
 
@@ -133,6 +134,9 @@ enum {
 #define _PSB_IRQ_MSVDX_FLAG	  (1<<19)
 #define _LNC_IRQ_TOPAZ_FLAG	  (1<<20)
 
+#define _PSB_PIPE_EVENT_FLAG	(_PSB_VSYNC_PIPEA_FLAG | \
+				 _PSB_VSYNC_PIPEB_FLAG)
+
 /* 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 | \
@@ -258,6 +262,8 @@ struct psb_intel_opregion {
 
 struct psb_ops;
 
+#define PSB_NUM_PIPE		3
+
 struct drm_psb_private {
 	struct drm_device *dev;
 	const struct psb_ops *ops;
@@ -324,8 +330,6 @@ struct drm_psb_private {
 	 * Sizes info
 	 */
 
-	struct drm_psb_sizes_arg sizes;
-
 	u32 fuse_reg_value;
 	u32 video_device_fuse;
 
@@ -602,7 +606,7 @@ struct drm_psb_private {
 	void *fbdev;
 
 	/* 2D acceleration */
-	struct mutex mutex_2d;
+	spinlock_t lock_2d;
 };
 
 

+ 33 - 28
drivers/gpu/drm/gma500/psb_intel_lvds.c

@@ -68,20 +68,23 @@ struct psb_intel_lvds_priv {
 static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	u32 retVal;
+	u32 ret;
 
 	if (gma_power_begin(dev, false)) {
-		retVal = ((REG_READ(BLC_PWM_CTL) &
-			  BACKLIGHT_MODULATION_FREQ_MASK) >>
-			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
+		ret = REG_READ(BLC_PWM_CTL);
 		gma_power_end(dev);
-	} else
-		retVal = ((dev_priv->saveBLC_PWM_CTL &
-			  BACKLIGHT_MODULATION_FREQ_MASK) >>
-			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
-
-	return retVal;
+	} else /* Powered off, use the saved value */
+		ret = dev_priv->saveBLC_PWM_CTL;
+
+	/* Top 15bits hold the frequency mask */
+	ret = (ret &  BACKLIGHT_MODULATION_FREQ_MASK) >>
+					BACKLIGHT_MODULATION_FREQ_SHIFT;
+
+        ret *= 2;	/* Return a 16bit range as needed for setting */
+        if (ret == 0)
+                dev_err(dev->dev, "BL bug: Reg %08x save %08X\n",
+                        REG_READ(BLC_PWM_CTL), dev_priv->saveBLC_PWM_CTL);
+	return ret;
 }
 
 /*
@@ -142,7 +145,7 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
 	max_pwm_blc = psb_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);
+	BUG_ON(max_pwm_blc == 0);
 
 	blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
 
@@ -154,6 +157,10 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
 		  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
 		  (blc_pwm_duty_cycle));
 
+        dev_info(dev->dev, "Backlight lvds set brightness %08x\n",
+		  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
+		  (blc_pwm_duty_cycle));
+
 	return 0;
 }
 
@@ -162,14 +169,12 @@ static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
  */
 void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
 {
-	/*u32 blc_pwm_ctl;*/
-	struct drm_psb_private *dev_priv =
-			(struct drm_psb_private *)dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 
 	dev_dbg(dev->dev, "backlight level is %d\n", level);
 
 	if (!dev_priv->lvds_bl) {
-		dev_err(dev->dev, "NO LVDS Backlight Info\n");
+		dev_err(dev->dev, "NO LVDS backlight info\n");
 		return;
 	}
 
@@ -190,11 +195,13 @@ static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
 	u32 blc_pwm_ctl;
 
 	if (gma_power_begin(dev, false)) {
-		blc_pwm_ctl =
-			REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+		blc_pwm_ctl = REG_READ(BLC_PWM_CTL);
+		blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK;
 		REG_WRITE(BLC_PWM_CTL,
 				(blc_pwm_ctl |
 				(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
+		dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
+					(level << BACKLIGHT_DUTY_CYCLE_SHIFT));
 		gma_power_end(dev);
 	} else {
 		blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
@@ -212,9 +219,11 @@ static void psb_intel_lvds_set_power(struct drm_device *dev,
 {
 	u32 pp_status;
 
-	if (!gma_power_begin(dev, true))
+	if (!gma_power_begin(dev, true)) {
+	        dev_err(dev->dev, "set power, chip off!\n");
 		return;
-
+        }
+        
 	if (on) {
 		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
 			  POWER_TARGET_ON);
@@ -296,9 +305,6 @@ static void psb_intel_lvds_restore(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	u32 pp_status;
-
-	/*struct drm_psb_private *dev_priv =
-				(struct drm_psb_private *)dev->dev_private;*/
 	struct psb_intel_output *psb_intel_output =
 					to_psb_intel_output(connector);
 	struct psb_intel_lvds_priv *lvds_priv =
@@ -382,7 +388,6 @@ 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");
@@ -622,7 +627,8 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
 			goto set_prop_error;
 		else {
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-			struct drm_psb_private *devp = encoder->dev->dev_private;
+			struct drm_psb_private *devp =
+						encoder->dev->dev_private;
 			struct backlight_device *bd = devp->backlight_device;
 			if (bd) {
 				bd->props.brightness = value;
@@ -695,8 +701,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
 	struct drm_encoder *encoder;
 	struct drm_display_mode *scan;	/* *modes, *bios_mode; */
 	struct drm_crtc *crtc;
-	struct drm_psb_private *dev_priv =
-				(struct drm_psb_private *)dev->dev_private;
+	struct drm_psb_private *dev_priv = dev->dev_private;
 	u32 lvds;
 	int pipe;
 
@@ -712,8 +717,8 @@ void psb_intel_lvds_init(struct drm_device *dev,
 	}
 
 	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,

+ 41 - 30
drivers/gpu/drm/gma500/psb_irq.c

@@ -137,22 +137,11 @@ void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
 	}
 }
 
-/**
- * Display controller interrupt handler for vsync/vblank.
- *
- */
-static void mid_vblank_handler(struct drm_device *dev, uint32_t pipe)
-{
-	drm_handle_vblank(dev, pipe);
-}
-
-
 /**
  * Display controller interrupt handler for pipe event.
  *
  */
-#define WAIT_STATUS_CLEAR_LOOP_COUNT 0xffff
-static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
+static void mid_pipe_event_handler(struct drm_device *dev, int pipe)
 {
 	struct drm_psb_private *dev_priv =
 	    (struct drm_psb_private *) dev->dev_private;
@@ -161,6 +150,7 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
 	uint32_t pipe_stat_reg = psb_pipestat(pipe);
 	uint32_t pipe_enable = dev_priv->pipestat[pipe];
 	uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
+	uint32_t pipe_clear;
 	uint32_t i = 0;
 
 	spin_lock(&dev_priv->irqmask_lock);
@@ -171,27 +161,23 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
 
 	spin_unlock(&dev_priv->irqmask_lock);
 
-	/* clear the 2nd level interrupt status bits */
-	/**
-	* FIXME: shouldn't use while loop here. However, the interrupt
-	* status 'sticky' bits cannot be cleared by setting '1' to that
-	* bit once...
-	*/
-	for (i = 0; i < WAIT_STATUS_CLEAR_LOOP_COUNT; i++) {
+	/* Clear the 2nd level interrupt status bits
+	 * Sometimes the bits are very sticky so we repeat until they unstick */
+	for (i = 0; i < 0xffff; i++) {
 		PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
-		(void) PSB_RVDC32(pipe_stat_reg);
+		pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status;
 
-		if ((PSB_RVDC32(pipe_stat_reg) & pipe_status) == 0)
+		if (pipe_clear == 0)
 			break;
 	}
 
-	if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)
+	if (pipe_clear)
 		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));
+		"%s, can't clear status bits for pipe %d, its value = 0x%x.\n",
+		__func__, pipe, PSB_RVDC32(pipe_stat_reg));
 
 	if (pipe_stat_val & PIPE_VBLANK_STATUS)
-		mid_vblank_handler(dev, pipe);
+		drm_handle_vblank(dev, pipe);
 
 	if (pipe_stat_val & PIPE_TE_STATUS)
 		drm_handle_vblank(dev, pipe);
@@ -202,8 +188,11 @@ static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
  */
 static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
 {
-	if (vdc_stat & _PSB_PIPEA_EVENT_FLAG)
+	if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG)
 		mid_pipe_event_handler(dev, 0);
+
+	if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG)
+		mid_pipe_event_handler(dev, 1);
 }
 
 irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
@@ -219,8 +208,13 @@ irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
 
 	vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
 
+	if (vdc_stat & _PSB_PIPE_EVENT_FLAG)
+		dsp_int = 1;
+
+	/* FIXME: Handle Medfield
 	if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG)
 		dsp_int = 1;
+	*/
 
 	if (vdc_stat & _PSB_IRQ_SGX_FLAG)
 		sgx_int = 1;
@@ -266,13 +260,18 @@ void psb_irq_preinstall(struct drm_device *dev)
 	if (gma_power_is_on(dev))
 		PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
 	if (dev->vblank_enabled[0])
-		dev_priv->vdc_irq_mask |= _PSB_PIPEA_EVENT_FLAG;
+		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
+	if (dev->vblank_enabled[1])
+		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
+
+	/* FIXME: Handle Medfield irq mask
 	if (dev->vblank_enabled[1])
 		dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG;
 	if (dev->vblank_enabled[2])
 		dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
+	*/
 
-	/*This register is safe even if display island is off*/
+	/* This register is safe even if display island is off */
 	PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
 	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
 }
@@ -464,7 +463,13 @@ int psb_enable_vblank(struct drm_device *dev, int pipe)
 
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
-	mid_enable_pipe_event(dev_priv, pipe);
+	if (pipe == 0)
+		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG;
+	else if (pipe == 1)
+		dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG;
+
+	PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
 	psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
 
 	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
@@ -482,7 +487,13 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
 
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
-	mid_disable_pipe_event(dev_priv, pipe);
+	if (pipe == 0)
+		dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG;
+	else if (pipe == 1)
+		dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG;
+
+	PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
 	psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
 
 	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);

+ 0 - 2
drivers/gpu/drm/gma500/psb_lid.c

@@ -52,8 +52,6 @@ static void psb_lid_timer_func(unsigned long data)
 			pp_status = REG_READ(PP_STATUS);
 		} while ((pp_status & PP_ON) == 0);
 	}
-		/* printk(KERN_INFO"%s: lid: closed\n", __FUNCTION__); */
-
 	dev_priv->lid_last_state =  readl(lid_state);
 
 lid_timer_schedule:

+ 91 - 0
include/drm/gma_drm.h

@@ -0,0 +1,91 @@
+/**************************************************************************
+ * Copyright (c) 2007-2011, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_DRM_H_
+#define _PSB_DRM_H_
+
+/*
+ *	Manage the LUT for an output
+ */
+struct drm_psb_dpst_lut_arg {
+	uint8_t lut[256];
+	int output_id;
+};
+
+/*
+ *	Validate modes
+ */
+struct drm_psb_mode_operation_arg {
+	u32 obj_id;
+	u16 operation;
+	struct drm_mode_modeinfo mode;
+	u64 data;
+};
+
+/*
+ *	Query the stolen memory for smarter management of
+ *	memory by the server
+ */
+struct drm_psb_stolen_memory_arg {
+	u32 base;
+	u32 size;
+};
+
+struct drm_psb_get_pipe_from_crtc_id_arg {
+	/** ID of CRTC being requested **/
+	u32 crtc_id;
+	/** pipe of requested CRTC **/
+	u32 pipe;
+};
+
+struct drm_psb_gem_create {
+	__u64 size;
+	__u32 handle;
+	__u32 flags;
+#define GMA_GEM_CREATE_STOLEN		1	/* Stolen memory can be used */
+};
+
+struct drm_psb_gem_mmap {
+	__u32 handle;
+	__u32 pad;
+	/**
+	 * Fake offset to use for subsequent mmap call
+	 *
+	 * This is a fixed-size type for 32/64 compatibility.
+	 */
+	__u64 offset;
+};
+
+/* Controlling the kernel modesetting buffers */
+
+#define DRM_GMA_GEM_CREATE	0x00		/* Create a GEM object */
+#define DRM_GMA_GEM_MMAP	0x01		/* Map GEM memory */
+#define DRM_GMA_STOLEN_MEMORY	0x02		/* Report stolen memory */
+#define DRM_GMA_2D_OP		0x03		/* Will be merged later */
+#define DRM_GMA_GAMMA		0x04		/* Set gamma table */
+#define DRM_GMA_ADB		0x05		/* Get backlight */
+#define DRM_GMA_DPST_BL		0x06		/* Set backlight */
+#define DRM_GMA_GET_PIPE_FROM_CRTC_ID 0x1	/* CRTC to physical pipe# */
+#define DRM_GMA_MODE_OPERATION	0x07		/* Mode validation/DC set */
+#define 	PSB_MODE_OPERATION_MODE_VALID	0x01
+
+
+#endif