diff options
Diffstat (limited to '')
| -rw-r--r-- | drivers/gpu/drm/gma500/framebuffer.c (renamed from drivers/staging/gma500/framebuffer.c) | 180 |
1 files changed, 81 insertions, 99 deletions
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 3f39a37456fc..830dfdd6bf15 100644 --- a/drivers/staging/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -32,6 +32,7 @@ #include <drm/drmP.h> #include <drm/drm.h> #include <drm/drm_crtc.h> +#include <drm/drm_fb_helper.h> #include "psb_drv.h" #include "psb_intel_reg.h" @@ -39,8 +40,6 @@ #include "framebuffer.h" #include "gtt.h" -#include "mdfld_output.h" - static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb); static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, struct drm_file *file_priv, @@ -103,19 +102,23 @@ static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info) * 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; + if (psbfb->gtt->npage) { + /* GTT roll shifts in 4K pages, we need to shift the right + number of pages */ + int pages = info->fix.line_length >> 12; + psb_gtt_roll(dev, psbfb->gtt, var->yoffset * pages); + } + return 0; } void psbfb_suspend(struct drm_device *dev) { - struct drm_framebuffer *fb = 0; - struct psb_framebuffer *psbfb = to_psb_fb(fb); + struct drm_framebuffer *fb; console_lock(); mutex_lock(&dev->mode_config.mutex); list_for_each_entry(fb, &dev->mode_config.fb_list, head) { + struct psb_framebuffer *psbfb = to_psb_fb(fb); struct fb_info *info = psbfb->fbdev; fb_set_suspend(info, 1); drm_fb_helper_blank(FB_BLANK_POWERDOWN, info); @@ -126,12 +129,12 @@ void psbfb_suspend(struct drm_device *dev) void psbfb_resume(struct drm_device *dev) { - struct drm_framebuffer *fb = 0; - struct psb_framebuffer *psbfb = to_psb_fb(fb); + struct drm_framebuffer *fb; console_lock(); mutex_lock(&dev->mode_config.mutex); list_for_each_entry(fb, &dev->mode_config.fb_list, head) { + struct psb_framebuffer *psbfb = to_psb_fb(fb); struct fb_info *info = psbfb->fbdev; fb_set_suspend(info, 0); drm_fb_helper_blank(FB_BLANK_UNBLANK, info); @@ -273,14 +276,17 @@ static struct fb_ops psbfb_unaccel_ops = { */ static int psb_framebuffer_init(struct drm_device *dev, struct psb_framebuffer *fb, - struct drm_mode_fb_cmd *mode_cmd, + struct drm_mode_fb_cmd2 *mode_cmd, struct gtt_range *gt) { + u32 bpp, depth; int ret; - if (mode_cmd->pitch & 63) + drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + + if (mode_cmd->pitches[0] & 63) return -EINVAL; - switch (mode_cmd->bpp) { + switch (bpp) { case 8: case 16: case 24: @@ -313,7 +319,7 @@ static int psb_framebuffer_init(struct drm_device *dev, static struct drm_framebuffer *psb_framebuffer_create (struct drm_device *dev, - struct drm_mode_fb_cmd *mode_cmd, + struct drm_mode_fb_cmd2 *mode_cmd, struct gtt_range *gt) { struct psb_framebuffer *fb; @@ -339,13 +345,12 @@ static struct drm_framebuffer *psb_framebuffer_create * * 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. + * we fail as we don't have the virtual mapping space to really vmap it + * and the kernel console code can't handle non linear framebuffers. * - * In this case the GEM object has no handle. + * Re-address this as and if the framebuffer layer grows this ability. */ -static struct gtt_range *psbfb_alloc(struct drm_device *dev, - int aligned_size, int force) +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 */ @@ -356,20 +361,7 @@ static struct gtt_range *psbfb_alloc(struct drm_device *dev, 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) - 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; + return NULL; } /** @@ -387,31 +379,48 @@ static int psbfb_create(struct psb_fbdev *fbdev, struct fb_info *info; struct drm_framebuffer *fb; struct psb_framebuffer *psbfb = &fbdev->pfb; - struct drm_mode_fb_cmd mode_cmd; + struct drm_mode_fb_cmd2 mode_cmd; struct device *device = &dev->pdev->dev; int size; int ret; struct gtt_range *backing; - int gtt_roll = 1; + u32 bpp, depth; + int gtt_roll = 0; + int pitch_lines = 0; mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; - mode_cmd.bpp = sizes->surface_bpp; + bpp = sizes->surface_bpp; /* No 24bit packed */ - if (mode_cmd.bpp == 24) - mode_cmd.bpp = 32; + if (bpp == 24) + bpp = 32; + + do { + /* + * Acceleration via the GTT requires pitch to be + * power of two aligned. Preferably page but less + * is ok with some fonts + */ + mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096 >> pitch_lines); + depth = sizes->surface_depth; - /* 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.pitches[0] * mode_cmd.height; + size = ALIGN(size, PAGE_SIZE); - size = mode_cmd.pitch * mode_cmd.height; - size = ALIGN(size, PAGE_SIZE); + /* Allocate the fb in the GTT with stolen page backing */ + backing = psbfb_alloc(dev, size); + + if (pitch_lines) + pitch_lines *= 2; + else + pitch_lines = 1; + gtt_roll++; + } while (backing == NULL && pitch_lines <= 16); + + /* The final pitch we accepted if we succeeded */ + pitch_lines /= 2; - /* Allocate the framebuffer in the GTT with stolen page backing */ - backing = psbfb_alloc(dev, size, 0); if (backing == NULL) { /* * We couldn't get the space we wanted, fall back to the @@ -420,16 +429,15 @@ static int psbfb_create(struct psb_fbdev *fbdev, */ gtt_roll = 0; /* Don't use GTT accelerated scrolling */ + pitch_lines = 64; - mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64); - mode_cmd.depth = sizes->surface_depth; + mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64); - size = mode_cmd.pitch * mode_cmd.height; + size = mode_cmd.pitches[0] * 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); + /* Allocate the framebuffer in the GTT with stolen page backing */ + backing = psbfb_alloc(dev, size); if (backing == NULL) return -ENOMEM; } @@ -443,6 +451,8 @@ static int psbfb_create(struct psb_fbdev *fbdev, } info->par = fbdev; + mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); + ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing); if (ret) goto out_unref; @@ -456,13 +466,12 @@ static int psbfb_create(struct psb_fbdev *fbdev, strcpy(info->fix.id, "psbfb"); info->flags = FBINFO_DEFAULT; - if (gtt_roll) { /* GTT rolling seems best */ + if (dev_priv->ops->accel_2d && pitch_lines > 8) /* 2D engine */ + info->fbops = &psbfb_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 */ + } else /* Software */ info->fbops = &psbfb_unaccel_ops; ret = fb_alloc_cmap(&info->cmap, 256, 0); @@ -474,24 +483,11 @@ 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; + info->fix.ypanstep = 0; - if (backing->stolen) { - /* Accessed stolen memory directly */ - info->screen_base = (char *)dev_priv->vram_addr + + /* Accessed stolen memory directly */ + info->screen_base = (char *)dev_priv->vram_addr + backing->offset; - } else { - /* Pin the pages into the GTT and create a mapping to them */ - psb_gtt_pin(backing); - info->screen_base = vm_map_ram(backing->pages, backing->npage, - -1, PAGE_KERNEL); - if (info->screen_base == NULL) { - psb_gtt_unpin(backing); - ret = -ENOMEM; - goto out_unref; - } - psbfb->vm_map = 1; - } info->screen_size = size; if (dev_priv->gtt.stolen_size) { @@ -504,7 +500,7 @@ static int psbfb_create(struct psb_fbdev *fbdev, info->apertures->ranges[0].size = dev_priv->gtt.stolen_size; } - drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, sizes->fb_width, sizes->fb_height); @@ -525,11 +521,8 @@ static int psbfb_create(struct psb_fbdev *fbdev, out_unref: if (backing->stolen) psb_gtt_free_range(dev, backing); - else { - if (psbfb->vm_map) - vm_unmap_ram(info->screen_base, backing->npage); + else drm_gem_object_unreference(&backing->gem); - } out_err1: mutex_unlock(&dev->struct_mutex); psb_gtt_free_range(dev, backing); @@ -546,7 +539,7 @@ out_err1: */ static struct drm_framebuffer *psb_user_framebuffer_create (struct drm_device *dev, struct drm_file *filp, - struct drm_mode_fb_cmd *cmd) + struct drm_mode_fb_cmd2 *cmd) { struct gtt_range *r; struct drm_gem_object *obj; @@ -555,7 +548,7 @@ static struct drm_framebuffer *psb_user_framebuffer_create * Find the GEM object and thus the gtt range object that is * to back this space */ - obj = drm_gem_object_lookup(dev, filp, cmd->handle); + obj = drm_gem_object_lookup(dev, filp, cmd->handles[0]); if (obj == NULL) return ERR_PTR(-ENOENT); @@ -603,13 +596,6 @@ int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev) if (fbdev->psb_fb_helper.fbdev) { info = fbdev->psb_fb_helper.fbdev; - - /* If this is our base framebuffer then kill any virtual map - for the framebuffer layer and unpin it */ - if (psbfb->vm_map) { - vm_unmap_ram(info->screen_base, psbfb->gtt->npage); - psb_gtt_unpin(psbfb->gtt); - } unregister_framebuffer(info); if (info->cmap.len) fb_dealloc_cmap(&info->cmap); @@ -761,13 +747,13 @@ static void psb_setup_outputs(struct drm_device *dev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct psb_intel_output *psb_intel_output = - to_psb_intel_output(connector); - struct drm_encoder *encoder = &psb_intel_output->enc; + struct psb_intel_encoder *psb_intel_encoder = + psb_intel_attached_encoder(connector); + struct drm_encoder *encoder = &psb_intel_encoder->base; int crtc_mask = 0, clone_mask = 0; /* valid crtcs */ - switch (psb_intel_output->type) { + switch (psb_intel_encoder->type) { case INTEL_OUTPUT_ANALOG: crtc_mask = (1 << 0); clone_mask = (1 << INTEL_OUTPUT_ANALOG); @@ -792,13 +778,10 @@ static void psb_setup_outputs(struct drm_device *dev) clone_mask = (1 << INTEL_OUTPUT_MIPI2); break; case INTEL_OUTPUT_HDMI: - /* 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)) + if (IS_MFLD(dev)) crtc_mask = (1 << 1); - else - crtc_mask = (1 << 0); /* Cedarview */ + else + crtc_mask = (1 << 0); clone_mask = (1 << INTEL_OUTPUT_HDMI); break; } @@ -810,8 +793,7 @@ static void psb_setup_outputs(struct drm_device *dev) void psb_modeset_init(struct drm_device *dev) { - struct drm_psb_private *dev_priv = - (struct drm_psb_private *) dev->dev_private; + struct drm_psb_private *dev_priv = dev->dev_private; struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; int i; @@ -823,7 +805,7 @@ void psb_modeset_init(struct drm_device *dev) dev->mode_config.funcs = (void *) &psb_mode_funcs; /* set memory base */ - /* MRST and PSB should use BAR 2*/ + /* Oaktrail and Poulsbo should use BAR 2*/ pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *) &(dev->mode_config.fb_base)); |
