4098 lines
121 KiB
Diff
4098 lines
121 KiB
Diff
This patch rolls up the following v4l-dvb upstream commits:
|
|
|
|
commit 9b44ed200f1584f029da82e60e1f284d1d8de3da
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:26 2010 -0300
|
|
|
|
V4L/DVB: IR: Port ene driver to new IR subsystem and enable it
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 46192437f6d17c49f37bef73c97a14f2ed278db0
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:25 2010 -0300
|
|
|
|
V4L/DVB: STAGING: remove lirc_ene0100 driver
|
|
|
|
Add latest unported version of this driver to media/IR.
|
|
Next patch will port it to ir core.
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit abf84383ecadc8ada1963f9976e887c6f0b1bad9
|
|
Author: Joe Perches <joe@perches.com>
|
|
Date: Mon Jul 12 17:50:03 2010 -0300
|
|
|
|
V4L/DVB: drivers/media: Remove unnecessary casts of private_data
|
|
|
|
Signed-off-by: Joe Perches <joe@perches.com>
|
|
Acked-by: Jarod Wilson <jarod@redhat.com>
|
|
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 26699e3cf2ce4938112ddf60e084feaf4ce435b5
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:20 2010 -0300
|
|
|
|
V4L/DVB: IR: NECX: support repeat
|
|
|
|
This adds support for repeat detecting for NECX variant
|
|
Tested with uneversal remote
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 7f01033b288bb86d4f9d2885966d2c255f3659c1
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:19 2010 -0300
|
|
|
|
V4L/DVB: IR: nec decoder: fix repeat
|
|
|
|
Repeat space is 4 units, not 8.
|
|
Current code would never trigger a repeat.
|
|
|
|
However that isn't true for NECX, so repeat there
|
|
must be handled differently.
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Reviewed-by: Andy Walls <awalls@md.metrocast.net>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 54f7413aa4ce44d18c7f9744e37ff64c4668daa6
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:18 2010 -0300
|
|
|
|
V4L/DVB: IR: JVC: make repeat work
|
|
|
|
Currently, jvc decoder will attempt misdetect next press as a repeat
|
|
of last keypress, therefore second keypress isn't detected.
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 951c6835be77d1baf619f7960c2beb22eea36947
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:24 2010 -0300
|
|
|
|
V4L/DVB: IR: report unknown scancodes the in-kernel decoders found
|
|
|
|
This way it is possible to use evtest to create keymap for unknown remote.
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 3879b56940f84f3b90fb77ad5860083930be4bac
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:23 2010 -0300
|
|
|
|
V4L/DVB: IR: extend interfaces to support more device settings
|
|
|
|
LIRC: add new IOCTL that enables learning mode (wide band receiver)
|
|
Still missing features: carrier report & timeout reports.
|
|
Will need to pack these into ir_raw_event
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 2f5fb55510cf309cd749f1af85e26274f9e360ab
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:22 2010 -0300
|
|
|
|
V4L/DVB: IR: add helper function for hardware with small o/b buffer
|
|
|
|
Some ir input devices have small buffer, and interrupt the host
|
|
each time it is full (or half full)
|
|
|
|
Add a helper that automaticly handles timeouts, and also
|
|
automaticly merges samples of same time (space-space)
|
|
Such samples might be placed by hardware because size of
|
|
sample in the buffer is small (a byte for example).
|
|
|
|
Also remove constness from ir_dev_props, because it now contains timeout
|
|
settings that driver might want to change
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Acked-by: Jarod Wilson <jarod@redhat.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 0f3f74ce40f25e80e3733e5d5293251568b03d83
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:21 2010 -0300
|
|
|
|
V4L/DVB: IR: Allow not to compile keymaps in
|
|
|
|
Currently, ir device registration fails if keymap requested by driver is not found.
|
|
Fix that by always compiling in the empty keymap, and using it as a failback.
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Acked-by: Jarod Wilson <jarod@redhat.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit daad37e3a9e0b9366da8eecb3e64bd47ac831938
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:17 2010 -0300
|
|
|
|
V4L/DVB: IR: replace workqueue with kthread
|
|
|
|
It is perfectly possible to have ir_raw_event_work
|
|
running concurently on two cpus, thus we must protect
|
|
it from that situation.
|
|
|
|
This stems from the fact that if hardware sends short packets of samples
|
|
we might end up queueing the work item more times that nessesary.
|
|
|
|
Such job isn't well suited for a workqueue, so use a kernel thread.
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 7c4be7bab7bb06974d649835cac66b5df984047f
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:16 2010 -0300
|
|
|
|
V4L/DVB: IR: replace spinlock with mutex
|
|
|
|
Some handlers (lirc for example) allocates memory on initialization,
|
|
doing so in atomic context is cumbersome.
|
|
Fixes warning about sleeping function in atomic context.
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 211ed16e58b2fdf0335e47546b252398b47e7790
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:15 2010 -0300
|
|
|
|
V4L/DVB: IR: minor fixes
|
|
|
|
* lirc: Don't propagate reset event to userspace
|
|
* lirc: Remove strange logic from lirc that would make first sample always be pulse
|
|
* Make TO_US macro actualy print what it should.
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit d8ffb6454250115ca0636d8481030466c1e3fdec
|
|
Author: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Date: Sat Jul 31 11:59:14 2010 -0300
|
|
|
|
V4L/DVB: IR: Kconfig fixes
|
|
|
|
Move IR drives below separate menu.
|
|
This allows to disable them.
|
|
Also correct a typo.
|
|
|
|
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 5af935cc96a291f90799bf6a2587d87329a91699
|
|
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
Date: Sun Aug 1 08:02:35 2010 -0300
|
|
|
|
V4L/DVB: dib0700: break keytable into NEC and RC-5 variants
|
|
|
|
Instead of having one big keytable with 2 protocols inside, break it
|
|
into two separate tables, being one for NEC and another for RC-5 variants,
|
|
and properly identify what variant should be used at the boards entries.
|
|
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
commit 50b9d21ae2ac1b85be46f1ee5aa1b5e588622361
|
|
Author: Jarod Wilson <jarod@redhat.com>
|
|
Date: Fri Aug 27 18:21:14 2010 -0300
|
|
|
|
V4L/DVB: mceusb: add two new ASUS device IDs
|
|
|
|
Reported in lirc sf.net tracker and on lirc mailing list
|
|
|
|
Signed-off-by: Jarod Wilson <jarod@redhat.com>
|
|
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
|
|
|
|
|
|
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@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@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@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@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@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@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@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@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/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@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@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@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@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
|