From patchwork Mon May 27 03:53:41 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Courbot X-Patchwork-Id: 2617641 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork2.kernel.org (Postfix) with ESMTP id B9B79DF215 for ; Mon, 27 May 2013 03:54:18 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UgoVl-0001xo-8E; Mon, 27 May 2013 03:54:17 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UgoVi-00063d-CV; Mon, 27 May 2013 03:54:14 +0000 Received: from hqemgate14.nvidia.com ([216.228.121.143]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UgoVf-00062W-CE; Mon, 27 May 2013 03:54:12 +0000 Received: from hqnvupgp08.nvidia.com (Not Verified[216.228.121.13]) by hqemgate14.nvidia.com id ; Sun, 26 May 2013 20:53:47 -0700 Received: from hqemhub01.nvidia.com ([172.20.12.94]) by hqnvupgp08.nvidia.com (PGP Universal service); Sun, 26 May 2013 20:53:48 -0700 X-PGP-Universal: processed; by hqnvupgp08.nvidia.com on Sun, 26 May 2013 20:53:48 -0700 Received: from percival.nvidia.com (172.20.144.16) by hqemhub01.nvidia.com (172.20.150.30) with Microsoft SMTP Server (TLS) id 8.3.298.1; Sun, 26 May 2013 20:53:47 -0700 From: Alexandre Courbot To: Andrew Morton , Stephen Warren Subject: [PATCH v2] video: simplefb: add mode parsing function Date: Mon, 27 May 2013 12:53:41 +0900 Message-ID: <1369626821-28494-1-git-send-email-acourbot@nvidia.com> X-Mailer: git-send-email 1.8.3 X-NVConfidentiality: public MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130526_235411_565510_3E58B9C1 X-CRM114-Status: GOOD ( 22.03 ) X-Spam-Score: -3.0 (---) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-3.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -1.1 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: gnurou@gmail.com, linux-fbdev@vger.kernel.org, Arnd Bergmann , devicetree-discuss@lists.ozlabs.org, linux-kernel@vger.kernel.org, Rob Clark , Alexandre Courbot , linux-rpi-kernel@lists.infradead.org, Olof Johansson , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org The naming scheme of simplefb's mode is precise enough to allow building the mode structure from it instead of using a static list of modes. This patch introduces a function that does this. In case exotic modes that cannot be represented from their name alone are needed, the static list of modes is still available as a backup. It also changes the order in which colors are declared from MSB first to the more standard LSB first. Signed-off-by: Alexandre Courbot --- Changes from v1: - amended documentation following Stephen's suggestion - allow parsing of bitfields larger than 9 bits - made it clear that the parsing order of bits is changed with respect to the original patch Andrew, since this patch introduces a (small) change in the DT bindings, could we try to merge it during the -rc cycle so we don't have to come with a more complex solution in the future? .../bindings/video/simple-framebuffer.txt | 12 +++- drivers/video/simplefb.c | 72 +++++++++++++++++++++- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/video/simple-framebuffer.txt b/Documentation/devicetree/bindings/video/simple-framebuffer.txt index 3ea4605..18d03e2 100644 --- a/Documentation/devicetree/bindings/video/simple-framebuffer.txt +++ b/Documentation/devicetree/bindings/video/simple-framebuffer.txt @@ -10,8 +10,16 @@ Required properties: - width: The width of the framebuffer in pixels. - height: The height of the framebuffer in pixels. - stride: The number of bytes in each line of the framebuffer. -- format: The format of the framebuffer surface. Valid values are: - - r5g6b5 (16-bit pixels, d[15:11]=r, d[10:5]=g, d[4:0]=b). +- format: The format of the framebuffer surface. Described as a sequence of + channel/num-bits pairs, where each pair describes how many bits are used + by a given color channel. Value channels are "r" (red), "g" (green), + "b" (blue), "a" (alpha) and "x" (unused). Channels are listed in bit + order, starting from the LSB. For instance, a format named "r5g6b5" + describes a 16-bit format where red is encoded in the 5 less significant + bits, green in the 6 following ones, and blue in the 5 last: + BBBBBGGG GGGRRRRR + ^ ^ + MSB LSB Example: diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c index e2e9e3e..1430752 100644 --- a/drivers/video/simplefb.c +++ b/drivers/video/simplefb.c @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -82,8 +83,72 @@ struct simplefb_format { struct fb_bitfield transp; }; +static struct simplefb_format *simplefb_parse_format(struct device *dev, + const char *str) +{ + struct simplefb_format *format; + unsigned int offset = 0; + unsigned int i = 0; + + format = devm_kzalloc(dev, sizeof(*format), GFP_KERNEL); + if (!format) + return ERR_PTR(-ENOMEM); + + while (str[i] != 0) { + struct fb_bitfield *field = NULL; + int length = 0; + + switch (str[i++]) { + case 'r': + case 'R': + field = &format->red; + break; + case 'g': + case 'G': + field = &format->green; + break; + case 'b': + case 'B': + field = &format->blue; + break; + case 'a': + case 'A': + field = &format->transp; + break; + case 'x': + case 'X': + break; + default: + goto error; + } + + if (!isdigit(str[i])) + goto error; + + while (isdigit(str[i])) { + length = length * 10 + (str[i++] - '0'); + } + + if (field) { + field->offset = offset; + field->length = length; + } + + offset += length; + } + + format->bits_per_pixel = (offset + 7) & ~0x7; + format->name = str; + return format; + +error: + dev_err(dev, "Invalid format string\n"); + return ERR_PTR(-EINVAL); +} + +/* if you use exotic modes that simplefb_parse_format cannot decode, you can + specify them here. */ static struct simplefb_format simplefb_formats[] = { - { "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0} }, }; struct simplefb_params { @@ -131,7 +196,10 @@ static int simplefb_parse_dt(struct platform_device *pdev, params->format = &simplefb_formats[i]; break; } - if (!params->format) { + if (!params->format) + params->format = simplefb_parse_format(&pdev->dev, format); + + if (IS_ERR(params->format)) { dev_err(&pdev->dev, "Invalid format value\n"); return -EINVAL; }