aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/gpu/drm/gma500/framebuffer.c
diff options
context:
space:
mode:
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));