Commit 8975626e authored by Zach Reizner's avatar Zach Reizner Committed by Dave Airlie

drm/cirrus: allow 32bpp framebuffers for cirrus drm

This patch allows framebuffers for cirrus to be created with
32bpp pixel formats provided that they do not violate certain
restrictions of the cirrus hardware.

v2: Use pci resource length for vram size.
Signed-off-by: default avatarZach Reizner <zachr@google.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent ebfdd6d5
...@@ -210,6 +210,9 @@ int cirrus_framebuffer_init(struct drm_device *dev, ...@@ -210,6 +210,9 @@ int cirrus_framebuffer_init(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd, struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj); struct drm_gem_object *obj);
bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
int bpp, int pitch);
/* cirrus_display.c */ /* cirrus_display.c */
int cirrus_modeset_init(struct cirrus_device *cdev); int cirrus_modeset_init(struct cirrus_device *cdev);
void cirrus_modeset_fini(struct cirrus_device *cdev); void cirrus_modeset_fini(struct cirrus_device *cdev);
......
...@@ -139,6 +139,7 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev, ...@@ -139,6 +139,7 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
struct drm_gem_object **gobj_p) struct drm_gem_object **gobj_p)
{ {
struct drm_device *dev = afbdev->helper.dev; struct drm_device *dev = afbdev->helper.dev;
struct cirrus_device *cdev = dev->dev_private;
u32 bpp, depth; u32 bpp, depth;
u32 size; u32 size;
struct drm_gem_object *gobj; struct drm_gem_object *gobj;
...@@ -146,8 +147,10 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev, ...@@ -146,8 +147,10 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
int ret = 0; int ret = 0;
drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
if (bpp > 24) if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
bpp, mode_cmd->pitches[0]))
return -EINVAL; return -EINVAL;
size = mode_cmd->pitches[0] * mode_cmd->height; size = mode_cmd->pitches[0] * mode_cmd->height;
ret = cirrus_gem_create(dev, size, true, &gobj); ret = cirrus_gem_create(dev, size, true, &gobj);
if (ret) if (ret)
......
...@@ -49,14 +49,16 @@ cirrus_user_framebuffer_create(struct drm_device *dev, ...@@ -49,14 +49,16 @@ cirrus_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp, struct drm_file *filp,
struct drm_mode_fb_cmd2 *mode_cmd) struct drm_mode_fb_cmd2 *mode_cmd)
{ {
struct cirrus_device *cdev = dev->dev_private;
struct drm_gem_object *obj; struct drm_gem_object *obj;
struct cirrus_framebuffer *cirrus_fb; struct cirrus_framebuffer *cirrus_fb;
int ret; int ret;
u32 bpp, depth; u32 bpp, depth;
drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); 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); return ERR_PTR(-EINVAL);
obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]); obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
...@@ -96,8 +98,7 @@ static int cirrus_vram_init(struct cirrus_device *cdev) ...@@ -96,8 +98,7 @@ static int cirrus_vram_init(struct cirrus_device *cdev)
{ {
/* BAR 0 is VRAM */ /* BAR 0 is VRAM */
cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0); cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0);
/* We have 4MB of VRAM */ cdev->mc.vram_size = pci_resource_len(cdev->dev->pdev, 0);
cdev->mc.vram_size = 4 * 1024 * 1024;
if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size, if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size,
"cirrusdrmfb_vram")) { "cirrusdrmfb_vram")) {
...@@ -312,3 +313,21 @@ cirrus_dumb_mmap_offset(struct drm_file *file, ...@@ -312,3 +313,21 @@ cirrus_dumb_mmap_offset(struct drm_file *file,
return ret; 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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment