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
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;
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);
dev_priv->fbdev = NULL;
}
-
static void psbfb_output_poll_changed(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
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);
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);
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;
}
/* 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;
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;
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);
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);
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);
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 */