From patchwork Fri Jul 26 20:36:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Ravnborg X-Patchwork-Id: 11061807 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C7AC01398 for ; Fri, 26 Jul 2019 20:36:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B0CEE28B2B for ; Fri, 26 Jul 2019 20:36:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9E7D428B55; Fri, 26 Jul 2019 20:36:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1311A28B2B for ; Fri, 26 Jul 2019 20:36:33 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C9C866EE56; Fri, 26 Jul 2019 20:36:30 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from asavdk4.altibox.net (asavdk4.altibox.net [109.247.116.15]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9EB1E6EE56 for ; Fri, 26 Jul 2019 20:36:29 +0000 (UTC) Received: from ravnborg.org (unknown [158.248.194.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by asavdk4.altibox.net (Postfix) with ESMTPS id BE40C8031E for ; Fri, 26 Jul 2019 22:36:27 +0200 (CEST) Date: Fri, 26 Jul 2019 22:36:26 +0200 From: Sam Ravnborg To: dri-devel@lists.freedesktop.org Subject: My penguin has blue feets (aka: RGB versus BGR troubles) Message-ID: <20190726203626.GA31474@ravnborg.org> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) X-CMAE-Score: 0 X-CMAE-Analysis: v=2.3 cv=VcLZwmh9 c=1 sm=1 tr=0 a=UWs3HLbX/2nnQ3s7vZ42gw==:117 a=UWs3HLbX/2nnQ3s7vZ42gw==:17 a=kj9zAlcOel0A:10 a=7gkXJVJtAAAA:8 a=8P7hZ89I2lEOGz5q5yUA:9 a=7L8W9jQ2ks-ETaML:21 a=P8xJQdmlEB9JbCTY:21 a=CjuIK1q_8ugA:10 a=E9Po1WZjFZOl8hwRPBS3:22 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Hi all. The Atmel at91sam9263 has a nice LCDC IP core that supports several formats: DRM_FORMAT_XBGR8888, DRM_FORMAT_BGR888, DRM_FORMAT_BGR565 (It also supports a palletized C8 format, but thats for later). The formats are all BGR formats - and some boards actually reverse Blue and Red when wiring up the display. I have added a DT property to identify boards with this difference. The penguin shown during boot of the kernel had blue feet which is a clear sign that RED and GREEN was reversed. So to fix this I (got help from imirkin on irc) I implmented a quirk. See patch below. With the quirk enabled I see: - penguin shown during kernel boot has yellow feets (OK) - modetest tell the driver reports: XB24 BG24 BG16 (as expected) - modetest -s fails with: # modetest -M atmel-lcdc -s 34:800x480-60Hz setting mode 800x480-60Hz@XR24 on connectors 34, crtc 32 failed to set mode: Function not implemented Snip from dmesg: drm:drm_ioctl] pid=208, dev=0xe201, auth=1, DRM_IOCTL_MODE_ADDFB2 [drm:drm_mode_addfb2] [FB:37] [drm:drm_ioctl] pid=208, dev=0xe201, auth=1, DRM_IOCTL_MODE_SETCRTC [drm:drm_mode_setcrtc] [CRTC:32:crtc-0] [drm:drm_mode_setcrtc] Invalid pixel format XR24 little-endian (0x34325258), modifier 0x0 ^^^^ [drm:drm_mode_object_put] OBJ ID: 37 (2) [drm:drm_ioctl] pid=208, ret = -22 [drm:drm_ioctl] pid=208, dev=0xe201, auth=1, DRM_IOCTL_MODE_DIRTYFB [drm:drm_mode_object_put] OBJ ID: 37 (2) [drm:drm_ioctl] pid=208, ret = -38 [drm:drm_ioctl] pid=208, dev=0xe201, auth=1, DRM_IOCTL_MODE_RMFB [drm:drm_mode_object_put] OBJ ID: 37 (2) [drm:drm_mode_object_put] OBJ ID: 37 (1) [drm:drm_ioctl] pid=208, dev=0xe201, auth=1, DRM_IOCTL_MODE_DESTROY_DUMB [drm:drm_release] open_count = 1 [drm:drm_file_free] pid = 208, device = 0xe201, open_count = 1 [drm:drm_lastclose] [drm:drm_lastclose] driver lastclose completed Notice that somehow we have a framebuffer in XR24 format, which is not supported by the driver. I have tried to tell that my driver supports DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB888, DRM_FORMAT_RGB565 and then modetest works. But in the output of modetest -s the blue and red colors are reversed. *Any* hints why modetest fails when my driver reports the correct formats? For reference I will post source for the driver in a follow-up mail. Sam The quirk I implmented looks like this (preliminary patch): From ab0f213e50fbe1b053d624745306252b28e6ecdc Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 21 Jul 2019 08:59:49 +0200 Subject: [PATCH 21/22] drm: add quirk_addfb_rgb_to_bgr Used for drivers where the format supported is default BGR. Then use this quirk to force drm_fb_helper to convert the framebuffer from RGB => BGR. Signed-off-by: Sam Ravnborg --- drivers/gpu/drm/drm_fb_helper.c | 46 +++++++++++++++++++++++---------- drivers/gpu/drm/drm_fourcc.c | 14 ++++++++++ include/drm/drm_mode_config.h | 7 +++++ 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index a7ba5b4902d6..adc1b1fcb153 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1236,9 +1236,9 @@ static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1, } static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var, - u8 depth) + struct drm_framebuffer *fb) { - switch (depth) { + switch (fb->format->depth) { case 8: var->red.offset = 0; var->green.offset = 0; @@ -1260,18 +1260,30 @@ static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var, var->transp.length = 1; break; case 16: - var->red.offset = 11; - var->green.offset = 5; - var->blue.offset = 0; + if (!fb->dev->mode_config.quirk_addfb_rgb_to_bgr) { + var->red.offset = 11; + var->green.offset = 5; + var->blue.offset = 0; + } else { + var->red.offset = 0; + var->green.offset = 5; + var->blue.offset = 11; + } var->red.length = 5; var->green.length = 6; var->blue.length = 5; var->transp.offset = 0; break; case 24: - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; + if (!fb->dev->mode_config.quirk_addfb_rgb_to_bgr) { + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + } else { + var->red.offset = 0; + var->green.offset = 8; + var->blue.offset = 16; + } var->red.length = 8; var->green.length = 8; var->blue.length = 8; @@ -1279,9 +1291,15 @@ static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var, var->transp.length = 0; break; case 32: - var->red.offset = 16; - var->green.offset = 8; - var->blue.offset = 0; + if (!fb->dev->mode_config.quirk_addfb_rgb_to_bgr) { + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + } else { + var->red.offset = 0; + var->green.offset = 8; + var->blue.offset = 16; + } var->red.length = 8; var->green.length = 8; var->blue.length = 8; @@ -1342,7 +1360,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, !var->blue.length && !var->transp.length && !var->red.msb_right && !var->green.msb_right && !var->blue.msb_right && !var->transp.msb_right) { - drm_fb_helper_fill_pixel_fmt(var, fb->format->depth); + drm_fb_helper_fill_pixel_fmt(var, fb); } /* @@ -1684,7 +1702,7 @@ static void drm_fb_helper_fill_var(struct fb_info *info, info->var.yoffset = 0; info->var.activate = FB_ACTIVATE_NOW; - drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth); + drm_fb_helper_fill_pixel_fmt(&info->var, fb); info->var.xres = fb_width; info->var.yres = fb_height; @@ -2205,7 +2223,7 @@ int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper, sizes->surface_width, sizes->surface_height, sizes->surface_bpp); - format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); + format = drm_driver_legacy_fb_format(fb_helper->dev, sizes->surface_bpp, sizes->surface_depth); buffer = drm_client_framebuffer_create(client, sizes->surface_width, sizes->surface_height, format); if (IS_ERR(buffer)) diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index c630064ccf41..972ea746c06d 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -126,6 +126,20 @@ uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, fmt == DRM_FORMAT_XRGB2101010) fmt = DRM_FORMAT_XBGR2101010; + if (dev->mode_config.quirk_addfb_rgb_to_bgr) { + switch (fmt) { + case DRM_FORMAT_RGB565: + fmt = DRM_FORMAT_BGR565; + break; + case DRM_FORMAT_RGB888: + fmt = DRM_FORMAT_BGR888; + break; + case DRM_FORMAT_XRGB8888: + fmt = DRM_FORMAT_XBGR8888; + break; + } + } + return fmt; } EXPORT_SYMBOL(drm_driver_legacy_fb_format); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index f57eea0481e0..58aa8c02232e 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -881,6 +881,13 @@ struct drm_mode_config { */ bool quirk_addfb_prefer_host_byte_order; + /** + * @quirk_addfb_rgb_to_bgr: + * + * TODO + */ + bool quirk_addfb_rgb_to_bgr; + /** * @async_page_flip: Does this device support async flips on the primary * plane?