From: Linus Walleij <linus.walleij@linaro.org>
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 4/6] video: ARM CLCD: support Nomadik variant
Date: Thu, 16 Jun 2016 09:36:16 +0000 [thread overview]
Message-ID: <1466069778-16087-5-git-send-email-linus.walleij@linaro.org> (raw)
In-Reply-To: <1466069778-16087-1-git-send-email-linus.walleij@linaro.org>
The Nomadik variant has a few special quirks that need to be respected
to make the driver work:
- The block need to be clocked during writing of the TIMn registers
or the bus will stall.
- Special bits in the control register select how many of the output
display lines get activated.
- Special bits in the control register select how to manage the
different 565 and 5551 modes.
- There is a packed 24bit graphics mode, i.e 888 pixels can be stored
in memory is three consecutive bytes, not evenly aligned to a 32bit
word.
This patch uses the vendor data pointer from the AMBA matching mechanism
to track the quirks for this variant, and adds two hooks that variants
can use to initialize boards and panels during start-up. These will
later be used to adopt a Nomadik board profile.
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- Just rebased. No comments so no changes.
ChangeLog v1->v2:
- No changes. Just reposting.
---
drivers/video/fbdev/amba-clcd.c | 106 ++++++++++++++++++++++++++++++++++++----
include/linux/amba/clcd.h | 42 ++++++++++++++++
2 files changed, 139 insertions(+), 9 deletions(-)
diff --git a/drivers/video/fbdev/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c
index 080e8a246faf..371f4e2aea6c 100644
--- a/drivers/video/fbdev/amba-clcd.c
+++ b/drivers/video/fbdev/amba-clcd.c
@@ -225,6 +225,15 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
var->blue.length = 4;
}
break;
+ case 24:
+ if (fb->vendor->packed_24_bit_pixels) {
+ var->red.length = 8;
+ var->green.length = 8;
+ var->blue.length = 8;
+ } else {
+ ret = -EINVAL;
+ }
+ break;
case 32:
/* If we can't do 888, reject */
caps &= CLCD_CAP_888;
@@ -311,6 +320,12 @@ static int clcdfb_set_par(struct fb_info *info)
clcdfb_disable(fb);
+ /* Some variants must be clocked here */
+ if (fb->vendor->clock_timregs && !fb->clk_enabled) {
+ fb->clk_enabled = true;
+ clk_enable(fb->clk);
+ }
+
writel(regs.tim0, fb->regs + CLCD_TIM0);
writel(regs.tim1, fb->regs + CLCD_TIM1);
writel(regs.tim2, fb->regs + CLCD_TIM2);
@@ -710,6 +725,42 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
if (r0 != 0 && b0 = 0)
fb->panel->bgr_connection = true;
+ if (fb->panel->caps && fb->vendor->st_bitmux_control) {
+ /*
+ * Set up the special bits for the Nomadik control register
+ * (other platforms tend to do this through an external
+ * register).
+ */
+
+ /* Offset of the highest used color */
+ int maxoff = max3(r0, g0, b0);
+ /* Most significant bit out, highest used bit */
+ int msb = 0;
+
+ if (fb->panel->caps & CLCD_CAP_888) {
+ msb = maxoff + 8 - 1;
+ } else if (fb->panel->caps & CLCD_CAP_565) {
+ msb = maxoff + 5 - 1;
+ fb->panel->cntl |= CNTL_ST_1XBPP_565;
+ } else if (fb->panel->caps & CLCD_CAP_5551) {
+ msb = maxoff + 5 - 1;
+ fb->panel->cntl |= CNTL_ST_1XBPP_5551;
+ } else if (fb->panel->caps & CLCD_CAP_444) {
+ msb = maxoff + 4 - 1;
+ fb->panel->cntl |= CNTL_ST_1XBPP_444;
+ }
+
+ /* Send out as many bits as we need */
+ if (msb > 17)
+ fb->panel->cntl |= CNTL_ST_CDWID_24;
+ else if (msb > 15)
+ fb->panel->cntl |= CNTL_ST_CDWID_18;
+ else if (msb > 11)
+ fb->panel->cntl |= CNTL_ST_CDWID_16;
+ else
+ fb->panel->cntl |= CNTL_ST_CDWID_12;
+ }
+
return fb->panel->caps ? 0 : -EINVAL;
}
@@ -725,9 +776,21 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)
if (!fb->panel)
return -ENOMEM;
- endpoint = of_graph_get_next_endpoint(fb->dev->dev.of_node, NULL);
- if (!endpoint)
- return -ENODEV;
+ /*
+ * Fetch the panel endpoint.
+ */
+ if (!endpoint) {
+ endpoint = of_graph_get_next_endpoint(fb->dev->dev.of_node,
+ NULL);
+ if (!endpoint)
+ return -ENODEV;
+ }
+
+ if (fb->vendor->init_panel) {
+ err = fb->vendor->init_panel(fb, endpoint);
+ if (err)
+ return err;
+ }
err = clcdfb_of_get_backlight(endpoint, fb->panel);
if (err)
@@ -764,11 +827,11 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)
if (of_property_read_u32_array(endpoint,
"arm,pl11x,tft-r0g0b0-pads",
- tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) = 0)
- return clcdfb_of_init_tft_panel(fb, tft_r0b0g0[0],
- tft_r0b0g0[1], tft_r0b0g0[2]);
+ tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) != 0)
+ return -ENOENT;
- return -ENOENT;
+ return clcdfb_of_init_tft_panel(fb, tft_r0b0g0[0],
+ tft_r0b0g0[1], tft_r0b0g0[2]);
}
static int clcdfb_of_vram_setup(struct clcd_fb *fb)
@@ -889,6 +952,7 @@ static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev)
static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
{
struct clcd_board *board = dev_get_platdata(&dev->dev);
+ struct clcd_vendor_data *vendor = id->data;
struct clcd_fb *fb;
int ret;
@@ -898,6 +962,12 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
if (!board)
return -EINVAL;
+ if (vendor->init_board) {
+ ret = vendor->init_board(dev, board);
+ if (ret)
+ return ret;
+ }
+
ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
if (ret)
goto out;
@@ -916,10 +986,11 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
}
fb->dev = dev;
+ fb->vendor = vendor;
fb->board = board;
- dev_info(&fb->dev->dev, "PL%03x rev%u at 0x%08llx\n",
- amba_part(dev), amba_rev(dev),
+ dev_info(&fb->dev->dev, "PL%03x designer %02x rev%u at 0x%08llx\n",
+ amba_part(dev), amba_manf(dev), amba_rev(dev),
(unsigned long long)dev->res.start);
ret = fb->board->setup(fb);
@@ -962,10 +1033,27 @@ static int clcdfb_remove(struct amba_device *dev)
return 0;
}
+static struct clcd_vendor_data vendor_arm = {
+ /* No special business */
+};
+
+static struct clcd_vendor_data vendor_nomadik = {
+ .clock_timregs = true,
+ .packed_24_bit_pixels = true,
+ .st_bitmux_control = true,
+};
+
static struct amba_id clcdfb_id_table[] = {
{
.id = 0x00041110,
.mask = 0x000ffffe,
+ .data = &vendor_arm,
+ },
+ /* ST Electronics Nomadik variant */
+ {
+ .id = 0x00180110,
+ .mask = 0x00fffffe,
+ .data = &vendor_nomadik,
},
{ 0, 0 },
};
diff --git a/include/linux/amba/clcd.h b/include/linux/amba/clcd.h
index 8b64ec0d574b..1035879b322c 100644
--- a/include/linux/amba/clcd.h
+++ b/include/linux/amba/clcd.h
@@ -67,6 +67,17 @@
#define CNTL_LDMAFIFOTIME (1 << 15)
#define CNTL_WATERMARK (1 << 16)
+/* ST Microelectronics variant bits */
+#define CNTL_ST_1XBPP_444 0x0
+#define CNTL_ST_1XBPP_5551 (1 << 17)
+#define CNTL_ST_1XBPP_565 (1 << 18)
+#define CNTL_ST_CDWID_12 0x0
+#define CNTL_ST_CDWID_16 (1 << 19)
+#define CNTL_ST_CDWID_18 (1 << 20)
+#define CNTL_ST_CDWID_24 ((1 << 19)|(1 << 20))
+#define CNTL_ST_CEAEN (1 << 21)
+#define CNTL_ST_LCDBPP24_PACKED (6 << 1)
+
enum {
/* individual formats */
CLCD_CAP_RGB444 = (1 << 0),
@@ -179,11 +190,38 @@ struct clcd_board {
struct amba_device;
struct clk;
+/**
+ * struct clcd_vendor_data - holds hardware (IP-block) vendor-specific
+ * variant information
+ *
+ * @clock_timregs: the CLCD needs to be clocked when accessing the
+ * timer registers, or the hardware will hang.
+ * @packed_24_bit_pixels: this variant supports 24bit packed pixel data,
+ * so that RGB accesses 3 bytes at a time, not just on even 32bit
+ * boundaries, packing the pixel data in memory. ST Microelectronics
+ * have this.
+ * @st_bitmux_control: ST Microelectronics have implemented output
+ * bit line multiplexing into the CLCD control register. This indicates
+ * that we need to use this.
+ * @init_board: custom board init function for this variant
+ * @init_panel: custom panel init function for this variant
+ */
+struct clcd_vendor_data {
+ bool clock_timregs;
+ bool packed_24_bit_pixels;
+ bool st_bitmux_control;
+ int (*init_board)(struct amba_device *adev,
+ struct clcd_board *board);
+ int (*init_panel)(struct clcd_fb *fb,
+ struct device_node *panel);
+};
+
/* this data structure describes each frame buffer device we find */
struct clcd_fb {
struct fb_info fb;
struct amba_device *dev;
struct clk *clk;
+ struct clcd_vendor_data *vendor;
struct clcd_panel *panel;
struct clcd_board *board;
void *board_data;
@@ -285,6 +323,10 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
else
val |= CNTL_LCDBPP16_444;
break;
+ case 24:
+ /* Modified variant supporting 24 bit packed pixels */
+ val |= CNTL_ST_LCDBPP24_PACKED;
+ break;
case 32:
val |= CNTL_LCDBPP24;
break;
--
2.4.11
next prev parent reply other threads:[~2016-06-16 9:36 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-16 9:36 [PATCH 0/6] CLCD support for Nomadik and Versatile series Linus Walleij
2016-06-16 9:36 ` [PATCH 1/6] video: ARM CLCD: backlight support for OF Linus Walleij
2016-06-16 9:36 ` [PATCH 2/6] video: ARM CLCD: support DT signal inversion flags Linus Walleij
2016-06-16 9:36 ` [PATCH 3/6] video: ARM CLCD: support pads connected in reverse order Linus Walleij
2016-06-16 9:36 ` Linus Walleij [this message]
2016-06-16 9:36 ` [PATCH 5/6] video: ARM CLCD: add special board and panel hooks for Nomadik Linus Walleij
2016-06-16 9:36 ` [PATCH 6/6] video: ARM CLCD: add special panel hook for Versatiles Linus Walleij
2016-07-04 12:41 ` [PATCH 0/6] CLCD support for Nomadik and Versatile series Linus Walleij
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1466069778-16087-5-git-send-email-linus.walleij@linaro.org \
--to=linus.walleij@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).