Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 268535
b: refs/heads/master
c: ef86de5
h: refs/heads/master
i:
  268533: 136b0b2
  268531: 14ff231
  268527: 8ff2569
v: v3
  • Loading branch information
Alan Cox authored and Greg Kroah-Hartman committed Sep 27, 2011
1 parent 9131d6b commit 72d3432
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 17 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c7e285bedb20cc0cfe999e1b285ab31a19e1902c
refs/heads/master: ef86de5832a2eee01c5dc4199cee0c48e9c14c3e
85 changes: 72 additions & 13 deletions trunk/drivers/staging/gma500/framebuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "psb_intel_reg.h"
#include "psb_intel_drv.h"
#include "framebuffer.h"
#include "gtt.h"

#include "mdfld_output.h"

Expand Down Expand Up @@ -91,6 +92,21 @@ 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)
psb_gtt_roll(dev, psbfb->gtt, var->yoffset);
return 0;
}

void psbfb_suspend(struct drm_device *dev)
{
Expand Down Expand Up @@ -217,6 +233,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,
Expand Down Expand Up @@ -304,18 +335,17 @@ 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.
*
* 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)
static struct gtt_range *psbfb_alloc(struct drm_device *dev,
int aligned_size, int force)
{
struct gtt_range *backing;
/* Begin by trying to use stolen memory backing */
Expand All @@ -326,6 +356,9 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
return backing;
psb_gtt_free_range(dev, backing);
}
if (!force)
return NULL;

/* Next try using GEM host memory */
backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
if (backing == NULL)
Expand Down Expand Up @@ -359,6 +392,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
int size;
int ret;
struct gtt_range *backing;
int gtt_roll = 1;

mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
Expand All @@ -368,17 +402,37 @@ static int psbfb_create(struct psb_fbdev *fbdev,
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);
/* Acceleration via the GTT requires pitch to be 4096 byte aligned
(ie 1024 or 2048 pixels in normal use) */
mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 4096);
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;
backing = psbfb_alloc(dev, size, 0);
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 */

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 when there is room */
backing = psbfb_alloc(dev, size, 1);
if (backing == NULL)
return -ENOMEM;
}

mutex_lock(&dev->struct_mutex);

Expand All @@ -402,11 +456,14 @@ 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 (gtt_roll) { /* GTT rolling seems best */
info->fbops = &psbfb_roll_ops;
info->flags |= FBINFO_HWACCEL_YPAN;
}
else if (dev_priv->ops->accel_2d) /* 2D engine */
info->fbops = &psbfb_ops;
else /* Software */
info->fbops = &psbfb_unaccel_ops;

ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) {
Expand All @@ -416,6 +473,8 @@ 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 = gtt_roll;

if (backing->stolen) {
/* Accessed stolen memory directly */
Expand Down
51 changes: 48 additions & 3 deletions trunk/drivers/staging/gma500/gtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,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;
}

Expand All @@ -113,7 +118,6 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
* 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;
Expand All @@ -131,6 +135,46 @@ 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
Expand Down Expand Up @@ -302,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,
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/staging/gma500/gtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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

0 comments on commit 72d3432

Please sign in to comment.