[v5,1/2] video: ARM CLCD: Add DT support

Message ID 1394036606-17784-1-git-send-email-pawel.moll@arm.com
State New
Headers show

Commit Message

Pawel Moll March 5, 2014, 4:23 p.m.
This patch adds basic DT bindings for the PL11x CLCD cells
and make their fbdev driver use them.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
Changes since v4:
- simplified the pads description property and made it optional

Changes since v3:
- changed wording and order of interrupt-names and interrupts
  properties documentation
- changed wording of arm,pl11x,framebuffer-base property
  documentation
- cleaned up binding documentation indentation

Changes since v2:
- replaced video-ram phandle with arm,pl11x,framebuffer-base
- replaced panel-* properties with arm,pl11x,panel-data-pads
- replaced max-framebuffer-size with max-memory-bandwidth
- modified clcdfb_of_init_tft_panel() to use the pads
  data and take differences between PL110 and PL110 into
  account

Changes since v1:
- minor code cleanups as suggested by Sylwester Nawrocki

 .../devicetree/bindings/video/arm,pl11x.txt        |  83 ++++++++
 drivers/video/Kconfig                              |   1 +
 drivers/video/amba-clcd.c                          | 219 +++++++++++++++++++++
 3 files changed, 303 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/arm,pl11x.txt

Comments

Tomi Valkeinen March 6, 2014, 10:21 a.m. | #1
Hi Pawel,

On 05/03/14 18:23, Pawel Moll wrote:
> This patch adds basic DT bindings for the PL11x CLCD cells
> and make their fbdev driver use them.

Is this an old HW, and presumably there won't be new users for it? If
yes, this is probably fine. If not, you might want to look at the video
ports and endpoints, which is used by at least three not-yet-merged series:

[PATCHv3 00/41] OMAPDSS: DT support v3
[PATCH v5 00/11] imx-drm dt bindings
[RFC PATCH v2 00/21] Add DSI display support for Exynos based boards

Using bindings like that would be more future proof, even if the current
driver doesn't use them.

 Tomi
Pawel Moll March 6, 2014, 3:23 p.m. | #2
On Thu, 2014-03-06 at 10:21 +0000, Tomi Valkeinen wrote:
> Is this an old HW, and presumably there won't be new users for it? If
> yes, this is probably fine. 

There is a DRM driver in the works, actually...

> If not, you might want to look at the video
> ports and endpoints, which is used by at least three not-yet-merged series:
> 
> [PATCHv3 00/41] OMAPDSS: DT support v3
> [PATCH v5 00/11] imx-drm dt bindings
> [RFC PATCH v2 00/21] Add DSI display support for Exynos based boards
> 
> Using bindings like that would be more future proof, even if the current
> driver doesn't use them.

... and this makes me try to get out of its way. In other words, I fully
agree with you, but I don't think this applies to this particular patch,
as I'm not even trying to represent the display pipeline. The (optional)
"display-timings" sub-node has been "borrowed" from other older drivers
and can be easily deprecated in the future, replaced by standard ones
(whatever final shape they will take :-). All other extra properties are
CLCD-specific and orthogonal.

Pawel

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tomi Valkeinen March 7, 2014, 11:35 a.m. | #3
On 06/03/14 17:23, Pawel Moll wrote:
> On Thu, 2014-03-06 at 10:21 +0000, Tomi Valkeinen wrote:
>> Is this an old HW, and presumably there won't be new users for it? If
>> yes, this is probably fine. 
> 
> There is a DRM driver in the works, actually...
> 
>> If not, you might want to look at the video
>> ports and endpoints, which is used by at least three not-yet-merged series:
>>
>> [PATCHv3 00/41] OMAPDSS: DT support v3
>> [PATCH v5 00/11] imx-drm dt bindings
>> [RFC PATCH v2 00/21] Add DSI display support for Exynos based boards
>>
>> Using bindings like that would be more future proof, even if the current
>> driver doesn't use them.
> 
> ... and this makes me try to get out of its way. In other words, I fully
> agree with you, but I don't think this applies to this particular patch,
> as I'm not even trying to represent the display pipeline. The (optional)

