aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/cirrus/cirrus_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/cirrus/cirrus_main.c')
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_main.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c
index 99c1983f99d2..4c2d68e9102d 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -49,14 +49,16 @@ cirrus_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
struct drm_mode_fb_cmd2 *mode_cmd)
{
+ struct cirrus_device *cdev = dev->dev_private;
struct drm_gem_object *obj;
struct cirrus_framebuffer *cirrus_fb;
int ret;
u32 bpp, depth;
drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
- /* cirrus can't handle > 24bpp framebuffers at all */
- if (bpp > 24)
+
+ if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
+ bpp, mode_cmd->pitches[0]))
return ERR_PTR(-EINVAL);
obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
@@ -96,8 +98,7 @@ static int cirrus_vram_init(struct cirrus_device *cdev)
{
/* BAR 0 is VRAM */
cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0);
- /* We have 4MB of VRAM */
- cdev->mc.vram_size = 4 * 1024 * 1024;
+ cdev->mc.vram_size = pci_resource_len(cdev->dev->pdev, 0);
if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size,
"cirrusdrmfb_vram")) {
@@ -179,17 +180,22 @@ int cirrus_driver_load(struct drm_device *dev, unsigned long flags)
}
r = cirrus_mm_init(cdev);
- if (r)
+ if (r) {
dev_err(&dev->pdev->dev, "fatal err on mm init\n");
+ goto out;
+ }
r = cirrus_modeset_init(cdev);
- if (r)
+ if (r) {
dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
+ goto out;
+ }
dev->mode_config.funcs = (void *)&cirrus_mode_funcs;
+
+ return 0;
out:
- if (r)
- cirrus_driver_unload(dev);
+ cirrus_driver_unload(dev);
return r;
}
@@ -307,3 +313,21 @@ out_unlock:
return ret;
}
+
+bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
+ int bpp, int pitch)
+{
+ const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */
+ const int max_size = cdev->mc.vram_size;
+
+ if (bpp > 32)
+ return false;
+
+ if (pitch > max_pitch)
+ return false;
+
+ if (pitch * height > max_size)
+ return false;
+
+ return true;
+}