Skip to content

Commit

Permalink
gma500: allow non stolen page backed framebuffer
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alan Cox authored and Greg Kroah-Hartman committed Apr 26, 2011
1 parent 541c81a commit 9886eb5
Showing 4 changed files with 65 additions and 17 deletions.
43 changes: 40 additions & 3 deletions drivers/staging/gma500/psb_fb.c
Original file line number Diff line number Diff line change
@@ -335,6 +335,38 @@ static struct drm_framebuffer *psb_framebuffer_create
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
* @fbdev: the framebuffer device
@@ -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;
2 changes: 2 additions & 0 deletions drivers/staging/gma500/psb_gem.c
Original file line number Diff line number Diff line change
@@ -39,6 +39,8 @@ int psb_gem_init_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);
}

1 change: 0 additions & 1 deletion drivers/staging/gma500/psb_gtt.c
Original file line number Diff line number Diff line change
@@ -298,7 +298,6 @@ struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
return NULL;
}


static void psb_gtt_destroy(struct kref *kref)
{
struct gtt_range *gt = container_of(kref, struct gtt_range, kref);
36 changes: 23 additions & 13 deletions drivers/staging/gma500/psb_intel_display.c
Original file line number Diff line number Diff line change
@@ -361,7 +361,13 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
if (!gma_power_begin(dev, true))
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;

offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);

REG_WRITE(dspstride, crtc->fb->pitch);
@@ -386,10 +392,12 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
default:
DRM_ERROR("Unknown color depth\n");
ret = -EINVAL;
psb_gtt_unpin(dev, psbfb->gtt);
goto psb_intel_pipe_set_base_exit;
}
REG_WRITE(dspcntr_reg, dspcntr);


DRM_DEBUG("Writing base %08lX %08lX %d %d\n", start, offset, x, y);
if (0 /* FIXMEAC - check what PSB needs */) {
REG_WRITE(dspbase, offset);
@@ -401,10 +409,12 @@ int psb_intel_pipe_set_base(struct drm_crtc *crtc,
REG_READ(dspbase);
}

psb_intel_pipe_set_base_exit:
/* 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:
gma_power_end(dev);

return ret;
}

@@ -1037,16 +1047,16 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
/* turn off the cursor */
temp = CURSOR_MODE_DISABLE;

if (gma_power_begin(dev, false)) {
if (gma_power_begin(dev, false)) {
REG_WRITE(control, temp);
REG_WRITE(base, 0);
gma_power_end(dev);
}

/* Unpin the old GEM object */
if (psb_intel_crtc->cursor_obj) {
gt = container_of(psb_intel_crtc->cursor_obj,
struct gtt_range, gem);
gt = container_of(psb_intel_crtc->cursor_obj,
struct gtt_range, gem);
psb_gtt_unpin(crtc->dev, gt);
drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
psb_intel_crtc->cursor_obj = NULL;
@@ -1089,16 +1099,16 @@ static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
temp |= (pipe << 28);
temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;

if (gma_power_begin(dev, false)) {
if (gma_power_begin(dev, false)) {
REG_WRITE(control, temp);
REG_WRITE(base, addr);
gma_power_end(dev);
}

/* unpin the old bo */
if (psb_intel_crtc->cursor_obj && psb_intel_crtc->cursor_obj != obj) {
gt = container_of(psb_intel_crtc->cursor_obj,
struct gtt_range, gem);
gt = container_of(psb_intel_crtc->cursor_obj,
struct gtt_range, gem);
psb_gtt_unpin(crtc->dev, gt);
drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
psb_intel_crtc->cursor_obj = obj;
@@ -1130,7 +1140,7 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)

addr = psb_intel_crtc->cursor_addr;

if (gma_power_begin(dev, false)) {
if (gma_power_begin(dev, false)) {
REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr);
gma_power_end(dev);
@@ -1183,7 +1193,7 @@ static int psb_intel_crtc_clock_get(struct drm_device *dev,
bool is_lvds;
struct drm_psb_private *dev_priv = dev->dev_private;

if (gma_power_begin(dev, false)) {
if (gma_power_begin(dev, false)) {
dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
@@ -1262,7 +1272,7 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
int vsync;
struct drm_psb_private *dev_priv = dev->dev_private;

if (gma_power_begin(dev, false)) {
if (gma_power_begin(dev, false)) {
htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
@@ -1387,10 +1397,10 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
psb_intel_crtc->cursor_addr = 0;

if (IS_MRST(dev))
drm_crtc_helper_add(&psb_intel_crtc->base,
drm_crtc_helper_add(&psb_intel_crtc->base,
&mrst_helper_funcs);
else
drm_crtc_helper_add(&psb_intel_crtc->base,
drm_crtc_helper_add(&psb_intel_crtc->base,
&psb_intel_helper_funcs);

/* Setup the array of drm_connector pointer array */

0 comments on commit 9886eb5

Please sign in to comment.