Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cee5ec43 authored by Dave Airlie's avatar Dave Airlie
Browse files

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
parents 04b3924d 1b22edfd
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -111,8 +111,9 @@ 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;
@@ -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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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;
}

/**
@@ -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);
	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);

		/* 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 +
							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
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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);
}
Loading