Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 282465
b: refs/heads/master
c: a6ba582
h: refs/heads/master
i:
  282463: 9fd3191
v: v3
  • Loading branch information
Alan Cox authored and Dave Airlie committed Dec 6, 2011
1 parent f4fa2e4 commit 9cda55b
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 13 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: 9242fe23d2ebab9c61dbc50d65f30cfa20a856ae
refs/heads/master: a6ba582d264f67074f669f76172e8a2afadff2a4
80 changes: 71 additions & 9 deletions trunk/drivers/gpu/drm/gma500/framebuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -306,6 +341,7 @@ 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
Expand Down Expand Up @@ -349,6 +385,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
int ret;
struct gtt_range *backing;
u32 bpp, depth;
int gtt_roll = 1;

mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
Expand All @@ -358,17 +395,38 @@ 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);
/* Acceleration via the GTT requires pitch to be 4096 byte aligned
(ie 1024 or 2048 pixels in normal use) */
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096);
depth = sizes->surface_depth;

size = mode_cmd.pitches[0] * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE);

/* Allocate the framebuffer in the GTT with stolen page backing */
/* Try and allocate with the alignment we need */
backing = psbfb_alloc(dev, size);
if (backing == NULL)
return -ENOMEM;
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
*
* FIXME: We could try alignments in a loop so that we can still
* accelerate power of two font sizes.
*/

gtt_roll = 0; /* Don't use GTT accelerated scrolling */

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);

Expand All @@ -394,11 +452,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 (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 @@ -408,6 +468,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 = 0;

/* Accessed stolen memory directly */
info->screen_base = (char *)dev_priv->vram_addr +
Expand Down
51 changes: 48 additions & 3 deletions trunk/drivers/gpu/drm/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/gpu/drm/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 9cda55b

Please sign in to comment.