From patchwork Wed Jul 25 03:08:41 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Herrenschmidt X-Patchwork-Id: 1234231 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 05D6BDF24C for ; Wed, 25 Jul 2012 03:25:23 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C91A1A09D6 for ; Tue, 24 Jul 2012 20:25:22 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) by gabe.freedesktop.org (Postfix) with ESMTP id 946329EB99 for ; Tue, 24 Jul 2012 20:22:41 -0700 (PDT) Received: from [127.0.0.1] (localhost.localdomain [127.0.0.1]) by gate.crashing.org (8.14.1/8.13.8) with ESMTP id q6P38fnS022497 for ; Tue, 24 Jul 2012 22:08:42 -0500 Message-ID: <1343185721.3715.37.camel@pasglop> Subject: [PATCH 5/6] drm/cirrus: Check for pitch limits rather than bpp limits From: Benjamin Herrenschmidt To: dri-devel@lists.freedesktop.org Date: Wed, 25 Jul 2012 13:08:41 +1000 X-Mailer: Evolution 3.2.3-0ubuntu6 Mime-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org The real HW limit that prevents from using 32bpp is a pitch limit of 4095 bytes. 32bpp is otherwise supported and works. This fixes the checks in the code to check the right thing (so that a userspace request to set a mode with a supported bpp but a too large pitch will fail appropriately). Additionally, we make the fbdev code try reducing the bpp if it hits the pitch limit in order to improve the chances of displaying a console at boot if the default or requested mode is too large to fit. Signed-off-by: Benjamin Herrenschmidt --- drivers/gpu/drm/cirrus/cirrus_fbdev.c | 28 +++++++++++++++++++++++++--- drivers/gpu/drm/cirrus/cirrus_main.c | 4 ++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index 9a276a5..1345215 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -109,9 +109,9 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev, int ret = 0; drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); - - if (bpp > 24) + if (mode_cmd->pitches[0] >= 4096) return -EINVAL; + size = mode_cmd->pitches[0] * mode_cmd->height; ret = cirrus_gem_create(dev, size, true, &gobj); if (ret) @@ -137,7 +137,29 @@ static int cirrusfb_create(struct cirrus_fbdev *gfbdev, mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8); + + /* Reduce bpp to fit pitch constraints if necessary */ + for (;;) { + mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8); + if (mode_cmd.pitches[0] < 4096) + break; + switch(sizes->surface_bpp) { + case 32: + sizes->surface_bpp = 24; + break; + case 24: + sizes->surface_bpp = 16; + break; + case 16: + sizes->surface_bpp = 8; + break; + default: + return -ENOMEM; + } + DRM_INFO("Selected mode has a too high pitch, reducing to %d bpp\n", + sizes->surface_bpp); + } + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); size = mode_cmd.pitches[0] * mode_cmd.height; diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c index e3c1225..ac1a5e5 100644 --- a/drivers/gpu/drm/cirrus/cirrus_main.c +++ b/drivers/gpu/drm/cirrus/cirrus_main.c @@ -64,8 +64,8 @@ cirrus_user_framebuffer_create(struct drm_device *dev, 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) + /* cirrus can't handle pitch >= 4096 */ + if (mode_cmd->pitches[0] >= 4096) return ERR_PTR(-EINVAL); obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);