Right, you are not, at the moment. My point was, if the driver is
extended later to support pipelines, or common panel/encoder drivers,
you (most likely) need to have similar bindings than the other people use.

Note that the same DT bindings you add here should also work for the DRM
driver in the future. So, in fact, the question is extended to: will the
fbdev or drm driver support common panels/encoders?

 Tomi
Pawel Moll March 10, 2014, 12:09 p.m. | #4
On Fri, 2014-03-07 at 11:35 +0000, Tomi Valkeinen wrote:
> > ... and this makes me try to get out of its way. In other words, I fully
> > agree with you, but I don't think this applies to this particular patch,
> > as I'm not even trying to represent the display pipeline. The (optional)
> 
> Right, you are not, at the moment. My point was, if the driver is
> extended later to support pipelines, or common panel/encoder drivers,
> you (most likely) need to have similar bindings than the other people use.

No argument here.

> Note that the same DT bindings you add here should also work for the DRM
> driver in the future. So, in fact, the question is extended to: will the
> fbdev 

No, I don't think so. It's a end of line for it, I believe. From my
personal point of view the main goal is to fill the last gap between DT
and non-DT support on one of the Versatile Express boards - CLCD works
fine when booted with ATAGs, doesn't work when booted with DT. It looks
bad.

> or drm driver support common panels/encoders?

I would hope so, yes. VE display pipeline is quite complex (more than I
would hope ;-) so to implement KMS in a proper way (with hotplugging,
bells and whistles) it will have to know more than now. But it's out of
scope for me.

Pawel

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tomi Valkeinen March 10, 2014, 12:23 p.m. | #5
On 10/03/14 14:09, Pawel Moll wrote:

>> Note that the same DT bindings you add here should also work for the DRM
>> driver in the future. So, in fact, the question is extended to: will the
>> fbdev 
> 
> No, I don't think so. It's a end of line for it, I believe. From my
> personal point of view the main goal is to fill the last gap between DT
> and non-DT support on one of the Versatile Express boards - CLCD works
> fine when booted with ATAGs, doesn't work when booted with DT. It looks
> bad.

The DT describes the hardware, and there should be only one description
of it, no matter what the used SW is. I see compatible = "arm,pl111" in
the dts. PL111 is the LCD controller, right? What will the DRM driver
use, then, if the "arm,pl111" DT data is designed to work only for the
fbdev?

 Tomi
Linus Walleij March 13, 2014, 9:30 a.m. | #6
On Thu, Mar 6, 2014 at 11:21 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> Hi Pawel,
>
> On 05/03/14 18:23, Pawel Moll wrote:
>> This patch adds basic DT bindings for the PL11x CLCD cells
>> and make their fbdev driver use them.
>
> Is this an old HW, and presumably there won't be new users for it?

AFAICT ARM really like to re-synthesize this piece of HW in every
new reference design they make. Plus a number of manufacturers
have used it in elder systems.

> If
> yes, this is probably fine. If not, you might want to look at the video
> ports and endpoints, which is used by at least three not-yet-merged series:
>
> [PATCHv3 00/41] OMAPDSS: DT support v3
> [PATCH v5 00/11] imx-drm dt bindings
> [RFC PATCH v2 00/21] Add DSI display support for Exynos based boards
>
> Using bindings like that would be more future proof, even if the current
> driver doesn't use them.

I take it that it shouldn't matter if the driver is for framebuffer or
DRM (as was implied by some answer here) the hardware
description should be the same no matter what, so the more
furture-proof the better.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pawel Moll March 13, 2014, 11:43 a.m. | #7
On Thu, 2014-03-13 at 09:30 +0000, Linus Walleij wrote:
> On Thu, Mar 6, 2014 at 11:21 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> > On 05/03/14 18:23, Pawel Moll wrote:
> >> This patch adds basic DT bindings for the PL11x CLCD cells
> >> and make their fbdev driver use them.
> >
> > Is this an old HW, and presumably there won't be new users for it?
> 
> AFAICT ARM really like to re-synthesize this piece of HW in every
> new reference design they make. 

