Re: [RFC PATCH 1/3] amba-clcd: Add Device Tree support to amba-clcd driver

Started by Ryan Harkin on Sep 21, 2012 · 2 messages from 2 authors · Last reply Sep 21, 2012

open the first message on its own page

Message details and related content
Hi Liviu,

Thanks for your feedback.  All good stuff...

On 20 September 2012 11:24, Liviu Dudau [off-list ref] wrote:
On Wed, Sep 19, 2012 at 05:04:24PM +0100, Ryan Harkin wrote:
quoted
Add support to parse the display configuration from device tree.

If the board does not provide platform specific functions in the struct
clcd_board contained with the amba device info, then defaults are provided
by the driver.

The device tree configuration can either ask for a DMA setup or provide a
framebuffer address to be remapped into the driver.

Signed-off-by: Ryan Harkin <redacted>
---
 drivers/video/amba-clcd.c |  253 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 253 insertions(+)
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 0a2cce7..01dbad1 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -16,7 +16,10 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/memblock.h>
 #include <linux/mm.h>
+#include <linux/of.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
@@ -391,6 +394,19 @@ static int clcdfb_blank(int blank_mode, struct fb_info *info)
      }
      return 0;
 }
+int clcdfb_mmap_dma(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);

101 more quoted lines

I see what you mean.  I'm happy to swap them if there are no objections.

quoted
+     const char *string;
+     int count, i, ret = 0;
+
+     count = of_property_count_strings(node, name);
+     if (count >= 0)
+             for (i = 0; i < count; i++)
+                     if (of_property_read_string_index(node, name, i,
+                                     &string) = 0)
+                             ret |= parse_setting(lookup, string);
+     return ret;
+}
+
+int get_val(struct device_node *node, const char *string)
+{
+     u32 ret = 0;
+
+     if (of_property_read_u32(node, string, &ret))
+             ret = -1;
+     return ret;
+}
+
+struct clcd_panel *getPanel(struct device_node *node)
+{
+     static struct clcd_panel panel;
+
+     panel.mode.refresh      = get_val(node, "refresh");
+     panel.mode.xres         = get_val(node, "xres");
+     panel.mode.yres         = get_val(node, "yres");
+     panel.mode.pixclock     = get_val(node, "pixclock");
+     panel.mode.left_margin  = get_val(node, "left_margin");
+     panel.mode.right_margin = get_val(node, "right_margin");
+     panel.mode.upper_margin = get_val(node, "upper_margin");
+     panel.mode.lower_margin = get_val(node, "lower_margin");
+     panel.mode.hsync_len    = get_val(node, "hsync_len");
+     panel.mode.vsync_len    = get_val(node, "vsync_len");
+     panel.mode.sync         = get_val(node, "sync");
+     panel.bpp               = get_val(node, "bpp");
+     panel.width             = (signed short) get_val(node, "width");
+     panel.height            = (signed short) get_val(node, "height");

34 more quoted lines

Agree.

quoted
+static int clcdfb_dt_init(struct clcd_fb *fb)
+{
+     int err = 0;
+     struct device_node *node;
+     const char *mode;
+     dma_addr_t dma;
+     u32 use_dma;
+     const __be32 *prop;
+     int len, na, ns;
+     phys_addr_t fb_base, fb_size;
+
+     node = fb->dev->dev.of_node;
+     if (!node)
+             return -ENODEV;
+
+     na = of_n_addr_cells(node);
+     ns = of_n_size_cells(node);
+
+     if (WARN_ON(of_property_read_string(node, "mode", &mode)))
+             return -ENODEV;
+
+     fb->panel = clcdfb_get_panel(mode);
+     if (!fb->panel)
+             return -EINVAL;
+     fb->fb.fix.smem_len = fb->panel->mode.xres * fb->panel->mode.yres * 2;
+
+     if (of_property_read_u32(node, "use_dma", &use_dma))
I haven't seen any documentation for this property. What's the intended use?
Good point.  Sorry for my ignorance, but is there a place I should put
such documentation?

When the A9 CoreTile uses the on-tile CLCD controller, it can use DMA
to handle the framebuffer.  DMA is not available to the motherboard
CLCD controller.

I was trying to keep the properties simple, but they are more complex
than just the two settings: use_dma and framebuffer.  If use_dma is
specified, the framebuffer property is not used; in this case, the
framebuffer is allocated by the DMA framework and the framebuffer
property is ignored.  If use_dma is not present or is set to <0>, the
code uses the framebuffer property to specify the address.

quoted
+             use_dma = 0;
+     if (use_dma) {
+             fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev,
+                     fb->fb.fix.smem_len, &dma, GFP_KERNEL);
+             if (!fb->fb.screen_base) {
+                     pr_err("CLCD: unable to map framebuffer\n");
+                     err = -ENOMEM;
+             } else
+                     fb->fb.fix.smem_start   = dma;
+     } else {
+             prop = of_get_property(node, "framebuffer", &len);
+             if (WARN_ON(!prop || len < (na + ns) * sizeof(*prop)))
+                     return -EINVAL;
+             fb_base = of_read_number(prop, na);
+             fb_size = of_read_number(prop + na, ns);
+
+             if (memblock_remove(fb_base, fb_size) != 0)
+                     return -EINVAL;
+
+             fb->fb.fix.smem_start = fb_base;
+             fb->fb.screen_base = ioremap_wc(fb->fb.fix.smem_start, fb_size);
+     }
+     return err;
+}
+#endif /* CONFIG_OF */
+
 static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
 {
      struct clcd_board *board = dev->dev.platform_data;
      struct clcd_fb *fb;
      int ret;

+#ifdef CONFIG_OF
+     if (dev->dev.of_node) {
+             const __be32 *prop;
+             int len, na, ns;
+             phys_addr_t reg_base;
+
+             na = of_n_addr_cells(dev->dev.of_node);

45 more quoted lines

Message details and related content
On Fri, 2012-09-21 at 11:35 +0100, Ryan Harkin wrote:
Good point.  Sorry for my ignorance, but is there a place I should put
such documentation?
Documentation/devicetree/bindings/fb/amba-clcd.txt :-)
When the A9 CoreTile uses the on-tile CLCD controller, it can use DMA
to handle the framebuffer.  DMA is not available to the motherboard
CLCD controller.
Uh, you probably mean that the motherboard CLCD must use the specialised
video memory, while the one in the test chip would normally use a buffer
allocated via the DMA API...
I was trying to keep the properties simple, but they are more complex
than just the two settings: use_dma and framebuffer.  If use_dma is
specified, the framebuffer property is not used; in this case, the
framebuffer is allocated by the DMA framework and the framebuffer
property is ignored.  If use_dma is not present or is set to <0>, the
code uses the framebuffer property to specify the address.
I'm not sure if the "framebuffer" property is really needed, at least in
the form you have it there now. I think I know you where you get it from
- HDLCD driver, right? It was sort-of-needed there, because we had to
reserve memory for the framebuffer, because you couldn't allocate big
enough (8MB if I remember correctly) area using the DMA alloc function.
But now, with the CMA in place it should be possible, so I believe it's
not even necessary in that case. Simply speaking - if the driver is not
told what address to use, it should get the memory on its own.

Now, as to the motherboard CLCD... That's where you actually could use
this property in the way you have there, to enforce the address of the
video RAM as the framebuffer. But maybe it would be better to have a
phandle to the video RAM node?

Cheers!

Paweł

Keyboard shortcuts
hback out one level
jnext message in thread / next series-diff position
kprevious message in thread / previous series-diff position
ldrill in
Escclose help / fold thread tree
?toggle this help