Re: [PATCH 1/2] video: ARM CLCD: Add DT support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Hi,

On 09/06/2013 07:23 PM, Pawel Moll wrote:
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@xxxxxxx>
---
  .../devicetree/bindings/video/arm,pl11x.txt        |  87 +++++++++
  drivers/video/Kconfig                              |   1 +
  drivers/video/amba-clcd.c                          | 214 +++++++++++++++++++++
  3 files changed, 302 insertions(+)
  create mode 100644 Documentation/devicetree/bindings/video/arm,pl11x.txt

diff --git a/Documentation/devicetree/bindings/video/arm,pl11x.txt b/Documentation/devicetree/bindings/video/arm,pl11x.txt
new file mode 100644
index 0000000..178aebb
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/arm,pl11x.txt
@@ -0,0 +1,87 @@
+* ARM PrimeCell Color LCD Controller (CLCD) PL110/PL111

nit: Shouldn't the abbreviation be CLCDC ?

+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
+- interrupts: either a single interrupt specifier representing the
+		combined interrupt output (CLCDINTR) or an array of
+		four interrupt specifiers for CLCDMBEINTR,
+		CLCDVCOMPINTR, CLCDLNBUINTR, CLCDFUFINTR; in the
+		latter case interrupt names must be specified
+		(see below)
+- interrupt-names: when four interrupts are specified, their names:
+			"mbe", "vcomp", "lnbu", "fuf"
+			must be specified in order respective to the
+			interrupt specifiers
+- clocks: contains phandle and clock specifier pairs for the entries
+		in the clock-names property. See
+		Documentation/devicetree/binding/clock/clock-bindings.txt
+- clocks names: should contain "clcdclk" and "apb_pclk"
+
+Optional properties:
+
+- video-ram: phandle to a node describing specialized video memory
+		(that is *not* described in the top level "memory" node)
+                that must be used as a framebuffer, eg. due to restrictions
+		of the system interconnect; the node must contain a
+		standard reg property describing the address and the size
+		of the memory area

It seems the "specialized video memory" is described by some vendor specific
DT binding ? Is it documented ? It sounds like you are unnecessarily repeating
the memory node details here.

Perhaps this binding/driver should use the common reserved memory bindings,
see thread http://www.spinics.net/lists/devicetree/msg02880.html

+- max-framebuffer-size: maximum size in bytes of the framebuffer the
+			system can handle, eg. in terms of available
+			memory bandwidth
+
+In the simplest case of a display panel being connected directly to the
+CLCD, it can be described in the node:
+
+- panel-dimensions: (optional) array of two numbers (width and height)
+			describing physical dimension in mm of the panel
+- panel-type: (required) must be "tft" or "stn", defines panel type
+- panel-tft-interface: (for "tft" panel type) array of 3 numbers defining
+			widths in bits of the R, G and B components
+- panel-tft-rb-swapped: (for "tft" panel type) if present means that
+			the R&  B components are swapped on the board
+- panel-stn-color: (for "stn" panel type) if present means that
+			the panel is a colour STN display, if missing
+			is a monochrome display
+- panel-stn-dual: (for "stn" panel type) if present means that there
+			are two STN displays connected
+- panel-stn-4bit: (for monochrome "stn" panel) if present means
+			that the monochrome display is connected
+			via 4 bit-wide interface

Are this vendor specific or common properties ? Shouldn't those be prefixed
with the vendor name ?

Anyway I think we need an RFC to possibly standardize properties that are
common across multiple panels and have them listed in a common DT binding.

It sounds a bit disappointing that for same class devices there are being
introduced custom DT properties for each available device. For instance,
the first 3 properties above look like they could apply to various display
panels and controllers.

+- display-timings: standard display timings sub-node, see
+			Documentation/devicetree/bindings/video/display-timing.txt
+
+Example:
+
+			clcd@1f0000 {
+				compatible = "arm,pl111", "arm,primecell";
+				reg =<0x1f0000 0x1000>;
+				interrupts =<14>;
+				clocks =<&v2m_oscclk1>,<&smbclk>;
+				clock-names = "clcdclk", "apb_pclk";
+
+				video-ram =<&v2m_vram>;
+				max-framebuffer-size =<614400>; /* 640x480 16bpp */
+
+				panel-type = "tft";
+				panel-tft-interface =<8 8 8>;
+				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 4cf1e1d..375bf63 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -316,6 +316,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 0a2cce7..145ca5a 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -25,6 +25,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>

@@ -542,6 +547,212 @@ static int clcdfb_register(struct clcd_fb *fb)
  	return ret;
  }