Not for long now, hopefully...

> > If
> > yes, this is probably fine. If not, you might want to look at the video
> > ports and endpoints, which is used by at least three not-yet-merged series:
> >
> > [PATCHv3 00/41] OMAPDSS: DT support v3
> > [PATCH v5 00/11] imx-drm dt bindings
> > [RFC PATCH v2 00/21] Add DSI display support for Exynos based boards
> >
> > Using bindings like that would be more future proof, even if the current
> > driver doesn't use them.
> 
> I take it that it shouldn't matter if the driver is for framebuffer or
> DRM (as was implied by some answer here) the hardware
> description should be the same no matter what, so the more
> furture-proof the better.

Again, no argument here - the clcd-specific properties will be of use
whatever happens in the future (the "immediate" display timing subnode
is optional and is cloned from other existing bindings, so no new
problem is introduced here). I'm just shying away from the discussions
on generic display (or CDF or video or whatever) bindings. Call me
coward if you wish (maybe just tired to death with this subject ;-)

Pawel

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Russell King - ARM Linux March 13, 2014, 12:01 p.m. | #8
On Mon, Mar 10, 2014 at 02:23:21PM +0200, Tomi Valkeinen wrote:
> On 10/03/14 14:09, Pawel Moll wrote:
> 
> >> Note that the same DT bindings you add here should also work for the DRM
> >> driver in the future. So, in fact, the question is extended to: will the
> >> fbdev 
> > 
> > No, I don't think so. It's a end of line for it, I believe. From my
> > personal point of view the main goal is to fill the last gap between DT
> > and non-DT support on one of the Versatile Express boards - CLCD works
> > fine when booted with ATAGs, doesn't work when booted with DT. It looks
> > bad.
> 
> The DT describes the hardware, and there should be only one description
> of it, no matter what the used SW is. I see compatible = "arm,pl111" in
> the dts. PL111 is the LCD controller, right? What will the DRM driver
> use, then, if the "arm,pl111" DT data is designed to work only for the
> fbdev?

If we could move forward with things like DT bindings for DRM (which
seems impossible) then we might be able to move forward with a proper
DT implementation for componentised video systems which would solve
this as you'd have the pl111 as just a CRTC component in a larger
subsystem representation which included things like encoders and
connectors - even for something as simple as the Versatile Express
boards.

These boards have a DVI connector which offers analogue (and probably
digital) output.  Previous boards like Versatile and Integrator have
offered VGA output and a connector for various LCD panels (sometimes
the connected LCD panel is identified via a set of GPIOs.)

So, going ahead with some bindings which include stuff like timing
information in a pl111 node seems wrong and boxes us in if we're going
to start representing connectors as well - as the timing should be part
of the panel node or similar.

So basically all movement on display subsystem DT representations is
now blocked because no one can agree how they should be represented in
a decent way.

Maybe board files were much better than this frigging DT crap.
Pawel Moll March 13, 2014, 1:12 p.m. | #9
On Mon, 2014-03-10 at 12:23 +0000, Tomi Valkeinen wrote:
> The DT describes the hardware, and there should be only one description
> of it, no matter what the used SW is. I see compatible = "arm,pl111" in
> the dts. PL111 is the LCD controller, right? 

Correct.

> What will the DRM driver
> use, then, 

Exactly the same properties, plus (hopefully) the generic display data,
when (if) ready.

> if the "arm,pl111" DT data is designed to work only for the
> fbdev?

The binding I proposed is *not* designed to work only with the fbdev
driver, no. That's what I was trying to say all way long, if I failed -
apologies.

So let me say it again: with the exception display timings subnode, all
other properties will be important for the DRM scan out driver as well.
As to the display timings, being optional can be easily marked as
deprecated and replaced with the proper solution.

Now, if you find any other property I proposed being non generic enough
(ie. fbdev-specific), I will happily discuss it. Once you get generic
display bindings in place, I will gladly do all that will be required to
make CLCD driver(s) use them. But I will rather drop and forget this
patch completely that get dragged into another
"display/video/CDF/DRM/whatever" discussion. Hope I made myself clear.

