|
@@ -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")) {
|
|
@@ -312,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;
|
|
|
+}
|