[kernel/f14/master] ir-core rebase to current upstream
Jarod Wilson
jwilson at fedoraproject.org
Fri Sep 10 15:58:13 UTC 2010
commit 17a76a95c4958dbe264bbd1b2cdb84be681fbef8
Author: Jarod Wilson <jarod at redhat.com>
Date: Fri Sep 10 11:57:42 2010 -0400
ir-core rebase to current upstream
Signed-off-by: Jarod Wilson <jarod at redhat.com>
config-generic | 3 +
kernel.spec | 6 +-
linux-2.6-v4l-dvb-ir-core-update-2.patch | 3989 ++++++++++++++++++++++++++++++
3 files changed, 3997 insertions(+), 1 deletions(-)
---
diff --git a/config-generic b/config-generic
index d7269a5..cf8619a 100644
--- a/config-generic
+++ b/config-generic
@@ -2582,6 +2582,7 @@ CONFIG_VIDEO_PVRUSB2_SYSFS=y
# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
CONFIG_RC_MAP=m
+CONFIG_IR_CORE=m
CONFIG_IR_NEC_DECODER=m
CONFIG_IR_RC5_DECODER=m
CONFIG_IR_RC6_DECODER=m
@@ -2589,9 +2590,11 @@ CONFIG_IR_JVC_DECODER=m
CONFIG_IR_SONY_DECODER=m
CONFIG_IR_RC5_SZ_DECODER=m
CONFIG_IR_LIRC_CODEC=m
+CONFIG_IR_ENE=m
CONFIG_IR_IMON=m
CONFIG_IR_MCEUSB=m
CONFIG_IR_STREAMZAP=m
+CONFIG_IR_WINBOND_CIR=m
CONFIG_V4L_MEM2MEM_DRIVERS=y
# CONFIG_VIDEO_MEM2MEM_TESTDEV is not set
diff --git a/kernel.spec b/kernel.spec
index c7f8bdd..e4fc678 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -691,6 +691,7 @@ Patch2914: linux-2.6-v4l-dvb-ir-core-streamzap.patch
Patch2915: lirc-staging-2.6.36.patch
#Patch2916: lirc-staging-2.6.36-fixes.patch
Patch2917: hdpvr-ir-enable.patch
+Patch2918: linux-2.6-v4l-dvb-ir-core-update-2.patch
Patch3000: linux-2.6-via-velocity-dma-fix.patch
@@ -1310,6 +1311,7 @@ ApplyPatch lirc-staging-2.6.36.patch
#ApplyOptionalPatch lirc-staging-2.6.36-fixes.patch
# enable IR receiver on Hauppauge HD PVR (v4l-dvb merge pending)
ApplyPatch hdpvr-ir-enable.patch
+ApplyPatch linux-2.6-v4l-dvb-ir-core-update-2.patch
# Fix DMA bug on via-velocity
ApplyPatch linux-2.6-via-velocity-dma-fix.patch
@@ -1341,7 +1343,6 @@ ApplyPatch dell-wmi-add-support-for-eject-key-studio-1555.patch
# bz #575873
ApplyPatch flexcop-fix-xlate_proc_name-warning.patch
-
# END OF PATCH APPLICATIONS
%endif
@@ -1928,6 +1929,9 @@ fi
# and build.
%changelog
+* Fri Sep 10 2010 Jarod Wilson <jarod at redhat.com> 2.6.35.4-26
+- ir-core rebase to current upstream
+
* Fri Sep 10 2010 Bastien Nocera <bnocera at redhat.com> - 2.6.35.4-25
- Update AppleIR patch to work, and support the enter key on
newer remotes
diff --git a/linux-2.6-v4l-dvb-ir-core-update-2.patch b/linux-2.6-v4l-dvb-ir-core-update-2.patch
new file mode 100644
index 0000000..449b496
--- /dev/null
+++ b/linux-2.6-v4l-dvb-ir-core-update-2.patch
@@ -0,0 +1,3989 @@
+diff -Naurp linux-2.6.35/drivers/media/IR/ene_ir.c linux-2.6.35.new/drivers/media/IR/ene_ir.c
+--- linux-2.6.35/drivers/media/IR/ene_ir.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.new/drivers/media/IR/ene_ir.c 2010-09-09 23:21:49.000000000 -0400
+@@ -0,0 +1,1023 @@
++/*
++ * driver for ENE KB3926 B/C/D CIR (pnp id: ENE0XXX)
++ *
++ * Copyright (C) 2010 Maxim Levitsky <maximlevitsky at 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/kernel.h>
++#include <linux/module.h>
++#include <linux/pnp.h>
++#include <linux/io.h>
++#include <linux/interrupt.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/input.h>
++#include <media/ir-core.h>
++#include <media/ir-common.h>
++#include "ene_ir.h"
++
++
++static int sample_period = -1;
++static int enable_idle = 1;
++static int input = 1;
++static int debug;
++static int txsim;
++
++static int ene_irq_status(struct ene_device *dev);
++
++/* read a hardware register */
++static u8 ene_hw_read_reg(struct ene_device *dev, u16 reg)
++{
++ u8 retval;
++ outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
++ outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
++ retval = inb(dev->hw_io + ENE_IO);
++
++ ene_dbg_verbose("reg %04x == %02x", reg, retval);
++ return retval;
++}
++
++/* write a hardware register */
++static void ene_hw_write_reg(struct ene_device *dev, u16 reg, u8 value)
++{
++ outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
++ outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
++ outb(value, dev->hw_io + ENE_IO);
++
++ ene_dbg_verbose("reg %04x <- %02x", reg, value);
++}
++
++/* change specific bits in hardware register */
++static void ene_hw_write_reg_mask(struct ene_device *dev,
++ u16 reg, u8 value, u8 mask)
++{
++ u8 regvalue;
++
++ outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
++ outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
++
++ regvalue = inb(dev->hw_io + ENE_IO) & ~mask;
++ regvalue |= (value & mask);
++ outb(regvalue, dev->hw_io + ENE_IO);
++
++ ene_dbg_verbose("reg %04x <- %02x (mask=%02x)", reg, value, mask);
++}
++
++/* detect hardware features */
++static int ene_hw_detect(struct ene_device *dev)
++{
++ u8 chip_major, chip_minor;
++ u8 hw_revision, old_ver;
++ u8 tmp;
++ u8 fw_capabilities;
++ int pll_freq;
++
++ tmp = ene_hw_read_reg(dev, ENE_HW_UNK);
++ ene_hw_write_reg(dev, ENE_HW_UNK, tmp & ~ENE_HW_UNK_CLR);
++
++ chip_major = ene_hw_read_reg(dev, ENE_HW_VER_MAJOR);
++ chip_minor = ene_hw_read_reg(dev, ENE_HW_VER_MINOR);
++
++ ene_hw_write_reg(dev, ENE_HW_UNK, tmp);
++ hw_revision = ene_hw_read_reg(dev, ENE_HW_VERSION);
++ old_ver = ene_hw_read_reg(dev, ENE_HW_VER_OLD);
++
++ pll_freq = (ene_hw_read_reg(dev, ENE_PLLFRH) << 4) +
++ (ene_hw_read_reg(dev, ENE_PLLFRL) >> 4);
++
++ if (pll_freq != 1000)
++ dev->rx_period_adjust = 4;
++ else
++ dev->rx_period_adjust = 2;
++
++
++ ene_printk(KERN_NOTICE, "PLL freq = %d\n", pll_freq);
++
++ if (hw_revision == 0xFF) {
++
++ ene_printk(KERN_WARNING, "device seems to be disabled\n");
++ ene_printk(KERN_WARNING,
++ "send a mail to lirc-list at lists.sourceforge.net\n");
++ ene_printk(KERN_WARNING, "please attach output of acpidump\n");
++ return -ENODEV;
++ }
++
++ if (chip_major == 0x33) {
++ ene_printk(KERN_WARNING, "chips 0x33xx aren't supported\n");
++ return -ENODEV;
++ }
++
++ if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
++ dev->hw_revision = ENE_HW_C;
++ } else if (old_ver == 0x24 && hw_revision == 0xC0) {
++ dev->hw_revision = ENE_HW_B;
++ ene_printk(KERN_NOTICE, "KB3926B detected\n");
++ } else {
++ dev->hw_revision = ENE_HW_D;
++ ene_printk(KERN_WARNING,
++ "unknown ENE chip detected, assuming KB3926D\n");
++ ene_printk(KERN_WARNING,
++ "driver support might be not complete");
++
++ }
++
++ ene_printk(KERN_DEBUG,
++ "chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x\n",
++ chip_major, chip_minor, old_ver, hw_revision);
++
++ /* detect features hardware supports */
++ if (dev->hw_revision < ENE_HW_C)
++ return 0;
++
++ fw_capabilities = ene_hw_read_reg(dev, ENE_FW2);
++ ene_dbg("Firmware capabilities: %02x", fw_capabilities);
++
++ dev->hw_gpio40_learning = fw_capabilities & ENE_FW2_GP40_AS_LEARN;
++ dev->hw_learning_and_tx_capable = fw_capabilities & ENE_FW2_LEARNING;
++
++ dev->hw_fan_as_normal_input = dev->hw_learning_and_tx_capable &&
++ (fw_capabilities & ENE_FW2_FAN_AS_NRML_IN);
++
++ ene_printk(KERN_NOTICE, "hardware features:\n");
++ ene_printk(KERN_NOTICE,
++ "learning and transmit %s, gpio40_learn %s, fan_in %s\n",
++ dev->hw_learning_and_tx_capable ? "on" : "off",
++ dev->hw_gpio40_learning ? "on" : "off",
++ dev->hw_fan_as_normal_input ? "on" : "off");
++
++ if (dev->hw_learning_and_tx_capable) {
++ ene_printk(KERN_WARNING,
++ "Device supports transmitting, but that support is\n");
++ ene_printk(KERN_WARNING,
++ "lightly tested. Please test it and mail\n");
++ ene_printk(KERN_WARNING,
++ "lirc-list at lists.sourceforge.net\n");
++ }
++ return 0;
++}
++
++/* this enables/disables IR input via gpio40*/
++static void ene_enable_gpio40_receive(struct ene_device *dev, int enable)
++{
++ ene_hw_write_reg_mask(dev, ENE_CIR_CONF2, enable ?
++ 0 : ENE_CIR_CONF2_GPIO40DIS,
++ ENE_CIR_CONF2_GPIO40DIS);
++}
++
++/* this enables/disables IR via standard input */
++static void ene_enable_normal_receive(struct ene_device *dev, int enable)
++{
++ ene_hw_write_reg(dev, ENE_CIR_CONF1, enable ? ENE_CIR_CONF1_RX_ON : 0);
++}
++
++/* this enables/disables IR input via unused fan tachtometer input */
++static void ene_enable_fan_receive(struct ene_device *dev, int enable)
++{
++ if (!enable)
++ ene_hw_write_reg(dev, ENE_FAN_AS_IN1, 0);
++ else {
++ ene_hw_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
++ ene_hw_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
++ }
++ dev->rx_fan_input_inuse = enable;
++}
++
++
++/* Sense current received carrier */
++static int ene_rx_sense_carrier(struct ene_device *dev)
++{
++ int period = ene_hw_read_reg(dev, ENE_RX_CARRIER);
++ int carrier;
++ ene_dbg("RX: hardware carrier period = %02x", period);
++
++ if (!(period & ENE_RX_CARRIER_VALID))
++ return 0;
++
++ period &= ~ENE_RX_CARRIER_VALID;
++
++ if (!period)
++ return 0;
++
++ carrier = 2000000 / period;
++ ene_dbg("RX: sensed carrier = %d Hz", carrier);
++ return carrier;
++}
++
++/* determine which input to use*/
++static void ene_rx_set_inputs(struct ene_device *dev)
++{
++ int learning_mode = dev->learning_enabled;
++
++ ene_dbg("RX: setup receiver, learning mode = %d", learning_mode);
++
++ ene_enable_normal_receive(dev, 1);
++
++ /* old hardware doesn't support learning mode for sure */
++ if (dev->hw_revision <= ENE_HW_B)
++ return;
++
++ /* receiver not learning capable, still set gpio40 correctly */
++ if (!dev->hw_learning_and_tx_capable) {
++ ene_enable_gpio40_receive(dev, !dev->hw_gpio40_learning);
++ return;
++ }
++
++ /* enable learning mode */
++ if (learning_mode) {
++ ene_enable_gpio40_receive(dev, dev->hw_gpio40_learning);
++
++ /* fan input is not used for learning */
++ if (dev->hw_fan_as_normal_input)
++ ene_enable_fan_receive(dev, 0);
++
++ /* disable learning mode */
++ } else {
++ if (dev->hw_fan_as_normal_input) {
++ ene_enable_fan_receive(dev, 1);
++ ene_enable_normal_receive(dev, 0);
++ } else
++ ene_enable_gpio40_receive(dev,
++ !dev->hw_gpio40_learning);
++ }
++
++ /* set few additional settings for this mode */
++ ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, learning_mode ?
++ ENE_CIR_CONF1_LEARN1 : 0, ENE_CIR_CONF1_LEARN1);
++
++ ene_hw_write_reg_mask(dev, ENE_CIR_CONF2, learning_mode ?
++ ENE_CIR_CONF2_LEARN2 : 0, ENE_CIR_CONF2_LEARN2);
++
++ if (dev->rx_fan_input_inuse) {
++ dev->props->rx_resolution = ENE_SAMPLE_PERIOD_FAN * 1000;
++
++ dev->props->timeout =
++ ENE_FAN_VALUE_MASK * ENE_SAMPLE_PERIOD_FAN * 1000;
++ } else {
++ dev->props->rx_resolution = sample_period * 1000;
++ dev->props->timeout = ENE_MAXGAP * 1000;
++ }
++}
++
++/* Enable the device for receive */
++static void ene_rx_enable(struct ene_device *dev)
++{
++ u8 reg_value;
++
++ if (dev->hw_revision < ENE_HW_C) {
++ ene_hw_write_reg(dev, ENEB_IRQ, dev->irq << 1);
++ ene_hw_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
++ } else {
++ reg_value = ene_hw_read_reg(dev, ENEC_IRQ) & 0xF0;
++ reg_value |= ENEC_IRQ_UNK_EN;
++ reg_value &= ~ENEC_IRQ_STATUS;
++ reg_value |= (dev->irq & ENEC_IRQ_MASK);
++ ene_hw_write_reg(dev, ENEC_IRQ, reg_value);
++ ene_hw_write_reg(dev, ENE_TX_UNK1, 0x63);
++ }
++
++ ene_hw_write_reg(dev, ENE_CIR_CONF2, 0x00);
++ ene_rx_set_inputs(dev);
++
++ /* set sampling period */
++ ene_hw_write_reg(dev, ENE_CIR_SAMPLE_PERIOD, sample_period);
++
++ /* ack any pending irqs - just in case */
++ ene_irq_status(dev);
++
++ /* enable firmware bits */
++ ene_hw_write_reg_mask(dev, ENE_FW1,
++ ENE_FW1_ENABLE | ENE_FW1_IRQ,
++ ENE_FW1_ENABLE | ENE_FW1_IRQ);
++
++ /* enter idle mode */
++ ir_raw_event_set_idle(dev->idev, 1);
++ ir_raw_event_reset(dev->idev);
++
++}
++
++/* Disable the device receiver */
++static void ene_rx_disable(struct ene_device *dev)
++{
++ /* disable inputs */
++ ene_enable_normal_receive(dev, 0);
++
++ if (dev->hw_fan_as_normal_input)
++ ene_enable_fan_receive(dev, 0);
++
++ /* disable hardware IRQ and firmware flag */
++ ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_ENABLE | ENE_FW1_IRQ);
++
++ ir_raw_event_set_idle(dev->idev, 1);
++ ir_raw_event_reset(dev->idev);
++}
++
++
++/* prepare transmission */
++static void ene_tx_prepare(struct ene_device *dev)
++{
++ u8 conf1;
++
++ conf1 = ene_hw_read_reg(dev, ENE_CIR_CONF1);
++ dev->saved_conf1 = conf1;
++
++ if (dev->hw_revision == ENE_HW_C)
++ conf1 &= ~ENE_CIR_CONF1_TX_CLEAR;
++
++ /* Enable TX engine */
++ conf1 |= ENE_CIR_CONF1_TX_ON;
++
++ /* Set carrier */
++ if (dev->tx_period) {
++
++ /* NOTE: duty cycle handling is just a guess, it might
++ not be aviable. Default values were tested */
++ int tx_period_in500ns = dev->tx_period * 2;
++
++ int tx_pulse_width_in_500ns =
++ tx_period_in500ns / (100 / dev->tx_duty_cycle);
++
++ if (!tx_pulse_width_in_500ns)
++ tx_pulse_width_in_500ns = 1;
++
++ ene_dbg("TX: pulse distance = %d * 500 ns", tx_period_in500ns);
++ ene_dbg("TX: pulse width = %d * 500 ns",
++ tx_pulse_width_in_500ns);
++
++ ene_hw_write_reg(dev, ENE_TX_PERIOD, ENE_TX_PERIOD_UNKBIT |
++ tx_period_in500ns);
++
++ ene_hw_write_reg(dev, ENE_TX_PERIOD_PULSE,
++ tx_pulse_width_in_500ns);
++
++ conf1 |= ENE_CIR_CONF1_TX_CARR;
++ } else
++ conf1 &= ~ENE_CIR_CONF1_TX_CARR;
++
++ ene_hw_write_reg(dev, ENE_CIR_CONF1, conf1);
++
++}
++
++/* end transmission */
++static void ene_tx_complete(struct ene_device *dev)
++{
++ ene_hw_write_reg(dev, ENE_CIR_CONF1, dev->saved_conf1);
++ dev->tx_buffer = NULL;
++}
++
++/* set transmit mask */
++static void ene_tx_hw_set_transmiter_mask(struct ene_device *dev)
++{
++ u8 txport1 = ene_hw_read_reg(dev, ENE_TX_PORT1) & ~ENE_TX_PORT1_EN;
++ u8 txport2 = ene_hw_read_reg(dev, ENE_TX_PORT2) & ~ENE_TX_PORT2_EN;
++
++ if (dev->transmitter_mask & 0x01)
++ txport1 |= ENE_TX_PORT1_EN;
++
++ if (dev->transmitter_mask & 0x02)
++ txport2 |= ENE_TX_PORT2_EN;
++
++ ene_hw_write_reg(dev, ENE_TX_PORT1, txport1);
++ ene_hw_write_reg(dev, ENE_TX_PORT2, txport2);
++}
++
++/* TX one sample - must be called with dev->hw_lock*/
++static void ene_tx_sample(struct ene_device *dev)
++{
++ u8 raw_tx;
++ u32 sample;
++
++ if (!dev->tx_buffer) {
++ ene_dbg("TX: attempt to transmit NULL buffer");
++ return;
++ }
++
++ /* Grab next TX sample */
++ if (!dev->tx_sample) {
++again:
++ if (dev->tx_pos == dev->tx_len + 1) {
++ if (!dev->tx_done) {
++ ene_dbg("TX: no more data to send");
++ dev->tx_done = 1;
++ goto exit;
++ } else {
++ ene_dbg("TX: last sample sent by hardware");
++ ene_tx_complete(dev);
++ complete(&dev->tx_complete);
++ return;
++ }
++ }
++
++ sample = dev->tx_buffer[dev->tx_pos++];
++ dev->tx_sample_pulse = !dev->tx_sample_pulse;
++
++ ene_dbg("TX: sample %8d (%s)", sample, dev->tx_sample_pulse ?
++ "pulse" : "space");
++
++ dev->tx_sample = DIV_ROUND_CLOSEST(sample, ENE_TX_SMPL_PERIOD);
++
++ /* guard against too short samples */
++ if (!dev->tx_sample)
++ goto again;
++ }
++
++ raw_tx = min(dev->tx_sample , (unsigned int)ENE_TX_SMLP_MASK);
++ dev->tx_sample -= raw_tx;
++
++ if (dev->tx_sample_pulse)
++ raw_tx |= ENE_TX_PULSE_MASK;
++
++ ene_hw_write_reg(dev, ENE_TX_INPUT1 + dev->tx_reg, raw_tx);
++ dev->tx_reg = !dev->tx_reg;
++exit:
++ /* simulate TX done interrupt */
++ if (txsim)
++ mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500);
++}
++
++/* timer to simulate tx done interrupt */
++static void ene_tx_irqsim(unsigned long data)
++{
++ struct ene_device *dev = (struct ene_device *)data;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev->hw_lock, flags);
++ ene_tx_sample(dev);
++ spin_unlock_irqrestore(&dev->hw_lock, flags);
++}
++
++
++/* read irq status and ack it */
++static int ene_irq_status(struct ene_device *dev)
++{
++ u8 irq_status;
++ u8 fw_flags1, fw_flags2;
++ int cur_rx_pointer;
++ int retval = 0;
++
++ fw_flags2 = ene_hw_read_reg(dev, ENE_FW2);
++ cur_rx_pointer = !!(fw_flags2 & ENE_FW2_BUF_HIGH);
++
++ if (dev->hw_revision < ENE_HW_C) {
++ irq_status = ene_hw_read_reg(dev, ENEB_IRQ_STATUS);
++
++ if (!(irq_status & ENEB_IRQ_STATUS_IR))
++ return 0;
++
++ ene_hw_write_reg(dev, ENEB_IRQ_STATUS,
++ irq_status & ~ENEB_IRQ_STATUS_IR);
++ dev->rx_pointer = cur_rx_pointer;
++ return ENE_IRQ_RX;
++ }
++
++ irq_status = ene_hw_read_reg(dev, ENEC_IRQ);
++
++ if (!(irq_status & ENEC_IRQ_STATUS))
++ return 0;
++
++ /* original driver does that twice - a workaround ? */
++ ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS);
++ ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS);
++
++ /* clear unknown flag in F8F9 */
++ if (fw_flags2 & ENE_FW2_IRQ_CLR)
++ ene_hw_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_IRQ_CLR);
++
++ /* check if this is a TX interrupt */
++ fw_flags1 = ene_hw_read_reg(dev, ENE_FW1);
++ if (fw_flags1 & ENE_FW1_TXIRQ) {
++ ene_hw_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
++ retval |= ENE_IRQ_TX;
++ }
++
++ /* Check if this is RX interrupt */
++ if (dev->rx_pointer != cur_rx_pointer) {
++ retval |= ENE_IRQ_RX;
++ dev->rx_pointer = cur_rx_pointer;
++
++ } else if (!(retval & ENE_IRQ_TX)) {
++ ene_dbg("RX: interrupt without change in RX pointer(%d)",
++ dev->rx_pointer);
++ retval |= ENE_IRQ_RX;
++ }
++
++ if ((retval & ENE_IRQ_RX) && (retval & ENE_IRQ_TX))
++ ene_dbg("both RX and TX interrupt at same time");
++
++ return retval;
++}
++
++/* interrupt handler */
++static irqreturn_t ene_isr(int irq, void *data)
++{
++ u16 hw_value;
++ int i, hw_sample;
++ int pulse;
++ int irq_status;
++ unsigned long flags;
++ int carrier = 0;
++ irqreturn_t retval = IRQ_NONE;
++ struct ene_device *dev = (struct ene_device *)data;
++ struct ir_raw_event ev;
++
++
++ spin_lock_irqsave(&dev->hw_lock, flags);
++ irq_status = ene_irq_status(dev);
++
++ if (!irq_status)
++ goto unlock;
++
++ retval = IRQ_HANDLED;
++
++ if (irq_status & ENE_IRQ_TX) {
++
++ if (!dev->hw_learning_and_tx_capable) {
++ ene_dbg("TX interrupt on unsupported device!");
++ goto unlock;
++ }
++ ene_tx_sample(dev);
++ }
++
++ if (!(irq_status & ENE_IRQ_RX))
++ goto unlock;
++
++
++ if (dev->carrier_detect_enabled || debug)
++ carrier = ene_rx_sense_carrier(dev);
++#if 0
++ /* TODO */
++ if (dev->carrier_detect_enabled && carrier)
++ ir_raw_event_report_frequency(dev->idev, carrier);
++#endif
++
++ for (i = 0; i < ENE_SAMPLES_SIZE; i++) {
++ hw_value = ene_hw_read_reg(dev,
++ ENE_SAMPLE_BUFFER + dev->rx_pointer * 4 + i);
++
++ if (dev->rx_fan_input_inuse) {
++ /* read high part of the sample */
++ hw_value |= ene_hw_read_reg(dev,
++ ENE_SAMPLE_BUFFER_FAN +
++ dev->rx_pointer * 4 + i) << 8;
++ pulse = hw_value & ENE_FAN_SMPL_PULS_MSK;
++
++ /* clear space bit, and other unused bits */
++ hw_value &= ENE_FAN_VALUE_MASK;
++ hw_sample = hw_value * ENE_SAMPLE_PERIOD_FAN;
++
++ } else {
++ pulse = !(hw_value & ENE_SAMPLE_SPC_MASK);
++ hw_value &= ENE_SAMPLE_VALUE_MASK;
++ hw_sample = hw_value * sample_period;
++
++ if (dev->rx_period_adjust) {
++ hw_sample *= (100 - dev->rx_period_adjust);
++ hw_sample /= 100;
++ }
++ }
++ /* no more data */
++ if (!(hw_value))
++ break;
++
++ ene_dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space");
++
++
++ ev.duration = hw_sample * 1000;
++ ev.pulse = pulse;
++ ir_raw_event_store_with_filter(dev->idev, &ev);
++ }
++
++ ir_raw_event_handle(dev->idev);
++unlock:
++ spin_unlock_irqrestore(&dev->hw_lock, flags);
++ return retval;
++}
++
++/* Initialize default settings */
++static void ene_setup_settings(struct ene_device *dev)
++{
++ dev->tx_period = 32;
++ dev->tx_duty_cycle = 25; /*%*/
++ dev->transmitter_mask = 3;
++
++ /* Force learning mode if (input == 2), otherwise
++ let user set it with LIRC_SET_REC_CARRIER */
++ dev->learning_enabled =
++ (input == 2 && dev->hw_learning_and_tx_capable);
++
++ dev->rx_pointer = -1;
++
++}
++
++/* outside interface: called on first open*/
++static int ene_open(void *data)
++{
++ struct ene_device *dev = (struct ene_device *)data;
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev->hw_lock, flags);
++ dev->in_use = 1;
++ ene_setup_settings(dev);
++ ene_rx_enable(dev);
++ spin_unlock_irqrestore(&dev->hw_lock, flags);
++ return 0;
++}
++
++/* outside interface: called on device close*/
++static void ene_close(void *data)
++{
++ struct ene_device *dev = (struct ene_device *)data;
++ unsigned long flags;
++ spin_lock_irqsave(&dev->hw_lock, flags);
++
++ ene_rx_disable(dev);
++ dev->in_use = 0;
++ spin_unlock_irqrestore(&dev->hw_lock, flags);
++}
++
++/* outside interface: set transmitter mask */
++static int ene_set_tx_mask(void *data, u32 tx_mask)
++{
++ struct ene_device *dev = (struct ene_device *)data;
++ unsigned long flags;
++ ene_dbg("TX: attempt to set transmitter mask %02x", tx_mask);
++
++ /* invalid txmask */
++ if (!tx_mask || tx_mask & ~0x3) {
++ ene_dbg("TX: invalid mask");
++ /* return count of transmitters */
++ return 2;
++ }
++
++ spin_lock_irqsave(&dev->hw_lock, flags);
++ dev->transmitter_mask = tx_mask;
++ spin_unlock_irqrestore(&dev->hw_lock, flags);
++ return 0;
++}
++
++/* outside interface : set tx carrier */
++static int ene_set_tx_carrier(void *data, u32 carrier)
++{
++ struct ene_device *dev = (struct ene_device *)data;
++ unsigned long flags;
++ u32 period = 1000000 / carrier; /* (1 / freq) (* # usec in 1 sec) */
++
++ ene_dbg("TX: attempt to set tx carrier to %d kHz", carrier);
++
++ if (period && (period > ENE_TX_PERIOD_MAX ||
++ period < ENE_TX_PERIOD_MIN)) {
++
++ ene_dbg("TX: out of range %d-%d carrier, "
++ "falling back to 32 kHz",
++ 1000 / ENE_TX_PERIOD_MIN,
++ 1000 / ENE_TX_PERIOD_MAX);
++
++ period = 32; /* this is just a coincidence!!! */
++ }
++ ene_dbg("TX: set carrier to %d kHz", carrier);
++
++ spin_lock_irqsave(&dev->hw_lock, flags);
++ dev->tx_period = period;
++ spin_unlock_irqrestore(&dev->hw_lock, flags);
++ return 0;
++}
++
++
++/* outside interface: enable learning mode */
++static int ene_set_learning_mode(void *data, int enable)
++{
++ struct ene_device *dev = (struct ene_device *)data;
++ unsigned long flags;
++ if (enable == dev->learning_enabled)
++ return 0;
++
++ spin_lock_irqsave(&dev->hw_lock, flags);
++ dev->learning_enabled = enable;
++ ene_rx_set_inputs(dev);
++ spin_unlock_irqrestore(&dev->hw_lock, flags);
++ return 0;
++}
++
++/* outside interface: set rec carrier */
++static int ene_set_rec_carrier(void *data, u32 min, u32 max)
++{
++ struct ene_device *dev = (struct ene_device *)data;
++ ene_set_learning_mode(dev,
++ max > ENE_NORMAL_RX_HI || min < ENE_NORMAL_RX_LOW);
++ return 0;
++}
++
++/* outside interface: enable or disable idle mode */
++static void ene_rx_set_idle(void *data, int idle)
++{
++ struct ene_device *dev = (struct ene_device *)data;
++ ene_dbg("%sabling idle mode", idle ? "en" : "dis");
++
++ ene_hw_write_reg_mask(dev, ENE_CIR_SAMPLE_PERIOD,
++ (enable_idle && idle) ? 0 : ENE_CIR_SAMPLE_OVERFLOW,
++ ENE_CIR_SAMPLE_OVERFLOW);
++}
++
++
++/* outside interface: transmit */
++static int ene_transmit(void *data, int *buf, u32 n)
++{
++ struct ene_device *dev = (struct ene_device *)data;
++ unsigned long flags;
++
++ dev->tx_buffer = buf;
++ dev->tx_len = n / sizeof(int);
++ dev->tx_pos = 0;
++ dev->tx_reg = 0;
++ dev->tx_done = 0;
++ dev->tx_sample = 0;
++ dev->tx_sample_pulse = 0;
++
++ ene_dbg("TX: %d samples", dev->tx_len);
++
++ spin_lock_irqsave(&dev->hw_lock, flags);
++
++ ene_tx_hw_set_transmiter_mask(dev);
++ ene_tx_prepare(dev);
++
++ /* Transmit first two samples */
++ ene_tx_sample(dev);
++ ene_tx_sample(dev);
++
++ spin_unlock_irqrestore(&dev->hw_lock, flags);
++
++ if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) {
++ ene_dbg("TX: timeout");
++ spin_lock_irqsave(&dev->hw_lock, flags);
++ ene_tx_complete(dev);
++ spin_unlock_irqrestore(&dev->hw_lock, flags);
++ } else
++ ene_dbg("TX: done");
++ return n;
++}
++
++
++/* probe entry */
++static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
++{
++ int error = -ENOMEM;
++ struct ir_dev_props *ir_props;
++ struct input_dev *input_dev;
++ struct ene_device *dev;
++
++ /* allocate memory */
++ input_dev = input_allocate_device();
++ ir_props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
++ dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
++
++ if (!input_dev || !ir_props || !dev)
++ goto error;
++
++ /* validate resources */
++ error = -ENODEV;
++
++ if (!pnp_port_valid(pnp_dev, 0) ||
++ pnp_port_len(pnp_dev, 0) < ENE_MAX_IO)
++ goto error;
++
++ if (!pnp_irq_valid(pnp_dev, 0))
++ goto error;
++
++ dev->hw_io = pnp_port_start(pnp_dev, 0);
++ dev->irq = pnp_irq(pnp_dev, 0);
++ spin_lock_init(&dev->hw_lock);
++
++ /* claim the resources */
++ error = -EBUSY;
++ if (!request_region(dev->hw_io, ENE_MAX_IO, ENE_DRIVER_NAME))
++ goto error;
++
++ if (request_irq(dev->irq, ene_isr,
++ IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev))
++ goto error;
++
++ pnp_set_drvdata(pnp_dev, dev);
++ dev->pnp_dev = pnp_dev;
++
++ /* detect hardware version and features */
++ error = ene_hw_detect(dev);
++ if (error)
++ goto error;
++
++ ene_setup_settings(dev);
++
++ if (!dev->hw_learning_and_tx_capable && txsim) {
++ dev->hw_learning_and_tx_capable = 1;
++ setup_timer(&dev->tx_sim_timer, ene_tx_irqsim,
++ (long unsigned int)dev);
++ ene_printk(KERN_WARNING,
++ "Simulation of TX activated\n");
++ }
++
++ ir_props->driver_type = RC_DRIVER_IR_RAW;
++ ir_props->allowed_protos = IR_TYPE_ALL;
++ ir_props->priv = dev;
++ ir_props->open = ene_open;
++ ir_props->close = ene_close;
++ ir_props->min_timeout = ENE_MINGAP * 1000;
++ ir_props->max_timeout = ENE_MAXGAP * 1000;
++ ir_props->timeout = ENE_MAXGAP * 1000;
++
++ if (dev->hw_revision == ENE_HW_B)
++ ir_props->s_idle = ene_rx_set_idle;
++
++
++ dev->props = ir_props;
++ dev->idev = input_dev;
++
++ /* don't allow too short/long sample periods */
++ if (sample_period < 5 || sample_period > 0x7F)
++ sample_period = -1;
++
++ /* choose default sample period */
++ if (sample_period == -1) {
++
++ sample_period = 50;
++
++ /* on revB, hardware idle mode eats first sample
++ if we set too low sample period */
++ if (dev->hw_revision == ENE_HW_B && enable_idle)
++ sample_period = 75;
++ }
++
++ ir_props->rx_resolution = sample_period * 1000;
++
++ if (dev->hw_learning_and_tx_capable) {
++
++ ir_props->s_learning_mode = ene_set_learning_mode;
++
++ if (input == 0)
++ ir_props->s_rx_carrier_range = ene_set_rec_carrier;
++
++ init_completion(&dev->tx_complete);
++ ir_props->tx_ir = ene_transmit;
++ ir_props->s_tx_mask = ene_set_tx_mask;
++ ir_props->s_tx_carrier = ene_set_tx_carrier;
++ ir_props->tx_resolution = ENE_TX_SMPL_PERIOD * 1000;
++ /* ir_props->s_carrier_report = ene_set_carrier_report; */
++ }
++
++
++ device_set_wakeup_capable(&pnp_dev->dev, 1);
++ device_set_wakeup_enable(&pnp_dev->dev, 1);
++
++ if (dev->hw_learning_and_tx_capable)
++ input_dev->name = "ENE eHome Infrared Remote Transceiver";
++ else
++ input_dev->name = "ENE eHome Infrared Remote Receiver";
++
++
++ error = -ENODEV;
++ if (ir_input_register(input_dev, RC_MAP_RC6_MCE, ir_props,
++ ENE_DRIVER_NAME))
++ goto error;
++
++
++ ene_printk(KERN_NOTICE, "driver has been succesfully loaded\n");
++ return 0;
++error:
++ if (dev->irq)
++ free_irq(dev->irq, dev);
++ if (dev->hw_io)
++ release_region(dev->hw_io, ENE_MAX_IO);
++
++ input_free_device(input_dev);
++ kfree(ir_props);
++ kfree(dev);
++ return error;
++}
++
++/* main unload function */
++static void ene_remove(struct pnp_dev *pnp_dev)
++{
++ struct ene_device *dev = pnp_get_drvdata(pnp_dev);
++ unsigned long flags;
++
++ spin_lock_irqsave(&dev->hw_lock, flags);
++ ene_rx_disable(dev);
++ spin_unlock_irqrestore(&dev->hw_lock, flags);
++
++ free_irq(dev->irq, dev);
++ release_region(dev->hw_io, ENE_MAX_IO);
++ ir_input_unregister(dev->idev);
++ kfree(dev->props);
++ kfree(dev);
++}
++
++/* enable wake on IR (wakes on specific button on original remote) */
++static void ene_enable_wake(struct ene_device *dev, int enable)
++{
++ enable = enable && device_may_wakeup(&dev->pnp_dev->dev);
++
++ ene_dbg("wake on IR %s", enable ? "enabled" : "disabled");
++
++ ene_hw_write_reg_mask(dev, ENE_FW1, enable ?
++ ENE_FW1_WAKE : 0, ENE_FW1_WAKE);
++}
++
++#ifdef CONFIG_PM
++static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
++{
++ struct ene_device *dev = pnp_get_drvdata(pnp_dev);
++ ene_enable_wake(dev, 1);
++ return 0;
++}
++
++static int ene_resume(struct pnp_dev *pnp_dev)
++{
++ struct ene_device *dev = pnp_get_drvdata(pnp_dev);
++ if (dev->in_use)
++ ene_rx_enable(dev);
++
++ ene_enable_wake(dev, 0);
++ return 0;
++}
++#endif
++
++static void ene_shutdown(struct pnp_dev *pnp_dev)
++{
++ struct ene_device *dev = pnp_get_drvdata(pnp_dev);
++ ene_enable_wake(dev, 1);
++}
++
++static const struct pnp_device_id ene_ids[] = {
++ {.id = "ENE0100",},
++ {.id = "ENE0200",},
++ {.id = "ENE0201",},
++ {.id = "ENE0202",},
++ {},
++};
++
++static struct pnp_driver ene_driver = {
++ .name = ENE_DRIVER_NAME,
++ .id_table = ene_ids,
++ .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
++
++ .probe = ene_probe,
++ .remove = __devexit_p(ene_remove),
++#ifdef CONFIG_PM
++ .suspend = ene_suspend,
++ .resume = ene_resume,
++#endif
++ .shutdown = ene_shutdown,
++};
++
++static int __init ene_init(void)
++{
++ return pnp_register_driver(&ene_driver);
++}
++
++static void ene_exit(void)
++{
++ pnp_unregister_driver(&ene_driver);
++}
++
++module_param(sample_period, int, S_IRUGO);
++MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)");
++
++module_param(enable_idle, bool, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(enable_idle,
++ "Enables turning off signal sampling after long inactivity time; "
++ "if disabled might help detecting input signal (default: enabled)"
++ " (KB3926B only)");
++
++module_param(input, bool, S_IRUGO);
++MODULE_PARM_DESC(input, "select which input to use "
++ "0 - auto, 1 - standard, 2 - wideband(KB3926C+)");
++
++module_param(debug, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(debug, "Enable debug (debug=2 verbose debug output)");
++
++module_param(txsim, bool, S_IRUGO);
++MODULE_PARM_DESC(txsim,
++ "Simulate TX features on unsupported hardware (dangerous)");
++
++MODULE_DEVICE_TABLE(pnp, ene_ids);
++MODULE_DESCRIPTION
++ ("Infrared input driver for KB3926B/KB3926C/KB3926D "
++ "(aka ENE0100/ENE0200/ENE0201) CIR port");
++
++MODULE_AUTHOR("Maxim Levitsky");
++MODULE_LICENSE("GPL");
++
++module_init(ene_init);
++module_exit(ene_exit);
+diff -Naurp linux-2.6.35/drivers/media/IR/ene_ir.h linux-2.6.35.new/drivers/media/IR/ene_ir.h
+--- linux-2.6.35/drivers/media/IR/ene_ir.h 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.new/drivers/media/IR/ene_ir.h 2010-09-09 23:21:49.000000000 -0400
+@@ -0,0 +1,235 @@
++/*
++ * driver for ENE KB3926 B/C/D CIR (also known as ENE0XXX)
++ *
++ * Copyright (C) 2010 Maxim Levitsky <maximlevitsky at 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/spinlock.h>
++
++
++/* hardware address */
++#define ENE_STATUS 0 /* hardware status - unused */
++#define ENE_ADDR_HI 1 /* hi byte of register address */
++#define ENE_ADDR_LO 2 /* low byte of register address */
++#define ENE_IO 3 /* read/write window */
++#define ENE_MAX_IO 4
++
++/* 8 bytes of samples, divided in 2 halfs*/
++#define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */
++#define ENE_SAMPLE_SPC_MASK 0x80 /* sample is space */
++#define ENE_SAMPLE_VALUE_MASK 0x7F
++#define ENE_SAMPLE_OVERFLOW 0x7F
++#define ENE_SAMPLES_SIZE 4
++
++/* fan input sample buffer */
++#define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */
++ /* each sample of normal buffer */
++#define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */
++ /* if set, says that sample is pulse */
++#define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */
++
++/* first firmware register */
++#define ENE_FW1 0xF8F8
++#define ENE_FW1_ENABLE 0x01 /* enable fw processing */
++#define ENE_FW1_TXIRQ 0x02 /* TX interrupt pending */
++#define ENE_FW1_WAKE 0x40 /* enable wake from S3 */
++#define ENE_FW1_IRQ 0x80 /* enable interrupt */
++
++/* second firmware register */
++#define ENE_FW2 0xF8F9
++#define ENE_FW2_BUF_HIGH 0x01 /* which half of the buffer to read */
++#define ENE_FW2_IRQ_CLR 0x04 /* clear this on IRQ */
++#define ENE_FW2_GP40_AS_LEARN 0x08 /* normal input is used as */
++ /* learning input */
++#define ENE_FW2_FAN_AS_NRML_IN 0x40 /* fan is used as normal input */
++#define ENE_FW2_LEARNING 0x80 /* hardware supports learning and TX */
++
++/* transmitter ports */
++#define ENE_TX_PORT2 0xFC01 /* this enables one or both */
++#define ENE_TX_PORT2_EN 0x20 /* TX ports */
++#define ENE_TX_PORT1 0xFC08
++#define ENE_TX_PORT1_EN 0x02
++
++/* IRQ registers block (for revision B) */
++#define ENEB_IRQ 0xFD09 /* IRQ number */
++#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */
++#define ENEB_IRQ_STATUS 0xFD80 /* irq status */
++#define ENEB_IRQ_STATUS_IR 0x20 /* IR irq */
++
++/* fan as input settings - only if learning capable */
++#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */
++#define ENE_FAN_AS_IN1_EN 0xCD
++#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */
++#define ENE_FAN_AS_IN2_EN 0x03
++#define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */
++
++/* IRQ registers block (for revision C,D) */
++#define ENEC_IRQ 0xFE9B /* new irq settings register */
++#define ENEC_IRQ_MASK 0x0F /* irq number mask */
++#define ENEC_IRQ_UNK_EN 0x10 /* always enabled */
++#define ENEC_IRQ_STATUS 0x20 /* irq status and ACK */
++
++/* CIR block settings */
++#define ENE_CIR_CONF1 0xFEC0
++#define ENE_CIR_CONF1_TX_CLEAR 0x01 /* clear that on revC */
++ /* while transmitting */
++#define ENE_CIR_CONF1_RX_ON 0x07 /* normal receiver enabled */
++#define ENE_CIR_CONF1_LEARN1 0x08 /* enabled on learning mode */
++#define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */
++#define ENE_CIR_CONF1_TX_CARR 0x80 /* send TX carrier or not */
++
++#define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */
++#define ENE_CIR_CONF2_LEARN2 0x10 /* set on enable learning */
++#define ENE_CIR_CONF2_GPIO40DIS 0x20 /* disable input via gpio40 */
++
++#define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */
++#define ENE_CIR_SAMPLE_OVERFLOW 0x80 /* interrupt on overflows if set */
++
++
++/* Two byte tx buffer */
++#define ENE_TX_INPUT1 0xFEC9
++#define ENE_TX_INPUT2 0xFECA
++#define ENE_TX_PULSE_MASK 0x80 /* Transmitted sample is pulse */
++#define ENE_TX_SMLP_MASK 0x7F
++#define ENE_TX_SMPL_PERIOD 50 /* transmit sample period - fixed */
++
++
++/* Unknown TX setting - TX sample period ??? */
++#define ENE_TX_UNK1 0xFECB /* set to 0x63 */
++
++/* Current received carrier period */
++#define ENE_RX_CARRIER 0xFECC /* RX period (500 ns) */
++#define ENE_RX_CARRIER_VALID 0x80 /* Register content valid */
++
++
++/* TX period (1/carrier) */
++#define ENE_TX_PERIOD 0xFECE /* TX period (500 ns) */
++#define ENE_TX_PERIOD_UNKBIT 0x80 /* This bit set on transmit*/
++#define ENE_TX_PERIOD_PULSE 0xFECF /* TX pulse period (500 ns)*/
++
++/* Hardware versions */
++#define ENE_HW_VERSION 0xFF00 /* hardware revision */
++#define ENE_PLLFRH 0xFF16
++#define ENE_PLLFRL 0xFF17
++
++#define ENE_HW_UNK 0xFF1D
++#define ENE_HW_UNK_CLR 0x04
++#define ENE_HW_VER_MAJOR 0xFF1E /* chip version */
++#define ENE_HW_VER_MINOR 0xFF1F
++#define ENE_HW_VER_OLD 0xFD00
++
++/* Normal/Learning carrier ranges - only valid if we have learning input*/
++/* TODO: test */
++#define ENE_NORMAL_RX_LOW 34
++#define ENE_NORMAL_RX_HI 38
++
++/* Tx carrier range */
++/* Hardware might be able to do more, but this range is enough for
++ all purposes */
++#define ENE_TX_PERIOD_MAX 32 /* corresponds to 29.4 kHz */
++#define ENE_TX_PERIOD_MIN 16 /* corrsponds to 62.5 kHz */
++
++
++
++/* Minimal and maximal gaps */
++
++/* Normal case:
++ Minimal gap is 0x7F * sample period
++ Maximum gap depends on hardware.
++ For KB3926B, it is unlimited, for newer models its around
++ 250000, after which HW stops sending samples, and that is
++ not possible to change */
++
++/* Fan case:
++ Both minimal and maximal gaps are same, and equal to 0xFFF * 0x61
++ And there is nothing to change this setting
++*/
++
++#define ENE_MAXGAP 250000
++#define ENE_MINGAP (127 * sample_period)
++
++/******************************************************************************/
++
++#define ENE_DRIVER_NAME "ene_ir"
++
++#define ENE_IRQ_RX 1
++#define ENE_IRQ_TX 2
++
++#define ENE_HW_B 1 /* 3926B */
++#define ENE_HW_C 2 /* 3926C */
++#define ENE_HW_D 3 /* 3926D */
++
++#define ene_printk(level, text, ...) \
++ printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__)
++
++#define ene_dbg(text, ...) \
++ if (debug) \
++ printk(KERN_DEBUG \
++ ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
++
++#define ene_dbg_verbose(text, ...) \
++ if (debug > 1) \
++ printk(KERN_DEBUG \
++ ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
++
++
++struct ene_device {
++ struct pnp_dev *pnp_dev;
++ struct input_dev *idev;
++ struct ir_dev_props *props;
++ int in_use;
++
++ /* hw IO settings */
++ unsigned long hw_io;
++ int irq;
++ spinlock_t hw_lock;
++
++ /* HW features */
++ int hw_revision; /* hardware revision */
++ bool hw_learning_and_tx_capable; /* learning capable */
++ bool hw_gpio40_learning; /* gpio40 is learning */
++ bool hw_fan_as_normal_input; /* fan input is used as */
++ /* regular input */
++ /* HW state*/
++ int rx_pointer; /* hw pointer to rx buffer */
++ bool rx_fan_input_inuse; /* is fan input in use for rx*/
++ int tx_reg; /* current reg used for TX */
++ u8 saved_conf1; /* saved FEC0 reg */
++
++ /* TX sample handling */
++ unsigned int tx_sample; /* current sample for TX */
++ bool tx_sample_pulse; /* current sample is pulse */
++
++ /* TX buffer */
++ int *tx_buffer; /* input samples buffer*/
++ int tx_pos; /* position in that bufer */
++ int tx_len; /* current len of tx buffer */
++ int tx_done; /* done transmitting */
++ /* one more sample pending*/
++ struct completion tx_complete; /* TX completion */
++ struct timer_list tx_sim_timer;
++
++ /* TX settings */
++ int tx_period;
++ int tx_duty_cycle;
++ int transmitter_mask;
++
++ /* RX settings */
++ bool learning_enabled; /* learning input enabled */
++ bool carrier_detect_enabled; /* carrier detect enabled */
++ int rx_period_adjust;
++};
+diff -Naurp linux-2.6.35/drivers/media/IR/imon.c linux-2.6.35.new/drivers/media/IR/imon.c
+--- linux-2.6.35/drivers/media/IR/imon.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/imon.c 2010-09-09 23:21:42.000000000 -0400
+@@ -406,7 +406,7 @@ static int display_close(struct inode *i
+ struct imon_context *ictx = NULL;
+ int retval = 0;
+
+- ictx = (struct imon_context *)file->private_data;
++ ictx = file->private_data;
+
+ if (!ictx) {
+ err("%s: no context for device", __func__);
+@@ -811,7 +811,7 @@ static ssize_t vfd_write(struct file *fi
+ const unsigned char vfd_packet6[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
+
+- ictx = (struct imon_context *)file->private_data;
++ ictx = file->private_data;
+ if (!ictx) {
+ err("%s: no context for device", __func__);
+ return -ENODEV;
+@@ -895,7 +895,7 @@ static ssize_t lcd_write(struct file *fi
+ int retval = 0;
+ struct imon_context *ictx;
+
+- ictx = (struct imon_context *)file->private_data;
++ ictx = file->private_data;
+ if (!ictx) {
+ err("%s: no context for device", __func__);
+ return -ENODEV;
+diff -Naurp linux-2.6.35/drivers/media/IR/ir-core-priv.h linux-2.6.35.new/drivers/media/IR/ir-core-priv.h
+--- linux-2.6.35/drivers/media/IR/ir-core-priv.h 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/ir-core-priv.h 2010-09-09 23:21:49.000000000 -0400
+@@ -32,7 +32,7 @@ struct ir_raw_handler {
+
+ struct ir_raw_event_ctrl {
+ struct list_head list; /* to keep track of raw clients */
+- struct work_struct rx_work; /* for the rx decoding workqueue */
++ struct task_struct *thread;
+ struct kfifo kfifo; /* fifo for the pulse/space durations */
+ ktime_t last_event; /* when last event occurred */
+ enum raw_event_type last_type; /* last event type */
+@@ -41,10 +41,13 @@ struct ir_raw_event_ctrl {
+
+ /* raw decoder state follows */
+ struct ir_raw_event prev_ev;
++ struct ir_raw_event this_ev;
+ struct nec_dec {
+ int state;
+ unsigned count;
+ u32 bits;
++ bool is_nec_x;
++ bool necx_repeat;
+ } nec;
+ struct rc5_dec {
+ int state;
+@@ -82,7 +85,7 @@ struct ir_raw_event_ctrl {
+ struct lirc_codec {
+ struct ir_input_dev *ir_dev;
+ struct lirc_driver *drv;
+- int lircdata;
++ int carrier_low;
+ } lirc;
+ };
+
+@@ -110,10 +113,9 @@ static inline void decrease_duration(str
+ ev->duration -= duration;
+ }
+
+-#define TO_US(duration) (((duration) + 500) / 1000)
++#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000)
+ #define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
+ #define IS_RESET(ev) (ev.duration == 0)
+-
+ /*
+ * Routines from ir-sysfs.c - Meant to be called only internally inside
+ * ir-core
+@@ -132,7 +134,8 @@ int ir_raw_handler_register(struct ir_ra
+ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
+ void ir_raw_init(void);
+
+-
++int ir_rcmap_init(void);
++void ir_rcmap_cleanup(void);
+ /*
+ * Decoder initialization code
+ *
+diff -Naurp linux-2.6.35/drivers/media/IR/ir-jvc-decoder.c linux-2.6.35.new/drivers/media/IR/ir-jvc-decoder.c
+--- linux-2.6.35/drivers/media/IR/ir-jvc-decoder.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/ir-jvc-decoder.c 2010-09-09 23:21:49.000000000 -0400
+@@ -32,6 +32,7 @@ enum jvc_state {
+ STATE_BIT_SPACE,
+ STATE_TRAILER_PULSE,
+ STATE_TRAILER_SPACE,
++ STATE_CHECK_REPEAT,
+ };
+
+ /**
+@@ -60,6 +61,7 @@ static int ir_jvc_decode(struct input_de
+ IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
++again:
+ switch (data->state) {
+
+ case STATE_INACTIVE:
+@@ -149,8 +151,18 @@ static int ir_jvc_decode(struct input_de
+ }
+
+ data->count = 0;
+- data->state = STATE_BIT_PULSE;
++ data->state = STATE_CHECK_REPEAT;
+ return 0;
++
++ case STATE_CHECK_REPEAT:
++ if (!ev.pulse)
++ break;
++
++ if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
++ data->state = STATE_INACTIVE;
++ else
++ data->state = STATE_BIT_PULSE;
++ goto again;
+ }
+
+ out:
+diff -Naurp linux-2.6.35/drivers/media/IR/ir-keytable.c linux-2.6.35.new/drivers/media/IR/ir-keytable.c
+--- linux-2.6.35/drivers/media/IR/ir-keytable.c 2010-08-01 18:11:14.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/ir-keytable.c 2010-09-09 23:21:49.000000000 -0400
+@@ -339,6 +339,8 @@ void ir_repeat(struct input_dev *dev)
+
+ spin_lock_irqsave(&ir->keylock, flags);
+
++ input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode);
++
+ if (!ir->keypressed)
+ goto out;
+
+@@ -370,6 +372,8 @@ void ir_keydown(struct input_dev *dev, i
+
+ spin_lock_irqsave(&ir->keylock, flags);
+
++ input_event(dev, EV_MSC, MSC_SCAN, scancode);
++
+ /* Repeat event? */
+ if (ir->keypressed &&
+ ir->last_scancode == scancode &&
+@@ -383,9 +387,11 @@ void ir_keydown(struct input_dev *dev, i
+ ir->last_toggle = toggle;
+ ir->last_keycode = keycode;
+
++
+ if (keycode == KEY_RESERVED)
+ goto out;
+
++
+ /* Register a keypress */
+ ir->keypressed = true;
+ IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
+@@ -428,7 +434,7 @@ static void ir_close(struct input_dev *i
+ */
+ int __ir_input_register(struct input_dev *input_dev,
+ const struct ir_scancode_table *rc_tab,
+- const struct ir_dev_props *props,
++ struct ir_dev_props *props,
+ const char *driver_name)
+ {
+ struct ir_input_dev *ir_dev;
+@@ -480,6 +486,8 @@ int __ir_input_register(struct input_dev
+
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(EV_REP, input_dev->evbit);
++ set_bit(EV_MSC, input_dev->evbit);
++ set_bit(MSC_SCAN, input_dev->mscbit);
+
+ if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) {
+ rc = -ENOMEM;
+@@ -497,8 +505,10 @@ int __ir_input_register(struct input_dev
+ goto out_event;
+ }
+
+- IR_dprintk(1, "Registered input device on %s for %s remote.\n",
+- driver_name, rc_tab->name);
++ IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
++ driver_name, rc_tab->name,
++ (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
++ " in raw mode" : "");
+
+ return 0;
+
+diff -Naurp linux-2.6.35/drivers/media/IR/ir-lirc-codec.c linux-2.6.35.new/drivers/media/IR/ir-lirc-codec.c
+--- linux-2.6.35/drivers/media/IR/ir-lirc-codec.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/ir-lirc-codec.c 2010-09-09 23:21:49.000000000 -0400
+@@ -32,6 +32,7 @@
+ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
+ {
+ struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
++ int sample;
+
+ if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
+ return 0;
+@@ -39,18 +40,20 @@ static int ir_lirc_decode(struct input_d
+ if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
+ return -EINVAL;
+
++ if (IS_RESET(ev))
++ return 0;
++
+ IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
+ TO_US(ev.duration), TO_STR(ev.pulse));
+
+- ir_dev->raw->lirc.lircdata += ev.duration / 1000;
++ sample = ev.duration / 1000;
+ if (ev.pulse)
+- ir_dev->raw->lirc.lircdata |= PULSE_BIT;
++ sample |= PULSE_BIT;
+
+ lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
+- (unsigned char *) &ir_dev->raw->lirc.lircdata);
++ (unsigned char *) &sample);
+ wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
+
+- ir_dev->raw->lirc.lircdata = 0;
+
+ return 0;
+ }
+@@ -74,14 +77,9 @@ static ssize_t ir_lirc_transmit_ir(struc
+ if (count > LIRCBUF_SIZE || count % 2 == 0)
+ return -EINVAL;
+
+- txbuf = kzalloc(sizeof(int) * LIRCBUF_SIZE, GFP_KERNEL);
+- if (!txbuf)
+- return -ENOMEM;
+-
+- if (copy_from_user(txbuf, buf, n)) {
+- ret = -EFAULT;
+- goto out;
+- }
++ txbuf = memdup_user(buf, n);
++ if (IS_ERR(txbuf))
++ return PTR_ERR(txbuf);
+
+ ir_dev = lirc->ir_dev;
+ if (!ir_dev) {
+@@ -97,13 +95,14 @@ out:
+ return ret;
+ }
+
+-static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
++static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
++ unsigned long __user arg)
+ {
+ struct lirc_codec *lirc;
+ struct ir_input_dev *ir_dev;
+ int ret = 0;
+ void *drv_data;
+- unsigned long val;
++ unsigned long val = 0;
+
+ lirc = lirc_get_pdata(filep);
+ if (!lirc)
+@@ -115,47 +114,106 @@ static long ir_lirc_ioctl(struct file *f
+
+ drv_data = ir_dev->props->priv;
+
+- switch (cmd) {
+- case LIRC_SET_TRANSMITTER_MASK:
++ if (_IOC_DIR(cmd) & _IOC_WRITE) {
+ ret = get_user(val, (unsigned long *)arg);
+ if (ret)
+ return ret;
++ }
++
++ switch (cmd) {
++
++ /* legacy support */
++ case LIRC_GET_SEND_MODE:
++ val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
++ break;
+
+- if (ir_dev->props && ir_dev->props->s_tx_mask)
++ case LIRC_SET_SEND_MODE:
++ if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
++ return -EINVAL;
++ break;
++
++ /* TX settings */
++ case LIRC_SET_TRANSMITTER_MASK:
++ if (ir_dev->props->s_tx_mask)
+ ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
+ else
+ return -EINVAL;
+ break;
+
+ case LIRC_SET_SEND_CARRIER:
+- ret = get_user(val, (unsigned long *)arg);
+- if (ret)
+- return ret;
+-
+- if (ir_dev->props && ir_dev->props->s_tx_carrier)
++ if (ir_dev->props->s_tx_carrier)
+ ir_dev->props->s_tx_carrier(drv_data, (u32)val);
+ else
+ return -EINVAL;
+ break;
+
+- case LIRC_GET_SEND_MODE:
+- val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
+- ret = put_user(val, (unsigned long *)arg);
++ case LIRC_SET_SEND_DUTY_CYCLE:
++ if (!ir_dev->props->s_tx_duty_cycle)
++ return -ENOSYS;
++
++ if (val <= 0 || val >= 100)
++ return -EINVAL;
++
++ ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
+ break;
+
+- case LIRC_SET_SEND_MODE:
+- ret = get_user(val, (unsigned long *)arg);
+- if (ret)
+- return ret;
++ /* RX settings */
++ case LIRC_SET_REC_CARRIER:
++ if (ir_dev->props->s_rx_carrier_range)
++ ret = ir_dev->props->s_rx_carrier_range(
++ ir_dev->props->priv,
++ ir_dev->raw->lirc.carrier_low, val);
++ else
++ return -ENOSYS;
+
+- if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
++ if (!ret)
++ ir_dev->raw->lirc.carrier_low = 0;
++ break;
++
++ case LIRC_SET_REC_CARRIER_RANGE:
++ if (val >= 0)
++ ir_dev->raw->lirc.carrier_low = val;
++ break;
++
++
++ case LIRC_GET_REC_RESOLUTION:
++ val = ir_dev->props->rx_resolution;
++ break;
++
++ case LIRC_SET_WIDEBAND_RECEIVER:
++ if (ir_dev->props->s_learning_mode)
++ return ir_dev->props->s_learning_mode(
++ ir_dev->props->priv, !!val);
++ else
++ return -ENOSYS;
++
++ /* Generic timeout support */
++ case LIRC_GET_MIN_TIMEOUT:
++ if (!ir_dev->props->max_timeout)
++ return -ENOSYS;
++ val = ir_dev->props->min_timeout / 1000;
++ break;
++
++ case LIRC_GET_MAX_TIMEOUT:
++ if (!ir_dev->props->max_timeout)
++ return -ENOSYS;
++ val = ir_dev->props->max_timeout / 1000;
++ break;
++
++ case LIRC_SET_REC_TIMEOUT:
++ if (val < ir_dev->props->min_timeout ||
++ val > ir_dev->props->max_timeout)
+ return -EINVAL;
++ ir_dev->props->timeout = val * 1000;
+ break;
+
+ default:
+ return lirc_dev_fop_ioctl(filep, cmd, arg);
+ }
+
++ if (_IOC_DIR(cmd) & _IOC_READ)
++ ret = put_user(val, (unsigned long *)arg);
++
+ return ret;
+ }
+
+@@ -192,7 +250,7 @@ static int ir_lirc_register(struct input
+ return rc;
+
+ rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+- if (!drv)
++ if (!rbuf)
+ goto rbuf_alloc_failed;
+
+ rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE);
+@@ -201,13 +259,28 @@ static int ir_lirc_register(struct input
+
+ features = LIRC_CAN_REC_MODE2;
+ if (ir_dev->props->tx_ir) {
++
+ features |= LIRC_CAN_SEND_PULSE;
+ if (ir_dev->props->s_tx_mask)
+ features |= LIRC_CAN_SET_TRANSMITTER_MASK;
+ if (ir_dev->props->s_tx_carrier)
+ features |= LIRC_CAN_SET_SEND_CARRIER;
++
++ if (ir_dev->props->s_tx_duty_cycle)
++ features |= LIRC_CAN_SET_REC_DUTY_CYCLE;
+ }
+
++ if (ir_dev->props->s_rx_carrier_range)
++ features |= LIRC_CAN_SET_REC_CARRIER |
++ LIRC_CAN_SET_REC_CARRIER_RANGE;
++
++ if (ir_dev->props->s_learning_mode)
++ features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
++
++ if (ir_dev->props->max_timeout)
++ features |= LIRC_CAN_SET_REC_TIMEOUT;
++
++
+ snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
+ ir_dev->driver_name);
+ drv->minor = -1;
+@@ -229,8 +302,6 @@ static int ir_lirc_register(struct input
+
+ ir_dev->raw->lirc.drv = drv;
+ ir_dev->raw->lirc.ir_dev = ir_dev;
+- ir_dev->raw->lirc.lircdata = PULSE_MASK;
+-
+ return 0;
+
+ lirc_register_failed:
+diff -Naurp linux-2.6.35/drivers/media/IR/ir-nec-decoder.c linux-2.6.35.new/drivers/media/IR/ir-nec-decoder.c
+--- linux-2.6.35/drivers/media/IR/ir-nec-decoder.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/ir-nec-decoder.c 2010-09-09 23:21:49.000000000 -0400
+@@ -20,12 +20,13 @@
+ #define NEC_HEADER_PULSE (16 * NEC_UNIT)
+ #define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */
+ #define NEC_HEADER_SPACE (8 * NEC_UNIT)
+-#define NEC_REPEAT_SPACE (8 * NEC_UNIT)
++#define NEC_REPEAT_SPACE (4 * NEC_UNIT)
+ #define NEC_BIT_PULSE (1 * NEC_UNIT)
+ #define NEC_BIT_0_SPACE (1 * NEC_UNIT)
+ #define NEC_BIT_1_SPACE (3 * NEC_UNIT)
+ #define NEC_TRAILER_PULSE (1 * NEC_UNIT)
+ #define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
++#define NECX_REPEAT_BITS 1
+
+ enum nec_state {
+ STATE_INACTIVE,
+@@ -67,8 +68,12 @@ static int ir_nec_decode(struct input_de
+ if (!ev.pulse)
+ break;
+
+- if (!eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2) &&
+- !eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
++ if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) {
++ data->is_nec_x = false;
++ data->necx_repeat = false;
++ } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
++ data->is_nec_x = true;
++ else
+ break;
+
+ data->count = 0;
+@@ -105,6 +110,17 @@ static int ir_nec_decode(struct input_de
+ if (ev.pulse)
+ break;
+
++ if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&
++ geq_margin(ev.duration,
++ NEC_TRAILER_SPACE, NEC_UNIT / 2)) {
++ IR_dprintk(1, "Repeat last key\n");
++ ir_repeat(input_dev);
++ data->state = STATE_INACTIVE;
++ return 0;
++
++ } else if (data->count > NECX_REPEAT_BITS)
++ data->necx_repeat = false;
++
+ data->bits <<= 1;
+ if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
+ data->bits |= 1;
+@@ -159,6 +175,9 @@ static int ir_nec_decode(struct input_de
+ IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
+ }
+
++ if (data->is_nec_x)
++ data->necx_repeat = true;
++
+ ir_keydown(input_dev, scancode, 0);
+ data->state = STATE_INACTIVE;
+ return 0;
+diff -Naurp linux-2.6.35/drivers/media/IR/ir-raw-event.c linux-2.6.35.new/drivers/media/IR/ir-raw-event.c
+--- linux-2.6.35/drivers/media/IR/ir-raw-event.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/ir-raw-event.c 2010-09-09 23:21:49.000000000 -0400
+@@ -12,9 +12,10 @@
+ * GNU General Public License for more details.
+ */
+
+-#include <linux/workqueue.h>
+-#include <linux/spinlock.h>
++#include <linux/kthread.h>
++#include <linux/mutex.h>
+ #include <linux/sched.h>
++#include <linux/freezer.h>
+ #include "ir-core-priv.h"
+
+ /* Define the max number of pulse/space transitions to buffer */
+@@ -24,7 +25,7 @@
+ static LIST_HEAD(ir_raw_client_list);
+
+ /* Used to handle IR raw handler extensions */
+-static DEFINE_SPINLOCK(ir_raw_handler_lock);
++static DEFINE_MUTEX(ir_raw_handler_lock);
+ static LIST_HEAD(ir_raw_handler_list);
+ static u64 available_protocols;
+
+@@ -33,20 +34,30 @@ static u64 available_protocols;
+ static struct work_struct wq_load;
+ #endif
+
+-static void ir_raw_event_work(struct work_struct *work)
++static int ir_raw_event_thread(void *data)
+ {
+ struct ir_raw_event ev;
+ struct ir_raw_handler *handler;
+- struct ir_raw_event_ctrl *raw =
+- container_of(work, struct ir_raw_event_ctrl, rx_work);
++ struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
+
+- while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
+- spin_lock(&ir_raw_handler_lock);
+- list_for_each_entry(handler, &ir_raw_handler_list, list)
+- handler->decode(raw->input_dev, ev);
+- spin_unlock(&ir_raw_handler_lock);
+- raw->prev_ev = ev;
++ while (!kthread_should_stop()) {
++ try_to_freeze();
++
++ mutex_lock(&ir_raw_handler_lock);
++
++ while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
++ list_for_each_entry(handler, &ir_raw_handler_list, list)
++ handler->decode(raw->input_dev, ev);
++ raw->prev_ev = ev;
++ }
++
++ mutex_unlock(&ir_raw_handler_lock);
++
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule();
+ }
++
++ return 0;
+ }
+
+ /**
+@@ -66,6 +77,9 @@ int ir_raw_event_store(struct input_dev
+ if (!ir->raw)
+ return -EINVAL;
+
++ IR_dprintk(2, "sample: (05%dus %s)\n",
++ TO_US(ev->duration), TO_STR(ev->pulse));
++
+ if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
+ return -ENOMEM;
+
+@@ -126,6 +140,90 @@ int ir_raw_event_store_edge(struct input
+ EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
+
+ /**
++ * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
++ * @input_dev: the struct input_dev device descriptor
++ * @type: the type of the event that has occurred
++ *
++ * This routine (which may be called from an interrupt context) works
++ * in similiar manner to ir_raw_event_store_edge.
++ * This routine is intended for devices with limited internal buffer
++ * It automerges samples of same type, and handles timeouts
++ */
++int ir_raw_event_store_with_filter(struct input_dev *input_dev,
++ struct ir_raw_event *ev)
++{
++ struct ir_input_dev *ir = input_get_drvdata(input_dev);
++ struct ir_raw_event_ctrl *raw = ir->raw;
++
++ if (!raw || !ir->props)
++ return -EINVAL;
++
++ /* Ignore spaces in idle mode */
++ if (ir->idle && !ev->pulse)
++ return 0;
++ else if (ir->idle)
++ ir_raw_event_set_idle(input_dev, 0);
++
++ if (!raw->this_ev.duration) {
++ raw->this_ev = *ev;
++ } else if (ev->pulse == raw->this_ev.pulse) {
++ raw->this_ev.duration += ev->duration;
++ } else {
++ ir_raw_event_store(input_dev, &raw->this_ev);
++ raw->this_ev = *ev;
++ }
++
++ /* Enter idle mode if nessesary */
++ if (!ev->pulse && ir->props->timeout &&
++ raw->this_ev.duration >= ir->props->timeout)
++ ir_raw_event_set_idle(input_dev, 1);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
++
++void ir_raw_event_set_idle(struct input_dev *input_dev, int idle)
++{
++ struct ir_input_dev *ir = input_get_drvdata(input_dev);
++ struct ir_raw_event_ctrl *raw = ir->raw;
++ ktime_t now;
++ u64 delta;
++
++ if (!ir->props)
++ return;
++
++ if (!ir->raw)
++ goto out;
++
++ if (idle) {
++ IR_dprintk(2, "enter idle mode\n");
++ raw->last_event = ktime_get();
++ } else {
++ IR_dprintk(2, "exit idle mode\n");
++
++ now = ktime_get();
++ delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));
++
++ WARN_ON(raw->this_ev.pulse);
++
++ raw->this_ev.duration =
++ min(raw->this_ev.duration + delta,
++ (u64)IR_MAX_DURATION);
++
++ ir_raw_event_store(input_dev, &raw->this_ev);
++
++ if (raw->this_ev.duration == IR_MAX_DURATION)
++ ir_raw_event_reset(input_dev);
++
++ raw->this_ev.duration = 0;
++ }
++out:
++ if (ir->props->s_idle)
++ ir->props->s_idle(ir->props->priv, idle);
++ ir->idle = idle;
++}
++EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
++
++/**
+ * ir_raw_event_handle() - schedules the decoding of stored ir data
+ * @input_dev: the struct input_dev device descriptor
+ *
+@@ -138,7 +236,7 @@ void ir_raw_event_handle(struct input_de
+ if (!ir->raw)
+ return;
+
+- schedule_work(&ir->raw->rx_work);
++ wake_up_process(ir->raw->thread);
+ }
+ EXPORT_SYMBOL_GPL(ir_raw_event_handle);
+
+@@ -147,9 +245,9 @@ u64
+ ir_raw_get_allowed_protocols()
+ {
+ u64 protocols;
+- spin_lock(&ir_raw_handler_lock);
++ mutex_lock(&ir_raw_handler_lock);
+ protocols = available_protocols;
+- spin_unlock(&ir_raw_handler_lock);
++ mutex_unlock(&ir_raw_handler_lock);
+ return protocols;
+ }
+
+@@ -167,7 +265,7 @@ int ir_raw_event_register(struct input_d
+ return -ENOMEM;
+
+ ir->raw->input_dev = input_dev;
+- INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
++
+ ir->raw->enabled_protocols = ~0;
+ rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
+ GFP_KERNEL);
+@@ -177,12 +275,23 @@ int ir_raw_event_register(struct input_d
+ return rc;
+ }
+
+- spin_lock(&ir_raw_handler_lock);
++ ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw,
++ "rc%u", (unsigned int)ir->devno);
++
++ if (IS_ERR(ir->raw->thread)) {
++ int ret = PTR_ERR(ir->raw->thread);
++
++ kfree(ir->raw);
++ ir->raw = NULL;
++ return ret;
++ }
++
++ mutex_lock(&ir_raw_handler_lock);
+ list_add_tail(&ir->raw->list, &ir_raw_client_list);
+ list_for_each_entry(handler, &ir_raw_handler_list, list)
+ if (handler->raw_register)
+ handler->raw_register(ir->raw->input_dev);
+- spin_unlock(&ir_raw_handler_lock);
++ mutex_unlock(&ir_raw_handler_lock);
+
+ return 0;
+ }
+@@ -195,14 +304,14 @@ void ir_raw_event_unregister(struct inpu
+ if (!ir->raw)
+ return;
+
+- cancel_work_sync(&ir->raw->rx_work);
++ kthread_stop(ir->raw->thread);
+
+- spin_lock(&ir_raw_handler_lock);
++ mutex_lock(&ir_raw_handler_lock);
+ list_del(&ir->raw->list);
+ list_for_each_entry(handler, &ir_raw_handler_list, list)
+ if (handler->raw_unregister)
+ handler->raw_unregister(ir->raw->input_dev);
+- spin_unlock(&ir_raw_handler_lock);
++ mutex_unlock(&ir_raw_handler_lock);
+
+ kfifo_free(&ir->raw->kfifo);
+ kfree(ir->raw);
+@@ -217,13 +326,13 @@ int ir_raw_handler_register(struct ir_ra
+ {
+ struct ir_raw_event_ctrl *raw;
+
+- spin_lock(&ir_raw_handler_lock);
++ mutex_lock(&ir_raw_handler_lock);
+ list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
+ if (ir_raw_handler->raw_register)
+ list_for_each_entry(raw, &ir_raw_client_list, list)
+ ir_raw_handler->raw_register(raw->input_dev);
+ available_protocols |= ir_raw_handler->protocols;
+- spin_unlock(&ir_raw_handler_lock);
++ mutex_unlock(&ir_raw_handler_lock);
+
+ return 0;
+ }
+@@ -233,13 +342,13 @@ void ir_raw_handler_unregister(struct ir
+ {
+ struct ir_raw_event_ctrl *raw;
+
+- spin_lock(&ir_raw_handler_lock);
++ mutex_lock(&ir_raw_handler_lock);
+ list_del(&ir_raw_handler->list);
+ if (ir_raw_handler->raw_unregister)
+ list_for_each_entry(raw, &ir_raw_client_list, list)
+ ir_raw_handler->raw_unregister(raw->input_dev);
+ available_protocols &= ~ir_raw_handler->protocols;
+- spin_unlock(&ir_raw_handler_lock);
++ mutex_unlock(&ir_raw_handler_lock);
+ }
+ EXPORT_SYMBOL(ir_raw_handler_unregister);
+
+diff -Naurp linux-2.6.35/drivers/media/IR/ir-sysfs.c linux-2.6.35.new/drivers/media/IR/ir-sysfs.c
+--- linux-2.6.35/drivers/media/IR/ir-sysfs.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/ir-sysfs.c 2010-09-09 23:21:49.000000000 -0400
+@@ -33,6 +33,22 @@ static struct class ir_input_class = {
+ .devnode = ir_devnode,
+ };
+
++static struct {
++ u64 type;
++ char *name;
++} proto_names[] = {
++ { IR_TYPE_UNKNOWN, "unknown" },
++ { IR_TYPE_RC5, "rc-5" },
++ { IR_TYPE_NEC, "nec" },
++ { IR_TYPE_RC6, "rc-6" },
++ { IR_TYPE_JVC, "jvc" },
++ { IR_TYPE_SONY, "sony" },
++ { IR_TYPE_RC5_SZ, "rc-5-sz" },
++ { IR_TYPE_LIRC, "lirc" },
++};
++
++#define PROTO_NONE "none"
++
+ /**
+ * show_protocols() - shows the current IR protocol(s)
+ * @d: the device descriptor
+@@ -50,6 +66,7 @@ static ssize_t show_protocols(struct dev
+ struct ir_input_dev *ir_dev = dev_get_drvdata(d);
+ u64 allowed, enabled;
+ char *tmp = buf;
++ int i;
+
+ if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
+ enabled = ir_dev->rc_tab.ir_type;
+@@ -63,45 +80,12 @@ static ssize_t show_protocols(struct dev
+ (long long)allowed,
+ (long long)enabled);
+
+- if (allowed & enabled & IR_TYPE_UNKNOWN)
+- tmp += sprintf(tmp, "[unknown] ");
+- else if (allowed & IR_TYPE_UNKNOWN)
+- tmp += sprintf(tmp, "unknown ");
+-
+- if (allowed & enabled & IR_TYPE_RC5)
+- tmp += sprintf(tmp, "[rc5] ");
+- else if (allowed & IR_TYPE_RC5)
+- tmp += sprintf(tmp, "rc5 ");
+-
+- if (allowed & enabled & IR_TYPE_NEC)
+- tmp += sprintf(tmp, "[nec] ");
+- else if (allowed & IR_TYPE_NEC)
+- tmp += sprintf(tmp, "nec ");
+-
+- if (allowed & enabled & IR_TYPE_RC6)
+- tmp += sprintf(tmp, "[rc6] ");
+- else if (allowed & IR_TYPE_RC6)
+- tmp += sprintf(tmp, "rc6 ");
+-
+- if (allowed & enabled & IR_TYPE_JVC)
+- tmp += sprintf(tmp, "[jvc] ");
+- else if (allowed & IR_TYPE_JVC)
+- tmp += sprintf(tmp, "jvc ");
+-
+- if (allowed & enabled & IR_TYPE_SONY)
+- tmp += sprintf(tmp, "[sony] ");
+- else if (allowed & IR_TYPE_SONY)
+- tmp += sprintf(tmp, "sony ");
+-
+- if (allowed & enabled & IR_TYPE_RC5_SZ)
+- tmp += sprintf(tmp, "[rc5sz] ");
+- else if (allowed & IR_TYPE_RC5_SZ)
+- tmp += sprintf(tmp, "rc5sz ");
+-
+- if (allowed & enabled & IR_TYPE_LIRC)
+- tmp += sprintf(tmp, "[lirc] ");
+- else if (allowed & IR_TYPE_LIRC)
+- tmp += sprintf(tmp, "lirc ");
++ for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
++ if (allowed & enabled & proto_names[i].type)
++ tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
++ else if (allowed & proto_names[i].type)
++ tmp += sprintf(tmp, "%s ", proto_names[i].name);
++ }
+
+ if (tmp != buf)
+ tmp--;
+@@ -121,6 +105,7 @@ static ssize_t show_protocols(struct dev
+ * Writing "+proto" will add a protocol to the list of enabled protocols.
+ * Writing "-proto" will remove a protocol from the list of enabled protocols.
+ * Writing "proto" will enable only "proto".
++ * Writing "none" will disable all protocols.
+ * Returns -EINVAL if an invalid protocol combination or unknown protocol name
+ * is used, otherwise @len.
+ */
+@@ -134,71 +119,63 @@ static ssize_t store_protocols(struct de
+ const char *tmp;
+ u64 type;
+ u64 mask;
+- int rc;
++ int rc, i, count = 0;
+ unsigned long flags;
+
+- tmp = skip_spaces(data);
++ if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
++ type = ir_dev->rc_tab.ir_type;
++ else
++ type = ir_dev->raw->enabled_protocols;
+
+- if (*tmp == '+') {
+- enable = true;
+- disable = false;
+- tmp++;
+- } else if (*tmp == '-') {
+- enable = false;
+- disable = true;
+- tmp++;
+- } else {
+- enable = false;
+- disable = false;
+- }
++ while ((tmp = strsep((char **) &data, " \n")) != NULL) {
++ if (!*tmp)
++ break;
++
++ if (*tmp == '+') {
++ enable = true;
++ disable = false;
++ tmp++;
++ } else if (*tmp == '-') {
++ enable = false;
++ disable = true;
++ tmp++;
++ } else {
++ enable = false;
++ disable = false;
++ }
+
+- if (!strncasecmp(tmp, "unknown", 7)) {
+- tmp += 7;
+- mask = IR_TYPE_UNKNOWN;
+- } else if (!strncasecmp(tmp, "rc5", 3)) {
+- tmp += 3;
+- mask = IR_TYPE_RC5;
+- } else if (!strncasecmp(tmp, "nec", 3)) {
+- tmp += 3;
+- mask = IR_TYPE_NEC;
+- } else if (!strncasecmp(tmp, "rc6", 3)) {
+- tmp += 3;
+- mask = IR_TYPE_RC6;
+- } else if (!strncasecmp(tmp, "jvc", 3)) {
+- tmp += 3;
+- mask = IR_TYPE_JVC;
+- } else if (!strncasecmp(tmp, "sony", 4)) {
+- tmp += 4;
+- mask = IR_TYPE_SONY;
+- } else if (!strncasecmp(tmp, "rc5sz", 5)) {
+- tmp += 5;
+- mask = IR_TYPE_RC5_SZ;
+- } else if (!strncasecmp(tmp, "lirc", 4)) {
+- tmp += 4;
+- mask = IR_TYPE_LIRC;
+- } else {
+- IR_dprintk(1, "Unknown protocol\n");
+- return -EINVAL;
++ if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
++ tmp += sizeof(PROTO_NONE);
++ mask = 0;
++ count++;
++ } else {
++ for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
++ if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) {
++ tmp += strlen(proto_names[i].name);
++ mask = proto_names[i].type;
++ break;
++ }
++ }
++ if (i == ARRAY_SIZE(proto_names)) {
++ IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
++ return -EINVAL;
++ }
++ count++;
++ }
++
++ if (enable)
++ type |= mask;
++ else if (disable)
++ type &= ~mask;
++ else
++ type = mask;
+ }
+
+- tmp = skip_spaces(tmp);
+- if (*tmp != '\0') {
+- IR_dprintk(1, "Invalid trailing characters\n");
++ if (!count) {
++ IR_dprintk(1, "Protocol not specified\n");
+ return -EINVAL;
+ }
+
+- if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
+- type = ir_dev->rc_tab.ir_type;
+- else
+- type = ir_dev->raw->enabled_protocols;
+-
+- if (enable)
+- type |= mask;
+- else if (disable)
+- type &= ~mask;
+- else
+- type = mask;
+-
+ if (ir_dev->props && ir_dev->props->change_protocol) {
+ rc = ir_dev->props->change_protocol(ir_dev->props->priv,
+ type);
+@@ -217,7 +194,6 @@ static ssize_t store_protocols(struct de
+ ir_dev->raw->enabled_protocols = type;
+ }
+
+-
+ IR_dprintk(1, "Current protocol(s): 0x%llx\n",
+ (long long)type);
+
+@@ -286,6 +262,7 @@ int ir_register_class(struct input_dev *
+ return devno;
+
+ ir_dev->dev.type = &rc_dev_type;
++
+ ir_dev->dev.class = &ir_input_class;
+ ir_dev->dev.parent = input_dev->dev.parent;
+ dev_set_name(&ir_dev->dev, "rc%d", devno);
+@@ -349,6 +326,7 @@ static int __init ir_core_init(void)
+
+ /* Initialize/load the decoders/keymap code that will be used */
+ ir_raw_init();
++ ir_rcmap_init();
+
+ return 0;
+ }
+@@ -356,6 +334,7 @@ static int __init ir_core_init(void)
+ static void __exit ir_core_exit(void)
+ {
+ class_unregister(&ir_input_class);
++ ir_rcmap_cleanup();
+ }
+
+ module_init(ir_core_init);
+diff -Naurp linux-2.6.35/drivers/media/IR/Kconfig linux-2.6.35.new/drivers/media/IR/Kconfig
+--- linux-2.6.35/drivers/media/IR/Kconfig 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/Kconfig 2010-09-09 23:21:49.000000000 -0400
+@@ -1,13 +1,22 @@
+-config IR_CORE
+- tristate
++menuconfig IR_CORE
++ tristate "Infrared remote controller adapters"
+ depends on INPUT
+ default INPUT
++ ---help---
++ Enable support for Remote Controllers on Linux. This is
++ needed in order to support several video capture adapters.
++
++ Enable this option if you have a video capture board even
++ if you don't need IR, as otherwise, you may not be able to
++ compile the driver for your adapter.
+
+ config VIDEO_IR
+ tristate
+ depends on IR_CORE
+ default IR_CORE
+
++if IR_CORE
++
+ config LIRC
+ tristate
+ default y
+@@ -16,7 +25,7 @@ config LIRC
+ Enable this option to build the Linux Infrared Remote
+ Control (LIRC) core device interface driver. The LIRC
+ interface passes raw IR to and from userspace, where the
+- LIRC daemon handles protocol decoding for IR reception ann
++ LIRC daemon handles protocol decoding for IR reception and
+ encoding for IR transmitting (aka "blasting").
+
+ source "drivers/media/IR/keymaps/Kconfig"
+@@ -44,6 +53,7 @@ config IR_RC5_DECODER
+ config IR_RC6_DECODER
+ tristate "Enable IR raw decoder for the RC6 protocol"
+ depends on IR_CORE
++ select BITREVERSE
+ default y
+
+ ---help---
+@@ -77,7 +87,9 @@ config IR_RC5_SZ_DECODER
+
+ ---help---
+ Enable this option if you have IR with RC-5 (streamzap) protocol,
+- and if the IR is decoded in software.
++ and if the IR is decoded in software. (The Streamzap PC Remote
++ uses an IR protocol that is almost standard RC-5, but not quite,
++ as it uses an additional bit).
+
+ config IR_LIRC_CODEC
+ tristate "Enable IR to LIRC bridge"
+@@ -113,6 +125,20 @@ config IR_MCEUSB
+ To compile this driver as a module, choose M here: the
+ module will be called mceusb.
+
++config IR_ENE
++ tristate "ENE eHome Receiver/Transciever (pnp id: ENE0100/ENE02xxx)"
++ depends on PNP
++ depends on IR_CORE
++ ---help---
++ Say Y here to enable support for integrated infrared receiver
++ /transciever made by ENE.
++
++ You can see if you have it by looking at lspnp output.
++ Output should include ENE0100 ENE0200 or something similiar.
++
++ To compile this driver as a module, choose M here: the
++ module will be called ene_ir.
++
+ config IR_STREAMZAP
+ tristate "Streamzap PC Remote IR Receiver"
+ depends on USB_ARCH_HAS_HCD
+@@ -124,3 +150,5 @@ config IR_STREAMZAP
+
+ To compile this driver as a module, choose M here: the
+ module will be called streamzap.
++
++endif #IR_CORE
+diff -Naurp linux-2.6.35/drivers/media/IR/keymaps/Makefile linux-2.6.35.new/drivers/media/IR/keymaps/Makefile
+--- linux-2.6.35/drivers/media/IR/keymaps/Makefile 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/keymaps/Makefile 2010-09-09 23:21:42.000000000 -0400
+@@ -14,10 +14,11 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t
+ rc-budget-ci-old.o \
+ rc-cinergy-1400.o \
+ rc-cinergy.o \
++ rc-dib0700-nec.o \
++ rc-dib0700-rc5.o \
+ rc-dm1105-nec.o \
+ rc-dntv-live-dvb-t.o \
+ rc-dntv-live-dvbt-pro.o \
+- rc-empty.o \
+ rc-em-terratec.o \
+ rc-encore-enltv2.o \
+ rc-encore-enltv.o \
+diff -Naurp linux-2.6.35/drivers/media/IR/keymaps/rc-dib0700-nec.c linux-2.6.35.new/drivers/media/IR/keymaps/rc-dib0700-nec.c
+--- linux-2.6.35/drivers/media/IR/keymaps/rc-dib0700-nec.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.new/drivers/media/IR/keymaps/rc-dib0700-nec.c 2010-09-09 23:21:42.000000000 -0400
+@@ -0,0 +1,124 @@
++/* rc-dvb0700-big.c - Keytable for devices in dvb0700
++ *
++ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab at redhat.com>
++ *
++ * TODO: This table is a real mess, as it merges RC codes from several
++ * devices into a big table. It also has both RC-5 and NEC codes inside.
++ * It should be broken into small tables, and the protocols should properly
++ * be indentificated.
++ *
++ * The table were imported from dib0700_devices.c.
++ *
++ * 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 <media/rc-map.h>
++
++static struct ir_scancode dib0700_nec_table[] = {
++ /* Key codes for the Pixelview SBTVD remote */
++ { 0x8613, KEY_MUTE },
++ { 0x8612, KEY_POWER },
++ { 0x8601, KEY_1 },
++ { 0x8602, KEY_2 },
++ { 0x8603, KEY_3 },
++ { 0x8604, KEY_4 },
++ { 0x8605, KEY_5 },
++ { 0x8606, KEY_6 },
++ { 0x8607, KEY_7 },
++ { 0x8608, KEY_8 },
++ { 0x8609, KEY_9 },
++ { 0x8600, KEY_0 },
++ { 0x860d, KEY_CHANNELUP },
++ { 0x8619, KEY_CHANNELDOWN },
++ { 0x8610, KEY_VOLUMEUP },
++ { 0x860c, KEY_VOLUMEDOWN },
++
++ { 0x860a, KEY_CAMERA },
++ { 0x860b, KEY_ZOOM },
++ { 0x861b, KEY_BACKSPACE },
++ { 0x8615, KEY_ENTER },
++
++ { 0x861d, KEY_UP },
++ { 0x861e, KEY_DOWN },
++ { 0x860e, KEY_LEFT },
++ { 0x860f, KEY_RIGHT },
++
++ { 0x8618, KEY_RECORD },
++ { 0x861a, KEY_STOP },
++
++ /* Key codes for the EvolutePC TVWay+ remote */
++ { 0x7a00, KEY_MENU },
++ { 0x7a01, KEY_RECORD },
++ { 0x7a02, KEY_PLAY },
++ { 0x7a03, KEY_STOP },
++ { 0x7a10, KEY_CHANNELUP },
++ { 0x7a11, KEY_CHANNELDOWN },
++ { 0x7a12, KEY_VOLUMEUP },
++ { 0x7a13, KEY_VOLUMEDOWN },
++ { 0x7a40, KEY_POWER },
++ { 0x7a41, KEY_MUTE },
++
++ /* Key codes for the Elgato EyeTV Diversity silver remote */
++ { 0x4501, KEY_POWER },
++ { 0x4502, KEY_MUTE },
++ { 0x4503, KEY_1 },
++ { 0x4504, KEY_2 },
++ { 0x4505, KEY_3 },
++ { 0x4506, KEY_4 },
++ { 0x4507, KEY_5 },
++ { 0x4508, KEY_6 },
++ { 0x4509, KEY_7 },
++ { 0x450a, KEY_8 },
++ { 0x450b, KEY_9 },
++ { 0x450c, KEY_LAST },
++ { 0x450d, KEY_0 },
++ { 0x450e, KEY_ENTER },
++ { 0x450f, KEY_RED },
++ { 0x4510, KEY_CHANNELUP },
++ { 0x4511, KEY_GREEN },
++ { 0x4512, KEY_VOLUMEDOWN },
++ { 0x4513, KEY_OK },
++ { 0x4514, KEY_VOLUMEUP },
++ { 0x4515, KEY_YELLOW },
++ { 0x4516, KEY_CHANNELDOWN },
++ { 0x4517, KEY_BLUE },
++ { 0x4518, KEY_LEFT }, /* Skip backwards */
++ { 0x4519, KEY_PLAYPAUSE },
++ { 0x451a, KEY_RIGHT }, /* Skip forward */
++ { 0x451b, KEY_REWIND },
++ { 0x451c, KEY_L }, /* Live */
++ { 0x451d, KEY_FASTFORWARD },
++ { 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
++ { 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
++ { 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
++ { 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */
++ { 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
++};
++
++static struct rc_keymap dib0700_nec_map = {
++ .map = {
++ .scan = dib0700_nec_table,
++ .size = ARRAY_SIZE(dib0700_nec_table),
++ .ir_type = IR_TYPE_NEC,
++ .name = RC_MAP_DIB0700_NEC_TABLE,
++ }
++};
++
++static int __init init_rc_map(void)
++{
++ return ir_register_map(&dib0700_nec_map);
++}
++
++static void __exit exit_rc_map(void)
++{
++ ir_unregister_map(&dib0700_nec_map);
++}
++
++module_init(init_rc_map)
++module_exit(exit_rc_map)
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at redhat.com>");
+diff -Naurp linux-2.6.35/drivers/media/IR/keymaps/rc-dib0700-rc5.c linux-2.6.35.new/drivers/media/IR/keymaps/rc-dib0700-rc5.c
+--- linux-2.6.35/drivers/media/IR/keymaps/rc-dib0700-rc5.c 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.new/drivers/media/IR/keymaps/rc-dib0700-rc5.c 2010-09-09 23:21:42.000000000 -0400
+@@ -0,0 +1,235 @@
++/* rc-dvb0700-big.c - Keytable for devices in dvb0700
++ *
++ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab at redhat.com>
++ *
++ * TODO: This table is a real mess, as it merges RC codes from several
++ * devices into a big table. It also has both RC-5 and NEC codes inside.
++ * It should be broken into small tables, and the protocols should properly
++ * be indentificated.
++ *
++ * The table were imported from dib0700_devices.c.
++ *
++ * 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 <media/rc-map.h>
++
++static struct ir_scancode dib0700_rc5_table[] = {
++ /* Key codes for the tiny Pinnacle remote*/
++ { 0x0700, KEY_MUTE },
++ { 0x0701, KEY_MENU }, /* Pinnacle logo */
++ { 0x0739, KEY_POWER },
++ { 0x0703, KEY_VOLUMEUP },
++ { 0x0709, KEY_VOLUMEDOWN },
++ { 0x0706, KEY_CHANNELUP },
++ { 0x070c, KEY_CHANNELDOWN },
++ { 0x070f, KEY_1 },
++ { 0x0715, KEY_2 },
++ { 0x0710, KEY_3 },
++ { 0x0718, KEY_4 },
++ { 0x071b, KEY_5 },
++ { 0x071e, KEY_6 },
++ { 0x0711, KEY_7 },
++ { 0x0721, KEY_8 },
++ { 0x0712, KEY_9 },
++ { 0x0727, KEY_0 },
++ { 0x0724, KEY_SCREEN }, /* 'Square' key */
++ { 0x072a, KEY_TEXT }, /* 'T' key */
++ { 0x072d, KEY_REWIND },
++ { 0x0730, KEY_PLAY },
++ { 0x0733, KEY_FASTFORWARD },
++ { 0x0736, KEY_RECORD },
++ { 0x073c, KEY_STOP },
++ { 0x073f, KEY_CANCEL }, /* '?' key */
++
++ /* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
++ { 0xeb01, KEY_POWER },
++ { 0xeb02, KEY_1 },
++ { 0xeb03, KEY_2 },
++ { 0xeb04, KEY_3 },
++ { 0xeb05, KEY_4 },
++ { 0xeb06, KEY_5 },
++ { 0xeb07, KEY_6 },
++ { 0xeb08, KEY_7 },
++ { 0xeb09, KEY_8 },
++ { 0xeb0a, KEY_9 },
++ { 0xeb0b, KEY_VIDEO },
++ { 0xeb0c, KEY_0 },
++ { 0xeb0d, KEY_REFRESH },
++ { 0xeb0f, KEY_EPG },
++ { 0xeb10, KEY_UP },
++ { 0xeb11, KEY_LEFT },
++ { 0xeb12, KEY_OK },
++ { 0xeb13, KEY_RIGHT },
++ { 0xeb14, KEY_DOWN },
++ { 0xeb16, KEY_INFO },
++ { 0xeb17, KEY_RED },
++ { 0xeb18, KEY_GREEN },
++ { 0xeb19, KEY_YELLOW },
++ { 0xeb1a, KEY_BLUE },
++ { 0xeb1b, KEY_CHANNELUP },
++ { 0xeb1c, KEY_VOLUMEUP },
++ { 0xeb1d, KEY_MUTE },
++ { 0xeb1e, KEY_VOLUMEDOWN },
++ { 0xeb1f, KEY_CHANNELDOWN },
++ { 0xeb40, KEY_PAUSE },
++ { 0xeb41, KEY_HOME },
++ { 0xeb42, KEY_MENU }, /* DVD Menu */
++ { 0xeb43, KEY_SUBTITLE },
++ { 0xeb44, KEY_TEXT }, /* Teletext */
++ { 0xeb45, KEY_DELETE },
++ { 0xeb46, KEY_TV },
++ { 0xeb47, KEY_DVD },
++ { 0xeb48, KEY_STOP },
++ { 0xeb49, KEY_VIDEO },
++ { 0xeb4a, KEY_AUDIO }, /* Music */
++ { 0xeb4b, KEY_SCREEN }, /* Pic */
++ { 0xeb4c, KEY_PLAY },
++ { 0xeb4d, KEY_BACK },
++ { 0xeb4e, KEY_REWIND },
++ { 0xeb4f, KEY_FASTFORWARD },
++ { 0xeb54, KEY_PREVIOUS },
++ { 0xeb58, KEY_RECORD },
++ { 0xeb5c, KEY_NEXT },
++
++ /* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
++ { 0x1e00, KEY_0 },
++ { 0x1e01, KEY_1 },
++ { 0x1e02, KEY_2 },
++ { 0x1e03, KEY_3 },
++ { 0x1e04, KEY_4 },
++ { 0x1e05, KEY_5 },
++ { 0x1e06, KEY_6 },
++ { 0x1e07, KEY_7 },
++ { 0x1e08, KEY_8 },
++ { 0x1e09, KEY_9 },
++ { 0x1e0a, KEY_KPASTERISK },
++ { 0x1e0b, KEY_RED },
++ { 0x1e0c, KEY_RADIO },
++ { 0x1e0d, KEY_MENU },
++ { 0x1e0e, KEY_GRAVE }, /* # */
++ { 0x1e0f, KEY_MUTE },
++ { 0x1e10, KEY_VOLUMEUP },
++ { 0x1e11, KEY_VOLUMEDOWN },
++ { 0x1e12, KEY_CHANNEL },
++ { 0x1e14, KEY_UP },
++ { 0x1e15, KEY_DOWN },
++ { 0x1e16, KEY_LEFT },
++ { 0x1e17, KEY_RIGHT },
++ { 0x1e18, KEY_VIDEO },
++ { 0x1e19, KEY_AUDIO },
++ { 0x1e1a, KEY_MEDIA },
++ { 0x1e1b, KEY_EPG },
++ { 0x1e1c, KEY_TV },
++ { 0x1e1e, KEY_NEXT },
++ { 0x1e1f, KEY_BACK },
++ { 0x1e20, KEY_CHANNELUP },
++ { 0x1e21, KEY_CHANNELDOWN },
++ { 0x1e24, KEY_LAST }, /* Skip backwards */
++ { 0x1e25, KEY_OK },
++ { 0x1e29, KEY_BLUE},
++ { 0x1e2e, KEY_GREEN },
++ { 0x1e30, KEY_PAUSE },
++ { 0x1e32, KEY_REWIND },
++ { 0x1e34, KEY_FASTFORWARD },
++ { 0x1e35, KEY_PLAY },
++ { 0x1e36, KEY_STOP },
++ { 0x1e37, KEY_RECORD },
++ { 0x1e38, KEY_YELLOW },
++ { 0x1e3b, KEY_GOTO },
++ { 0x1e3d, KEY_POWER },
++
++ /* Key codes for the Leadtek Winfast DTV Dongle */
++ { 0x0042, KEY_POWER },
++ { 0x077c, KEY_TUNER },
++ { 0x0f4e, KEY_PRINT }, /* PREVIEW */
++ { 0x0840, KEY_SCREEN }, /* full screen toggle*/
++ { 0x0f71, KEY_DOT }, /* frequency */
++ { 0x0743, KEY_0 },
++ { 0x0c41, KEY_1 },
++ { 0x0443, KEY_2 },
++ { 0x0b7f, KEY_3 },
++ { 0x0e41, KEY_4 },
++ { 0x0643, KEY_5 },
++ { 0x097f, KEY_6 },
++ { 0x0d7e, KEY_7 },
++ { 0x057c, KEY_8 },
++ { 0x0a40, KEY_9 },
++ { 0x0e4e, KEY_CLEAR },
++ { 0x047c, KEY_CHANNEL }, /* show channel number */
++ { 0x0f41, KEY_LAST }, /* recall */
++ { 0x0342, KEY_MUTE },
++ { 0x064c, KEY_RESERVED }, /* PIP button*/
++ { 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
++ { 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
++ { 0x0b70, KEY_RECORD },
++ { 0x037d, KEY_VOLUMEUP },
++ { 0x017d, KEY_VOLUMEDOWN },
++ { 0x0242, KEY_CHANNELUP },
++ { 0x007d, KEY_CHANNELDOWN },
++
++ /* Key codes for Nova-TD "credit card" remote control. */
++ { 0x1d00, KEY_0 },
++ { 0x1d01, KEY_1 },
++ { 0x1d02, KEY_2 },
++ { 0x1d03, KEY_3 },
++ { 0x1d04, KEY_4 },
++ { 0x1d05, KEY_5 },
++ { 0x1d06, KEY_6 },
++ { 0x1d07, KEY_7 },
++ { 0x1d08, KEY_8 },
++ { 0x1d09, KEY_9 },
++ { 0x1d0a, KEY_TEXT },
++ { 0x1d0d, KEY_MENU },
++ { 0x1d0f, KEY_MUTE },
++ { 0x1d10, KEY_VOLUMEUP },
++ { 0x1d11, KEY_VOLUMEDOWN },
++ { 0x1d12, KEY_CHANNEL },
++ { 0x1d14, KEY_UP },
++ { 0x1d15, KEY_DOWN },
++ { 0x1d16, KEY_LEFT },
++ { 0x1d17, KEY_RIGHT },
++ { 0x1d1c, KEY_TV },
++ { 0x1d1e, KEY_NEXT },
++ { 0x1d1f, KEY_BACK },
++ { 0x1d20, KEY_CHANNELUP },
++ { 0x1d21, KEY_CHANNELDOWN },
++ { 0x1d24, KEY_LAST },
++ { 0x1d25, KEY_OK },
++ { 0x1d30, KEY_PAUSE },
++ { 0x1d32, KEY_REWIND },
++ { 0x1d34, KEY_FASTFORWARD },
++ { 0x1d35, KEY_PLAY },
++ { 0x1d36, KEY_STOP },
++ { 0x1d37, KEY_RECORD },
++ { 0x1d3b, KEY_GOTO },
++ { 0x1d3d, KEY_POWER },
++};
++
++static struct rc_keymap dib0700_rc5_map = {
++ .map = {
++ .scan = dib0700_rc5_table,
++ .size = ARRAY_SIZE(dib0700_rc5_table),
++ .ir_type = IR_TYPE_RC5,
++ .name = RC_MAP_DIB0700_RC5_TABLE,
++ }
++};
++
++static int __init init_rc_map(void)
++{
++ return ir_register_map(&dib0700_rc5_map);
++}
++
++static void __exit exit_rc_map(void)
++{
++ ir_unregister_map(&dib0700_rc5_map);
++}
++
++module_init(init_rc_map)
++module_exit(exit_rc_map)
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab at redhat.com>");
+diff -Naurp linux-2.6.35/drivers/media/IR/keymaps/rc-rc6-mce.c linux-2.6.35.new/drivers/media/IR/keymaps/rc-rc6-mce.c
+--- linux-2.6.35/drivers/media/IR/keymaps/rc-rc6-mce.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/keymaps/rc-rc6-mce.c 2010-09-09 23:21:49.000000000 -0400
+@@ -74,6 +74,8 @@ static struct ir_scancode rc6_mce[] = {
+ { 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
+ { 0x800f044d, KEY_TITLE },
+
++ { 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */
++
+ { 0x800f040c, KEY_POWER },
+ { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
+
+diff -Naurp linux-2.6.35/drivers/media/IR/keymaps/rc-streamzap.c linux-2.6.35.new/drivers/media/IR/keymaps/rc-streamzap.c
+--- linux-2.6.35/drivers/media/IR/keymaps/rc-streamzap.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/keymaps/rc-streamzap.c 2010-09-09 23:21:42.000000000 -0400
+@@ -60,7 +60,7 @@ static struct rc_keymap streamzap_map =
+ .map = {
+ .scan = streamzap,
+ .size = ARRAY_SIZE(streamzap),
+- .ir_type = IR_TYPE_RC5,
++ .ir_type = IR_TYPE_RC5_SZ,
+ .name = RC_MAP_STREAMZAP,
+ }
+ };
+diff -Naurp linux-2.6.35/drivers/media/IR/Makefile linux-2.6.35.new/drivers/media/IR/Makefile
+--- linux-2.6.35/drivers/media/IR/Makefile 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/Makefile 2010-09-09 23:21:42.000000000 -0400
+@@ -17,4 +17,5 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-c
+ # stand-alone IR receivers/transmitters
+ obj-$(CONFIG_IR_IMON) += imon.o
+ obj-$(CONFIG_IR_MCEUSB) += mceusb.o
++obj-$(CONFIG_IR_ENE) += ene_ir.o
+ obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
+diff -Naurp linux-2.6.35/drivers/media/IR/mceusb.c linux-2.6.35.new/drivers/media/IR/mceusb.c
+--- linux-2.6.35/drivers/media/IR/mceusb.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/mceusb.c 2010-09-09 23:21:49.000000000 -0400
+@@ -120,6 +120,10 @@ static struct usb_device_id mceusb_dev_t
+ { USB_DEVICE(VENDOR_PHILIPS, 0x0613) },
+ /* Philips eHome Infrared Transceiver */
+ { USB_DEVICE(VENDOR_PHILIPS, 0x0815) },
++ /* Philips/Spinel plus IR transceiver for ASUS */
++ { USB_DEVICE(VENDOR_PHILIPS, 0x206c) },
++ /* Philips/Spinel plus IR transceiver for ASUS */
++ { USB_DEVICE(VENDOR_PHILIPS, 0x2088) },
+ /* Realtek MCE IR Receiver */
+ { USB_DEVICE(VENDOR_REALTEK, 0x0161) },
+ /* SMK/Toshiba G83C0004D410 */
+@@ -427,7 +431,7 @@ static void mceusb_dev_printdata(struct
+ }
+ }
+
+-static void usb_async_callback(struct urb *urb, struct pt_regs *regs)
++static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
+ {
+ struct mceusb_dev *ir;
+ int len;
+@@ -476,7 +480,7 @@ static void mce_request_packet(struct mc
+ /* outbound data */
+ usb_fill_int_urb(async_urb, ir->usbdev,
+ usb_sndintpipe(ir->usbdev, ep->bEndpointAddress),
+- async_buf, size, (usb_complete_t) usb_async_callback,
++ async_buf, size, (usb_complete_t)mce_async_callback,
+ ir, ep->bInterval);
+ memcpy(async_buf, data, size);
+
+@@ -919,7 +923,6 @@ static int __devinit mceusb_dev_probe(st
+ struct usb_endpoint_descriptor *ep = NULL;
+ struct usb_endpoint_descriptor *ep_in = NULL;
+ struct usb_endpoint_descriptor *ep_out = NULL;
+- struct usb_host_config *config;
+ struct mceusb_dev *ir = NULL;
+ int pipe, maxp, i;
+ char buf[63], name[128] = "";
+@@ -929,7 +932,6 @@ static int __devinit mceusb_dev_probe(st
+
+ dev_dbg(&intf->dev, ": %s called\n", __func__);
+
+- config = dev->actconfig;
+ idesc = intf->cur_altsetting;
+
+ is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0;
+diff -Naurp linux-2.6.35/drivers/media/IR/rc-map.c linux-2.6.35.new/drivers/media/IR/rc-map.c
+--- linux-2.6.35/drivers/media/IR/rc-map.c 2010-08-01 18:11:14.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/rc-map.c 2010-09-09 23:21:49.000000000 -0400
+@@ -82,3 +82,26 @@ void ir_unregister_map(struct rc_keymap
+ }
+ EXPORT_SYMBOL_GPL(ir_unregister_map);
+
++
++static struct ir_scancode empty[] = {
++ { 0x2a, KEY_COFFEE },
++};
++
++static struct rc_keymap empty_map = {
++ .map = {
++ .scan = empty,
++ .size = ARRAY_SIZE(empty),
++ .ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
++ .name = RC_MAP_EMPTY,
++ }
++};
++
++int ir_rcmap_init(void)
++{
++ return ir_register_map(&empty_map);
++}
++
++void ir_rcmap_cleanup(void)
++{
++ ir_unregister_map(&empty_map);
++}
+diff -Naurp linux-2.6.35/drivers/media/IR/rc-map.c.orig linux-2.6.35.new/drivers/media/IR/rc-map.c.orig
+--- linux-2.6.35/drivers/media/IR/rc-map.c.orig 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.new/drivers/media/IR/rc-map.c.orig 2010-09-09 23:21:42.000000000 -0400
+@@ -0,0 +1,84 @@
++/* ir-raw-event.c - handle IR Pulse/Space event
++ *
++ * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab at redhat.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 version 2 of the License.
++ *
++ * 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.
++ */
++
++#include <media/ir-core.h>
++#include <linux/spinlock.h>
++#include <linux/delay.h>
++
++/* Used to handle IR raw handler extensions */
++static LIST_HEAD(rc_map_list);
++static DEFINE_SPINLOCK(rc_map_lock);
++
++static struct rc_keymap *seek_rc_map(const char *name)
++{
++ struct rc_keymap *map = NULL;
++
++ spin_lock(&rc_map_lock);
++ list_for_each_entry(map, &rc_map_list, list) {
++ if (!strcmp(name, map->map.name)) {
++ spin_unlock(&rc_map_lock);
++ return map;
++ }
++ }
++ spin_unlock(&rc_map_lock);
++
++ return NULL;
++}
++
++struct ir_scancode_table *get_rc_map(const char *name)
++{
++
++ struct rc_keymap *map;
++
++ map = seek_rc_map(name);
++#ifdef MODULE
++ if (!map) {
++ int rc = request_module(name);
++ if (rc < 0) {
++ printk(KERN_ERR "Couldn't load IR keymap %s\n", name);
++ return NULL;
++ }
++ msleep(20); /* Give some time for IR to register */
++
++ map = seek_rc_map(name);
++ }
++#endif
++ if (!map) {
++ printk(KERN_ERR "IR keymap %s not found\n", name);
++ return NULL;
++ }
++
++ printk(KERN_INFO "Registered IR keymap %s\n", map->map.name);
++
++ return &map->map;
++}
++EXPORT_SYMBOL_GPL(get_rc_map);
++
++int ir_register_map(struct rc_keymap *map)
++{
++ spin_lock(&rc_map_lock);
++ list_add_tail(&map->list, &rc_map_list);
++ spin_unlock(&rc_map_lock);
++ return 0;
++}
++EXPORT_SYMBOL_GPL(ir_register_map);
++
++void ir_unregister_map(struct rc_keymap *map)
++{
++ spin_lock(&rc_map_lock);
++ list_del(&map->list);
++ spin_unlock(&rc_map_lock);
++}
++EXPORT_SYMBOL_GPL(ir_unregister_map);
++
+diff -Naurp linux-2.6.35/drivers/media/IR/rc-map.c.rej linux-2.6.35.new/drivers/media/IR/rc-map.c.rej
+--- linux-2.6.35/drivers/media/IR/rc-map.c.rej 1969-12-31 19:00:00.000000000 -0500
++++ linux-2.6.35.new/drivers/media/IR/rc-map.c.rej 2010-09-09 23:21:42.000000000 -0400
+@@ -0,0 +1,13 @@
++--- drivers/media/IR/rc-map.c
+++++ drivers/media/IR/rc-map.c
++@@ -100,8 +100,10 @@
++ {
++ return ir_register_map(&empty_map);
++ }
+++EXPORT_SYMBOL_GPL(ir_rcmap_init);
++
++ void ir_rcmap_cleanup(void)
++ {
++ ir_unregister_map(&empty_map);
++ }
+++EXPORT_SYMBOL_GPL(ir_rcmap_cleanup);
+diff -Naurp linux-2.6.35/drivers/media/IR/streamzap.c linux-2.6.35.new/drivers/media/IR/streamzap.c
+--- linux-2.6.35/drivers/media/IR/streamzap.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/media/IR/streamzap.c 2010-09-09 23:21:42.000000000 -0400
+@@ -71,9 +71,9 @@ MODULE_DEVICE_TABLE(usb, streamzap_table
+
+ /* from ir-rc5-sz-decoder.c */
+ #ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
+-#define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder")
++#define load_rc5_sz_decode() request_module("ir-rc5-sz-decoder")
+ #else
+-#define load_rc5_sz_decode() 0
++#define load_rc5_sz_decode() 0
+ #endif
+
+ enum StreamzapDecoderState {
+@@ -244,9 +244,9 @@ static void streamzap_callback(struct ur
+ break;
+ }
+
+- dev_info(sz->dev, "%s: received urb, len %d\n", __func__, len);
++ dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
+ for (i = 0; i < len; i++) {
+- dev_info(sz->dev, "sz idx %d: %x\n",
++ dev_dbg(sz->dev, "sz idx %d: %x\n",
+ i, (unsigned char)sz->buf_in[i]);
+ switch (sz->decoder_state) {
+ case PulseSpace:
+diff -Naurp linux-2.6.35/drivers/staging/lirc/Kconfig linux-2.6.35.new/drivers/staging/lirc/Kconfig
+--- linux-2.6.35/drivers/staging/lirc/Kconfig 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/staging/lirc/Kconfig 2010-09-09 23:21:42.000000000 -0400
+@@ -18,14 +18,6 @@ config LIRC_BT829
+ help
+ Driver for the IR interface on BT829-based hardware
+
+-config LIRC_ENE0100
+- tristate "ENE KB3924/ENE0100 CIR Port Reciever"
+- depends on LIRC_STAGING && PNP
+- help
+- This is a driver for CIR port handled by ENE KB3924 embedded
+- controller found on some notebooks.
+- It appears on PNP list as ENE0100.
+-
+ config LIRC_I2C
+ tristate "I2C Based IR Receivers"
+ depends on LIRC_STAGING && I2C
+diff -Naurp linux-2.6.35/drivers/staging/lirc/lirc_ene0100.c linux-2.6.35.new/drivers/staging/lirc/lirc_ene0100.c
+--- linux-2.6.35/drivers/staging/lirc/lirc_ene0100.c 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/staging/lirc/lirc_ene0100.c 1969-12-31 19:00:00.000000000 -0500
+@@ -1,646 +0,0 @@
+-/*
+- * driver for ENE KB3926 B/C/D CIR (also known as ENE0100)
+- *
+- * Copyright (C) 2009 Maxim Levitsky <maximlevitsky at 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/kernel.h>
+-#include <linux/module.h>
+-#include <linux/pnp.h>
+-#include <linux/io.h>
+-#include <linux/interrupt.h>
+-#include <linux/sched.h>
+-#include "lirc_ene0100.h"
+-
+-static int sample_period = 75;
+-static int enable_idle = 1;
+-static int enable_learning;
+-
+-static void ene_set_idle(struct ene_device *dev, int idle);
+-static void ene_set_inputs(struct ene_device *dev, int enable);
+-
+-/* read a hardware register */
+-static u8 ene_hw_read_reg(struct ene_device *dev, u16 reg)
+-{
+- outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
+- outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
+- return inb(dev->hw_io + ENE_IO);
+-}
+-
+-/* write a hardware register */
+-static void ene_hw_write_reg(struct ene_device *dev, u16 reg, u8 value)
+-{
+- outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
+- outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
+- outb(value, dev->hw_io + ENE_IO);
+-}
+-
+-/* change specific bits in hardware register */
+-static void ene_hw_write_reg_mask(struct ene_device *dev,
+- u16 reg, u8 value, u8 mask)
+-{
+- u8 regvalue;
+-
+- outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
+- outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
+-
+- regvalue = inb(dev->hw_io + ENE_IO) & ~mask;
+- regvalue |= (value & mask);
+- outb(regvalue, dev->hw_io + ENE_IO);
+-}
+-
+-/* read irq status and ack it */
+-static int ene_hw_irq_status(struct ene_device *dev, int *buffer_pointer)
+-{
+- u8 irq_status;
+- u8 fw_flags1, fw_flags2;
+-
+- fw_flags2 = ene_hw_read_reg(dev, ENE_FW2);
+-
+- if (buffer_pointer)
+- *buffer_pointer = 4 * (fw_flags2 & ENE_FW2_BUF_HIGH);
+-
+- if (dev->hw_revision < ENE_HW_C) {
+- irq_status = ene_hw_read_reg(dev, ENEB_IRQ_STATUS);
+-
+- if (!(irq_status & ENEB_IRQ_STATUS_IR))
+- return 0;
+- ene_hw_write_reg(dev, ENEB_IRQ_STATUS,
+- irq_status & ~ENEB_IRQ_STATUS_IR);
+-
+- /* rev B support only recieving */
+- return ENE_IRQ_RX;
+- }
+-
+- irq_status = ene_hw_read_reg(dev, ENEC_IRQ);
+-
+- if (!(irq_status & ENEC_IRQ_STATUS))
+- return 0;
+-
+- /* original driver does that twice - a workaround ? */
+- ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS);
+- ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS);
+-
+- /* clear unknown flag in F8F9 */
+- if (fw_flags2 & ENE_FW2_IRQ_CLR)
+- ene_hw_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_IRQ_CLR);
+-
+- /* check if this is a TX interrupt */
+- fw_flags1 = ene_hw_read_reg(dev, ENE_FW1);
+-
+- if (fw_flags1 & ENE_FW1_TXIRQ) {
+- ene_hw_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
+- return ENE_IRQ_TX;
+- } else
+- return ENE_IRQ_RX;
+-}
+-
+-static int ene_hw_detect(struct ene_device *dev)
+-{
+- u8 chip_major, chip_minor;
+- u8 hw_revision, old_ver;
+- u8 tmp;
+- u8 fw_capabilities;
+-
+- tmp = ene_hw_read_reg(dev, ENE_HW_UNK);
+- ene_hw_write_reg(dev, ENE_HW_UNK, tmp & ~ENE_HW_UNK_CLR);
+-
+- chip_major = ene_hw_read_reg(dev, ENE_HW_VER_MAJOR);
+- chip_minor = ene_hw_read_reg(dev, ENE_HW_VER_MINOR);
+-
+- ene_hw_write_reg(dev, ENE_HW_UNK, tmp);
+- hw_revision = ene_hw_read_reg(dev, ENE_HW_VERSION);
+- old_ver = ene_hw_read_reg(dev, ENE_HW_VER_OLD);
+-
+- if (hw_revision == 0xFF) {
+-
+- ene_printk(KERN_WARNING, "device seems to be disabled\n");
+- ene_printk(KERN_WARNING,
+- "send a mail to lirc-list at lists.sourceforge.net\n");
+- ene_printk(KERN_WARNING, "please attach output of acpidump\n");
+-
+- return -ENODEV;
+- }
+-
+- if (chip_major == 0x33) {
+- ene_printk(KERN_WARNING, "chips 0x33xx aren't supported yet\n");
+- return -ENODEV;
+- }
+-
+- if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
+- dev->hw_revision = ENE_HW_C;
+- ene_printk(KERN_WARNING,
+- "KB3926C detected, driver support is not complete!\n");
+-
+- } else if (old_ver == 0x24 && hw_revision == 0xC0) {
+- dev->hw_revision = ENE_HW_B;
+- ene_printk(KERN_NOTICE, "KB3926B detected\n");
+- } else {
+- dev->hw_revision = ENE_HW_D;
+- ene_printk(KERN_WARNING,
+- "unknown ENE chip detected, assuming KB3926D\n");
+- ene_printk(KERN_WARNING, "driver support incomplete");
+-
+- }
+-
+- ene_printk(KERN_DEBUG, "chip is 0x%02x%02x - 0x%02x, 0x%02x\n",
+- chip_major, chip_minor, old_ver, hw_revision);
+-
+-
+- /* detect features hardware supports */
+-
+- if (dev->hw_revision < ENE_HW_C)
+- return 0;
+-
+- fw_capabilities = ene_hw_read_reg(dev, ENE_FW2);
+-
+- dev->hw_gpio40_learning = fw_capabilities & ENE_FW2_GP40_AS_LEARN;
+- dev->hw_learning_and_tx_capable = fw_capabilities & ENE_FW2_LEARNING;
+-
+- dev->hw_fan_as_normal_input = dev->hw_learning_and_tx_capable &&
+- fw_capabilities & ENE_FW2_FAN_AS_NRML_IN;
+-
+- ene_printk(KERN_NOTICE, "hardware features:\n");
+- ene_printk(KERN_NOTICE,
+- "learning and tx %s, gpio40_learn %s, fan_in %s\n",
+- dev->hw_learning_and_tx_capable ? "on" : "off",
+- dev->hw_gpio40_learning ? "on" : "off",
+- dev->hw_fan_as_normal_input ? "on" : "off");
+-
+- if (!dev->hw_learning_and_tx_capable && enable_learning)
+- enable_learning = 0;
+-
+- if (dev->hw_learning_and_tx_capable) {
+- ene_printk(KERN_WARNING,
+- "Device supports transmitting, but the driver doesn't\n");
+- ene_printk(KERN_WARNING,
+- "due to lack of hardware to test against.\n");
+- ene_printk(KERN_WARNING,
+- "Send a mail to: lirc-list at lists.sourceforge.net\n");
+- }
+- return 0;
+-}
+-
+-/* hardware initialization */
+-static int ene_hw_init(void *data)
+-{
+- u8 reg_value;
+- struct ene_device *dev = (struct ene_device *)data;
+- dev->in_use = 1;
+-
+- if (dev->hw_revision < ENE_HW_C) {
+- ene_hw_write_reg(dev, ENEB_IRQ, dev->irq << 1);
+- ene_hw_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
+- } else {
+- reg_value = ene_hw_read_reg(dev, ENEC_IRQ) & 0xF0;
+- reg_value |= ENEC_IRQ_UNK_EN;
+- reg_value &= ~ENEC_IRQ_STATUS;
+- reg_value |= (dev->irq & ENEC_IRQ_MASK);
+- ene_hw_write_reg(dev, ENEC_IRQ, reg_value);
+- ene_hw_write_reg(dev, ENE_TX_UNK1, 0x63);
+- }
+-
+- ene_hw_write_reg(dev, ENE_CIR_CONF2, 0x00);
+- ene_set_inputs(dev, enable_learning);
+-
+- /* set sampling period */
+- ene_hw_write_reg(dev, ENE_CIR_SAMPLE_PERIOD, sample_period);
+-
+- /* ack any pending irqs - just in case */
+- ene_hw_irq_status(dev, NULL);
+-
+- /* enter idle mode */
+- ene_set_idle(dev, 1);
+-
+- /* enable firmware bits */
+- ene_hw_write_reg_mask(dev, ENE_FW1,
+- ENE_FW1_ENABLE | ENE_FW1_IRQ,
+- ENE_FW1_ENABLE | ENE_FW1_IRQ);
+- /* clear stats */
+- dev->sample = 0;
+- return 0;
+-}
+-
+-/* this enables gpio40 signal, used if connected to wide band input*/
+-static void ene_enable_gpio40(struct ene_device *dev, int enable)
+-{
+- ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, enable ?
+- 0 : ENE_CIR_CONF2_GPIO40DIS,
+- ENE_CIR_CONF2_GPIO40DIS);
+-}
+-
+-/* this enables the classic sampler */
+-static void ene_enable_normal_recieve(struct ene_device *dev, int enable)
+-{
+- ene_hw_write_reg(dev, ENE_CIR_CONF1, enable ? ENE_CIR_CONF1_ADC_ON : 0);
+-}
+-
+-/* this enables recieve via fan input */
+-static void ene_enable_fan_recieve(struct ene_device *dev, int enable)
+-{
+- if (!enable)
+- ene_hw_write_reg(dev, ENE_FAN_AS_IN1, 0);
+- else {
+- ene_hw_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
+- ene_hw_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
+- }
+- dev->fan_input_inuse = enable;
+-}
+-
+-/* determine which input to use*/
+-static void ene_set_inputs(struct ene_device *dev, int learning_enable)
+-{
+- ene_enable_normal_recieve(dev, 1);
+-
+- /* old hardware doesn't support learning mode for sure */
+- if (dev->hw_revision <= ENE_HW_B)
+- return;
+-
+- /* reciever not learning capable, still set gpio40 correctly */
+- if (!dev->hw_learning_and_tx_capable) {
+- ene_enable_gpio40(dev, !dev->hw_gpio40_learning);
+- return;
+- }
+-
+- /* enable learning mode */
+- if (learning_enable) {
+- ene_enable_gpio40(dev, dev->hw_gpio40_learning);
+-
+- /* fan input is not used for learning */
+- if (dev->hw_fan_as_normal_input)
+- ene_enable_fan_recieve(dev, 0);
+-
+- /* disable learning mode */
+- } else {
+- if (dev->hw_fan_as_normal_input) {
+- ene_enable_fan_recieve(dev, 1);
+- ene_enable_normal_recieve(dev, 0);
+- } else
+- ene_enable_gpio40(dev, !dev->hw_gpio40_learning);
+- }
+-
+- /* set few additional settings for this mode */
+- ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, learning_enable ?
+- ENE_CIR_CONF1_LEARN1 : 0, ENE_CIR_CONF1_LEARN1);
+-
+- ene_hw_write_reg_mask(dev, ENE_CIR_CONF2, learning_enable ?
+- ENE_CIR_CONF2_LEARN2 : 0, ENE_CIR_CONF2_LEARN2);
+-}
+-
+-/* deinitialization */
+-static void ene_hw_deinit(void *data)
+-{
+- struct ene_device *dev = (struct ene_device *)data;
+-
+- /* disable samplers */
+- ene_enable_normal_recieve(dev, 0);
+-
+- if (dev->hw_fan_as_normal_input)
+- ene_enable_fan_recieve(dev, 0);
+-
+- /* disable hardware IRQ and firmware flag */
+- ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_ENABLE | ENE_FW1_IRQ);
+-
+- ene_set_idle(dev, 1);
+- dev->in_use = 0;
+-}
+-
+-/* sends current sample to userspace */
+-static void send_sample(struct ene_device *dev)
+-{
+- int value = abs(dev->sample) & PULSE_MASK;
+-
+- if (dev->sample > 0)
+- value |= PULSE_BIT;
+-
+- if (!lirc_buffer_full(dev->lirc_driver->rbuf)) {
+- lirc_buffer_write(dev->lirc_driver->rbuf, (void *)&value);
+- wake_up(&dev->lirc_driver->rbuf->wait_poll);
+- }
+- dev->sample = 0;
+-}
+-
+-/* this updates current sample */
+-static void update_sample(struct ene_device *dev, int sample)
+-{
+- if (!dev->sample)
+- dev->sample = sample;
+- else if (same_sign(dev->sample, sample))
+- dev->sample += sample;
+- else {
+- send_sample(dev);
+- dev->sample = sample;
+- }
+-}
+-
+-/* enable or disable idle mode */
+-static void ene_set_idle(struct ene_device *dev, int idle)
+-{
+- struct timeval now;
+- int disable = idle && enable_idle && (dev->hw_revision < ENE_HW_C);
+-
+- ene_hw_write_reg_mask(dev, ENE_CIR_SAMPLE_PERIOD,
+- disable ? 0 : ENE_CIR_SAMPLE_OVERFLOW,
+- ENE_CIR_SAMPLE_OVERFLOW);
+- dev->idle = idle;
+-
+- /* remember when we have entered the idle mode */
+- if (idle) {
+- do_gettimeofday(&dev->gap_start);
+- return;
+- }
+-
+- /* send the gap between keypresses now */
+- do_gettimeofday(&now);
+-
+- if (now.tv_sec - dev->gap_start.tv_sec > 16)
+- dev->sample = space(PULSE_MASK);
+- else
+- dev->sample = dev->sample +
+- space(1000000ull * (now.tv_sec - dev->gap_start.tv_sec))
+- + space(now.tv_usec - dev->gap_start.tv_usec);
+-
+- if (abs(dev->sample) > PULSE_MASK)
+- dev->sample = space(PULSE_MASK);
+- send_sample(dev);
+-}
+-
+-/* interrupt handler */
+-static irqreturn_t ene_hw_irq(int irq, void *data)
+-{
+- u16 hw_value;
+- int i, hw_sample;
+- int space;
+- int buffer_pointer;
+- int irq_status;
+-
+- struct ene_device *dev = (struct ene_device *)data;
+- irq_status = ene_hw_irq_status(dev, &buffer_pointer);
+-
+- if (!irq_status)
+- return IRQ_NONE;
+-
+- /* TODO: only RX for now */
+- if (irq_status == ENE_IRQ_TX)
+- return IRQ_HANDLED;
+-
+- for (i = 0; i < ENE_SAMPLES_SIZE; i++) {
+-
+- hw_value = ene_hw_read_reg(dev,
+- ENE_SAMPLE_BUFFER + buffer_pointer + i);
+-
+- if (dev->fan_input_inuse) {
+- /* read high part of the sample */
+- hw_value |= ene_hw_read_reg(dev,
+- ENE_SAMPLE_BUFFER_FAN + buffer_pointer + i) << 8;
+-
+- /* test for _space_ bit */
+- space = !(hw_value & ENE_FAN_SMPL_PULS_MSK);
+-
+- /* clear space bit, and other unused bits */
+- hw_value &= ENE_FAN_VALUE_MASK;
+- hw_sample = hw_value * ENE_SAMPLE_PERIOD_FAN;
+-
+- } else {
+- space = hw_value & ENE_SAMPLE_SPC_MASK;
+- hw_value &= ENE_SAMPLE_VALUE_MASK;
+- hw_sample = hw_value * sample_period;
+- }
+-
+- /* no more data */
+- if (!(hw_value))
+- break;
+-
+- if (space)
+- hw_sample *= -1;
+-
+- /* overflow sample recieved, handle it */
+-
+- if (!dev->fan_input_inuse && hw_value == ENE_SAMPLE_OVERFLOW) {
+-
+- if (dev->idle)
+- continue;
+-
+- if (dev->sample > 0 || abs(dev->sample) <= ENE_MAXGAP)
+- update_sample(dev, hw_sample);
+- else
+- ene_set_idle(dev, 1);
+-
+- continue;
+- }
+-
+- /* normal first sample recieved */
+- if (!dev->fan_input_inuse && dev->idle) {
+- ene_set_idle(dev, 0);
+-
+- /* discard first recieved value, its random
+- since its the time signal was off before
+- first pulse if idle mode is enabled, HW
+- does that for us */
+-
+- if (!enable_idle)
+- continue;
+- }
+- update_sample(dev, hw_sample);
+- send_sample(dev);
+- }
+- return IRQ_HANDLED;
+-}
+-
+-static int ene_probe(struct pnp_dev *pnp_dev,
+- const struct pnp_device_id *dev_id)
+-{
+- struct ene_device *dev;
+- struct lirc_driver *lirc_driver;
+- int error = -ENOMEM;
+-
+- dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
+-
+- if (!dev)
+- goto err1;
+-
+- dev->pnp_dev = pnp_dev;
+- pnp_set_drvdata(pnp_dev, dev);
+-
+-
+- /* prepare lirc interface */
+- error = -ENOMEM;
+- lirc_driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+-
+- if (!lirc_driver)
+- goto err2;
+-
+- dev->lirc_driver = lirc_driver;
+-
+- strcpy(lirc_driver->name, ENE_DRIVER_NAME);
+- lirc_driver->minor = -1;
+- lirc_driver->code_length = sizeof(int) * 8;
+- lirc_driver->features = LIRC_CAN_REC_MODE2;
+- lirc_driver->data = dev;
+- lirc_driver->set_use_inc = ene_hw_init;
+- lirc_driver->set_use_dec = ene_hw_deinit;
+- lirc_driver->dev = &pnp_dev->dev;
+- lirc_driver->owner = THIS_MODULE;
+-
+- lirc_driver->rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+-
+- if (!lirc_driver->rbuf)
+- goto err3;
+-
+- if (lirc_buffer_init(lirc_driver->rbuf, sizeof(int), sizeof(int) * 256))
+- goto err4;
+-
+- error = -ENODEV;
+- if (lirc_register_driver(lirc_driver))
+- goto err5;
+-
+- /* validate resources */
+- if (!pnp_port_valid(pnp_dev, 0) ||
+- pnp_port_len(pnp_dev, 0) < ENE_MAX_IO)
+- goto err6;
+-
+- if (!pnp_irq_valid(pnp_dev, 0))
+- goto err6;
+-
+- dev->hw_io = pnp_port_start(pnp_dev, 0);
+- dev->irq = pnp_irq(pnp_dev, 0);
+-
+- /* claim the resources */
+- error = -EBUSY;
+- if (!request_region(dev->hw_io, ENE_MAX_IO, ENE_DRIVER_NAME))
+- goto err6;
+-
+- if (request_irq(dev->irq, ene_hw_irq,
+- IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev))
+- goto err7;
+-
+- /* detect hardware version and features */
+- error = ene_hw_detect(dev);
+- if (error)
+- goto err8;
+-
+- ene_printk(KERN_NOTICE, "driver has been succesfully loaded\n");
+- return 0;
+-
+-err8:
+- free_irq(dev->irq, dev);
+-err7:
+- release_region(dev->hw_io, ENE_MAX_IO);
+-err6:
+- lirc_unregister_driver(lirc_driver->minor);
+-err5:
+- lirc_buffer_free(lirc_driver->rbuf);
+-err4:
+- kfree(lirc_driver->rbuf);
+-err3:
+- kfree(lirc_driver);
+-err2:
+- kfree(dev);
+-err1:
+- return error;
+-}
+-
+-static void ene_remove(struct pnp_dev *pnp_dev)
+-{
+- struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+- ene_hw_deinit(dev);
+- free_irq(dev->irq, dev);
+- release_region(dev->hw_io, ENE_MAX_IO);
+- lirc_unregister_driver(dev->lirc_driver->minor);
+- lirc_buffer_free(dev->lirc_driver->rbuf);
+- kfree(dev->lirc_driver);
+- kfree(dev);
+-}
+-
+-#ifdef CONFIG_PM
+-
+-/* TODO: make 'wake on IR' configurable and add .shutdown */
+-/* currently impossible due to lack of kernel support */
+-
+-static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
+-{
+- struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+- ene_hw_write_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, ENE_FW1_WAKE);
+- return 0;
+-}
+-
+-static int ene_resume(struct pnp_dev *pnp_dev)
+-{
+- struct ene_device *dev = pnp_get_drvdata(pnp_dev);
+- if (dev->in_use)
+- ene_hw_init(dev);
+-
+- ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_WAKE);
+- return 0;
+-}
+-
+-#endif
+-
+-static const struct pnp_device_id ene_ids[] = {
+- {.id = "ENE0100",},
+- {},
+-};
+-
+-static struct pnp_driver ene_driver = {
+- .name = ENE_DRIVER_NAME,
+- .id_table = ene_ids,
+- .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
+-
+- .probe = ene_probe,
+- .remove = __devexit_p(ene_remove),
+-
+-#ifdef CONFIG_PM
+- .suspend = ene_suspend,
+- .resume = ene_resume,
+-#endif
+-};
+-
+-static int __init ene_init(void)
+-{
+- if (sample_period < 5) {
+- ene_printk(KERN_ERR, "sample period must be at\n");
+- ene_printk(KERN_ERR, "least 5 us, (at least 30 recommended)\n");
+- return -EINVAL;
+- }
+- return pnp_register_driver(&ene_driver);
+-}
+-
+-static void ene_exit(void)
+-{
+- pnp_unregister_driver(&ene_driver);
+-}
+-
+-module_param(sample_period, int, S_IRUGO);
+-MODULE_PARM_DESC(sample_period, "Hardware sample period (75 us default)");
+-
+-module_param(enable_idle, bool, S_IRUGO | S_IWUSR);
+-MODULE_PARM_DESC(enable_idle,
+- "Enables turning off signal sampling after long inactivity time; "
+- "if disabled might help detecting input signal (default: enabled)");
+-
+-module_param(enable_learning, bool, S_IRUGO);
+-MODULE_PARM_DESC(enable_learning, "Use wide band (learning) reciever");
+-
+-MODULE_DEVICE_TABLE(pnp, ene_ids);
+-MODULE_DESCRIPTION
+- ("LIRC driver for KB3926B/KB3926C/KB3926D (aka ENE0100) CIR port");
+-MODULE_AUTHOR("Maxim Levitsky");
+-MODULE_LICENSE("GPL");
+-
+-module_init(ene_init);
+-module_exit(ene_exit);
+diff -Naurp linux-2.6.35/drivers/staging/lirc/lirc_ene0100.h linux-2.6.35.new/drivers/staging/lirc/lirc_ene0100.h
+--- linux-2.6.35/drivers/staging/lirc/lirc_ene0100.h 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/staging/lirc/lirc_ene0100.h 1969-12-31 19:00:00.000000000 -0500
+@@ -1,169 +0,0 @@
+-/*
+- * driver for ENE KB3926 B/C/D CIR (also known as ENE0100)
+- *
+- * Copyright (C) 2009 Maxim Levitsky <maximlevitsky at 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 <media/lirc.h>
+-#include <media/lirc_dev.h>
+-
+-/* hardware address */
+-#define ENE_STATUS 0 /* hardware status - unused */
+-#define ENE_ADDR_HI 1 /* hi byte of register address */
+-#define ENE_ADDR_LO 2 /* low byte of register address */
+-#define ENE_IO 3 /* read/write window */
+-#define ENE_MAX_IO 4
+-
+-/* 8 bytes of samples, divided in 2 halfs*/
+-#define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */
+-#define ENE_SAMPLE_SPC_MASK (1 << 7) /* sample is space */
+-#define ENE_SAMPLE_VALUE_MASK 0x7F
+-#define ENE_SAMPLE_OVERFLOW 0x7F
+-#define ENE_SAMPLES_SIZE 4
+-
+-/* fan input sample buffer */
+-#define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */
+- /* each sample of normal buffer */
+-
+-#define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */
+- /* if set, says that sample is pulse */
+-#define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */
+-
+-/* first firmware register */
+-#define ENE_FW1 0xF8F8
+-#define ENE_FW1_ENABLE (1 << 0) /* enable fw processing */
+-#define ENE_FW1_TXIRQ (1 << 1) /* TX interrupt pending */
+-#define ENE_FW1_WAKE (1 << 6) /* enable wake from S3 */
+-#define ENE_FW1_IRQ (1 << 7) /* enable interrupt */
+-
+-/* second firmware register */
+-#define ENE_FW2 0xF8F9
+-#define ENE_FW2_BUF_HIGH (1 << 0) /* which half of the buffer to read */
+-#define ENE_FW2_IRQ_CLR (1 << 2) /* clear this on IRQ */
+-#define ENE_FW2_GP40_AS_LEARN (1 << 4) /* normal input is used as */
+- /* learning input */
+-#define ENE_FW2_FAN_AS_NRML_IN (1 << 6) /* fan is used as normal input */
+-#define ENE_FW2_LEARNING (1 << 7) /* hardware supports learning and TX */
+-
+-/* fan as input settings - only if learning capable */
+-#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */
+-#define ENE_FAN_AS_IN1_EN 0xCD
+-#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */
+-#define ENE_FAN_AS_IN2_EN 0x03
+-#define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */
+-
+-/* IRQ registers block (for revision B) */
+-#define ENEB_IRQ 0xFD09 /* IRQ number */
+-#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */
+-#define ENEB_IRQ_STATUS 0xFD80 /* irq status */
+-#define ENEB_IRQ_STATUS_IR (1 << 5) /* IR irq */
+-
+-/* IRQ registers block (for revision C,D) */
+-#define ENEC_IRQ 0xFE9B /* new irq settings register */
+-#define ENEC_IRQ_MASK 0x0F /* irq number mask */
+-#define ENEC_IRQ_UNK_EN (1 << 4) /* always enabled */
+-#define ENEC_IRQ_STATUS (1 << 5) /* irq status and ACK */
+-
+-/* CIR block settings */
+-#define ENE_CIR_CONF1 0xFEC0
+-#define ENE_CIR_CONF1_ADC_ON 0x7 /* reciever on gpio40 enabled */
+-#define ENE_CIR_CONF1_LEARN1 (1 << 3) /* enabled on learning mode */
+-#define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */
+-#define ENE_CIR_CONF1_TX_CARR (1 << 7) /* send TX carrier or not */
+-
+-#define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */
+-#define ENE_CIR_CONF2_LEARN2 (1 << 4) /* set on enable learning */
+-#define ENE_CIR_CONF2_GPIO40DIS (1 << 5) /* disable normal input via gpio40 */
+-
+-#define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */
+-#define ENE_CIR_SAMPLE_OVERFLOW (1 << 7) /* interrupt on overflows if set */
+-
+-
+-/* transmitter - not implemented yet */
+-/* KB3926C and higher */
+-/* transmission is very similiar to recieving, a byte is written to */
+-/* ENE_TX_INPUT, in same manner as it is read from sample buffer */
+-/* sample period is fixed*/
+-
+-
+-/* transmitter ports */
+-#define ENE_TX_PORT1 0xFC01 /* this enables one or both */
+-#define ENE_TX_PORT1_EN (1 << 5) /* TX ports */
+-#define ENE_TX_PORT2 0xFC08
+-#define ENE_TX_PORT2_EN (1 << 1)
+-
+-#define ENE_TX_INPUT 0xFEC9 /* next byte to transmit */
+-#define ENE_TX_SPC_MASK (1 << 7) /* Transmitted sample is space */
+-#define ENE_TX_UNK1 0xFECB /* set to 0x63 */
+-#define ENE_TX_SMPL_PERIOD 50 /* transmit sample period */
+-
+-
+-#define ENE_TX_CARRIER 0xFECE /* TX carrier * 2 (khz) */
+-#define ENE_TX_CARRIER_UNKBIT 0x80 /* This bit set on transmit */
+-#define ENE_TX_CARRIER_LOW 0xFECF /* TX carrier / 2 */
+-
+-/* Hardware versions */
+-#define ENE_HW_VERSION 0xFF00 /* hardware revision */
+-#define ENE_HW_UNK 0xFF1D
+-#define ENE_HW_UNK_CLR (1 << 2)
+-#define ENE_HW_VER_MAJOR 0xFF1E /* chip version */
+-#define ENE_HW_VER_MINOR 0xFF1F
+-#define ENE_HW_VER_OLD 0xFD00
+-
+-#define same_sign(a, b) ((((a) > 0) && (b) > 0) || ((a) < 0 && (b) < 0))
+-
+-#define ENE_DRIVER_NAME "enecir"
+-#define ENE_MAXGAP 250000 /* this is amount of time we wait
+- before turning the sampler, chosen
+- arbitry */
+-
+-#define space(len) (-(len)) /* add a space */
+-
+-/* software defines */
+-#define ENE_IRQ_RX 1
+-#define ENE_IRQ_TX 2
+-
+-#define ENE_HW_B 1 /* 3926B */
+-#define ENE_HW_C 2 /* 3926C */
+-#define ENE_HW_D 3 /* 3926D */
+-
+-#define ene_printk(level, text, ...) \
+- printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__)
+-
+-struct ene_device {
+- struct pnp_dev *pnp_dev;
+- struct lirc_driver *lirc_driver;
+-
+- /* hw settings */
+- unsigned long hw_io;
+- int irq;
+-
+- int hw_revision; /* hardware revision */
+- int hw_learning_and_tx_capable; /* learning capable */
+- int hw_gpio40_learning; /* gpio40 is learning */
+- int hw_fan_as_normal_input; /* fan input is used as regular input */
+-
+- /* device data */
+- int idle;
+- int fan_input_inuse;
+-
+- int sample;
+- int in_use;
+-
+- struct timeval gap_start;
+-};
+diff -Naurp linux-2.6.35/drivers/staging/lirc/Makefile linux-2.6.35.new/drivers/staging/lirc/Makefile
+--- linux-2.6.35/drivers/staging/lirc/Makefile 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/drivers/staging/lirc/Makefile 2010-09-09 23:21:42.000000000 -0400
+@@ -4,7 +4,6 @@
+ # Each configuration option enables a list of files.
+
+ obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o
+-obj-$(CONFIG_LIRC_ENE0100) += lirc_ene0100.o
+ obj-$(CONFIG_LIRC_I2C) += lirc_i2c.o
+ obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o
+ obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
+diff -Naurp linux-2.6.35/include/media/ir-core.h linux-2.6.35.new/include/media/ir-core.h
+--- linux-2.6.35/include/media/ir-core.h 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/include/media/ir-core.h 2010-09-09 23:21:49.000000000 -0400
+@@ -41,6 +41,11 @@ enum rc_driver_type {
+ * anything with it. Yet, as the same keycode table can be used with other
+ * devices, a mask is provided to allow its usage. Drivers should generally
+ * leave this field in blank
++ * @timeout: optional time after which device stops sending data
++ * @min_timeout: minimum timeout supported by device
++ * @max_timeout: maximum timeout supported by device
++ * @rx_resolution : resolution (in ns) of input sampler
++ * @tx_resolution: resolution (in ns) of output sampler
+ * @priv: driver-specific data, to be used on the callbacks
+ * @change_protocol: allow changing the protocol used on hardware decoders
+ * @open: callback to allow drivers to enable polling/irq when IR input device
+@@ -49,19 +54,36 @@ enum rc_driver_type {
+ * is opened.
+ * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs)
+ * @s_tx_carrier: set transmit carrier frequency
++ * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%)
++ * @s_rx_carrier: inform driver about carrier it is expected to handle
+ * @tx_ir: transmit IR
++ * @s_idle: optional: enable/disable hardware idle mode, upon which,
++ device doesn't interrupt host until it sees IR pulses
++ * @s_learning_mode: enable wide band receiver used for learning
+ */
+ struct ir_dev_props {
+ enum rc_driver_type driver_type;
+ unsigned long allowed_protos;
+ u32 scanmask;
++
++ u32 timeout;
++ u32 min_timeout;
++ u32 max_timeout;
++
++ u32 rx_resolution;
++ u32 tx_resolution;
++
+ void *priv;
+ int (*change_protocol)(void *priv, u64 ir_type);
+ int (*open)(void *priv);
+ void (*close)(void *priv);
+ int (*s_tx_mask)(void *priv, u32 mask);
+ int (*s_tx_carrier)(void *priv, u32 carrier);
++ int (*s_tx_duty_cycle)(void *priv, u32 duty_cycle);
++ int (*s_rx_carrier_range)(void *priv, u32 min, u32 max);
+ int (*tx_ir)(void *priv, int *txbuf, u32 n);
++ void (*s_idle)(void *priv, int enable);
++ int (*s_learning_mode)(void *priv, int enable);
+ };
+
+ struct ir_input_dev {
+@@ -69,9 +91,10 @@ struct ir_input_dev {
+ char *driver_name; /* Name of the driver module */
+ struct ir_scancode_table rc_tab; /* scan/key table */
+ unsigned long devno; /* device number */
+- const struct ir_dev_props *props; /* Device properties */
++ struct ir_dev_props *props; /* Device properties */
+ struct ir_raw_event_ctrl *raw; /* for raw pulse/space events */
+ struct input_dev *input_dev; /* the input device associated with this device */
++ bool idle;
+
+ /* key info - needed by IR keycode handlers */
+ spinlock_t keylock; /* protects the below members */
+@@ -95,12 +118,12 @@ enum raw_event_type {
+ /* From ir-keytable.c */
+ int __ir_input_register(struct input_dev *dev,
+ const struct ir_scancode_table *ir_codes,
+- const struct ir_dev_props *props,
++ struct ir_dev_props *props,
+ const char *driver_name);
+
+ static inline int ir_input_register(struct input_dev *dev,
+ const char *map_name,
+- const struct ir_dev_props *props,
++ struct ir_dev_props *props,
+ const char *driver_name) {
+ struct ir_scancode_table *ir_codes;
+ struct ir_input_dev *ir_dev;
+@@ -110,8 +133,12 @@ static inline int ir_input_register(stru
+ return -EINVAL;
+
+ ir_codes = get_rc_map(map_name);
+- if (!ir_codes)
+- return -EINVAL;
++ if (!ir_codes) {
++ ir_codes = get_rc_map(RC_MAP_EMPTY);
++
++ if (!ir_codes)
++ return -EINVAL;
++ }
+
+ rc = __ir_input_register(dev, ir_codes, props, driver_name);
+ if (rc < 0)
+@@ -144,6 +171,10 @@ struct ir_raw_event {
+ void ir_raw_event_handle(struct input_dev *input_dev);
+ int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev);
+ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type);
++int ir_raw_event_store_with_filter(struct input_dev *input_dev,
++ struct ir_raw_event *ev);
++void ir_raw_event_set_idle(struct input_dev *input_dev, int idle);
++
+ static inline void ir_raw_event_reset(struct input_dev *input_dev)
+ {
+ struct ir_raw_event ev = { .pulse = false, .duration = 0 };
+diff -Naurp linux-2.6.35/include/media/lirc.h linux-2.6.35.new/include/media/lirc.h
+--- linux-2.6.35/include/media/lirc.h 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/include/media/lirc.h 2010-09-09 23:21:42.000000000 -0400
+@@ -77,6 +77,7 @@
+ #define LIRC_CAN_SET_REC_FILTER 0x08000000
+
+ #define LIRC_CAN_MEASURE_CARRIER 0x02000000
++#define LIRC_CAN_USE_WIDEBAND_RECEIVER 0x04000000
+
+ #define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK)
+ #define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK)
+@@ -145,7 +146,7 @@
+ * if enabled from the next key press on the driver will send
+ * LIRC_MODE2_FREQUENCY packets
+ */
+-#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32)
++#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32)
+
+ /*
+ * to set a range use
+@@ -162,4 +163,6 @@
+ #define LIRC_SETUP_START _IO('i', 0x00000021)
+ #define LIRC_SETUP_END _IO('i', 0x00000022)
+
++#define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32)
++
+ #endif
+diff -Naurp linux-2.6.35/include/media/rc-map.h linux-2.6.35.new/include/media/rc-map.h
+--- linux-2.6.35/include/media/rc-map.h 2010-09-09 23:19:00.000000000 -0400
++++ linux-2.6.35.new/include/media/rc-map.h 2010-09-09 23:21:42.000000000 -0400
+@@ -70,6 +70,8 @@ void rc_map_init(void);
+ #define RC_MAP_BUDGET_CI_OLD "rc-budget-ci-old"
+ #define RC_MAP_CINERGY_1400 "rc-cinergy-1400"
+ #define RC_MAP_CINERGY "rc-cinergy"
++#define RC_MAP_DIB0700_NEC_TABLE "rc-dib0700-nec"
++#define RC_MAP_DIB0700_RC5_TABLE "rc-dib0700-rc5"
+ #define RC_MAP_DM1105_NEC "rc-dm1105-nec"
+ #define RC_MAP_DNTV_LIVE_DVBT_PRO "rc-dntv-live-dvbt-pro"
+ #define RC_MAP_DNTV_LIVE_DVB_T "rc-dntv-live-dvb-t"
+@@ -125,6 +127,7 @@ void rc_map_init(void);
+ #define RC_MAP_VIDEOMATE_TV_PVR "rc-videomate-tv-pvr"
+ #define RC_MAP_WINFAST "rc-winfast"
+ #define RC_MAP_WINFAST_USBII_DELUXE "rc-winfast-usbii-deluxe"
++
+ /*
+ * Please, do not just append newer Remote Controller names at the end.
+ * The names should be ordered in alphabetical order
More information about the scm-commits
mailing list