Pawel

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/Documentation/devicetree/bindings/video/arm,pl11x.txt b/Documentation/devicetree/bindings/video/arm,pl11x.txt
new file mode 100644
index 0000000..75da7b7
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/arm,pl11x.txt
@@ -0,0 +1,83 @@ 
+* ARM PrimeCell Color LCD Controller PL110/PL111
+
+See also Documentation/devicetree/bindings/arm/primecell.txt
+
+Required properties:
+
+- compatible: must be one of:
+	"arm,pl110", "arm,primecell"
+	"arm,pl111", "arm,primecell"
+
+- reg: base address and size of the control registers block
+
+- interrupt-names: either the single entry "combined" representing a
+	combined interrupt output (CLCDINTR), or the four entries
+	"mbe", "vcomp", "lnbu", "fuf" representing the individual
+	CLCDMBEINTR, CLCDVCOMPINTR, CLCDLNBUINTR, CLCDFUFINTR interrupts
+
+- interrupts: contains an interrupt specifier for each entry in
+	interrupt-names
+
+- clocks-names: should contain "clcdclk" and "apb_pclk"
+
+- clocks: contains phandle and clock specifier pairs for the entries
+	in the clock-names property. See
+	Documentation/devicetree/binding/clock/clock-bindings.txt
+
+Optional properties:
+
+- arm,pl11x,framebuffer-base: a pair of two 32-bit values, address and size,
+	defining the framebuffer that must be used; if not present, the
+	framebuffer may be located anywhere in the memory
+
+- arm,pl11x,tft-r0g0b0-pads: when connected to a TFT panel, an array of three
+	32-bit values, defining the way CLD pads are wired up; this implicitly
+	defines available color modes, for example:
+	- PL111 TFT 4:4:4 panel:
+		arm,pl11x,tft-r0g0b0-pads = <4 15 20>;
+	- PL110 TFT (1:)5:5:5 panel:
+		arm,pl11x,tft-r0g0b0-pads = <1 7 13>;
+	- PL111 TFT (1:)5:5:5 panel:
+		arm,pl11x,tft-r0g0b0-pads = <3 11 19>;
+	- PL111 TFT 5:6:5 panel:
+		arm,pl11x,tft-r0g0b0-pads = <3 10 19>;
+	- PL110 and PL111 TFT 8:8:8 panel:
+		arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+	- PL110 and PL111 TFT 8:8:8 panel, R & B components swapped:
+		arm,pl11x,tft-r0g0b0-pads = <16 8 0>;
+
+- max-memory-bandwidth: maximum bandwidth in bytes per second that the
+	cell's memory interface can handle
+
+- display-timings: standard display timings sub-node, defining possible
+	video modes of a connected panel; for details see
+	Documentation/devicetree/bindings/video/display-timing.txt
+
+Example:
+
+	clcd@1f0000 {
+		compatible = "arm,pl111", "arm,primecell";
+		reg = <0x1f0000 0x1000>;
+		interrupt-names = "combined";
+		interrupts = <14>;
+		clock-names = "clcdclk", "apb_pclk";
+		clocks = <&v2m_oscclk1>, <&smbclk>;
+
+		arm,pl11x,framebuffer-base = <0x18000000 0x00800000>;
+		arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+		max-memory-bandwidth = <36864000>; /* bps, 640x480@60 16bpp */
+		display-timings {
+			native-mode = <&v2m_clcd_timing0>;
+			v2m_clcd_timing0: vga {
+				clock-frequency = <25175000>;
+				hactive = <640>;
+				hback-porch = <40>;
+				hfront-porch = <24>;
+				hsync-len = <96>;
+				vactive = <480>;
+				vback-porch = <32>;
+				vfront-porch = <11>;
+				vsync-len = <2>;
+			};
+		};
+	};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index dade5b7..c1d25c9 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -317,6 +317,7 @@  config FB_ARMCLCD
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	select VIDEOMODE_HELPERS if OF
 	help
 	  This framebuffer device driver is for the ARM PrimeCell PL110
 	  Colour LCD controller.  ARM PrimeCells provide the building
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 14d6b37..5a165dd 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -26,6 +26,11 @@ 
 #include <linux/amba/clcd.h>
 #include <linux/clk.h>
 #include <linux/hardirq.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <video/of_display_timing.h>
