diff options
Diffstat (limited to 'drivers/staging/gma500/psb_fb.c')
-rw-r--r-- | drivers/staging/gma500/psb_fb.c | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c index f36e83f..ae097cd 100644 --- a/drivers/staging/gma500/psb_fb.c +++ b/drivers/staging/gma500/psb_fb.c @@ -336,6 +336,38 @@ err: } /** + * psbfb_alloc - allocate frame buffer memory + * @dev: the DRM device + * @aligned_size: space needed + * + * Allocate the frame buffer. In the usual case we get a GTT range that + * is stolen memory backed and life is simple. If there isn't sufficient + * stolen memory or the system has no stolen memory we allocate a range + * and back it with a GEM object. + * + * In this case the GEM object has no handle. + */ +static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size) +{ + struct gtt_range *backing; + /* Begin by trying to use stolen memory backing */ + backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1); + if (backing) + return backing; + /* Next try using GEM host memory */ + backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0); + if (backing == NULL) + return NULL; + + /* Now back it with an object */ + if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) { + psb_gtt_free_range(dev, backing); + return NULL; + } + return backing; +} + +/** * psbfb_create - create a framebuffer * @fbdev: the framebuffer device * @sizes: specification of the layout @@ -368,7 +400,7 @@ static int psbfb_create(struct psb_fbdev *fbdev, aligned_size = ALIGN(size, PAGE_SIZE); /* Allocate the framebuffer in the GTT with stolen page backing */ - backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1); + backing = psbfb_alloc(dev, aligned_size); if (backing == NULL) return -ENOMEM; @@ -523,7 +555,13 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev) if (fbdev->psb_fb_helper.fbdev) { info = fbdev->psb_fb_helper.fbdev; - psb_gtt_free_range(dev, psbfb->gtt); + /* FIXME: this is a bit more inside knowledge than I'd like + but I don't see how to make a fake GEM object of the + stolen space nicely */ + if (psbfb->gtt->stolen) + psb_gtt_free_range(dev, psbfb->gtt); + else + drm_gem_object_unreference(&psbfb->gtt->gem); unregister_framebuffer(info); iounmap(info->screen_base); framebuffer_release(info); @@ -571,7 +609,6 @@ void psb_fbdev_fini(struct drm_device *dev) dev_priv->fbdev = NULL; } - static void psbfb_output_poll_changed(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; |