0015-lirc-added-support-for-RaspberryPi-GPIO.patch 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. From 96fbef3b8f8ab61f7f32d52b54d7993117a5fdbc Mon Sep 17 00:00:00 2001
  2. From: Aron Szabo <aron@aron.ws>
  3. Date: Sat, 16 Jun 2012 12:15:55 +0200
  4. Subject: [PATCH 015/114] lirc: added support for RaspberryPi GPIO
  5. lirc_rpi: Use read_current_timer to determine transmitter delay. Thanks to jjmz and others
  6. See: https://github.com/raspberrypi/linux/issues/525
  7. lirc: Remove restriction on gpio pins that can be used with lirc
  8. Compute Module, for example could use different pins
  9. lirc_rpi: Add parameter to specify input pin pull
  10. Depending on the connected IR circuitry it might be desirable to change the
  11. gpios internal pull from it pull-down default behaviour. Add a module
  12. parameter to allow the user to set it explicitly.
  13. Signed-off-by: Julian Scheel <julian@jusst.de>
  14. lirc-rpi: Use the higher-level irq control functions
  15. This module used to access the irq_chip methods of the
  16. gpio controller directly, rather than going through the
  17. standard enable_irq/irq_set_irq_type functions. This
  18. caused problems on pinctrl-bcm2835 which only implements
  19. the irq_enable/disable methods and not irq_unmask/mask.
  20. lirc-rpi: Correct the interrupt usage
  21. 1) Correct the use of enable_irq (i.e. don't call it so often)
  22. 2) Correct the shutdown sequence.
  23. 3) Avoid a bcm2708_gpio driver quirk by setting the irq flags earlier
  24. ---
  25. drivers/staging/media/lirc/Kconfig | 6 +
  26. drivers/staging/media/lirc/Makefile | 1 +
  27. drivers/staging/media/lirc/lirc_rpi.c | 659 ++++++++++++++++++++++++++++++++++
  28. 3 files changed, 666 insertions(+)
  29. create mode 100644 drivers/staging/media/lirc/lirc_rpi.c
  30. --- a/drivers/staging/media/lirc/Kconfig
  31. +++ b/drivers/staging/media/lirc/Kconfig
  32. @@ -38,6 +38,12 @@ config LIRC_PARALLEL
  33. help
  34. Driver for Homebrew Parallel Port Receivers
  35. +config LIRC_RPI
  36. + tristate "Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi"
  37. + depends on LIRC
  38. + help
  39. + Driver for Homebrew GPIO Port Receiver/Transmitter for the RaspberryPi
  40. +
  41. config LIRC_SASEM
  42. tristate "Sasem USB IR Remote"
  43. depends on LIRC && USB
  44. --- a/drivers/staging/media/lirc/Makefile
  45. +++ b/drivers/staging/media/lirc/Makefile
  46. @@ -7,6 +7,7 @@ obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o
  47. obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o
  48. obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
  49. obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o
  50. +obj-$(CONFIG_LIRC_RPI) += lirc_rpi.o
  51. obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o
  52. obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o
  53. obj-$(CONFIG_LIRC_SIR) += lirc_sir.o
  54. --- /dev/null
  55. +++ b/drivers/staging/media/lirc/lirc_rpi.c
  56. @@ -0,0 +1,659 @@
  57. +/*
  58. + * lirc_rpi.c
  59. + *
  60. + * lirc_rpi - Device driver that records pulse- and pause-lengths
  61. + * (space-lengths) (just like the lirc_serial driver does)
  62. + * between GPIO interrupt events on the Raspberry Pi.
  63. + * Lots of code has been taken from the lirc_serial module,
  64. + * so I would like say thanks to the authors.
  65. + *
  66. + * Copyright (C) 2012 Aron Robert Szabo <aron@reon.hu>,
  67. + * Michael Bishop <cleverca22@gmail.com>
  68. + * This program is free software; you can redistribute it and/or modify
  69. + * it under the terms of the GNU General Public License as published by
  70. + * the Free Software Foundation; either version 2 of the License, or
  71. + * (at your option) any later version.
  72. + *
  73. + * This program is distributed in the hope that it will be useful,
  74. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  75. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  76. + * GNU General Public License for more details.
  77. + *
  78. + * You should have received a copy of the GNU General Public License
  79. + * along with this program; if not, write to the Free Software
  80. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  81. + */
  82. +
  83. +#include <linux/module.h>
  84. +#include <linux/errno.h>
  85. +#include <linux/interrupt.h>
  86. +#include <linux/sched.h>
  87. +#include <linux/kernel.h>
  88. +#include <linux/time.h>
  89. +#include <linux/timex.h>
  90. +#include <linux/string.h>
  91. +#include <linux/delay.h>
  92. +#include <linux/platform_device.h>
  93. +#include <linux/irq.h>
  94. +#include <linux/spinlock.h>
  95. +#include <media/lirc.h>
  96. +#include <media/lirc_dev.h>
  97. +#include <mach/gpio.h>
  98. +#include <linux/gpio.h>
  99. +
  100. +#include <linux/platform_data/bcm2708.h>
  101. +
  102. +#define LIRC_DRIVER_NAME "lirc_rpi"
  103. +#define RBUF_LEN 256
  104. +#define LIRC_TRANSMITTER_LATENCY 50
  105. +
  106. +#ifndef MAX_UDELAY_MS
  107. +#define MAX_UDELAY_US 5000
  108. +#else
  109. +#define MAX_UDELAY_US (MAX_UDELAY_MS*1000)
  110. +#endif
  111. +
  112. +#define dprintk(fmt, args...) \
  113. + do { \
  114. + if (debug) \
  115. + printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \
  116. + fmt, ## args); \
  117. + } while (0)
  118. +
  119. +/* module parameters */
  120. +
  121. +/* set the default GPIO input pin */
  122. +static int gpio_in_pin = 18;
  123. +/* set the default pull behaviour for input pin */
  124. +static int gpio_in_pull = BCM2708_PULL_DOWN;
  125. +/* set the default GPIO output pin */
  126. +static int gpio_out_pin = 17;
  127. +/* enable debugging messages */
  128. +static bool debug;
  129. +/* -1 = auto, 0 = active high, 1 = active low */
  130. +static int sense = -1;
  131. +/* use softcarrier by default */
  132. +static bool softcarrier = 1;
  133. +/* 0 = do not invert output, 1 = invert output */
  134. +static bool invert = 0;
  135. +
  136. +struct gpio_chip *gpiochip;
  137. +static int irq_num;
  138. +
  139. +/* forward declarations */
  140. +static long send_pulse(unsigned long length);
  141. +static void send_space(long length);
  142. +static void lirc_rpi_exit(void);
  143. +
  144. +static struct platform_device *lirc_rpi_dev;
  145. +static struct timeval lasttv = { 0, 0 };
  146. +static struct lirc_buffer rbuf;
  147. +static spinlock_t lock;
  148. +
  149. +/* initialized/set in init_timing_params() */
  150. +static unsigned int freq = 38000;
  151. +static unsigned int duty_cycle = 50;
  152. +static unsigned long period;
  153. +static unsigned long pulse_width;
  154. +static unsigned long space_width;
  155. +
  156. +static void safe_udelay(unsigned long usecs)
  157. +{
  158. + while (usecs > MAX_UDELAY_US) {
  159. + udelay(MAX_UDELAY_US);
  160. + usecs -= MAX_UDELAY_US;
  161. + }
  162. + udelay(usecs);
  163. +}
  164. +
  165. +static int init_timing_params(unsigned int new_duty_cycle,
  166. + unsigned int new_freq)
  167. +{
  168. + if (1000 * 1000000L / new_freq * new_duty_cycle / 100 <=
  169. + LIRC_TRANSMITTER_LATENCY)
  170. + return -EINVAL;
  171. + if (1000 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <=
  172. + LIRC_TRANSMITTER_LATENCY)
  173. + return -EINVAL;
  174. + duty_cycle = new_duty_cycle;
  175. + freq = new_freq;
  176. + period = 1000 * 1000000L / freq;
  177. + pulse_width = period * duty_cycle / 100;
  178. + space_width = period - pulse_width;
  179. + dprintk("in init_timing_params, freq=%d pulse=%ld, "
  180. + "space=%ld\n", freq, pulse_width, space_width);
  181. + return 0;
  182. +}
  183. +
  184. +static long send_pulse_softcarrier(unsigned long length)
  185. +{
  186. + int flag;
  187. + unsigned long actual, target;
  188. + unsigned long actual_us, initial_us, target_us;
  189. +
  190. + length *= 1000;
  191. +
  192. + actual = 0; target = 0; flag = 0;
  193. + read_current_timer(&actual_us);
  194. +
  195. + while (actual < length) {
  196. + if (flag) {
  197. + gpiochip->set(gpiochip, gpio_out_pin, invert);
  198. + target += space_width;
  199. + } else {
  200. + gpiochip->set(gpiochip, gpio_out_pin, !invert);
  201. + target += pulse_width;
  202. + }
  203. + initial_us = actual_us;
  204. + target_us = actual_us + (target - actual) / 1000;
  205. + /*
  206. + * Note - we've checked in ioctl that the pulse/space
  207. + * widths are big enough so that d is > 0
  208. + */
  209. + if ((int)(target_us - actual_us) > 0)
  210. + udelay(target_us - actual_us);
  211. + read_current_timer(&actual_us);
  212. + actual += (actual_us - initial_us) * 1000;
  213. + flag = !flag;
  214. + }
  215. + return (actual-length) / 1000;
  216. +}
  217. +
  218. +static long send_pulse(unsigned long length)
  219. +{
  220. + if (length <= 0)
  221. + return 0;
  222. +
  223. + if (softcarrier) {
  224. + return send_pulse_softcarrier(length);
  225. + } else {
  226. + gpiochip->set(gpiochip, gpio_out_pin, !invert);
  227. + safe_udelay(length);
  228. + return 0;
  229. + }
  230. +}
  231. +
  232. +static void send_space(long length)
  233. +{
  234. + gpiochip->set(gpiochip, gpio_out_pin, invert);
  235. + if (length <= 0)
  236. + return;
  237. + safe_udelay(length);
  238. +}
  239. +
  240. +static void rbwrite(int l)
  241. +{
  242. + if (lirc_buffer_full(&rbuf)) {
  243. + /* no new signals will be accepted */
  244. + dprintk("Buffer overrun\n");
  245. + return;
  246. + }
  247. + lirc_buffer_write(&rbuf, (void *)&l);
  248. +}
  249. +
  250. +static void frbwrite(int l)
  251. +{
  252. + /* simple noise filter */
  253. + static int pulse, space;
  254. + static unsigned int ptr;
  255. +
  256. + if (ptr > 0 && (l & PULSE_BIT)) {
  257. + pulse += l & PULSE_MASK;
  258. + if (pulse > 250) {
  259. + rbwrite(space);
  260. + rbwrite(pulse | PULSE_BIT);
  261. + ptr = 0;
  262. + pulse = 0;
  263. + }
  264. + return;
  265. + }
  266. + if (!(l & PULSE_BIT)) {
  267. + if (ptr == 0) {
  268. + if (l > 20000) {
  269. + space = l;
  270. + ptr++;
  271. + return;
  272. + }
  273. + } else {
  274. + if (l > 20000) {
  275. + space += pulse;
  276. + if (space > PULSE_MASK)
  277. + space = PULSE_MASK;
  278. + space += l;
  279. + if (space > PULSE_MASK)
  280. + space = PULSE_MASK;
  281. + pulse = 0;
  282. + return;
  283. + }
  284. + rbwrite(space);
  285. + rbwrite(pulse | PULSE_BIT);
  286. + ptr = 0;
  287. + pulse = 0;
  288. + }
  289. + }
  290. + rbwrite(l);
  291. +}
  292. +
  293. +static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs)
  294. +{
  295. + struct timeval tv;
  296. + long deltv;
  297. + int data;
  298. + int signal;
  299. +
  300. + /* use the GPIO signal level */
  301. + signal = gpiochip->get(gpiochip, gpio_in_pin);
  302. +
  303. + if (sense != -1) {
  304. + /* get current time */
  305. + do_gettimeofday(&tv);
  306. +
  307. + /* calc time since last interrupt in microseconds */
  308. + deltv = tv.tv_sec-lasttv.tv_sec;
  309. + if (tv.tv_sec < lasttv.tv_sec ||
  310. + (tv.tv_sec == lasttv.tv_sec &&
  311. + tv.tv_usec < lasttv.tv_usec)) {
  312. + printk(KERN_WARNING LIRC_DRIVER_NAME
  313. + ": AIEEEE: your clock just jumped backwards\n");
  314. + printk(KERN_WARNING LIRC_DRIVER_NAME
  315. + ": %d %d %lx %lx %lx %lx\n", signal, sense,
  316. + tv.tv_sec, lasttv.tv_sec,
  317. + tv.tv_usec, lasttv.tv_usec);
  318. + data = PULSE_MASK;
  319. + } else if (deltv > 15) {
  320. + data = PULSE_MASK; /* really long time */
  321. + if (!(signal^sense)) {
  322. + /* sanity check */
  323. + printk(KERN_WARNING LIRC_DRIVER_NAME
  324. + ": AIEEEE: %d %d %lx %lx %lx %lx\n",
  325. + signal, sense, tv.tv_sec, lasttv.tv_sec,
  326. + tv.tv_usec, lasttv.tv_usec);
  327. + /*
  328. + * detecting pulse while this
  329. + * MUST be a space!
  330. + */
  331. + sense = sense ? 0 : 1;
  332. + }
  333. + } else {
  334. + data = (int) (deltv*1000000 +
  335. + (tv.tv_usec - lasttv.tv_usec));
  336. + }
  337. + frbwrite(signal^sense ? data : (data|PULSE_BIT));
  338. + lasttv = tv;
  339. + wake_up_interruptible(&rbuf.wait_poll);
  340. + }
  341. +
  342. + return IRQ_HANDLED;
  343. +}
  344. +
  345. +static int is_right_chip(struct gpio_chip *chip, void *data)
  346. +{
  347. + dprintk("is_right_chip %s %d\n", chip->label, strcmp(data, chip->label));
  348. +
  349. + if (strcmp(data, chip->label) == 0)
  350. + return 1;
  351. + return 0;
  352. +}
  353. +
  354. +static int init_port(void)
  355. +{
  356. + int i, nlow, nhigh, ret;
  357. +
  358. + gpiochip = gpiochip_find("bcm2708_gpio", is_right_chip);
  359. +
  360. + if (!gpiochip)
  361. + return -ENODEV;
  362. +
  363. + if (gpio_request(gpio_out_pin, LIRC_DRIVER_NAME " ir/out")) {
  364. + printk(KERN_ALERT LIRC_DRIVER_NAME
  365. + ": cant claim gpio pin %d\n", gpio_out_pin);
  366. + ret = -ENODEV;
  367. + goto exit_init_port;
  368. + }
  369. +
  370. + if (gpio_request(gpio_in_pin, LIRC_DRIVER_NAME " ir/in")) {
  371. + printk(KERN_ALERT LIRC_DRIVER_NAME
  372. + ": cant claim gpio pin %d\n", gpio_in_pin);
  373. + ret = -ENODEV;
  374. + goto exit_gpio_free_out_pin;
  375. + }
  376. +
  377. + bcm2708_gpio_setpull(gpiochip, gpio_in_pin, gpio_in_pull);
  378. + gpiochip->direction_input(gpiochip, gpio_in_pin);
  379. + gpiochip->direction_output(gpiochip, gpio_out_pin, 1);
  380. + gpiochip->set(gpiochip, gpio_out_pin, invert);
  381. +
  382. + irq_num = gpiochip->to_irq(gpiochip, gpio_in_pin);
  383. + dprintk("to_irq %d\n", irq_num);
  384. +
  385. + /* if pin is high, then this must be an active low receiver. */
  386. + if (sense == -1) {
  387. + /* wait 1/2 sec for the power supply */
  388. + msleep(500);
  389. +
  390. + /*
  391. + * probe 9 times every 0.04s, collect "votes" for
  392. + * active high/low
  393. + */
  394. + nlow = 0;
  395. + nhigh = 0;
  396. + for (i = 0; i < 9; i++) {
  397. + if (gpiochip->get(gpiochip, gpio_in_pin))
  398. + nlow++;
  399. + else
  400. + nhigh++;
  401. + msleep(40);
  402. + }
  403. + sense = (nlow >= nhigh ? 1 : 0);
  404. + printk(KERN_INFO LIRC_DRIVER_NAME
  405. + ": auto-detected active %s receiver on GPIO pin %d\n",
  406. + sense ? "low" : "high", gpio_in_pin);
  407. + } else {
  408. + printk(KERN_INFO LIRC_DRIVER_NAME
  409. + ": manually using active %s receiver on GPIO pin %d\n",
  410. + sense ? "low" : "high", gpio_in_pin);
  411. + }
  412. +
  413. + return 0;
  414. +
  415. + exit_gpio_free_out_pin:
  416. + gpio_free(gpio_out_pin);
  417. +
  418. + exit_init_port:
  419. + return ret;
  420. +}
  421. +
  422. +// called when the character device is opened
  423. +static int set_use_inc(void *data)
  424. +{
  425. + int result;
  426. +
  427. + /* initialize timestamp */
  428. + do_gettimeofday(&lasttv);
  429. +
  430. + result = request_irq(irq_num,
  431. + (irq_handler_t) irq_handler,
  432. + IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING,
  433. + LIRC_DRIVER_NAME, (void*) 0);
  434. +
  435. + switch (result) {
  436. + case -EBUSY:
  437. + printk(KERN_ERR LIRC_DRIVER_NAME
  438. + ": IRQ %d is busy\n",
  439. + irq_num);
  440. + return -EBUSY;
  441. + case -EINVAL:
  442. + printk(KERN_ERR LIRC_DRIVER_NAME
  443. + ": Bad irq number or handler\n");
  444. + return -EINVAL;
  445. + default:
  446. + dprintk("Interrupt %d obtained\n",
  447. + irq_num);
  448. + break;
  449. + };
  450. +
  451. + /* initialize pulse/space widths */
  452. + init_timing_params(duty_cycle, freq);
  453. +
  454. + return 0;
  455. +}
  456. +
  457. +static void set_use_dec(void *data)
  458. +{
  459. + /* GPIO Pin Falling/Rising Edge Detect Disable */
  460. + irq_set_irq_type(irq_num, 0);
  461. + disable_irq(irq_num);
  462. +
  463. + free_irq(irq_num, (void *) 0);
  464. +
  465. + dprintk(KERN_INFO LIRC_DRIVER_NAME
  466. + ": freed IRQ %d\n", irq_num);
  467. +}
  468. +
  469. +static ssize_t lirc_write(struct file *file, const char *buf,
  470. + size_t n, loff_t *ppos)
  471. +{
  472. + int i, count;
  473. + unsigned long flags;
  474. + long delta = 0;
  475. + int *wbuf;
  476. +
  477. + count = n / sizeof(int);
  478. + if (n % sizeof(int) || count % 2 == 0)
  479. + return -EINVAL;
  480. + wbuf = memdup_user(buf, n);
  481. + if (IS_ERR(wbuf))
  482. + return PTR_ERR(wbuf);
  483. + spin_lock_irqsave(&lock, flags);
  484. +
  485. + for (i = 0; i < count; i++) {
  486. + if (i%2)
  487. + send_space(wbuf[i] - delta);
  488. + else
  489. + delta = send_pulse(wbuf[i]);
  490. + }
  491. + gpiochip->set(gpiochip, gpio_out_pin, invert);
  492. +
  493. + spin_unlock_irqrestore(&lock, flags);
  494. + kfree(wbuf);
  495. + return n;
  496. +}
  497. +
  498. +static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  499. +{
  500. + int result;
  501. + __u32 value;
  502. +
  503. + switch (cmd) {
  504. + case LIRC_GET_SEND_MODE:
  505. + return -ENOIOCTLCMD;
  506. + break;
  507. +
  508. + case LIRC_SET_SEND_MODE:
  509. + result = get_user(value, (__u32 *) arg);
  510. + if (result)
  511. + return result;
  512. + /* only LIRC_MODE_PULSE supported */
  513. + if (value != LIRC_MODE_PULSE)
  514. + return -ENOSYS;
  515. + break;
  516. +
  517. + case LIRC_GET_LENGTH:
  518. + return -ENOSYS;
  519. + break;
  520. +
  521. + case LIRC_SET_SEND_DUTY_CYCLE:
  522. + dprintk("SET_SEND_DUTY_CYCLE\n");
  523. + result = get_user(value, (__u32 *) arg);
  524. + if (result)
  525. + return result;
  526. + if (value <= 0 || value > 100)
  527. + return -EINVAL;
  528. + return init_timing_params(value, freq);
  529. + break;
  530. +
  531. + case LIRC_SET_SEND_CARRIER:
  532. + dprintk("SET_SEND_CARRIER\n");
  533. + result = get_user(value, (__u32 *) arg);
  534. + if (result)
  535. + return result;
  536. + if (value > 500000 || value < 20000)
  537. + return -EINVAL;
  538. + return init_timing_params(duty_cycle, value);
  539. + break;
  540. +
  541. + default:
  542. + return lirc_dev_fop_ioctl(filep, cmd, arg);
  543. + }
  544. + return 0;
  545. +}
  546. +
  547. +static const struct file_operations lirc_fops = {
  548. + .owner = THIS_MODULE,
  549. + .write = lirc_write,
  550. + .unlocked_ioctl = lirc_ioctl,
  551. + .read = lirc_dev_fop_read,
  552. + .poll = lirc_dev_fop_poll,
  553. + .open = lirc_dev_fop_open,
  554. + .release = lirc_dev_fop_close,
  555. + .llseek = no_llseek,
  556. +};
  557. +
  558. +static struct lirc_driver driver = {
  559. + .name = LIRC_DRIVER_NAME,
  560. + .minor = -1,
  561. + .code_length = 1,
  562. + .sample_rate = 0,
  563. + .data = NULL,
  564. + .add_to_buf = NULL,
  565. + .rbuf = &rbuf,
  566. + .set_use_inc = set_use_inc,
  567. + .set_use_dec = set_use_dec,
  568. + .fops = &lirc_fops,
  569. + .dev = NULL,
  570. + .owner = THIS_MODULE,
  571. +};
  572. +
  573. +static struct platform_driver lirc_rpi_driver = {
  574. + .driver = {
  575. + .name = LIRC_DRIVER_NAME,
  576. + .owner = THIS_MODULE,
  577. + },
  578. +};
  579. +
  580. +static int __init lirc_rpi_init(void)
  581. +{
  582. + int result;
  583. +
  584. + /* Init read buffer. */
  585. + result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
  586. + if (result < 0)
  587. + return -ENOMEM;
  588. +
  589. + result = platform_driver_register(&lirc_rpi_driver);
  590. + if (result) {
  591. + printk(KERN_ERR LIRC_DRIVER_NAME
  592. + ": lirc register returned %d\n", result);
  593. + goto exit_buffer_free;
  594. + }
  595. +
  596. + lirc_rpi_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
  597. + if (!lirc_rpi_dev) {
  598. + result = -ENOMEM;
  599. + goto exit_driver_unregister;
  600. + }
  601. +
  602. + result = platform_device_add(lirc_rpi_dev);
  603. + if (result)
  604. + goto exit_device_put;
  605. +
  606. + return 0;
  607. +
  608. + exit_device_put:
  609. + platform_device_put(lirc_rpi_dev);
  610. +
  611. + exit_driver_unregister:
  612. + platform_driver_unregister(&lirc_rpi_driver);
  613. +
  614. + exit_buffer_free:
  615. + lirc_buffer_free(&rbuf);
  616. +
  617. + return result;
  618. +}
  619. +
  620. +static void lirc_rpi_exit(void)
  621. +{
  622. + if (!lirc_rpi_dev->dev.of_node)
  623. + platform_device_unregister(lirc_rpi_dev);
  624. + platform_driver_unregister(&lirc_rpi_driver);
  625. + lirc_buffer_free(&rbuf);
  626. +}
  627. +
  628. +static int __init lirc_rpi_init_module(void)
  629. +{
  630. + int result;
  631. +
  632. + result = lirc_rpi_init();
  633. + if (result)
  634. + return result;
  635. +
  636. + if (gpio_in_pin >= BCM2708_NR_GPIOS || gpio_out_pin >= BCM2708_NR_GPIOS) {
  637. + result = -EINVAL;
  638. + printk(KERN_ERR LIRC_DRIVER_NAME
  639. + ": invalid GPIO pin(s) specified!\n");
  640. + goto exit_rpi;
  641. + }
  642. +
  643. + result = init_port();
  644. + if (result < 0)
  645. + goto exit_rpi;
  646. +
  647. + driver.features = LIRC_CAN_SET_SEND_DUTY_CYCLE |
  648. + LIRC_CAN_SET_SEND_CARRIER |
  649. + LIRC_CAN_SEND_PULSE |
  650. + LIRC_CAN_REC_MODE2;
  651. +
  652. + driver.dev = &lirc_rpi_dev->dev;
  653. + driver.minor = lirc_register_driver(&driver);
  654. +
  655. + if (driver.minor < 0) {
  656. + printk(KERN_ERR LIRC_DRIVER_NAME
  657. + ": device registration failed with %d\n", result);
  658. + result = -EIO;
  659. + goto exit_rpi;
  660. + }
  661. +
  662. + printk(KERN_INFO LIRC_DRIVER_NAME ": driver registered!\n");
  663. +
  664. + return 0;
  665. +
  666. + exit_rpi:
  667. + lirc_rpi_exit();
  668. +
  669. + return result;
  670. +}
  671. +
  672. +static void __exit lirc_rpi_exit_module(void)
  673. +{
  674. + lirc_unregister_driver(driver.minor);
  675. +
  676. + gpio_free(gpio_out_pin);
  677. + gpio_free(gpio_in_pin);
  678. +
  679. + lirc_rpi_exit();
  680. +
  681. + printk(KERN_INFO LIRC_DRIVER_NAME ": cleaned up module\n");
  682. +}
  683. +
  684. +module_init(lirc_rpi_init_module);
  685. +module_exit(lirc_rpi_exit_module);
  686. +
  687. +MODULE_DESCRIPTION("Infra-red receiver and blaster driver for Raspberry Pi GPIO.");
  688. +MODULE_AUTHOR("Aron Robert Szabo <aron@reon.hu>");
  689. +MODULE_AUTHOR("Michael Bishop <cleverca22@gmail.com>");
  690. +MODULE_LICENSE("GPL");
  691. +
  692. +module_param(gpio_out_pin, int, S_IRUGO);
  693. +MODULE_PARM_DESC(gpio_out_pin, "GPIO output/transmitter pin number of the BCM"
  694. + " processor. (default 17");
  695. +
  696. +module_param(gpio_in_pin, int, S_IRUGO);
  697. +MODULE_PARM_DESC(gpio_in_pin, "GPIO input pin number of the BCM processor."
  698. + " (default 18");
  699. +
  700. +module_param(gpio_in_pull, int, S_IRUGO);
  701. +MODULE_PARM_DESC(gpio_in_pull, "GPIO input pin pull configuration."
  702. + " (0 = off, 1 = up, 2 = down, default down)");
  703. +
  704. +module_param(sense, int, S_IRUGO);
  705. +MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit"
  706. + " (0 = active high, 1 = active low )");
  707. +
  708. +module_param(softcarrier, bool, S_IRUGO);
  709. +MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)");
  710. +
  711. +module_param(invert, bool, S_IRUGO);
  712. +MODULE_PARM_DESC(invert, "Invert output (0 = off, 1 = on, default off");
  713. +
  714. +module_param(debug, bool, S_IRUGO | S_IWUSR);
  715. +MODULE_PARM_DESC(debug, "Enable debugging messages");