aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2014-10-29 14:04:24 -0400
committerDave Airlie <airlied@redhat.com>2014-11-19 20:42:46 -0500
commit8975626ea35adcca561f8a81dedccfbc5dd8ec72 (patch)
treeacf4290d5b83894212eb71dc51d2a5c088fa67b3
parentebfdd6d5e837bd1c170b9bdd749fee2a4183a7f5 (diff)
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: Zach Reizner <zachr@google.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_drv.h3
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_fbdev.c5
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_main.c27
3 files changed, 30 insertions, 5 deletions
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
index d44e69daa239..693a4565c4ff 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.h
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -210,6 +210,9 @@ int cirrus_framebuffer_init(struct drm_device *dev,
210 struct drm_mode_fb_cmd2 *mode_cmd, 210 struct drm_mode_fb_cmd2 *mode_cmd,
211 struct drm_gem_object *obj); 211 struct drm_gem_object *obj);
212 212
213bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
214 int bpp, int pitch);
215
213 /* cirrus_display.c */ 216 /* cirrus_display.c */
214int cirrus_modeset_init(struct cirrus_device *cdev); 217int cirrus_modeset_init(struct cirrus_device *cdev);
215void cirrus_modeset_fini(struct cirrus_device *cdev); 218void cirrus_modeset_fini(struct cirrus_device *cdev);
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
index d231b1c317af..502a89eb54b5 100644
--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
@@ -139,6 +139,7 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
139 struct drm_gem_object **gobj_p) 139 struct drm_gem_object **gobj_p)
140{ 140{
141 struct drm_device *dev = afbdev->helper.dev; 141 struct drm_device *dev = afbdev->helper.dev;
142 struct cirrus_device *cdev = dev->dev_private;
142 u32 bpp, depth; 143 u32 bpp, depth;
143 u32 size; 144 u32 size;
144 struct drm_gem_object *gobj; 145 struct drm_gem_object *gobj;
@@ -146,8 +147,10 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
146 int ret = 0; 147 int ret = 0;
147 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); 148 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
148 149
149 if (bpp > 24) 150 if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
151 bpp, mode_cmd->pitches[0]))
150 return -EINVAL; 152 return -EINVAL;
153
151 size = mode_cmd->pitches[0] * mode_cmd->height; 154 size = mode_cmd->pitches[0] * mode_cmd->height;
152 ret = cirrus_gem_create(dev, size, true, &gobj); 155 ret = cirrus_gem_create(dev, size, true, &gobj);
153 if (ret) 156 if (ret)
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c
index ab7cb547c570..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,
49 struct drm_file *filp, 49 struct drm_file *filp,
50 struct drm_mode_fb_cmd2 *mode_cmd) 50 struct drm_mode_fb_cmd2 *mode_cmd)
51{ 51{
52 struct cirrus_device *cdev = dev->dev_private;
52 struct drm_gem_object *obj; 53 struct drm_gem_object *obj;
53 struct cirrus_framebuffer *cirrus_fb; 54 struct cirrus_framebuffer *cirrus_fb;
54 int ret; 55 int ret;
55 u32 bpp, depth; 56 u32 bpp, depth;
56 57
57 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); 58 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
58 /* cirrus can't handle > 24bpp framebuffers at all */ 59
59 if (bpp > 24) 60 if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
61 bpp, mode_cmd->pitches[0]))
60 return ERR_PTR(-EINVAL); 62 return ERR_PTR(-EINVAL);
61 63
62 obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]); 64 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{ 98{
97 /* BAR 0 is VRAM */ 99 /* BAR 0 is VRAM */
98 cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0); 100 cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0);
99 /* We have 4MB of VRAM */ 101 cdev->mc.vram_size = pci_resource_len(cdev->dev->pdev, 0);
100 cdev->mc.vram_size = 4 * 1024 * 1024;
101 102
102 if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size, 103 if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size,
103 "cirrusdrmfb_vram")) { 104 "cirrusdrmfb_vram")) {
@@ -312,3 +313,21 @@ out_unlock:
312 return ret; 313 return ret;
313 314
314} 315}
316
317bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
318 int bpp, int pitch)
319{
320 const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */
321 const int max_size = cdev->mc.vram_size;
322
323 if (bpp > 32)
324 return false;
325
326 if (pitch > max_pitch)
327 return false;
328
329 if (pitch * height > max_size)
330 return false;
331
332 return true;
333}