+#include <video/of_videomode.h>
 
 #include <asm/sizes.h>
 
@@ -543,6 +548,217 @@  static int clcdfb_register(struct clcd_fb *fb)
 	return ret;
 }
 
+#ifdef CONFIG_OF
+static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
+{
+	static struct {
+		unsigned int part;
+		u32 r0, g0, b0;
+		u32 caps;
+	} panels[] = {
+		{ 0x110, 1,  7, 13, CLCD_CAP_5551 },
+		{ 0x110, 0,  8, 16, CLCD_CAP_888 },
+		{ 0x111, 4, 14, 20, CLCD_CAP_444 },
+		{ 0x111, 3, 11, 19, CLCD_CAP_444 | CLCD_CAP_5551 },
+		{ 0x111, 3, 10, 19, CLCD_CAP_444 | CLCD_CAP_5551 |
+				    CLCD_CAP_565 },
+		{ 0x111, 0,  8, 16, CLCD_CAP_444 | CLCD_CAP_5551 |
+				    CLCD_CAP_565 | CLCD_CAP_888 },
+	};
+	int i;
+
+	/* Bypass pixel clock divider, data output on the falling edge */
+	fb->panel->tim2 = TIM2_BCD | TIM2_IPC;
+
+	/* TFT display, vert. comp. interrupt at the start of the back porch */
+	fb->panel->cntl |= CNTL_LCDTFT | CNTL_LCDVCOMP(1);
+
+	fb->panel->caps = 0;
+
+	/* Match the setup with known variants */
+	for (i = 0; i < ARRAY_SIZE(panels) && !fb->panel->caps; i++) {
+		if (amba_part(fb->dev) != panels[i].part)
+			continue;
+		if (g0 != panels[i].g0)
+			continue;
+		if (r0 == panels[i].r0 && b0 == panels[i].b0)
+			fb->panel->caps = panels[i].caps & CLCD_CAP_RGB;
+		if (r0 == panels[i].b0 && b0 == panels[i].r0)
+			fb->panel->caps = panels[i].caps & CLCD_CAP_BGR;
+	}
+
+	return fb->panel->caps ? 0 : -EINVAL;
+}
+
+static int clcdfb_snprintf_mode(char *buf, int size, struct fb_videomode *mode)
+{
+	return snprintf(buf, size, "%ux%u@%u", mode->xres, mode->yres,
+			mode->refresh);
+}
+
+static int clcdfb_of_init_display(struct clcd_fb *fb)
+{
+	struct device_node *node = fb->dev->dev.of_node;
+	int err, len;
+	char *mode_name;
+	u32 max_bandwidth;
+	u32 tft_r0b0g0[3];
+
+	fb->panel = devm_kzalloc(&fb->dev->dev, sizeof(*fb->panel), GFP_KERNEL);
+	if (!fb->panel)
+		return -ENOMEM;
+
+	err = of_get_fb_videomode(node, &fb->panel->mode, OF_USE_NATIVE_MODE);
+	if (err)
+		return err;
+
+	len = clcdfb_snprintf_mode(NULL, 0, &fb->panel->mode);
+	mode_name = devm_kzalloc(&fb->dev->dev, len + 1, GFP_KERNEL);
+	clcdfb_snprintf_mode(mode_name, len + 1, &fb->panel->mode);
+	fb->panel->mode.name = mode_name;
+
+	err = of_property_read_u32(node, "max-memory-bandwidth",
+			&max_bandwidth);
+	if (!err)
+		fb->panel->bpp = 8 * max_bandwidth / (fb->panel->mode.xres *
+				fb->panel->mode.yres * fb->panel->mode.refresh);
+	else
+		fb->panel->bpp = 32;
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	fb->panel->cntl |= CNTL_BEBO;
+#endif
+	fb->panel->width = -1;
+	fb->panel->height = -1;
+
+	if (of_property_read_u32_array(node, "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]);
+
+	return -ENOENT;
+}
+
+static int clcdfb_of_vram_setup(struct clcd_fb *fb)
+{
+	int err;
+	u32 values[2];
+	phys_addr_t phys_base;
+	size_t size;
+
+	err = clcdfb_of_init_display(fb);
+	if (err)
+		return err;
+
+	err = of_property_read_u32_array(fb->dev->dev.of_node,
+			"arm,pl11x,framebuffer-base",
+			values, ARRAY_SIZE(values));
+	if (err)
+		return err;
+
+	phys_base = values[0];
+	size = values[1];
+
+	fb->fb.screen_base = ioremap(phys_base, size);
+	if (!fb->fb.screen_base)
+		return -ENOMEM;
+
+	fb->fb.fix.smem_start = phys_base;
+	fb->fb.fix.smem_len = size;
+
+	return 0;
+}
+
+static int clcdfb_of_vram_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	unsigned long off, user_size, kernel_size;
+
+
+	off = vma->vm_pgoff << PAGE_SHIFT;
+	user_size = vma->vm_end - vma->vm_start;
+	kernel_size = fb->fb.fix.smem_len;
+
+	if (off >= kernel_size || user_size > (kernel_size - off))
+		return -ENXIO;
+
+	return remap_pfn_range(vma, vma->vm_start,
+			__phys_to_pfn(fb->fb.fix.smem_start) + vma->vm_pgoff,
+			user_size,
+			pgprot_writecombine(vma->vm_page_prot));
+}
+
+static void clcdfb_of_vram_remove(struct clcd_fb *fb)
+{
+	iounmap(fb->fb.screen_base);
+}
+
+static int clcdfb_of_dma_setup(struct clcd_fb *fb)
+{
+	unsigned long framesize;
+	dma_addr_t dma;
+	int err;
+
+	err = clcdfb_of_init_display(fb);
+	if (err)
+		return err;
+
+	framesize = fb->panel->mode.xres * fb->panel->mode.yres *
+			fb->panel->bpp / 8;
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
+			&dma, GFP_KERNEL);
+	if (!fb->fb.screen_base)
+		return -ENOMEM;
+
+	fb->fb.fix.smem_start = dma;
+	fb->fb.fix.smem_len = framesize;
+
+	return 0;
+}
+
+static int clcdfb_of_dma_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	return dma_mmap_writecombine(&fb->dev->dev, vma, fb->fb.screen_base,
+			fb->fb.fix.smem_start, fb->fb.fix.smem_len);
+}
+
+static void clcdfb_of_dma_remove(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+			fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev)
+{
+	struct clcd_board *board = devm_kzalloc(&dev->dev, sizeof(*board),
+			GFP_KERNEL);
+	struct device_node *node = dev->dev.of_node;
+
+	if (!board)
+		return NULL;
+
+	board->name = of_node_full_name(node);
+	board->caps = CLCD_CAP_ALL;
+	board->check = clcdfb_check;
+	board->decode = clcdfb_decode;
+	if (of_find_property(node, "arm,pl11x,framebuffer-base", NULL)) {
+		board->setup = clcdfb_of_vram_setup;
+		board->mmap = clcdfb_of_vram_mmap;
+		board->remove = clcdfb_of_vram_remove;
+	} else {
+		board->setup = clcdfb_of_dma_setup;
+		board->mmap = clcdfb_of_dma_mmap;
+		board->remove = clcdfb_of_dma_remove;
+	}
+
+	return board;
+}
+#else
+static struct clcd_board *clcdfb_of_get_board(struct amba_dev *dev)
+{
+	return NULL;
+}
+#endif
+
 static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct clcd_board *board = dev_get_platdata(&dev->dev);
@@ -550,6 +766,9 @@  static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
 	int ret;
 
 	if (!board)
+		board = clcdfb_of_get_board(dev);
+
+	if (!board)
 		return -EINVAL;
 
 	ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));