gma500: allow non stolen page backed framebuffer
For Moorestown at least we may not have stolen RAM with which to back the initial framebuffer. Allow a GEM backing. At this point we should have all the bits in place needed to make it work once it has been debugged. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
541c81ab4b
commit
9886eb59f8
4 changed files with 65 additions and 17 deletions
|
@ -335,6 +335,38 @@ err:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* psbfb_create - create a framebuffer
|
||||||
* @fbdev: the framebuffer device
|
* @fbdev: the framebuffer device
|
||||||
|
@ -368,7 +400,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
||||||
aligned_size = ALIGN(size, PAGE_SIZE);
|
aligned_size = ALIGN(size, PAGE_SIZE);
|
||||||
|
|
||||||
/* Allocate the framebuffer in the GTT with stolen page backing */
|
/* 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)
|
if (backing == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -523,7 +555,13 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
|
||||||
|
|
||||||
if (fbdev->psb_fb_helper.fbdev) {
|
if (fbdev->psb_fb_helper.fbdev) {
|
||||||
info = fbdev->psb_fb_helper.fbdev;
|
info = fbdev->psb_fb_helper.fbdev;
|
||||||
|
/* 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);
|
psb_gtt_free_range(dev, psbfb->gtt);
|
||||||
|
else
|
||||||
|
drm_gem_object_unreference(&psbfb->gtt->gem);
|
||||||
unregister_framebuffer(info);
|
unregister_framebuffer(info);
|
||||||
iounmap(info->screen_base);
|
iounmap(info->screen_base);
|
||||||
framebuffer_release(info);
|
framebuffer_release(info);
|
||||||
|
@ -571,7 +609,6 @@ void psb_fbdev_fini(struct drm_device *dev)
|
||||||
dev_priv->fbdev = NULL;
|
dev_priv->fbdev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void psbfb_output_poll_changed(struct drm_device *dev)
|
static void psbfb_output_poll_changed(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||||
|
|
|
@ -39,6 +39,8 @@ int psb_gem_init_object(struct drm_gem_object *obj)
|
||||||
|
|
||||||
void psb_gem_free_object(struct drm_gem_object *obj)
|
void psb_gem_free_object(struct drm_gem_object *obj)
|
||||||
{
|
{
|
||||||
|
struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
|
||||||
|
psb_gtt_free_range(obj->dev, gtt);
|
||||||
drm_gem_object_release(obj);
|
drm_gem_object_release(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -298,7 +298,6 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void psb_gtt_destroy(struct kref *kref)
|
static void psb_gtt_destroy(struct kref *kref)
|
||||||
{
|
{
|
||||||
struct gtt_range *gt = container_of(kref, struct gtt_range, kref);
|
struct gtt_range *gt = container_of(kref, struct gtt_range, kref);
|
||||||
|
|
|
@ -361,7 +361,13 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
|
||||||
if (!gma_power_begin(dev, true))
|
if (!gma_power_begin(dev, true))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* We are displaying this buffer, make sure it is actually loaded
|
||||||
|
into the GTT */
|
||||||
|
ret = psb_gtt_pin(dev, psbfb->gtt);
|
||||||
|
if (ret < 0)
|
||||||
|
goto psb_intel_pipe_set_base_exit;
|
||||||
start = psbfb->gtt->offset;
|
start = psbfb->gtt->offset;
|
||||||
|
|
||||||
offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
|
offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
|
||||||
|
|
||||||
REG_WRITE(dspstride, crtc->fb->pitch);
|
REG_WRITE(dspstride, crtc->fb->pitch);
|
||||||
|
@ -386,10 +392,12 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
|
||||||
default:
|
default:
|
||||||
DRM_ERROR("Unknown color depth\n");
|
DRM_ERROR("Unknown color depth\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
psb_gtt_unpin(dev, psbfb->gtt);
|
||||||
goto psb_intel_pipe_set_base_exit;
|
goto psb_intel_pipe_set_base_exit;
|
||||||
}
|
}
|
||||||
REG_WRITE(dspcntr_reg, dspcntr);
|
REG_WRITE(dspcntr_reg, dspcntr);
|
||||||
|
|
||||||
|
|
||||||
DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
|
DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
|
||||||
if (0 /* FIXMEAC - check what PSB needs */) {
|
if (0 /* FIXMEAC - check what PSB needs */) {
|
||||||
REG_WRITE(dspbase, offset);
|
REG_WRITE(dspbase, offset);
|
||||||
|
@ -401,10 +409,12 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
|
||||||
REG_READ(dspbase);
|
REG_READ(dspbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If there was a previous display we can now unpin it */
|
||||||
|
if (old_fb)
|
||||||
|
psb_gtt_unpin(dev, to_psb_fb(old_fb)->gtt);
|
||||||
|
|
||||||
psb_intel_pipe_set_base_exit:
|
psb_intel_pipe_set_base_exit:
|
||||||
|
|
||||||
gma_power_end(dev);
|
gma_power_end(dev);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue