Add LCD register abstraction for MIPI DCS like controllers. This
hides LCD controller interface implementation details.
When built with debugfs, the register is available to userspace.

Signed-off-by: Noralf Trønnes <nor...@tronnes.org>
---
 drivers/staging/fbtft/Kconfig                 |   2 +
 drivers/staging/fbtft/Makefile                |   6 +-
 drivers/staging/fbtft/lcdreg/Kconfig          |   4 +
 drivers/staging/fbtft/lcdreg/Makefile         |   3 +
 drivers/staging/fbtft/lcdreg/internal.h       |   9 +
 drivers/staging/fbtft/lcdreg/lcdreg-core.c    | 187 ++++++++++++++++++
 drivers/staging/fbtft/lcdreg/lcdreg-debugfs.c | 272 ++++++++++++++++++++++++++
 drivers/staging/fbtft/lcdreg/lcdreg.h         | 151 ++++++++++++++
 8 files changed, 632 insertions(+), 2 deletions(-)
 create mode 100644 drivers/staging/fbtft/lcdreg/Kconfig
 create mode 100644 drivers/staging/fbtft/lcdreg/Makefile
 create mode 100644 drivers/staging/fbtft/lcdreg/internal.h
 create mode 100644 drivers/staging/fbtft/lcdreg/lcdreg-core.c
 create mode 100644 drivers/staging/fbtft/lcdreg/lcdreg-debugfs.c
 create mode 100644 drivers/staging/fbtft/lcdreg/lcdreg.h

diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig
index 995a910..2d1490f 100644
--- a/drivers/staging/fbtft/Kconfig
+++ b/drivers/staging/fbtft/Kconfig
@@ -167,3 +167,5 @@ config FB_FLEX
 config FB_TFT_FBTFT_DEVICE
        tristate "Module to for adding FBTFT devices"
        depends on FB_TFT
+
+source "drivers/staging/fbtft/lcdreg/Kconfig"
diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile
index e773f0f..2769421 100644
--- a/drivers/staging/fbtft/Makefile
+++ b/drivers/staging/fbtft/Makefile
@@ -1,8 +1,10 @@
-# Core module
+# Core modules
 obj-$(CONFIG_FB_TFT)             += fbtft.o
 fbtft-y                          += fbtft-core.o fbtft-sysfs.o fbtft-bus.o 
fbtft-io.o
 
-# drivers
+obj-$(CONFIG_LCDREG)             += lcdreg/
+
+# Controller drivers
 obj-$(CONFIG_FB_TFT_AGM1264K_FL) += fb_agm1264k-fl.o
 obj-$(CONFIG_FB_TFT_BD663474)    += fb_bd663474.o
 obj-$(CONFIG_FB_TFT_HX8340BN)    += fb_hx8340bn.o
diff --git a/drivers/staging/fbtft/lcdreg/Kconfig 
b/drivers/staging/fbtft/lcdreg/Kconfig
new file mode 100644
index 0000000..ec0c097
--- /dev/null
+++ b/drivers/staging/fbtft/lcdreg/Kconfig
@@ -0,0 +1,4 @@
+config LCDREG
+       tristate
+       depends on GPIOLIB
+       default n
diff --git a/drivers/staging/fbtft/lcdreg/Makefile 
b/drivers/staging/fbtft/lcdreg/Makefile
new file mode 100644
index 0000000..c9ea774
--- /dev/null
+++ b/drivers/staging/fbtft/lcdreg/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_LCDREG)                   += lcdreg.o
+lcdreg-y                               += lcdreg-core.o
+lcdreg-$(CONFIG_DEBUG_FS)              += lcdreg-debugfs.o
diff --git a/drivers/staging/fbtft/lcdreg/internal.h 
b/drivers/staging/fbtft/lcdreg/internal.h
new file mode 100644
index 0000000..04035b9
--- /dev/null
+++ b/drivers/staging/fbtft/lcdreg/internal.h
@@ -0,0 +1,9 @@
+#include "lcdreg.h"
+
+#ifdef CONFIG_DEBUG_FS
+extern void lcdreg_debugfs_init(struct lcdreg *reg);
+extern void lcdreg_debugfs_exit(struct lcdreg *reg);
+#else
+static inline void lcdreg_debugfs_init(struct lcdreg *reg) { }
+static inline void lcdreg_debugfs_exit(struct lcdreg *reg) { }
+#endif
diff --git a/drivers/staging/fbtft/lcdreg/lcdreg-core.c 
b/drivers/staging/fbtft/lcdreg/lcdreg-core.c
new file mode 100644
index 0000000..4a1131c
--- /dev/null
+++ b/drivers/staging/fbtft/lcdreg/lcdreg-core.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2015 Noralf Trønnes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "internal.h"
+#include "lcdreg.h"
+
+/**
+ * Write to LCD register
+ *
+ * @reg: LCD register
+ * @regnr: Register number
+ * @transfer: Transfer to write
+ */
+int lcdreg_write(struct lcdreg *reg, unsigned regnr,
+                struct lcdreg_transfer *transfer)
+{
+       if (!transfer)
+               return -EINVAL;
+
+       if (!transfer->width)
+               transfer->width = reg->def_width;
+
+       dev_dbg(reg->dev,
+               "lcdreg_write: regnr=0x%02x, index=%u, count=%u, width=%u\n",
+               regnr, transfer->index, transfer->count, transfer->width);
+       lcdreg_dbg_transfer_buf(transfer);
+
+       return reg->write(reg, regnr, transfer);
+}
+EXPORT_SYMBOL(lcdreg_write);
+
+/**
+ * Write 32-bit wide buffer to LCD register
+ * @reg: lcdreg
+ * @regnr: Register number
+ * @buf: Buffer to write
+ * @count: Number of words to write
+ */
+int lcdreg_write_buf32(struct lcdreg *reg, unsigned regnr, const u32 *buf,
+                      unsigned count)
+{
+       struct lcdreg_transfer tr = {
+               .index = 1,
+               .width = reg->def_width,
+               .count = count,
+       };
+       int i, ret;
+
+       if (!buf)
+               return -EINVAL;
+
+       tr.buf = kmalloc_array(count, sizeof(*buf), GFP_KERNEL);
+       if (!tr.buf)
+               return -ENOMEM;
+
+       if (reg->def_width <= 8)
+               for (i = 0; i < tr.count; i++)
+                       ((u8 *)tr.buf)[i] = buf[i];
+       else
+               for (i = 0; i < tr.count; i++)
+                       ((u16 *)tr.buf)[i] = buf[i];
+       ret = lcdreg_write(reg, regnr, &tr);
+       kfree(tr.buf);
+
+       return ret;
+}
+EXPORT_SYMBOL(lcdreg_write_buf32);
+
+/**
+ * Read from LCD register
+ *
+ * @reg: LCD register
+ * @regnr: Register number
+ * @transfer: Transfer to read into
+ */
+int lcdreg_read(struct lcdreg *reg, unsigned regnr,
+               struct lcdreg_transfer *transfer)
+{
+       int ret;
+
+       if (!transfer)
+               return -EINVAL;
+
+       if (!transfer->width)
+               transfer->width = reg->def_width;
+
+       dev_dbg(reg->dev,
+               "lcdreg_read: regnr=0x%02x, index=%u, count=%u, width=%u\n",
+               regnr, transfer->index, transfer->count, transfer->width);
+
+       ret = reg->read(reg, regnr, transfer);
+
+       lcdreg_dbg_transfer_buf(transfer);
+
+       return ret;
+}
+EXPORT_SYMBOL(lcdreg_read);
+
+/**
+ * Read from LCD register into 32-bit wide buffer
+ * @reg: LCD register
+ * @regnr: Register number
+ * @buf: Buffer to read into
+ * @count: Number of words to read
+ */
+int lcdreg_readreg_buf32(struct lcdreg *reg, unsigned regnr, u32 *buf,
+                        unsigned count)
+{
+       struct lcdreg_transfer tr = {
+               .index = (reg->quirks & LCDREG_INDEX0_ON_READ) ? 0 : 1,
+               .count = count,
+       };
+       int i, ret;
+
+       if (!buf || !count)
+               return -EINVAL;
+
+       tr.buf = kmalloc_array(count, sizeof(*buf), GFP_KERNEL);
+       if (!tr.buf)
+               return -ENOMEM;
+
+       ret = lcdreg_read(reg, regnr, &tr);
+       if (ret) {
+               kfree(tr.buf);
+               return ret;
+       }
+
+       if (reg->def_width <= 8)
+               for (i = 0; i < count; i++)
+                       buf[i] = ((u8 *)tr.buf)[i];
+       else
+               for (i = 0; i < count; i++)
+                       buf[i] = ((u16 *)tr.buf)[i];
+       kfree(tr.buf);
+
+       return ret;
+}
+EXPORT_SYMBOL(lcdreg_readreg_buf32);
+
+static void devm_lcdreg_release(struct device *dev, void *res)
+{
+       struct lcdreg *reg = *(struct lcdreg **)res;
+
+       lcdreg_debugfs_exit(reg);
+       mutex_destroy(&reg->lock);
+}
+
+/**
+ * Device managed lcdreg initialization
+ *
+ * @dev: Device backing the LCD register
+ * @reg: LCD register
+ */
+struct lcdreg *devm_lcdreg_init(struct device *dev, struct lcdreg *reg)
+{
+
+       struct lcdreg **ptr;
+
+       if (!dev || !reg)
+               return ERR_PTR(-EINVAL);
+
+       ptr = devres_alloc(devm_lcdreg_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       *ptr = reg;
+       devres_add(dev, ptr);
+       reg->dev = dev;
+       mutex_init(&reg->lock);
+       lcdreg_debugfs_init(reg);
+
+       return reg;
+}
+EXPORT_SYMBOL(devm_lcdreg_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/fbtft/lcdreg/lcdreg-debugfs.c 
b/drivers/staging/fbtft/lcdreg/lcdreg-debugfs.c
new file mode 100644
index 0000000..1cba4c2
--- /dev/null
+++ b/drivers/staging/fbtft/lcdreg/lcdreg-debugfs.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2015 Noralf Trønnes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "lcdreg.h"
+
+static struct dentry *lcdreg_debugfs_root;
+
+static int lcdreg_userbuf_to_u32(const char __user *user_buf, size_t count,
+                                u32 *dest, size_t dest_size)
+{
+       char *buf, *start;
+       unsigned long value;
+       int ret = 0;
+       int i;
+
+       buf = kmalloc(count, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       if (copy_from_user(buf, user_buf, count)) {
+               kfree(buf);
+               return -EFAULT;
+       }
+       buf[count] = 0;
+       for (i = 0; i < count; i++)
+               if (buf[i] == ' ' || buf[i] == '\n')
+                       buf[i] = 0;
+       i = 0;
+       start = buf;
+       while (start < buf + count) {
+               if (*start == 0) {
+                       start++;
+                       continue;
+               }
+               if (i == dest_size) {
+                       ret = -EFBIG;
+                       break;
+               }
+               if (kstrtoul(start, 16, &value)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               dest[i++] = value;
+               while (*start != 0)
+                       start++;
+       };
+       kfree(buf);
+       if (ret)
+               return ret;
+
+       return i ? i : -EINVAL;
+}
+
+static ssize_t lcdreg_debugfs_write_file(struct file *file,
+                                        const char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct lcdreg *reg = file->private_data;
+       int ret;
+       u32 txbuf[128];
+
+       ret = lcdreg_userbuf_to_u32(user_buf, count, txbuf, ARRAY_SIZE(txbuf));
+       if (ret <= 0)
+               return -EINVAL;
+
+       add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+
+       lcdreg_lock(reg);
+       ret = lcdreg_write_buf32(reg, txbuf[0], txbuf + 1, ret - 1);
+       lcdreg_unlock(reg);
+
+       return ret ? ret : count;
+}
+
+static const struct file_operations lcdreg_debugfs_write_fops = {
+       .open = simple_open,
+       .write = lcdreg_debugfs_write_file,
+       .llseek = default_llseek,
+};
+
+static ssize_t lcdreg_debugfs_read_wr(struct file *file,
+                                     const char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct lcdreg *reg = file->private_data;
+       struct lcdreg_transfer tr = {
+               .index = (reg->quirks & LCDREG_INDEX0_ON_READ) ? 0 : 1,
+               .width = reg->debugfs_read_width,
+               .count = 1,
+       };
+       u32 txbuf[1];
+       char *buf = NULL;
+       int ret;
+
+       ret = lcdreg_userbuf_to_u32(user_buf, count, txbuf, ARRAY_SIZE(txbuf));
+       if (ret != 1)
+               return -EINVAL;
+
+       tr.buf = kmalloc(lcdreg_bytes_per_word(tr.width), GFP_KERNEL);
+       if (!tr.buf)
+               return -ENOMEM;
+
+       add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+
+       lcdreg_lock(reg);
+       ret = lcdreg_read(reg, txbuf[0], &tr);
+       lcdreg_unlock(reg);
+       if (ret)
+               goto error_out;
+
+       if (!reg->debugfs_read_result) {
+               reg->debugfs_read_result = kmalloc(16, GFP_KERNEL);
+               if (!reg->debugfs_read_result) {
+                       ret = -ENOMEM;
+                       goto error_out;
+               }
+       }
+
+       buf = reg->debugfs_read_result;
+
+       switch (tr.width) {
+       case 8:
+               snprintf(buf, 16, "%02x\n", *(u8 *)tr.buf);
+               break;
+       case 16:
+               snprintf(buf, 16, "%04x\n", *(u16 *)tr.buf);
+               break;
+       case 24:
+       case 32:
+               snprintf(buf, 16, "%08x\n", *(u32 *)tr.buf);
+               break;
+       default:
+               ret = -EINVAL;
+               goto error_out;
+       }
+
+error_out:
+       kfree(tr.buf);
+       if (ret) {
+               kfree(reg->debugfs_read_result);
+               reg->debugfs_read_result = NULL;
+               return ret;
+       }
+
+       return count;
+}
+
+static ssize_t lcdreg_debugfs_read_rd(struct file *file,
+                                    char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       struct lcdreg *reg = file->private_data;
+
+       if (*ppos < 0 || !count)
+               return -EINVAL;
+
+       if (!reg->debugfs_read_result)
+               return -ENODATA;
+
+       return simple_read_from_buffer(user_buf, count, ppos,
+                                      reg->debugfs_read_result,
+                                      strlen(reg->debugfs_read_result));
+}
+
+static const struct file_operations lcdreg_debugfs_read_fops = {
+       .open = simple_open,
+       .read = lcdreg_debugfs_read_rd,
+       .write = lcdreg_debugfs_read_wr,
+       .llseek = default_llseek,
+};
+
+static ssize_t lcdreg_debugfs_reset_wr(struct file *file,
+                                      const char __user *user_buf,
+                                      size_t count, loff_t *ppos)
+{
+       struct lcdreg *reg = file->private_data;
+
+       add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+       lcdreg_reset(reg);
+
+       return count;
+}
+
+static const struct file_operations lcdreg_debugfs_reset_fops = {
+       .open = simple_open,
+       .write = lcdreg_debugfs_reset_wr,
+       .llseek = default_llseek,
+};
+
+static int lcdreg_debugfs_readwidth_set(void *data, u64 val)
+{
+       struct lcdreg *reg = data;
+
+       reg->debugfs_read_width = val;
+
+       return 0;
+}
+static int lcdreg_debugfs_readwidth_get(void *data, u64 *val)
+{
+       struct lcdreg *reg = data;
+
+       /*
+       * def_width is not set when lcdreg_debugfs_init() is run, it's
+       * set later by the controller init code. Hence the need for this
+       * late assignment.
+       */
+       if (!reg->debugfs_read_width)
+               reg->debugfs_read_width = reg->def_width;
+
+       *val = reg->debugfs_read_width;
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(lcdreg_debugfs_readwidth_fops,
+                       lcdreg_debugfs_readwidth_get,
+                       lcdreg_debugfs_readwidth_set, "%llu\n");
+
+void lcdreg_debugfs_init(struct lcdreg *reg)
+{
+       if (IS_ERR_OR_NULL(lcdreg_debugfs_root))
+               return;
+
+       reg->debugfs = debugfs_create_dir(dev_name(reg->dev),
+                                         lcdreg_debugfs_root);
+       if (!reg->debugfs) {
+               dev_warn(reg->dev, "Failed to create debugfs directory\n");
+               return;
+       }
+
+       debugfs_create_file("read_width", 0440, reg->debugfs, reg,
+                           &lcdreg_debugfs_readwidth_fops);
+       debugfs_create_file("read", 0660, reg->debugfs, reg,
+                           &lcdreg_debugfs_read_fops);
+       debugfs_create_file("write", 0220, reg->debugfs, reg,
+                           &lcdreg_debugfs_write_fops);
+       debugfs_create_file("reset", 0220, reg->debugfs, reg,
+                           &lcdreg_debugfs_reset_fops);
+}
+
+void lcdreg_debugfs_exit(struct lcdreg *reg)
+{
+       debugfs_remove_recursive(reg->debugfs);
+}
+
+static int lcdreg_debugfs_module_init(void)
+{
+       lcdreg_debugfs_root = debugfs_create_dir("lcdreg", NULL);
+       if (!lcdreg_debugfs_root)
+               pr_warn("lcdreg: Failed to create debugfs root\n");
+       return 0;
+}
+module_init(lcdreg_debugfs_module_init);
+
+static void lcdreg_debugfs_module_exit(void)
+{
+       debugfs_remove_recursive(lcdreg_debugfs_root);
+}
+module_exit(lcdreg_debugfs_module_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/fbtft/lcdreg/lcdreg.h 
b/drivers/staging/fbtft/lcdreg/lcdreg.h
new file mode 100644
index 0000000..0ddf40e
--- /dev/null
+++ b/drivers/staging/fbtft/lcdreg/lcdreg.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2015 Noralf Trønnes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_LCDREG_H
+#define __LINUX_LCDREG_H
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+/**
+ * struct lcdreg_transfer - LCD register transfer
+ *
+ * @index: register index (address)
+ *         Known under the following names:
+ *         D/C (command=0, data=1)
+ *         RS (register selection: index=0, data=1)
+ *         D/I (data/index: index=0, data=1)
+ * @buf: data array to transfer
+ * @count: number of items in array
+ * @width: override default regwidth
+ */
+struct lcdreg_transfer {
+       unsigned index;
+       void *buf;
+       unsigned count;
+       unsigned width;
+};
+
+/**
+ * struct lcdreg - interface to LCD register
+ *
+ * @dev: device interface
+ * @lock: mutex for register access locking
+ * @def_width: default register width
+ * @readable: LCD register is readable
+ * @write: write to LCD register
+ * @read: read from LCD register
+ * @reset: reset LCD controller
+ * @quirks: Deviations from the MIPI DBI standard
+ */
+struct lcdreg {
+       struct device *dev;
+       struct mutex lock;
+       unsigned def_width;
+       bool readable;
+
+       int (*write)(struct lcdreg *reg, unsigned regnr,
+                    struct lcdreg_transfer *transfer);
+       int (*read)(struct lcdreg *reg, unsigned regnr,
+                   struct lcdreg_transfer *transfer);
+       void (*reset)(struct lcdreg *reg);
+
+       u64 quirks;
+/* slowdown command (index=0) */
+#define LCDREG_SLOW_INDEX0_WRITE       BIT(0)
+/*
+ * The MIPI DBI spec states that D/C should be HIGH during register reading.
+ * However, not all SPI master drivers support cs_change on last transfer and
+ * there are LCD controllers that ignore D/C on read.
+ */
+#define LCDREG_INDEX0_ON_READ          BIT(1)
+
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *debugfs;
+       u32 debugfs_read_width;
+       char *debugfs_read_result;
+#endif
+};
+
+struct lcdreg *devm_lcdreg_init(struct device *dev,
+                                        struct lcdreg *reg);
+extern int lcdreg_write(struct lcdreg *reg, unsigned regnr,
+                       struct lcdreg_transfer *transfer);
+extern int lcdreg_write_buf32(struct lcdreg *reg, unsigned regnr,
+                             const u32 *data, unsigned count);
+
+#define lcdreg_writereg(lcdreg, regnr, seq...) \
+({\
+       u32 d[] = { seq };\
+       lcdreg_write_buf32(lcdreg, regnr, d, ARRAY_SIZE(d));\
+})
+
+extern int lcdreg_read(struct lcdreg *reg, unsigned regnr,
+                      struct lcdreg_transfer *transfer);
+extern int lcdreg_readreg_buf32(struct lcdreg *reg, unsigned regnr, u32 *buf,
+                               unsigned count);
+
+static inline void lcdreg_reset(struct lcdreg *reg)
+{
+       reg->reset(reg);
+}
+
+static inline void lcdreg_lock(struct lcdreg *reg)
+{
+       mutex_lock(&reg->lock);
+}
+
+static inline void lcdreg_unlock(struct lcdreg *reg)
+{
+       mutex_unlock(&reg->lock);
+}
+
+static inline bool lcdreg_is_readable(struct lcdreg *reg)
+{
+       return reg->readable;
+}
+
+static inline unsigned lcdreg_bytes_per_word(unsigned bits_per_word)
+{
+       if (bits_per_word <= 8)
+               return 1;
+       else if (bits_per_word <= 16)
+               return 2;
+       else /* bits_per_word <= 32 */
+               return 4;
+}
+
+#if defined(CONFIG_DYNAMIC_DEBUG)
+
+#define lcdreg_dbg_transfer_buf(transfer)                            \
+do {                                                                 \
+       int groupsize = lcdreg_bytes_per_word(transfer->width);      \
+       size_t len = min_t(size_t, 32, transfer->count * groupsize); \
+                                                                    \
+       print_hex_dump_debug("    buf=", DUMP_PREFIX_NONE, 32,       \
+                       groupsize, transfer->buf, len, false);       \
+} while (0)
+
+#elif defined(DEBUG)
+
+#define lcdreg_dbg_transfer_buf(transfer)                            \
+do {                                                                 \
+       int groupsize = lcdreg_bytes_per_word(transfer->width);      \
+       size_t len = min_t(size_t, 32, transfer->count * groupsize); \
+                                                                    \
+       print_hex_dump(KERN_DEBUG, "    buf=", DUMP_PREFIX_NONE, 32, \
+                       groupsize, transfer->buf, len, false);       \
+} while (0)
+#else
+
+#define lcdreg_dbg_transfer_buf(transfer)
+
+#endif /* DEBUG || CONFIG_DYNAMIC_DEBUG */
+
+#endif /* __LINUX_LCDREG_H */
-- 
2.2.2

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to