brcm2708: remove linux 4.1 support
[openwrt/svn-archive/archive.git] / target / linux / brcm2708 / patches-4.1 / 0016-lirc-added-support-for-RaspberryPi-GPIO.patch
diff --git a/target/linux/brcm2708/patches-4.1/0016-lirc-added-support-for-RaspberryPi-GPIO.patch b/target/linux/brcm2708/patches-4.1/0016-lirc-added-support-for-RaspberryPi-GPIO.patch
deleted file mode 100644 (file)
index 05aa134..0000000
+++ /dev/null
@@ -1,848 +0,0 @@
-From 04646f6a5ffec4a5cd55999e85df839278860cb1 Mon Sep 17 00:00:00 2001
-From: Aron Szabo <aron@aron.ws>
-Date: Sat, 16 Jun 2012 12:15:55 +0200
-Subject: [PATCH 016/222] lirc: added support for RaspberryPi GPIO
-
-lirc_rpi: Use read_current_timer to determine transmitter delay. Thanks to jjmz and others
-See: https://github.com/raspberrypi/linux/issues/525
-
-lirc: Remove restriction on gpio pins that can be used with lirc
-
-Compute Module, for example could use different pins
-
-lirc_rpi: Add parameter to specify input pin pull
-
-Depending on the connected IR circuitry it might be desirable to change the
-gpios internal pull from it pull-down default behaviour. Add a module
-parameter to allow the user to set it explicitly.
-
-Signed-off-by: Julian Scheel <julian@jusst.de>
-
-lirc-rpi: Use the higher-level irq control functions
-
-This module used to access the irq_chip methods of the
-gpio controller directly, rather than going through the
-standard enable_irq/irq_set_irq_type functions. This
-caused problems on pinctrl-bcm2835 which only implements
-the irq_enable/disable methods and not irq_unmask/mask.
-
-lirc-rpi: Correct the interrupt usage
-
-1) Correct the use of enable_irq (i.e. don't call it so often)
-2) Correct the shutdown sequence.
-3) Avoid a bcm2708_gpio driver quirk by setting the irq flags earlier
-
-lirc-rpi: use getnstimeofday instead of read_current_timer
-
-read_current_timer isn't guaranteed to return values in
-microseconds, and indeed it doesn't on a Pi2.
-
-Issue: linux#827
-
-lirc-rpi: Add device tree support, and a suitable overlay
-
-The overlay supports DT parameters that match the old module
-parameters, except that gpio_in_pull should be set using the
-strings "up", "down" or "off".
-
-lirc-rpi: Also support pinctrl-bcm2835 in non-DT mode
----
- drivers/staging/media/lirc/Kconfig    |   6 +
- drivers/staging/media/lirc/Makefile   |   1 +
- drivers/staging/media/lirc/lirc_rpi.c | 765 ++++++++++++++++++++++++++++++++++
- 3 files changed, 772 insertions(+)
- create mode 100644 drivers/staging/media/lirc/lirc_rpi.c
-
---- a/drivers/staging/media/lirc/Kconfig
-+++ b/drivers/staging/media/lirc/Kconfig
-@@ -32,6 +32,12 @@ config LIRC_PARALLEL
-       help
-         Driver for Homebrew Parallel Port Receivers
-+config LIRC_RPI
-+      tristate "Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi"
-+      depends on LIRC
-+      help
-+        Driver for Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi
-+
- config LIRC_SASEM
-       tristate "Sasem USB IR Remote"
-       depends on LIRC && USB
---- a/drivers/staging/media/lirc/Makefile
-+++ b/drivers/staging/media/lirc/Makefile
-@@ -6,6 +6,7 @@
- obj-$(CONFIG_LIRC_BT829)      += lirc_bt829.o
- obj-$(CONFIG_LIRC_IMON)               += lirc_imon.o
- obj-$(CONFIG_LIRC_PARALLEL)   += lirc_parallel.o
-+obj-$(CONFIG_LIRC_RPI)                += lirc_rpi.o
- obj-$(CONFIG_LIRC_SASEM)      += lirc_sasem.o
- obj-$(CONFIG_LIRC_SERIAL)     += lirc_serial.o
- obj-$(CONFIG_LIRC_SIR)                += lirc_sir.o
---- /dev/null
-+++ b/drivers/staging/media/lirc/lirc_rpi.c
-@@ -0,0 +1,765 @@
-+/*
-+ * lirc_rpi.c
-+ *
-+ * lirc_rpi - Device driver that records pulse- and pause-lengths
-+ *          (space-lengths) (just like the lirc_serial driver does)
-+ *          between GPIO interrupt events on the Raspberry Pi.
-+ *          Lots of code has been taken from the lirc_serial module,
-+ *          so I would like say thanks to the authors.
-+ *
-+ * Copyright (C) 2012 Aron Robert Szabo <aron@reon.hu>,
-+ *                  Michael Bishop <cleverca22@gmail.com>
-+ *  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.
-+ *
-+ *  This program is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *  GNU General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU General Public License
-+ *  along with this program; if not, write to the Free Software
-+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+#include <linux/kernel.h>
-+#include <linux/time.h>
-+#include <linux/timex.h>
-+#include <linux/timekeeping.h>
-+#include <linux/string.h>
-+#include <linux/delay.h>
-+#include <linux/platform_device.h>
-+#include <linux/irq.h>
-+#include <linux/spinlock.h>
-+#include <media/lirc.h>
-+#include <media/lirc_dev.h>
-+#include <mach/gpio.h>
-+#include <linux/gpio.h>
-+#include <linux/of_platform.h>
-+
-+#include <linux/platform_data/bcm2708.h>
-+
-+#define LIRC_DRIVER_NAME "lirc_rpi"
-+#define RBUF_LEN 256
-+#define LIRC_TRANSMITTER_LATENCY 50
-+
-+#ifndef MAX_UDELAY_MS
-+#define MAX_UDELAY_US 5000
-+#else
-+#define MAX_UDELAY_US (MAX_UDELAY_MS*1000)
-+#endif
-+
-+#define dprintk(fmt, args...)                                 \
-+      do {                                                    \
-+              if (debug)                                      \
-+                      printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \
-+                             fmt, ## args);                   \
-+      } while (0)
-+
-+/* module parameters */
-+
-+/* set the default GPIO input pin */
-+static int gpio_in_pin = 18;
-+/* set the default pull behaviour for input pin */
-+static int gpio_in_pull = BCM2708_PULL_DOWN;
-+/* set the default GPIO output pin */
-+static int gpio_out_pin = 17;
-+/* enable debugging messages */
-+static bool debug;
-+/* -1 = auto, 0 = active high, 1 = active low */
-+static int sense = -1;
-+/* use softcarrier by default */
-+static bool softcarrier = 1;
-+/* 0 = do not invert output, 1 = invert output */
-+static bool invert = 0;
-+
-+struct gpio_chip *gpiochip;
-+static int irq_num;
-+
-+/* forward declarations */
-+static long send_pulse(unsigned long length);
-+static void send_space(long length);
-+static void lirc_rpi_exit(void);
-+
-+static struct platform_device *lirc_rpi_dev;
-+static struct timeval lasttv = { 0, 0 };
-+static struct lirc_buffer rbuf;
-+static spinlock_t lock;
-+
-+/* initialized/set in init_timing_params() */
-+static unsigned int freq = 38000;
-+static unsigned int duty_cycle = 50;
-+static unsigned long period;
-+static unsigned long pulse_width;
-+static unsigned long space_width;
-+
-+static void safe_udelay(unsigned long usecs)
-+{
-+      while (usecs > MAX_UDELAY_US) {
-+              udelay(MAX_UDELAY_US);
-+              usecs -= MAX_UDELAY_US;
-+      }
-+      udelay(usecs);
-+}
-+
-+static unsigned long read_current_us(void)
-+{
-+      struct timespec now;
-+      getnstimeofday(&now);
-+      return (now.tv_sec * 1000000) + (now.tv_nsec/1000);
-+}
-+
-+static int init_timing_params(unsigned int new_duty_cycle,
-+      unsigned int new_freq)
-+{
-+      if (1000 * 1000000L / new_freq * new_duty_cycle / 100 <=
-+          LIRC_TRANSMITTER_LATENCY)
-+              return -EINVAL;
-+      if (1000 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <=
-+          LIRC_TRANSMITTER_LATENCY)
-+              return -EINVAL;
-+      duty_cycle = new_duty_cycle;
-+      freq = new_freq;
-+      period = 1000 * 1000000L / freq;
-+      pulse_width = period * duty_cycle / 100;
-+      space_width = period - pulse_width;
-+      dprintk("in init_timing_params, freq=%d pulse=%ld, "
-+              "space=%ld\n", freq, pulse_width, space_width);
-+      return 0;
-+}
-+
-+static long send_pulse_softcarrier(unsigned long length)
-+{
-+      int flag;
-+      unsigned long actual, target;
-+      unsigned long actual_us, initial_us, target_us;
-+
-+      length *= 1000;
-+
-+      actual = 0; target = 0; flag = 0;
-+      actual_us = read_current_us();
-+
-+      while (actual < length) {
-+              if (flag) {
-+                      gpiochip->set(gpiochip, gpio_out_pin, invert);
-+                      target += space_width;
-+              } else {
-+                      gpiochip->set(gpiochip, gpio_out_pin, !invert);
-+                      target += pulse_width;
-+              }
-+              initial_us = actual_us;
-+              target_us = actual_us + (target - actual) / 1000;
-+              /*
-+               * Note - we've checked in ioctl that the pulse/space
-+               * widths are big enough so that d is > 0
-+               */
-+              if  ((int)(target_us - actual_us) > 0)
-+                      udelay(target_us - actual_us);
-+              actual_us = read_current_us();
-+              actual += (actual_us - initial_us) * 1000;
-+              flag = !flag;
-+      }
-+      return (actual-length) / 1000;
-+}
-+
-+static long send_pulse(unsigned long length)
-+{
-+      if (length <= 0)
-+              return 0;
-+
-+      if (softcarrier) {
-+              return send_pulse_softcarrier(length);
-+      } else {
-+              gpiochip->set(gpiochip, gpio_out_pin, !invert);
-+              safe_udelay(length);
-+              return 0;
-+      }
-+}
-+
-+static void send_space(long length)
-+{
-+      gpiochip->set(gpiochip, gpio_out_pin, invert);
-+      if (length <= 0)
-+              return;
-+      safe_udelay(length);
-+}
-+
-+static void rbwrite(int l)
-+{
-+      if (lirc_buffer_full(&rbuf)) {
-+              /* no new signals will be accepted */
-+              dprintk("Buffer overrun\n");
-+              return;
-+      }
-+      lirc_buffer_write(&rbuf, (void *)&l);
-+}
-+
-+static void frbwrite(int l)
-+{
-+      /* simple noise filter */
-+      static int pulse, space;
-+      static unsigned int ptr;
-+
-+      if (ptr > 0 && (l & PULSE_BIT)) {
-+              pulse += l & PULSE_MASK;
-+              if (pulse > 250) {
-+                      rbwrite(space);
-+                      rbwrite(pulse | PULSE_BIT);
-+                      ptr = 0;
-+                      pulse = 0;
-+              }
-+              return;
-+      }
-+      if (!(l & PULSE_BIT)) {
-+              if (ptr == 0) {
-+                      if (l > 20000) {
-+                              space = l;
-+                              ptr++;
-+                              return;
-+                      }
-+              } else {
-+                      if (l > 20000) {
-+                              space += pulse;
-+                              if (space > PULSE_MASK)
-+                                      space = PULSE_MASK;
-+                              space += l;
-+                              if (space > PULSE_MASK)
-+                                      space = PULSE_MASK;
-+                              pulse = 0;
-+                              return;
-+                      }
-+                      rbwrite(space);
-+                      rbwrite(pulse | PULSE_BIT);
-+                      ptr = 0;
-+                      pulse = 0;
-+              }
-+      }
-+      rbwrite(l);
-+}
-+
-+static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs)
-+{
-+      struct timeval tv;
-+      long deltv;
-+      int data;
-+      int signal;
-+
-+      /* use the GPIO signal level */
-+      signal = gpiochip->get(gpiochip, gpio_in_pin);
-+
-+      if (sense != -1) {
-+              /* get current time */
-+              do_gettimeofday(&tv);
-+
-+              /* calc time since last interrupt in microseconds */
-+              deltv = tv.tv_sec-lasttv.tv_sec;
-+              if (tv.tv_sec < lasttv.tv_sec ||
-+                  (tv.tv_sec == lasttv.tv_sec &&
-+                   tv.tv_usec < lasttv.tv_usec)) {
-+                      printk(KERN_WARNING LIRC_DRIVER_NAME
-+                             ": AIEEEE: your clock just jumped backwards\n");
-+                      printk(KERN_WARNING LIRC_DRIVER_NAME
-+                             ": %d %d %lx %lx %lx %lx\n", signal, sense,
-+                             tv.tv_sec, lasttv.tv_sec,
-+                             tv.tv_usec, lasttv.tv_usec);
-+                      data = PULSE_MASK;
-+              } else if (deltv > 15) {
-+                      data = PULSE_MASK; /* really long time */
-+                      if (!(signal^sense)) {
-+                              /* sanity check */
-+                              printk(KERN_WARNING LIRC_DRIVER_NAME
-+                                     ": AIEEEE: %d %d %lx %lx %lx %lx\n",
-+                                     signal, sense, tv.tv_sec, lasttv.tv_sec,
-+                                     tv.tv_usec, lasttv.tv_usec);
-+                              /*
-+                               * detecting pulse while this
-+                               * MUST be a space!
-+                               */
-+                              sense = sense ? 0 : 1;
-+                      }
-+              } else {
-+                      data = (int) (deltv*1000000 +
-+                                    (tv.tv_usec - lasttv.tv_usec));
-+              }
-+              frbwrite(signal^sense ? data : (data|PULSE_BIT));
-+              lasttv = tv;
-+              wake_up_interruptible(&rbuf.wait_poll);
-+      }
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static int is_right_chip(struct gpio_chip *chip, void *data)
-+{
-+      dprintk("is_right_chip %s %d\n", chip->label, strcmp(data, chip->label));
-+
-+      if (strcmp(data, chip->label) == 0)
-+              return 1;
-+      return 0;
-+}
-+
-+static inline int read_bool_property(const struct device_node *np,
-+                                   const char *propname,
-+                                   bool *out_value)
-+{
-+      u32 value = 0;
-+      int err = of_property_read_u32(np, propname, &value);
-+      if (err == 0)
-+              *out_value = (value != 0);
-+      return err;
-+}
-+
-+static void read_pin_settings(struct device_node *node)
-+{
-+      u32 pin;
-+      int index;
-+
-+      for (index = 0;
-+           of_property_read_u32_index(
-+                   node,
-+                   "brcm,pins",
-+                   index,
-+                   &pin) == 0;
-+           index++) {
-+              u32 function;
-+              int err;
-+              err = of_property_read_u32_index(
-+                      node,
-+                      "brcm,function",
-+                      index,
-+                      &function);
-+              if (err == 0) {
-+                      if (function == 1) /* Output */
-+                              gpio_out_pin = pin;
-+                      else if (function == 0) /* Input */
-+                              gpio_in_pin = pin;
-+              }
-+      }
-+}
-+
-+static int init_port(void)
-+{
-+      int i, nlow, nhigh, ret;
-+      struct device_node *node;
-+
-+      node = lirc_rpi_dev->dev.of_node;
-+
-+      gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);
-+
-+      /*
-+       * Because of the lack of a setpull function, only support
-+       * pinctrl-bcm2835 if using device tree.
-+      */
-+      if (!gpiochip && node)
-+              gpiochip = gpiochip_find("pinctrl-bcm2835", is_right_chip);
-+
-+      if (!gpiochip) {
-+              pr_err(LIRC_DRIVER_NAME ": gpio chip not found!\n");
-+              return -ENODEV;
-+      }
-+
-+      if (node) {
-+              struct device_node *pins_node;
-+
-+              pins_node = of_parse_phandle(node, "pinctrl-0", 0);
-+              if (!pins_node) {
-+                      printk(KERN_ERR LIRC_DRIVER_NAME
-+                             ": pinctrl settings not found!\n");
-+                      ret = -EINVAL;
-+                      goto exit_init_port;
-+              }
-+
-+              read_pin_settings(pins_node);
-+
-+              of_property_read_u32(node, "rpi,sense", &sense);
-+
-+              read_bool_property(node, "rpi,softcarrier", &softcarrier);
-+
-+              read_bool_property(node, "rpi,invert", &invert);
-+
-+              read_bool_property(node, "rpi,debug", &debug);
-+
-+      }
-+      else
-+      {
-+              if (gpio_in_pin >= BCM2708_NR_GPIOS ||
-+                  gpio_out_pin >= BCM2708_NR_GPIOS) {
-+                      ret = -EINVAL;
-+                      printk(KERN_ERR LIRC_DRIVER_NAME
-+                             ": invalid GPIO pin(s) specified!\n");
-+                      goto exit_init_port;
-+              }
-+
-+              if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) {
-+                      printk(KERN_ALERT LIRC_DRIVER_NAME
-+                             ": cant claim gpio pin %d\n", gpio_out_pin);
-+                      ret = -ENODEV;
-+                      goto exit_init_port;
-+              }
-+
-+              if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) {
-+                      printk(KERN_ALERT LIRC_DRIVER_NAME
-+                             ": cant claim gpio pin %d\n", gpio_in_pin);
-+                      ret = -ENODEV;
-+                      goto exit_gpio_free_out_pin;
-+              }
-+
-+              bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull);
-+              gpiochip->direction_input(gpiochip, gpio_in_pin);
-+              gpiochip->direction_output(gpiochip, gpio_out_pin, 1);
-+      }
-+
-+      gpiochip->set(gpiochip, gpio_out_pin, invert);
-+
-+      irq_num = gpiochip->to_irq(gpiochip, gpio_in_pin);
-+      dprintk("to_irq %d\n", irq_num);
-+
-+      /* if pin is high, then this must be an active low receiver. */
-+      if (sense == -1) {
-+              /* wait 1/2 sec for the power supply */
-+              msleep(500);
-+
-+              /*
-+               * probe 9 times every 0.04s, collect "votes" for
-+               * active high/low
-+               */
-+              nlow = 0;
-+              nhigh = 0;
-+              for (i = 0; i < 9; i++) {
-+                      if (gpiochip->get(gpiochip, gpio_in_pin))
-+                              nlow++;
-+                      else
-+                              nhigh++;
-+                      msleep(40);
-+              }
-+              sense = (nlow >= nhigh ? 1 : 0);
-+              printk(KERN_INFO LIRC_DRIVER_NAME
-+                     ": auto-detected active %s receiver on GPIO pin %d\n",
-+                     sense ? "low" : "high", gpio_in_pin);
-+      } else {
-+              printk(KERN_INFO LIRC_DRIVER_NAME
-+                     ": manually using active %s receiver on GPIO pin %d\n",
-+                     sense ? "low" : "high", gpio_in_pin);
-+      }
-+
-+      return 0;
-+
-+      exit_gpio_free_out_pin:
-+      gpio_free(gpio_out_pin);
-+
-+      exit_init_port:
-+      return ret;
-+}
-+
-+// called when the character device is opened
-+static int set_use_inc(void *data)
-+{
-+      int result;
-+
-+      /* initialize timestamp */
-+      do_gettimeofday(&lasttv);
-+
-+      result = request_irq(irq_num,
-+                           (irq_handler_t) irq_handler,
-+                           IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING,
-+                           LIRC_DRIVER_NAME, (void*) 0);
-+
-+      switch (result) {
-+      case -EBUSY:
-+              printk(KERN_ERR LIRC_DRIVER_NAME
-+                     ": IRQ %d is busy\n",
-+                     irq_num);
-+              return -EBUSY;
-+      case -EINVAL:
-+              printk(KERN_ERR LIRC_DRIVER_NAME
-+                     ": Bad irq number or handler\n");
-+              return -EINVAL;
-+      default:
-+              dprintk("Interrupt %d obtained\n",
-+                      irq_num);
-+              break;
-+      };
-+
-+      /* initialize pulse/space widths */
-+      init_timing_params(duty_cycle, freq);
-+
-+      return 0;
-+}
-+
-+static void set_use_dec(void *data)
-+{
-+      /* GPIO Pin Falling/Rising Edge Detect Disable */
-+      irq_set_irq_type(irq_num, 0);
-+      disable_irq(irq_num);
-+
-+      free_irq(irq_num, (void *) 0);
-+
-+      dprintk(KERN_INFO LIRC_DRIVER_NAME
-+              ": freed IRQ %d\n", irq_num);
-+}
-+
-+static ssize_t lirc_write(struct file *file, const char *buf,
-+      size_t n, loff_t *ppos)
-+{
-+      int i, count;
-+      unsigned long flags;
-+      long delta = 0;
-+      int *wbuf;
-+
-+      count = n / sizeof(int);
-+      if (n % sizeof(int) || count % 2 == 0)
-+              return -EINVAL;
-+      wbuf = memdup_user(buf, n);
-+      if (IS_ERR(wbuf))
-+              return PTR_ERR(wbuf);
-+      spin_lock_irqsave(&lock, flags);
-+
-+      for (i = 0; i < count; i++) {
-+              if (i%2)
-+                      send_space(wbuf[i] - delta);
-+              else
-+                      delta = send_pulse(wbuf[i]);
-+      }
-+      gpiochip->set(gpiochip, gpio_out_pin, invert);
-+
-+      spin_unlock_irqrestore(&lock, flags);
-+      kfree(wbuf);
-+      return n;
-+}
-+
-+static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-+{
-+      int result;
-+      __u32 value;
-+
-+      switch (cmd) {
-+      case LIRC_GET_SEND_MODE:
-+              return -ENOIOCTLCMD;
-+              break;
-+
-+      case LIRC_SET_SEND_MODE:
-+              result = get_user(value, (__u32 *) arg);
-+              if (result)
-+                      return result;
-+              /* only LIRC_MODE_PULSE supported */
-+              if (value != LIRC_MODE_PULSE)
-+                      return -ENOSYS;
-+              break;
-+
-+      case LIRC_GET_LENGTH:
-+              return -ENOSYS;
-+              break;
-+
-+      case LIRC_SET_SEND_DUTY_CYCLE:
-+              dprintk("SET_SEND_DUTY_CYCLE\n");
-+              result = get_user(value, (__u32 *) arg);
-+              if (result)
-+                      return result;
-+              if (value <= 0 || value > 100)
-+                      return -EINVAL;
-+              return init_timing_params(value, freq);
-+              break;
-+
-+      case LIRC_SET_SEND_CARRIER:
-+              dprintk("SET_SEND_CARRIER\n");
-+              result = get_user(value, (__u32 *) arg);
-+              if (result)
-+                      return result;
-+              if (value > 500000 || value < 20000)
-+                      return -EINVAL;
-+              return init_timing_params(duty_cycle, value);
-+              break;
-+
-+      default:
-+              return lirc_dev_fop_ioctl(filep, cmd, arg);
-+      }
-+      return 0;
-+}
-+
-+static const struct file_operations lirc_fops = {
-+      .owner          = THIS_MODULE,
-+      .write          = lirc_write,
-+      .unlocked_ioctl = lirc_ioctl,
-+      .read           = lirc_dev_fop_read,
-+      .poll           = lirc_dev_fop_poll,
-+      .open           = lirc_dev_fop_open,
-+      .release        = lirc_dev_fop_close,
-+      .llseek         = no_llseek,
-+};
-+
-+static struct lirc_driver driver = {
-+      .name           = LIRC_DRIVER_NAME,
-+      .minor          = -1,
-+      .code_length    = 1,
-+      .sample_rate    = 0,
-+      .data           = NULL,
-+      .add_to_buf     = NULL,
-+      .rbuf           = &rbuf,
-+      .set_use_inc    = set_use_inc,
-+      .set_use_dec    = set_use_dec,
-+      .fops           = &lirc_fops,
-+      .dev            = NULL,
-+      .owner          = THIS_MODULE,
-+};
-+
-+static const struct of_device_id lirc_rpi_of_match[] = {
-+      { .compatible = "rpi,lirc-rpi", },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, lirc_rpi_of_match);
-+
-+static struct platform_driver lirc_rpi_driver = {
-+      .driver = {
-+              .name   = LIRC_DRIVER_NAME,
-+              .owner  = THIS_MODULE,
-+              .of_match_table = of_match_ptr(lirc_rpi_of_match),
-+      },
-+};
-+
-+static int __init lirc_rpi_init(void)
-+{
-+      struct device_node *node;
-+      int result;
-+
-+      /* Init read buffer. */
-+      result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
-+      if (result < 0)
-+              return -ENOMEM;
-+
-+      result = platform_driver_register(&lirc_rpi_driver);
-+      if (result) {
-+              printk(KERN_ERR LIRC_DRIVER_NAME
-+                     ": lirc register returned %d\n", result);
-+              goto exit_buffer_free;
-+      }
-+
-+      node = of_find_compatible_node(NULL, NULL,
-+                                     lirc_rpi_of_match[0].compatible);
-+
-+      if (node) {
-+              /* DT-enabled */
-+              lirc_rpi_dev = of_find_device_by_node(node);
-+              WARN_ON(lirc_rpi_dev->dev.of_node != node);
-+              of_node_put(node);
-+      }
-+      else {
-+              lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
-+              if (!lirc_rpi_dev) {
-+                      result = -ENOMEM;
-+                      goto exit_driver_unregister;
-+              }
-+
-+              result = platform_device_add(lirc_rpi_dev);
-+              if (result)
-+                      goto exit_device_put;
-+      }
-+
-+      return 0;
-+
-+      exit_device_put:
-+      platform_device_put(lirc_rpi_dev);
-+
-+      exit_driver_unregister:
-+      platform_driver_unregister(&lirc_rpi_driver);
-+
-+      exit_buffer_free:
-+      lirc_buffer_free(&rbuf);
-+
-+      return result;
-+}
-+
-+static void lirc_rpi_exit(void)
-+{
-+      if (!lirc_rpi_dev->dev.of_node)
-+              platform_device_unregister(lirc_rpi_dev);
-+      platform_driver_unregister(&lirc_rpi_driver);
-+      lirc_buffer_free(&rbuf);
-+}
-+
-+static int __init lirc_rpi_init_module(void)
-+{
-+      int result;
-+
-+      result = lirc_rpi_init();
-+      if (result)
-+              return result;
-+
-+      result = init_port();
-+      if (result < 0)
-+              goto exit_rpi;
-+
-+      driver.features = LIRC_CAN_SET_SEND_DUTY_CYCLE |
-+                        LIRC_CAN_SET_SEND_CARRIER |
-+                        LIRC_CAN_SEND_PULSE |
-+                        LIRC_CAN_REC_MODE2;
-+
-+      driver.dev = &lirc_rpi_dev->dev;
-+      driver.minor = lirc_register_driver(&driver);
-+
-+      if (driver.minor < 0) {
-+              printk(KERN_ERR LIRC_DRIVER_NAME
-+                     ": device registration failed with %d\n", result);
-+              result = -EIO;
-+              goto exit_rpi;
-+      }
-+
-+      printk(KERN_INFO LIRC_DRIVER_NAME ": driver registered!\n");
-+
-+      return 0;
-+
-+      exit_rpi:
-+      lirc_rpi_exit();
-+
-+      return result;
-+}
-+
-+static void __exit lirc_rpi_exit_module(void)
-+{
-+      lirc_unregister_driver(driver.minor);
-+
-+      gpio_free(gpio_out_pin);
-+      gpio_free(gpio_in_pin);
-+
-+      lirc_rpi_exit();
-+
-+      printk(KERN_INFO LIRC_DRIVER_NAME ": cleaned up module\n");
-+}
-+
-+module_init(lirc_rpi_init_module);
-+module_exit(lirc_rpi_exit_module);
-+
-+MODULE_DESCRIPTION("Infra-red receiver and blaster driver for Raspberry Pi GPIO.");
-+MODULE_AUTHOR("Aron Robert Szabo <aron@reon.hu>");
-+MODULE_AUTHOR("Michael Bishop <cleverca22@gmail.com>");
-+MODULE_LICENSE("GPL");
-+
-+module_param(gpio_out_pin, int, S_IRUGO);
-+MODULE_PARM_DESC(gpio_out_pin, "GPIO output/transmitter pin number of the BCM"
-+               " processor. (default 17");
-+
-+module_param(gpio_in_pin, int, S_IRUGO);
-+MODULE_PARM_DESC(gpio_in_pin, "GPIO input pin number of the BCM processor."
-+               " (default 18");
-+
-+module_param(gpio_in_pull, int, S_IRUGO);
-+MODULE_PARM_DESC(gpio_in_pull, "GPIO input pin pull configuration."
-+               " (0 = off, 1 = up, 2 = down, default down)");
-+
-+module_param(sense, int, S_IRUGO);
-+MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"
-+               " (0 = active high, 1 = active low )");
-+
-+module_param(softcarrier, bool, S_IRUGO);
-+MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)");
-+
-+module_param(invert, bool, S_IRUGO);
-+MODULE_PARM_DESC(invert, "Invert output (0 = off, 1 = on, default off");
-+
-+module_param(debug, bool, S_IRUGO | S_IWUSR);
-+MODULE_PARM_DESC(debug, "Enable debugging messages");