diff options
author | James Morris <jmorris@namei.org> | 2011-11-16 12:39:48 +1100 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-11-16 12:39:48 +1100 |
commit | 24942c8e5cc8696064ee207ff29d4cf21f70dafc (patch) | |
tree | 08a8221eb72ec3da7746d7d76f6f5915ce77cde7 /drivers/staging/gma500/framebuffer.c | |
parent | e163bc8e4a0cd1cdffadb58253f7651201722d56 (diff) | |
parent | ff0ff78068dd8a962358dbbdafa9d6f24540d3e5 (diff) | |
download | linux-stable-24942c8e5cc8696064ee207ff29d4cf21f70dafc.tar.gz linux-stable-24942c8e5cc8696064ee207ff29d4cf21f70dafc.tar.bz2 linux-stable-24942c8e5cc8696064ee207ff29d4cf21f70dafc.zip |
Merge branch 'master'; commit 'v3.2-rc2' into next
Diffstat (limited to 'drivers/staging/gma500/framebuffer.c')
-rw-r--r-- | drivers/staging/gma500/framebuffer.c | 92 |
1 files changed, 77 insertions, 15 deletions
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c index ebfde13ec18f..3f39a37456fc 100644 --- a/drivers/staging/gma500/framebuffer.c +++ b/drivers/staging/gma500/framebuffer.c @@ -37,6 +37,7 @@ #include "psb_intel_reg.h" #include "psb_intel_drv.h" #include "framebuffer.h" +#include "gtt.h" #include "mdfld_output.h" @@ -91,6 +92,21 @@ 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) + psb_gtt_roll(dev, psbfb->gtt, var->yoffset); + return 0; +} void psbfb_suspend(struct drm_device *dev) { @@ -217,6 +233,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, @@ -304,6 +335,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 @@ -311,11 +343,9 @@ static struct drm_framebuffer *psb_framebuffer_create * and back it with a GEM object. * * In this case the GEM object has no handle. - * - * FIXME: console speed up - allocate twice the space if room and use - * hardware scrolling for acceleration. */ -static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size) +static struct gtt_range *psbfb_alloc(struct drm_device *dev, + int aligned_size, int force) { struct gtt_range *backing; /* Begin by trying to use stolen memory backing */ @@ -326,6 +356,9 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size) return backing; psb_gtt_free_range(dev, backing); } + if (!force) + return NULL; + /* Next try using GEM host memory */ backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0); if (backing == NULL) @@ -359,6 +392,7 @@ static int psbfb_create(struct psb_fbdev *fbdev, int size; int ret; struct gtt_range *backing; + int gtt_roll = 1; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; @@ -368,17 +402,37 @@ static int psbfb_create(struct psb_fbdev *fbdev, if (mode_cmd.bpp == 24) mode_cmd.bpp = 32; - /* HW requires pitch to be 64 byte aligned */ - mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.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.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 4096); mode_cmd.depth = sizes->surface_depth; size = mode_cmd.pitch * 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; + backing = psbfb_alloc(dev, size, 0); + 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 + */ + + gtt_roll = 0; /* Don't use GTT accelerated scrolling */ + + mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64); + mode_cmd.depth = sizes->surface_depth; + + size = mode_cmd.pitch * mode_cmd.height; + size = ALIGN(size, PAGE_SIZE); + + /* Allocate the framebuffer in the GTT with stolen page + backing when there is room */ + backing = psbfb_alloc(dev, size, 1); + if (backing == NULL) + return -ENOMEM; + } mutex_lock(&dev->struct_mutex); @@ -402,11 +456,14 @@ 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) { @@ -416,6 +473,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 = gtt_roll; if (backing->stolen) { /* Accessed stolen memory directly */ @@ -733,9 +792,12 @@ static void psb_setup_outputs(struct drm_device *dev) clone_mask = (1 << INTEL_OUTPUT_MIPI2); break; case INTEL_OUTPUT_HDMI: - if (IS_MFLD(dev)) + /* HDMI on crtc 1 for SoC devices and crtc 0 for + Cedarview. HDMI on Poulsbo is only via external + logic */ + if (IS_MFLD(dev) || IS_MRST(dev)) crtc_mask = (1 << 1); - else /* FIXME: review Oaktrail */ + else crtc_mask = (1 << 0); /* Cedarview */ clone_mask = (1 << INTEL_OUTPUT_HDMI); break; |