Hi, On 04/25/2014 11:38 AM, Александр Берсенев wrote: > This patch introduces Consumer IR(CIR) support for cubietruck. It was > ported > from sunxi linux 3.4 and supports only NEC protocol. > > Changes from the original driver: > - moved kernel's Input Subsystem API > - initialization code was rewritten > - using devm_ functions to simplify cleanup > - moved gpio and timers initialization to *.dts and *.dtsi files > - using sun7i_ir_data struct to hold driver state instead of global vars > - obtain mmio adresses dynamicly instead of using fixed adresses like > 0xf1c200b0 > > It was tested on 20 A20 boards. Now it only works on Cubietrucks, but I > believe > it is not hard to make it work on other sunxi architectures. > > Alexander Bersenev, Institute of Mathematics and Mechanics, Russia > > Signed-off-by: Alexander Bersenev <b...@hackerdom.ru>
First of all many thanks for working on this! Besides all the very useful remarks Julian has already made, I've one very important remark. The original allwinner code uses its own ir protocol decoding code, and I see that your version uses this too. This is not acceptable for upstream kernel inclusion. You should modify the code to use the existing in kernel ir decoders instead, this should also give you support for more protocols then just the nec protocol. For an example of a driver using the existing in kernel ir decoders see: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/media/rc/st_rc.c Note your new driver should probably also live under drivers/media/rc and as such should be send upstream through the linux-media mailinglist. One last remark, you use "raw" printk in several places, please use dev_err, dev_err, etc. instead. Regards, Hans > > diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts > b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts > index ebf6a2f..42e79a9 100644 > --- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts > +++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts > @@ -121,6 +121,13 @@ > }; > }; > > + ir: ir@01c21800 { > + pinctrl-names = "default"; > + pinctrl-0 = <&ir_pin_cubietruck>; > + gpios = <&pio 1 4 0>; > + }; > + > + > uart0: serial@01c28000 { > pinctrl-names = "default"; > pinctrl-0 = <&uart0_pins_a>; > diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi > b/arch/arm/boot/dts/sun7i-a20.dtsi > index 15ea85e..c0202c6 100644 > --- a/arch/arm/boot/dts/sun7i-a20.dtsi > +++ b/arch/arm/boot/dts/sun7i-a20.dtsi > @@ -85,6 +85,14 @@ > clock-output-names = "pll1"; > }; > > + pll3: clk@01c20010 { > + #clock-cells = <0>; > + compatible = "allwinner,sun4i-a10-pll1-clk"; > + reg = <0x01c20010 0x4>; > + clocks = <&osc24M>; > + clock-output-names = "pll3"; > + }; > + > pll4: clk@01c20018 { > #clock-cells = <0>; > compatible = "allwinner,sun4i-a10-pll1-clk"; > @@ -302,6 +310,7 @@ > compatible = "allwinner,sun4i-a10-mod0-clk"; > reg = <0x01c200b0 0x4>; > clocks = <&osc24M>, <&pll6 1>, <&pll5 1>; > + clock-frequency = <3000000>; > clock-output-names = "ir0"; > }; > > @@ -591,6 +600,13 @@ > allwinner,pull = <0>; > }; > > + ir_pin_cubietruck: ir_pin@0 { > + allwinner,pins = "PB4"; > + allwinner,function = "ir0"; > + allwinner,drive = <0>; > + allwinner,pull = <0>; > + }; > + > uart2_pins_a: uart2@0 { > allwinner,pins = "PI16", "PI17", "PI18", "PI19"; > allwinner,function = "uart2"; > @@ -750,6 +766,14 @@ > status = "disabled"; > }; > > + ir: ir@01c21800 { > + compatible = "allwinner,sun7i-a20-ir"; > + reg = <0x01c21800 0x100>; > + interrupts = <0 5 4>; > + clocks = <&apb0_gates 6>, <&ir0_clk>; > + }; > + > + > sid: eeprom@01c23800 { > compatible = "allwinner,sun7i-a20-sid"; > reg = <0x01c23800 0x200>; > @@ -931,5 +955,14 @@ > #interrupt-cells = <3>; > interrupts = <1 9 0xf04>; > }; > + > + timer { > + compatible ="arm,armv7-timer"; > + interrupts = <1 13 0x308>, > + <1 14 0x308>, > + <1 11 0x308>, > + <1 10 0x308>; > + clock-frequency = <24000000>; > + }; > }; > }; > diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c > index 3be8846..83a20fa 100644 > --- a/drivers/clk/sunxi/clk-sunxi.c > +++ b/drivers/clk/sunxi/clk-sunxi.c > @@ -1036,11 +1036,17 @@ static void __init sunxi_gates_clk_setup(struct > device_node *node, > /* No driver claims this clock, but it should remain gated */ > ignore = !strcmp("ahb_sdram", clk_name) ? CLK_IGNORE_UNUSED : 0; > > + > clk_data->clks[i] = clk_register_gate(NULL, clk_name, > clk_parent, ignore, > reg + 4 * (i/32), i % 32, > 0, &clk_lock); > WARN_ON(IS_ERR(clk_data->clks[i])); > + > + if(!IS_ERR(clk_data->clks[i])) { > + clk_register_clkdev(clk_data->clks[i], clk_name, NULL); > + } > + > > j++; > } > diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig > index d8a51cd..53d778f 100644 > --- a/drivers/input/keyboard/Kconfig > +++ b/drivers/input/keyboard/Kconfig > @@ -662,4 +662,10 @@ config KEYBOARD_CROS_EC > To compile this driver as a module, choose M here: the > module will be called cros_ec_keyb. > > +config IR_SUNXI > + tristate "sunxi IR support" > + > endif > + > + > + > diff --git a/drivers/input/keyboard/Makefile > b/drivers/input/keyboard/Makefile > index f3265bd..97bc1b7 100644 > --- a/drivers/input/keyboard/Makefile > +++ b/drivers/input/keyboard/Makefile > @@ -58,3 +58,4 @@ obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o > obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o > obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o > obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o > +obj-$(CONFIG_IR_SUNXI) += sunxi-ir.o > diff --git a/drivers/input/keyboard/sunxi-ir.c > b/drivers/input/keyboard/sunxi-ir.c > new file mode 100644 > index 0000000..ca37a4b > --- /dev/null > +++ b/drivers/input/keyboard/sunxi-ir.c > @@ -0,0 +1,576 @@ > +/* > + * drivers/input/keyboard/sunxi-ir.c > + * > + * (C) Copyright 2007-2012 > + * Allwinner Technology Co., Ltd. <www.allwinnertech.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/init.h> > +#include <linux/input.h> > +#include <linux/delay.h> > +#include <linux/interrupt.h> > +#include <linux/keyboard.h> > +#include <linux/ioport.h> > +#include <asm/irq.h> > +#include <linux/io.h> > +#include <linux/slab.h> > +#include <linux/timer.h> > +#include <linux/irq.h> > +#include <linux/of_platform.h> > +#include <linux/clk.h> > +#include <linux/clk-provider.h> > + > + > +#include "ir-keymap.h" > + > +#define MAX_KEYS 256 > + > +#ifdef DEBUG_IR > +#define DEBUG_IR_LEVEL0 > +#define DEBUG_IR_LEVEL1 > +#define dprintk(level, fmt, arg...) (if (debug >= level) \ > + printk(KERN_DEBUG fmt , ## arg)) > +#else > +#undef DEBUG_IR_LEVEL0 > +#undef DEBUG_IR_LEVEL1 > +#define dprintk(level, fmt, arg...) > +#endif > + > +// > +/* Registers */ > +#define IR_REG(x) (x) > + > +#define IR_CTRL_REG IR_REG(0x00) /* IR Control */ > +#define IR_RXCFG_REG IR_REG(0x10) /* Rx Config */ > +#define IR_RXDAT_REG IR_REG(0x20) /* Rx Data */ > +#define IR_RXINTE_REG IR_REG(0x2c) /* Rx Interrupt Enable */ > +#define IR_RXINTS_REG IR_REG(0x30) /* Rx Interrupt Status */ > +#define IR_SPLCFG_REG IR_REG(0x34) /* IR Sample Config */ > + > +/* Bit Definition of IR_RXINTS_REG Register */ > +#define IR_RXINTS_RXOF (0x1 << 0) /* Rx FIFO Overflow */ > +#define IR_RXINTS_RXPE (0x1 << 1) /* Rx Packet End */ > +#define IR_RXINTS_RXDA (0x1 << 4) /* Rx FIFO Data Available */ > + > +#ifdef CONFIG_ARCH_SUN5I > +#define IR_FIFO_SIZE 64 /* 64Bytes */ > +#else > +#define IR_FIFO_SIZE 16 /* 16Bytes */ > +#endif > +/* Frequency of Sample Clock = 23437.5Hz, Cycle is 42.7us */ > +/* Pulse of NEC Remote >560us */ > +#define IR_RXFILT_VAL 8 /* Filter Threshold = 8*42.7 = ~341us < 500us */ > +#define IR_RXIDLE_VAL 2 /* Idle Threshold = (2+1)*128*42.7 = ~16.4ms > 9ms > */ > + > +#define IR_L1_MIN 80 /* 80*42.7 = ~3.4ms, Lead1(4.5ms) > IR_L1_MIN */ > +#define IR_L0_MIN 40 /* 40*42.7 = ~1.7ms, Lead0(4.5ms) Lead0R(2.25ms)> > IR_L0_MIN */ > +#define IR_PMAX 26 /* 26*42.7 = ~1109us ~= 561*2, Pluse < IR_PMAX */ > +#define IR_DMID 26 /* 26*42.7 = ~1109us ~= 561*2, D1 > IR_DMID, D0 =< > IR_DMID */ > +#define IR_DMAX 53 /* 53*42.7 = ~2263us ~= 561*4, D < IR_DMAX */ > + > +#define IR_RAW_BUF_SIZE 128 > +#define IR_ERROR_CODE 0xffffffff > +#define IR_REPEAT_CODE 0x00000000 > +#define DRV_VERSION "1.00" > + > +struct ir_raw_buffer { > + unsigned long dcnt; /*Packet Count*/ > + unsigned char buf[IR_RAW_BUF_SIZE]; > +}; > + > +#ifdef DEBUG_IR > +static int debug = 8; > +#endif > + > + > +struct sun7i_ir_data { > + struct device *dev; > + struct input_dev *input; > + void __iomem *base; > + > + u32 ir_keycodes[MAX_KEYS]; > + unsigned long ir_code; > + int timer_used; > + > + struct ir_raw_buffer ir_rawbuf; > + > + unsigned int ir_cnt; > + struct timer_list *s_timer; > +}; > + > + > +static inline void ir_reset_rawbuffer(struct sun7i_ir_data *ir) > +{ > + ir->ir_rawbuf.dcnt = 0; > +} > + > +static inline void ir_write_rawbuffer(struct sun7i_ir_data *ir, unsigned > char data) > +{ > + if (ir->ir_rawbuf.dcnt < IR_RAW_BUF_SIZE) > + ir->ir_rawbuf.buf[ir->ir_rawbuf.dcnt++] = data; > + else > + printk("ir_write_rawbuffer: IR Rx buffer full\n"); > +} > + > +static inline unsigned char ir_read_rawbuffer(struct sun7i_ir_data *ir) > +{ > + unsigned char data = 0x00; > + > + if (ir->ir_rawbuf.dcnt > 0) > + data = ir->ir_rawbuf.buf[--ir->ir_rawbuf.dcnt]; > + > + return data; > +} > + > +static inline int ir_rawbuffer_empty(struct sun7i_ir_data *ir) > +{ > + return (ir->ir_rawbuf.dcnt == 0); > +} > + > +static inline int ir_rawbuffer_full(struct sun7i_ir_data *ir) > +{ > + return (ir->ir_rawbuf.dcnt >= IR_RAW_BUF_SIZE); > +} > + > +static void ir_clk_cfg(struct sun7i_ir_data *ir) > +{ > + struct clk *apb_clk; > + struct clk *apb_ir_clk; > + struct clk *ir_clk; > + > + unsigned long rate = 3000000; /* 3 MHz */ > + unsigned long tmp = 0; > + > + apb_ir_clk = devm_clk_get(ir->dev, "apb0_ir0"); > + if (IS_ERR(apb_ir_clk)) { > + printk(KERN_ERR "try to get apb_ir0 clock failed\n"); > + return; > + } > + > + if (clk_prepare_enable(apb_ir_clk)) { > + printk("try to enable apb_ir_clk failed\n"); > + return; > + } > + > + > + ir_clk = devm_clk_get(ir->dev, "ir0"); > + if (IS_ERR(ir_clk)) { > + printk("try to get ir0 clock failed\n"); > + return; > + } > + > + if (clk_set_rate(ir_clk, rate)) { > + printk("set ir0 clock freq to 3M failed\n"); > + return; > + } > + > + if (clk_prepare_enable(ir_clk)) { > + printk("try to enable ir_clk failed\n"); > + return; > + } > +} > + > +static void ir_reg_cfg(struct sun7i_ir_data *ir) > +{ > + unsigned long tmp = 0; > + /* Enable IR Mode */ > + tmp = 0x3 << 4; // 110000 > + writel(tmp, ir->base + IR_CTRL_REG); > + > + /* Config IR Sample Register */ > + tmp = 0x1 << 0; /* Fsample = 3MHz/128 =23437.5Hz (42.7us) */ > + > + tmp |= (IR_RXFILT_VAL & 0x3f) << 2; /* Set Filter Threshold */ > + tmp |= (IR_RXIDLE_VAL & 0xff) << 8; /* Set Idle Threshold */ > + writel(tmp, ir->base + IR_SPLCFG_REG); > + > + /* Invert Input Signal */ > + writel(0x1 << 2, ir->base + IR_RXCFG_REG); > + > + /* Clear All Rx Interrupt Status */ > + writel(0xff, ir->base + IR_RXINTS_REG); > + > + /* Set Rx Interrupt Enable */ > + tmp = (0x1 << 4) | 0x3; > +// #ifdef CONFIG_ARCH_SUN5I > + tmp |= ((IR_FIFO_SIZE >> 2) - 1) << 8; /* Rx FIFO Threshold = FIFOsz/4 */ > +// #else > + // tmp |= ((IR_FIFO_SIZE >> 1) - 1) << 8; /* Rx FIFO Threshold = FIFOsz/2 > */ > +// #endif > + writel(tmp, ir->base + IR_RXINTE_REG); > + > + /* Enable IR Module */ > + tmp = readl(ir->base + IR_CTRL_REG); > + tmp |= 0x3; > + writel(tmp, ir->base + IR_CTRL_REG); > +} > + > +static void ir_setup(struct sun7i_ir_data *ir) > +{ > + dprintk(2, "ir_setup: ir setup start!!\n"); > + > + ir->ir_code = 0; > + ir->timer_used = 0; > + > + ir_reset_rawbuffer(ir); > + ir_clk_cfg(ir); > + ir_reg_cfg(ir); > + > + dprintk(2, "ir_setup: ir setup end!!\n"); > +} > + > +static inline unsigned char ir_get_data(struct sun7i_ir_data *ir) > +{ > + return (unsigned char)(readl(ir->base + IR_RXDAT_REG)); > +} > + > +static inline unsigned long ir_get_intsta(struct sun7i_ir_data *ir) > +{ > + return readl(ir->base + IR_RXINTS_REG); > +} > + > +static inline void ir_clr_intsta(struct sun7i_ir_data *ir, unsigned long > bitmap) > +{ > + unsigned long tmp = readl(ir->base + IR_RXINTS_REG); > + > + tmp &= ~0xff; > + tmp |= bitmap&0xff; > + writel(tmp, ir->base + IR_RXINTS_REG); > +} > + > +static unsigned long ir_packet_handler(unsigned char *buf, unsigned long > dcnt) > +{ > + unsigned long len; > + unsigned char val = 0x00; > + unsigned char last = 0x00; > + unsigned long code = 0; > + int bitcnt = 0; > + unsigned long i = 0; > + > + dprintk(2, "dcnt = %d\n", (int)dcnt); > + > + /* Find Lead '1' */ > + len = 0; > + for (i = 0; i < dcnt; i++) { > + val = buf[i]; > + if (val & 0x80) { > + len += val & 0x7f; > + } else { > + if (len > IR_L1_MIN) > + break; > + len = 0; > + } > + } > + > + if ((val & 0x80) || (len <= IR_L1_MIN)) > + return IR_ERROR_CODE; /* Invalid Code */ > + > + /*Find Lead '0'*/ > + len = 0; > + for (; i < dcnt; i++) { > + val = buf[i]; > + if (val & 0x80) { > + if (len > IR_L0_MIN) > + break; > + len = 0; > + } else { > + len += val & 0x7f; > + } > + } > + > + if ((!(val & 0x80)) || (len <= IR_L0_MIN)) > + return IR_ERROR_CODE; /* Invalid Code */ > + > + /* go decoding */ > + code = 0; /* 0 for Repeat Code */ > + bitcnt = 0; > + last = 1; > + len = 0; > + for (; i < dcnt; i++) { > + val = buf[i]; > + if (last) { > + if (val & 0x80) { > + len += val & 0x7f; > + } else { > + if (len > IR_PMAX) /* Error Pulse */ > + return IR_ERROR_CODE; > + last = 0; > + len = val & 0x7f; > + } > + } else { > + if (val & 0x80) { > + if (len > IR_DMAX) { /* Error Distant */ > + return IR_ERROR_CODE; > + } else { > + if (len > IR_DMID) > + /*data '1'*/ > + code |= 1 << bitcnt; > + bitcnt++; > + if (bitcnt == 32) > + break; /* decode over */ > + } > + last = 1; > + len = val & 0x7f; > + } else { > + len += val & 0x7f; > + } > + } > + } > + > + return code; > +} > + > +static int ir_code_valid(unsigned long code) > +{ > + unsigned long tmp1, tmp2; > + > +#ifdef IR_CHECK_ADDR_CODE > + /* Check Address Value */ > + if ((code & 0xffff) != (IR_ADDR_CODE & 0xffff)) > + return 0; /* Address Error */ > + > + tmp1 = code & 0x00ff0000; > + tmp2 = (code & 0xff000000) >> 8; > + > + return ((tmp1 ^ tmp2) == 0x00ff0000); /* Check User Code */ > +#else > + /* Do Not Check Address Value */ > + tmp1 = code & 0x00ff00ff; > + tmp2 = (code & 0xff00ff00) >> 8; > + > + return (((tmp1 ^ tmp2) & 0x00ff0000) == 0x00ff0000); > +#endif /* IR_CHECK_ADDR_CODE */ > +} > + > + > +static void ir_timer_handle(unsigned long arg) > +{ > + struct sun7i_ir_data *ir = (struct sun7i_ir_data *) arg; > + > + del_timer(ir->s_timer); > + ir->timer_used = 0; > +// /* Time Out, means that the key is up */ > + input_report_key(ir->input, ir->ir_keycodes[(ir->ir_code >> 16) & 0xff], > 0); > + input_sync(ir->input); > +#ifdef DEBUG_IR_LEVEL1 > + printk("IR KEY TIMER OUT UP\n"); > +#endif > + ir->ir_cnt = 0; > + > + dprintk(2, "ir_timer_handle: timeout\n"); > +} > + > + > +static irqreturn_t sun7i_ir_irq(int irq, void *dev_id) > +{ > + struct sun7i_ir_data *ir = dev_id; > + > + unsigned long dcnt; > + unsigned long i = 0; > + unsigned long intsta; > + > + intsta = ir_get_intsta(ir); > + > + ir_clr_intsta(ir, intsta); > + > +// /* Read Data Every Time Enter this Routine*/ > +// #ifdef CONFIG_ARCH_SUN5I > +// dcnt = (ir_get_intsta() >> 8) & 0x3f; > +// #else > + dcnt = (ir_get_intsta(ir) >> 8) & 0x1f; > +// #endif > + > +// /* Read FIFO */ > + for (i = 0; i < dcnt; i++) { > + if (ir_rawbuffer_full(ir)) { > +#ifdef DEBUG_IR_LEVEL0 > + printk("ir_irq_service: raw buffer full\n"); > +#endif > + break; > + } else { > + ir_write_rawbuffer(ir, ir_get_data(ir)); > + } > + } > + > + if (intsta & IR_RXINTS_RXPE) { /* Packet End */ > + unsigned long code; > + int code_valid; > + > + code = ir_packet_handler(ir->ir_rawbuf.buf, ir->ir_rawbuf.dcnt); > + ir->ir_rawbuf.dcnt = 0; > + code_valid = ir_code_valid(code); > + > + if (ir->timer_used) { > + if (code_valid) { /* the pre-key is released */ > +// #ifdef CONFIG_ARCH_SUN5I > +// input_report_key(ir_dev, ir_keycodes[(ir_code >> 16) & 0xff], 0); > +// input_sync(ir_dev); > +// #endif > +#ifdef DEBUG_IR_LEVEL1 > + printk("IR KEY UP\n"); > +#endif > + ir->ir_cnt = 0; > + } > + if ((code == IR_REPEAT_CODE) || (code_valid)) /* Error, may interfere > from other sources */ > + mod_timer(ir->s_timer, jiffies + (HZ/5)); > + } else { > + if (code_valid) { > + ir->s_timer->expires = jiffies + (HZ/5); /* 200ms timeout */ > + add_timer(ir->s_timer); > + ir->timer_used = 1; > + } > + } > + > + if (ir->timer_used) { > + ir->ir_cnt++; > + if (ir->ir_cnt == 1) { > + if (code_valid) { > + ir->ir_code = code; /* update saved code with a new valid code */ > + } > +// #ifdef DEBUG_IR_LEVEL0 > + printk("IR RAW CODE : %lu\n", (ir->ir_code >> 16) & 0xff); > +// #endif > + input_report_key(ir->input, ir_keycodes[(ir->ir_code >> 16) & 0xff], 1); > +#ifdef DEBUG_IR_LEVEL0 > + printk("IR CODE : %d\n", ir_keycodes[(ir_code >> 16) & 0xff]); > +#endif > + input_sync(ir->input); > +#ifdef DEBUG_IR_LEVEL1 > + printk("IR KEY VALE %d\n", ir_keycodes[(ir_code >> 16) & 0xff]); > +#endif > + } > + } > + > + dprintk(1, "ir_irq_service: Rx Packet End, code=0x%x, ir_code=0x%x, > timer_used=%d\n", (int)code, (int)ir_code, timer_used); > + } > + > + if (intsta & IR_RXINTS_RXOF) { /* FIFO Overflow */ > + /* flush raw buffer */ > + ir_reset_rawbuffer(ir); > +#ifdef DEBUG_IR_LEVEL0 > + printk("ir_irq_service: Rx FIFO Overflow!!\n"); > +#endif > + } > + > + > + return IRQ_HANDLED; > +} > + > +static int sun7i_ir_probe(struct platform_device *pdev) > +{ > + struct sun7i_ir_data *ir; > + struct device *dev = &pdev->dev; > + int i, ret; > + > + ir = devm_kzalloc(dev, sizeof(struct sun7i_ir_data), GFP_KERNEL); > + if (!ir) > + return -ENOMEM; > + > + for (i = 0; i < MAX_KEYS; i++) { > + ir->ir_keycodes[i] = ir_keycodes[i]; > + } > + > + ir->dev = dev; > + ir->input = devm_input_allocate_device(dev); > + if (!ir->input) > + return -ENOMEM; > + > + ir->input->name = pdev->name; > + ir->input->phys = "sun7i_ir/input0"; > + ir->input->id.bustype = BUS_HOST; > + ir->input->id.vendor = 0x0001; > + ir->input->id.product = 0x0001; > + ir->input->id.version = 0x0100; > + ir->input->evbit[0] = BIT(EV_KEY); > + > + ir->s_timer = 0; > + > + for (i = 0; i < MAX_KEYS; i++) { > + set_bit(ir->ir_keycodes[i], ir->input->keybit); > + } > + input_set_drvdata(ir->input, ir); > + > + ir->base = devm_ioremap_resource(dev, > + platform_get_resource(pdev, IORESOURCE_MEM, 0)); > + if (IS_ERR(ir->base)) { > + return PTR_ERR(ir->base); > + } > + > + ret = devm_request_irq(dev, platform_get_irq(pdev, 0), sun7i_ir_irq, > + 0, "sun7i-ir", ir); > + if (ret) > + return ret; > + > + ir->s_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); > + if (!ir->s_timer) { > + ret = -ENOMEM; > + printk("IR FAIL TO Request Time\n"); > + return ret; > + } > + > + init_timer(ir->s_timer); > + ir->s_timer->function = &ir_timer_handle; > + ir->s_timer->data = ir; > + > + ir_setup(ir); > + > + ret = input_register_device(ir->input); > + if (ret) > + return ret; > + > + platform_set_drvdata(pdev, ir); > + return 0; > +} > + > +static int sun7i_ir_remove(struct platform_device *pdev) > +{ > + struct sun7i_ir_data *ir = dev_get_drvdata(&pdev->dev); > + > + if(!ir) { > + return 0; > + } > + > + kfree(ir->s_timer); > + > + return 0; > +} > + > +static const struct of_device_id sun7i_ir_of_match[] = { > + { .compatible = "allwinner,sun7i-a20-ir", }, > + { /* sentinel */ } > +}; > +MODULE_DEVICE_TABLE(of, sun7i_ir_of_match); > + > + > +static struct platform_driver sun7i_ir_driver = { > + .driver = { > + .owner = THIS_MODULE, > + .name = "sun7i-a20-ir", > + .of_match_table = of_match_ptr(sun7i_ir_of_match), > + }, > + .probe = sun7i_ir_probe, > + .remove = sun7i_ir_remove, > +}; > + > + > +module_platform_driver(sun7i_ir_driver); > + > +MODULE_DESCRIPTION("Remote IR driver"); > +MODULE_AUTHOR("DanielWang"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/input/keyboard/ir-keymap.h > b/drivers/input/keyboard/ir-keymap.h > new file mode 100644 > index 0000000..d813311 > --- /dev/null > +++ b/drivers/input/keyboard/ir-keymap.h > @@ -0,0 +1,573 @@ > +/* > + * drivers/input/keyboard/ir-keymap.h > + * > + * (C) Copyright 2007-2012 > + * Allwinner Technology Co., Ltd. <www.allwinnertech.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 > + */ > + > + > +#ifndef __IR_KEYMAP_H__ > + > +#define __IR_KEYMAP_H__ > + > + > +/*IR IO Mapping Config*/ > +//0--PIOB10, 1--PIOB17 > +#define IR_IO_MAPPING 1 > + > +/*IR Key Match Config*/ > +//#define IR_CHECK_ADDR_CODE > +#define IR_ADDR_CODE (0x7f80) //(addr|((~addr)<<8)) > +//#define INPUT_VALUE_MAPPING > + > +/* > +0x0d -- KEY_ESC > +0x12 -- KEY_UP > +0x18 -- KEY_DOWN > +0x16 -- KEY_LEFT > +0x14 -- KEY_RIGHT > +0x15 -- KEY_ENTER > +0x1F -- KEY_VOLUMEDOWN > +0x1E -- KEY_VOLUMEUP > +0x00 -- KEY_POWER > + > +*/ > +#ifdef INPUT_VALUE_MAPPING > +static const unsigned int ir_keycodes[]= > +{ > + [0x00] = KEY_POWER, > + [0x01] = KEY_RESERVED, > + [0x02] = KEY_RESERVED, > + [0x03] = KEY_RESERVED, > + [0x04] = KEY_RESERVED, > + [0x05] = KEY_RESERVED, > + [0x06] = KEY_RESERVED, > + [0x07] = KEY_RESERVED, > + [0x08] = KEY_RESERVED, > + [0x09] = KEY_RESERVED, > + [0x0A] = KEY_RESERVED, > + [0x0B] = KEY_RESERVED, > + [0x0C] = KEY_RESERVED, > + [0x0D] = KEY_ESC, > + [0x0E] = KEY_RESERVED, > + [0x0F] = KEY_RESERVED, > + [0x10] = KEY_RESERVED, > + [0x11] = KEY_RESERVED, > + [0x12] = KEY_UP, > + [0x13] = KEY_RESERVED, > + [0x14] = KEY_RIGHT, > + [0x15] = KEY_ENTER, > + [0x16] = KEY_LEFT, > + [0x17] = KEY_RESERVED, > + [0x18] = KEY_DOWN, > + [0x19] = KEY_RESERVED, > + [0x1A] = KEY_RESERVED, > + [0x1B] = KEY_RESERVED, > + [0x1C] = KEY_RESERVED, > + [0x1D] = KEY_RESERVED, > + [0x1E] = KEY_VOLUMEUP, > + [0x1F] = KEY_VOLUMEDOWN, > + [0x20] = KEY_RESERVED, > + [0x21] = KEY_RESERVED, > + [0x22] = KEY_RESERVED, > + [0x23] = KEY_RESERVED, > + [0x24] = KEY_RESERVED, > + [0x25] = KEY_RESERVED, > + [0x26] = KEY_RESERVED, > + [0x27] = KEY_RESERVED, > + [0x28] = KEY_RESERVED, > + [0x29] = KEY_RESERVED, > + [0x2A] = KEY_RESERVED, > + [0x2B] = KEY_RESERVED, > + [0x2C] = KEY_RESERVED, > + [0x2D] = KEY_RESERVED, > + [0x2E] = KEY_RESERVED, > + [0x2F] = KEY_RESERVED, > + [0x30] = KEY_RESERVED, > + [0x31] = KEY_RESERVED, > + [0x32] = KEY_RESERVED, > + [0x33] = KEY_RESERVED, > + [0x34] = KEY_RESERVED, > + [0x35] = KEY_RESERVED, > + [0x36] = KEY_RESERVED, > + [0x37] = KEY_RESERVED, > + [0x38] = KEY_RESERVED, > + [0x39] = KEY_RESERVED, > + [0x3A] = KEY_RESERVED, > + [0x3B] = KEY_RESERVED, > + [0x3C] = KEY_RESERVED, > + [0x3D] = KEY_RESERVED, > + [0x3E] = KEY_RESERVED, > + [0x3F] = KEY_RESERVED, > + [0x40] = KEY_RESERVED, > + [0x41] = KEY_RESERVED, > + [0x42] = KEY_RESERVED, > + [0x43] = KEY_RESERVED, > + [0x44] = KEY_RESERVED, > + [0x45] = KEY_RESERVED, > + [0x46] = KEY_RESERVED, > + [0x47] = KEY_RESERVED, > + [0x48] = KEY_RESERVED, > + [0x49] = KEY_RESERVED, > + [0x4A] = KEY_RESERVED, > + [0x4B] = KEY_RESERVED, > + [0x4C] = KEY_RESERVED, > + [0x4D] = KEY_RESERVED, > + [0x4E] = KEY_RESERVED, > + [0x4F] = KEY_RESERVED, > + [0x50] = KEY_RESERVED, > + [0x51] = KEY_RESERVED, > + [0x52] = KEY_RESERVED, > + [0x53] = KEY_RESERVED, > + [0x54] = KEY_RESERVED, > + [0x55] = KEY_RESERVED, > + [0x56] = KEY_RESERVED, > + [0x57] = KEY_RESERVED, > + [0x58] = KEY_RESERVED, > + [0x59] = KEY_RESERVED, > + [0x5A] = KEY_RESERVED, > + [0x5B] = KEY_RESERVED, > + [0x5C] = KEY_RESERVED, > + [0x5D] = KEY_RESERVED, > + [0x5E] = KEY_RESERVED, > + [0x5F] = KEY_RESERVED, > + [0x60] = KEY_RESERVED, > + [0x61] = KEY_RESERVED, > + [0x62] = KEY_RESERVED, > + [0x63] = KEY_RESERVED, > + [0x64] = KEY_RESERVED, > + [0x65] = KEY_RESERVED, > + [0x66] = KEY_RESERVED, > + [0x67] = KEY_RESERVED, > + [0x68] = KEY_RESERVED, > + [0x69] = KEY_RESERVED, > + [0x6A] = KEY_RESERVED, > + [0x6B] = KEY_RESERVED, > + [0x6C] = KEY_RESERVED, > + [0x6D] = KEY_RESERVED, > + [0x6E] = KEY_RESERVED, > + [0x6F] = KEY_RESERVED, > + [0x70] = KEY_RESERVED, > + [0x71] = KEY_RESERVED, > + [0x72] = KEY_RESERVED, > + [0x73] = KEY_RESERVED, > + [0x74] = KEY_RESERVED, > + [0x75] = KEY_RESERVED, > + [0x76] = KEY_RESERVED, > + [0x77] = KEY_RESERVED, > + [0x78] = KEY_RESERVED, > + [0x79] = KEY_RESERVED, > + [0x7A] = KEY_RESERVED, > + [0x7B] = KEY_RESERVED, > + [0x7C] = KEY_RESERVED, > + [0x7D] = KEY_RESERVED, > + [0x7E] = KEY_RESERVED, > + [0x7F] = KEY_RESERVED, > + [0x80] = KEY_RESERVED, > + [0x81] = KEY_RESERVED, > + [0x82] = KEY_RESERVED, > + [0x83] = KEY_RESERVED, > + [0x84] = KEY_RESERVED, > + [0x85] = KEY_RESERVED, > + [0x86] = KEY_RESERVED, > + [0x87] = KEY_RESERVED, > + [0x88] = KEY_RESERVED, > + [0x89] = KEY_RESERVED, > + [0x8A] = KEY_RESERVED, > + [0x8B] = KEY_RESERVED, > + [0x8C] = KEY_RESERVED, > + [0x8D] = KEY_RESERVED, > + [0x8E] = KEY_RESERVED, > + [0x8F] = KEY_RESERVED, > + [0x90] = KEY_RESERVED, > + [0x91] = KEY_RESERVED, > + [0x92] = KEY_RESERVED, > + [0x93] = KEY_RESERVED, > + [0x94] = KEY_RESERVED, > + [0x95] = KEY_RESERVED, > + [0x96] = KEY_RESERVED, > + [0x97] = KEY_RESERVED, > + [0x98] = KEY_RESERVED, > + [0x99] = KEY_RESERVED, > + [0x9A] = KEY_RESERVED, > + [0x9B] = KEY_RESERVED, > + [0x9C] = KEY_RESERVED, > + [0x9D] = KEY_RESERVED, > + [0x9E] = KEY_RESERVED, > + [0x9F] = KEY_RESERVED, > + [0xA0] = KEY_RESERVED, > + [0xA1] = KEY_RESERVED, > + [0xA2] = KEY_RESERVED, > + [0xA3] = KEY_RESERVED, > + [0xA4] = KEY_RESERVED, > + [0xA5] = KEY_RESERVED, > + [0xA6] = KEY_RESERVED, > + [0xA7] = KEY_RESERVED, > + [0xA8] = KEY_RESERVED, > + [0xA9] = KEY_RESERVED, > + [0xAA] = KEY_RESERVED, > + [0xAB] = KEY_RESERVED, > + [0xAC] = KEY_RESERVED, > + [0xAD] = KEY_RESERVED, > + [0xAE] = KEY_RESERVED, > + [0xAF] = KEY_RESERVED, > + [0xB0] = KEY_RESERVED, > + [0xB1] = KEY_RESERVED, > + [0xB2] = KEY_RESERVED, > + [0xB3] = KEY_RESERVED, > + [0xB4] = KEY_RESERVED, > + [0xB5] = KEY_RESERVED, > + [0xB6] = KEY_RESERVED, > + [0xB7] = KEY_RESERVED, > + [0xB8] = KEY_RESERVED, > + [0xB9] = KEY_RESERVED, > + [0xBA] = KEY_RESERVED, > + [0xBB] = KEY_RESERVED, > + [0xBC] = KEY_RESERVED, > + [0xBD] = KEY_RESERVED, > + [0xBE] = KEY_RESERVED, > + [0xBF] = KEY_RESERVED, > + [0xC0] = KEY_RESERVED, > + [0xC1] = KEY_RESERVED, > + [0xC2] = KEY_RESERVED, > + [0xC3] = KEY_RESERVED, > + [0xC4] = KEY_RESERVED, > + [0xC5] = KEY_RESERVED, > + [0xC6] = KEY_RESERVED, > + [0xC7] = KEY_RESERVED, > + [0xC8] = KEY_RESERVED, > + [0xC9] = KEY_RESERVED, > + [0xCA] = KEY_RESERVED, > + [0xCB] = KEY_RESERVED, > + [0xCC] = KEY_RESERVED, > + [0xCD] = KEY_RESERVED, > + [0xCE] = KEY_RESERVED, > + [0xCF] = KEY_RESERVED, > + [0xD0] = KEY_RESERVED, > + [0xD1] = KEY_RESERVED, > + [0xD2] = KEY_RESERVED, > + [0xD3] = KEY_RESERVED, > + [0xD4] = KEY_RESERVED, > + [0xD5] = KEY_RESERVED, > + [0xD6] = KEY_RESERVED, > + [0xD7] = KEY_RESERVED, > + [0xD8] = KEY_RESERVED, > + [0xD9] = KEY_RESERVED, > + [0xDA] = KEY_RESERVED, > + [0xDB] = KEY_RESERVED, > + [0xDC] = KEY_RESERVED, > + [0xDD] = KEY_RESERVED, > + [0xDE] = KEY_RESERVED, > + [0xDF] = KEY_RESERVED, > + [0xE0] = KEY_RESERVED, > + [0xE1] = KEY_RESERVED, > + [0xE2] = KEY_RESERVED, > + [0xE3] = KEY_RESERVED, > + [0xE4] = KEY_RESERVED, > + [0xE5] = KEY_RESERVED, > + [0xE6] = KEY_RESERVED, > + [0xE7] = KEY_RESERVED, > + [0xE8] = KEY_RESERVED, > + [0xE9] = KEY_RESERVED, > + [0xEA] = KEY_RESERVED, > + [0xEB] = KEY_RESERVED, > + [0xEC] = KEY_RESERVED, > + [0xED] = KEY_RESERVED, > + [0xEE] = KEY_RESERVED, > + [0xEF] = KEY_RESERVED, > + [0xF0] = KEY_RESERVED, > + [0xF1] = KEY_RESERVED, > + [0xF2] = KEY_RESERVED, > + [0xF3] = KEY_RESERVED, > + [0xF4] = KEY_RESERVED, > + [0xF5] = KEY_RESERVED, > + [0xF6] = KEY_RESERVED, > + [0xF7] = KEY_RESERVED, > + [0xF8] = KEY_RESERVED, > + [0xF9] = KEY_RESERVED, > + [0xFA] = KEY_RESERVED, > + [0xFB] = KEY_RESERVED, > + [0xFC] = KEY_RESERVED, > + [0xFD] = KEY_RESERVED, > + [0xFE] = KEY_RESERVED, > + [0xFF] = KEY_RESERVED > +}; > +#else > +static const unsigned int ir_keycodes[]= > +{ > + [0x00] = 0xff, > + [0x01] = 0x01, > + [0x02] = 0x02, > + [0x03] = 0x03, > + [0x04] = 0x04, > + [0x05] = 0x05, > + [0x06] = 0x06, > + [0x07] = 0x07, > + [0x08] = 0x08, > + [0x09] = 0x09, > + [0x0A] = 0x0A, > + [0x0B] = 0x0B, > + [0x0C] = 0x0C, > + [0x0D] = 0x0D, > + [0x0E] = 0x0E, > + [0x0F] = 0x0F, > + [0x10] = 0x10, > + [0x11] = 0x11, > + [0x12] = 0x12, > + [0x13] = 0x13, > + [0x14] = 0x14, > + [0x15] = 0x15, > + [0x16] = 0x16, > + [0x17] = 0x17, > + [0x18] = 0x18, > + [0x19] = 0x19, > + [0x1A] = 0x1A, > + [0x1B] = 0x1B, > + [0x1C] = 0x1C, > + [0x1D] = 0x1D, > + [0x1E] = 0x1E, > + [0x1F] = 0x1F, > + [0x20] = 0x20, > + [0x21] = 0x21, > + [0x22] = 0x22, > + [0x23] = 0x23, > + [0x24] = 0x24, > + [0x25] = 0x25, > + [0x26] = 0x26, > + [0x27] = 0x27, > + [0x28] = 0x28, > + [0x29] = 0x29, > + [0x2A] = 0x2A, > + [0x2B] = 0x2B, > + [0x2C] = 0x2C, > + [0x2D] = 0x2D, > + [0x2E] = 0x2E, > + [0x2F] = 0x2F, > + [0x30] = 0x30, > + [0x31] = 0x31, > + [0x32] = 0x32, > + [0x33] = 0x33, > + [0x34] = 0x34, > + [0x35] = 0x35, > + [0x36] = 0x36, > + [0x37] = 0x37, > + [0x38] = 0x38, > + [0x39] = 0x39, > + [0x3A] = 0x3A, > + [0x3B] = 0x3B, > + [0x3C] = 0x3C, > + [0x3D] = 0x3D, > + [0x3E] = 0x3E, > + [0x3F] = 0x3F, > + [0x40] = 0x40, > + [0x41] = 0x41, > + [0x42] = 0x42, > + [0x43] = 0x43, > + [0x44] = 0x44, > + [0x45] = 0x45, > + [0x46] = 0x46, > + [0x47] = 0x47, > + [0x48] = 0x48, > + [0x49] = 0x49, > + [0x4A] = 0x4A, > + [0x4B] = 0x4B, > + [0x4C] = 0x4C, > + [0x4D] = 0x4D, > + [0x4E] = 0x4E, > + [0x4F] = 0x4F, > + [0x50] = 0x50, > + [0x51] = 0x51, > + [0x52] = 0x52, > + [0x53] = 0x53, > + [0x54] = 0x54, > + [0x55] = 0x55, > + [0x56] = 0x56, > + [0x57] = 0x57, > + [0x58] = 0x58, > + [0x59] = 0x59, > + [0x5A] = 0x5A, > + [0x5B] = 0x5B, > + [0x5C] = 0x5C, > + [0x5D] = 0x5D, > + [0x5E] = 0x5E, > + [0x5F] = 0x5F, > + [0x60] = 0x60, > + [0x61] = 0x61, > + [0x62] = 0x62, > + [0x63] = 0x63, > + [0x64] = 0x64, > + [0x65] = 0x65, > + [0x66] = 0x66, > + [0x67] = 0x67, > + [0x68] = 0x68, > + [0x69] = 0x69, > + [0x6A] = 0x6A, > + [0x6B] = 0x6B, > + [0x6C] = 0x6C, > + [0x6D] = 0x6D, > + [0x6E] = 0x6E, > + [0x6F] = 0x6F, > + [0x70] = 0x70, > + [0x71] = 0x71, > + [0x72] = 0x72, > + [0x73] = 0x73, > + [0x74] = 0x74, > + [0x75] = 0x75, > + [0x76] = 0x76, > + [0x77] = 0x77, > + [0x78] = 0x78, > + [0x79] = 0x79, > + [0x7A] = 0x7A, > + [0x7B] = 0x7B, > + [0x7C] = 0x7C, > + [0x7D] = 0x7D, > + [0x7E] = 0x7E, > + [0x7F] = 0x7F, > + [0x80] = 0x80, > + [0x81] = 0x81, > + [0x82] = 0x82, > + [0x83] = 0x83, > + [0x84] = 0x84, > + [0x85] = 0x85, > + [0x86] = 0x86, > + [0x87] = 0x87, > + [0x88] = 0x88, > + [0x89] = 0x89, > + [0x8A] = 0x8A, > + [0x8B] = 0x8B, > + [0x8C] = 0x8C, > + [0x8D] = 0x8D, > + [0x8E] = 0x8E, > + [0x8F] = 0x8F, > + [0x90] = 0x90, > + [0x91] = 0x91, > + [0x92] = 0x92, > + [0x93] = 0x93, > + [0x94] = 0x94, > + [0x95] = 0x95, > + [0x96] = 0x96, > + [0x97] = 0x97, > + [0x98] = 0x98, > + [0x99] = 0x99, > + [0x9A] = 0x9A, > + [0x9B] = 0x9B, > + [0x9C] = 0x9C, > + [0x9D] = 0x9D, > + [0x9E] = 0x9E, > + [0x9F] = 0x9F, > + [0xA0] = 0xA0, > + [0xA1] = 0xA1, > + [0xA2] = 0xA2, > + [0xA3] = 0xA3, > + [0xA4] = 0xA4, > + [0xA5] = 0xA5, > + [0xA6] = 0xA6, > + [0xA7] = 0xA7, > + [0xA8] = 0xA8, > + [0xA9] = 0xA9, > + [0xAA] = 0xAA, > + [0xAB] = 0xAB, > + [0xAC] = 0xAC, > + [0xAD] = 0xAD, > + [0xAE] = 0xAE, > + [0xAF] = 0xAF, > + [0xB0] = 0xB0, > + [0xB1] = 0xB1, > + [0xB2] = 0xB2, > + [0xB3] = 0xB3, > + [0xB4] = 0xB4, > + [0xB5] = 0xB5, > + [0xB6] = 0xB6, > + [0xB7] = 0xB7, > + [0xB8] = 0xB8, > + [0xB9] = 0xB9, > + [0xBA] = 0xBA, > + [0xBB] = 0xBB, > + [0xBC] = 0xBC, > + [0xBD] = 0xBD, > + [0xBE] = 0xBE, > + [0xBF] = 0xBF, > + [0xC0] = 0xC0, > + [0xC1] = 0xC1, > + [0xC2] = 0xC2, > + [0xC3] = 0xC3, > + [0xC4] = 0xC4, > + [0xC5] = 0xC5, > + [0xC6] = 0xC6, > + [0xC7] = 0xC7, > + [0xC8] = 0xC8, > + [0xC9] = 0xC9, > + [0xCA] = 0xCA, > + [0xCB] = 0xCB, > + [0xCC] = 0xCC, > + [0xCD] = 0xCD, > + [0xCE] = 0xCE, > + [0xCF] = 0xCF, > + [0xD0] = 0xD0, > + [0xD1] = 0xD1, > + [0xD2] = 0xD2, > + [0xD3] = 0xD3, > + [0xD4] = 0xD4, > + [0xD5] = 0xD5, > + [0xD6] = 0xD6, > + [0xD7] = 0xD7, > + [0xD8] = 0xD8, > + [0xD9] = 0xD9, > + [0xDA] = 0xDA, > + [0xDB] = 0xDB, > + [0xDC] = 0xDC, > + [0xDD] = 0xDD, > + [0xDE] = 0xDE, > + [0xDF] = 0xDF, > + [0xE0] = 0xE0, > + [0xE1] = 0xE1, > + [0xE2] = 0xE2, > + [0xE3] = 0xE3, > + [0xE4] = 0xE4, > + [0xE5] = 0xE5, > + [0xE6] = 0xE6, > + [0xE7] = 0xE7, > + [0xE8] = 0xE8, > + [0xE9] = 0xE9, > + [0xEA] = 0xEA, > + [0xEB] = 0xEB, > + [0xEC] = 0xEC, > + [0xED] = 0xED, > + [0xEE] = 0xEE, > + [0xEF] = 0xEF, > + [0xF0] = 0xF0, > + [0xF1] = 0xF1, > + [0xF2] = 0xF2, > + [0xF3] = 0xF3, > + [0xF4] = 0xF4, > + [0xF5] = 0xF5, > + [0xF6] = 0xF6, > + [0xF7] = 0xF7, > + [0xF8] = 0xF8, > + [0xF9] = 0xF9, > + [0xFA] = 0xFA, > + [0xFB] = 0xFB, > + [0xFC] = 0xFC, > + [0xFD] = 0xFD, > + [0xFE] = 0xFE, > + [0xFF] = 0xFF > +}; > + > +#endif > + > +#endif /*__IR_KEYMAP_H__*/ > -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.