+#ifdef CONFIG_OF
+static int clcdfb_of_get_tft_panel(struct device_node *node,
+		struct clcd_panel *panel)
+{
+	int err;
+	u32 rgb[3];
+	int r, g, b;

Couldn't these be 'unsigned int' ?

+	err = of_property_read_u32_array(node, "panel-tft-interface", rgb, 3);
+	if (err)
+		return err;
+
+	r = rgb[0];
+	g = rgb[1];
+	b = rgb[2];
+
+	/* Bypass pixel clock divider, data output on the falling edge */
+	panel->tim2 = TIM2_BCD | TIM2_IPC;
+
+	/* TFT display, vert. comp. interrupt at the start of the back porch */
+	panel->cntl |= CNTL_LCDTFT | CNTL_LCDVCOMP(1);
+
+	if (r>= 4&&  g>= 4&&  b>= 4)
+		panel->caps |= CLCD_CAP_444;
+	if (r>= 5&&  g>= 5&&  b>= 5)
+		panel->caps |= CLCD_CAP_5551;
+	if (r>= 5&&  g>= 6&&  b>= 5)
+		panel->caps |= CLCD_CAP_565;
+	if (r>= 8&&  g>= 8&&  b>= 8)
+		panel->caps |= CLCD_CAP_888;
+
+	if (of_get_property(node, "panel-tft-rb-swapped", NULL))
+		panel->caps&= ~CLCD_CAP_RGB;
+	else
+		panel->caps&= ~CLCD_CAP_BGR;
+
+	return 0;
+}
+
+static int clcdfb_of_init_display(struct clcd_fb *fb)
+{
+	struct device_node *node = fb->dev->dev.of_node;
+	u32 max_size;
+	u32 dimensions[2];
+	char *mode_name;
+	int len, err;
+	const char *panel_type;
+
+	fb->panel = devm_kzalloc(&fb->dev->dev, sizeof(*fb->panel), GFP_KERNEL);
+	if (!fb->panel)
+		return -ENOMEM;
+
+	err = of_get_fb_videomode(fb->dev->dev.of_node,&fb->panel->mode,

'node' could be reused here.

+			OF_USE_NATIVE_MODE);
+	if (err)
+		return err;
+
+	len = snprintf(NULL, 0, "%ux%u@%u", fb->panel->mode.xres,
+			fb->panel->mode.yres, fb->panel->mode.refresh);
+	mode_name = devm_kzalloc(&fb->dev->dev, len + 1, GFP_KERNEL);
+	snprintf(mode_name, len + 1, "%ux%u@%u", fb->panel->mode.xres,
+			fb->panel->mode.yres, fb->panel->mode.refresh);

Don't you want to just use kasprintf() here instead and free mode_name
manually in the remove() callback ?

+	fb->panel->mode.name = mode_name;
+
+	err = of_property_read_u32(node, "max-framebuffer-size",&max_size);
+	if (!err)
+		fb->panel->bpp = max_size / (fb->panel->mode.xres *
+				fb->panel->mode.yres) * 8;
+	else
+		fb->panel->bpp = 32;
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	fb->panel->cntl |= CNTL_BEBO;
+#endif
+
+	if (of_property_read_u32_array(node, "panel-dimensions",
+			dimensions, 2) == 0) {
+		fb->panel->width = dimensions[0];
+		fb->panel->height = dimensions[1];
+	} else {
+		fb->panel->width = -1;
+		fb->panel->height = -1;
+	}
+
+	panel_type = of_get_property(node, "panel-type",&len);
+	if (strncmp(panel_type, "tft", len) == 0)
+		return clcdfb_of_get_tft_panel(node, fb->panel);
+	else
+		return -EINVAL;
+}
+
+static int clcdfb_of_vram_setup(struct clcd_fb *fb)
+{
+	const __be32 *prop = of_get_property(fb->dev->dev.of_node, "video-ram",
+			NULL);
+	struct device_node *node = of_find_node_by_phandle(be32_to_cpup(prop));

This looks like open coding function of_parse_phandle(), why not just:

	struct device_node *node = of_parse_phandle(fb->dev->dev.of_node,
					"video-ram", 0);
?
+	u64 size;
+	int err;
+
+	if (!node)
+		return -ENODEV;
+
+	err = clcdfb_of_init_display(fb);
+	if (err)
+		return err;
+
+	fb->fb.screen_base = of_iomap(node, 0);
+	if (!fb->fb.screen_base)
+		return -ENOMEM;
+
+	fb->fb.fix.smem_start = of_translate_address(node,
+			of_get_address(node, 0,&size, NULL));
+	fb->fb.fix.smem_len = size;
+
+	return 0;
+}

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




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux